Diapositive 1 - New Commerce Solutions

publicité
Introduction
●
AJAX: Asynchronous Javascript and XML
●
Similarités entre les WebServices et les requêtes
XmlHttpRequest. (REST Services)
●
Une requête est passée, elle contient une fonction et
des paramètres. Une réponse nous est retournée en
XML, Text ou Javascript (JSON)
●
●
Les requêtes ont un but spécifique et donc remplissent
une fonction spécifique.
La démo de cette présentation se trouve ici :
http://www.newcommerce.ca/demo
Crédit photo: http://ptitecocci.deviantart.com
AJAX – Exemple d'utilisation
●
●
●
●
Je suis sur Google Suggest et je cherche à faire une recherche. Je commence à
taper quelques lettres dans le but de former un mot.
À chaque frappe, la page web (html + javascript) côté client attrape l'événement et
fait une requête auprès du service de suggestion de google pour obtenir des
possibilités de recherches basées sur les lettres entrez. ( GET
http://www.google.com/complete/search?hl=en&js=true&qu=g )
Google suggest fait une recherche du côté serveur et retourne en format javascript
les recherches les plus populaires débutant par les lettres entrées par l'utilisateur.
( sendRPCDone(frameElement, "gjr", new Array("gjr", "gjr.paknet.com.pk", "gjr
garch", "gjradio", "gjrealsource", "gjr krishnan", "gjrealsource.com", "gjrentals",
"gjrentals.com", "gjrealtors.org"), new Array("68,900 results", "1 result", "861
results", "101 results", "162 results", "591 results", "1 result", "29 results", "1
result", " "), new Array(""));)
La page web (html+javascript) reçoit ces informations et les démontre à l'utilisateur
à l'aide de dHTML et Javascript
Introduction à l'objet XmlHttpRequest
●
L'object xmlHttpRequest est utilisé en Javascript pour communiquer avec le serveur
HTTP, soit le site web.
<code:javascript>
function getXMLHTTP(){
var xhr = null;
if(window.XMLHttpRequest) // Firefox et autres
xhr = new XMLHttpRequest();
else if(window.ActiveXObject){ // Internet Explorer
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
}
else { // XMLHttpRequest non supporté par le navigateur
alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest...");
xhr = false;
}
return xhr;
}
</code:javascript>
Objectif
●
●
●
Utiliser AJAX pour la validation de données dans un
formulaire
Développeer l'algorithme de validation :
Méchanisme de validation en temps réel, c'est-à-dire au fur et à
mesure que les données sont insérées dans le formulaire.
●
Il y aura trois états pour le champ: jaune, vert et rouge
●
Affichage du message d'erreur à côté du champ à valider.
État du champ
●
●
●
Initialement, le champ n'a pas d'état. Son background est blanc
et il n'y a aucun message à côté
Une fois le focus activé sur le champ, il entre à l'état Jaune.
C'est-à-dire que le background du champ change et un message
guidant l'entrée de donnée peut apparaître à sa droite.
Si le champ a une longueur de contenu fixe, c'est-à-dire que son
contenu doit être composé d'un contenir un certain nombre de
caractères et que ce nombre est atteint alors que les données
saisies ne répondent pas au critère de validation, le champ passe
au Rouge. Dans les mêmes conditions si les données saisies
correspondent au critère de validation, le champ passe au Vert.
État du champ (suite)
●
●
Si l'utilisateur quitte le champ alors que les données qui y sont
saisies ne correspondent pas au critère de validation, le champ
passe au Rouge.
Si l'utilisateur quitte le champ alors que les données répondent
au critère de validation, le champ passe au Vert.
État du champ (suite)
État initial
le champ n'a pas reçu
le focus encore
Jaune
le champ reçoit le focus
et le visiteur tape
Rouge
les données saisies ne
répondent pas au
critère
de validation
Vert
les données saisies
répondent au critère
de validation
Types de données à traiter
●
●
●
●
●
●
Données qui sont validables avec une simple fonction
javascript ou une regular expression.
Des données à format prédéfini. Par exemple un numéro de
téléphone ou un code postal.
Aide à l'utilisateur pour formater le champ en temps réel.
Données qui nécessitent une vérification du côté
serveur pour la validation
Pour empêcher la duplication de certaines informations (nom
d'utilisateur)
Pour empêcher un utilisateur d'avoir deux comptes (adresse
email)
Intro. manipulation html javascript
●
Chaque balise HTML peut contenir un identificateur
unique: son 'id'
<input type='text' id='zipcode' length='6' />
●
Pour obtenir un élément on utilise la commande
'getElementById' ou sa version simplifiée (crossbrowser friendly) comme suit :
Intro. manipulation html javascript
<code:javascript>
function getElement(layerID) {
if (document.getElementById)
return document.getElementById(layerID);
else if (document.all)
return document.all.layerID;
else
// on a un problème
return null;
}
// exemple
var zipCodeEl = getElement('zipcode');
</code:javascript>
Intro. manipulation html javascript
●
De là on peut éditer toutes ses propriétés
incluant ses éléments de style CSS
<code:javascript>
function setColors(el, bg, fg){
if (el.style){
if(bgl) el.style.backgroundColor = bg;
if(fg) el.style.color = fg;
}
}
// obtenir l'élément
var zipCodeEl = getElement(“zipcode');
// changer sa couleur de background à jaune, et de foreground (texte) à noir.
setColors(zipCodeEl, “#cad116”, “#000000”);
</code:javascript>
Intro. manipulation html javascript
●
Exemple de d'autres propriétés qu'on peut modifier:
●
.style.width, .style.height
●
.style.margin
●
.style.border, borderColor, borderStyle ...
●
.style.clear, .style.cursor, .style.display
●
.style.font, fontFamily, fontSize, fintStretch, fontWeight
●
.style.lineHeight
●
.style.lef, top (position)
●
.style.overflow, .style.opacity, .style.padding
●
InnerHTML ***, etc..
Intro. manipulation html javascript
●
Pour obtenir toute la liste, vous pouvez utiliser le DOM
Inspector. Sélectionnez une node dans la fenêtre de
gauche et dans la fenêtre de droite choisissez
Object – Javascript Object.
Utilisation de la propriété innerHTML
●
Étant donnée la structure du HTML, c'est-à-dire que
chaque tag peut en contenir d'autres, nous avons en
notre possession une propriété TRÈS utile:
.innerHTML. Prenez le tableau suivant:
<table id='tableau' cellspacing='1' cellpadding='4'>
<tr id='range'>
<td id='col01'>Hello</td>
<td id='col02'>Bonjour</td>
</tr>
</table>
Utilisation de la propriété innerHTML
●
Maintenant on peut manipuler ce tableau et son
contenu directement en javascript
<code:javascript>
var tableau = getElement('tableau');
var range = getElement('range');
var col1 = getElement('col01');
var col2 = getElement('col02');
col1.innerHTML = “Konishuwa”;
col2.innerHTML = “Buenas Dias”;
range.innerHTML = “<td>Konishuwa</td><td>Buenas Dias</td>
<td>Danke</td>”;
tableau = “<tr><td>Konishuwa</td><td>Buenas Dias</td><td>Danke</td></tr>
<tr><td>Bonjour</td><td>Hello</td><td> .... </td></tr>”;
</code:javascript>
Utilisation de la propriété innerHTML
●
Les possibilités sont illimitées...
Champ, couleurs et message d'erreur
●
dans notre exemple précédent
nous avons à gauche un libellé, suivit de notre champ et à
droite le message d'erreur. En HTML, en utilisant les tableaux,
cela se traduit en...
<table border=”0” cellpadding=”2” cellspacing=”0”>
<tr bgcolor="#0A3F7B"> <td width="33%" align="right">Code Postal</td>
<td width="25%" bgcolor="#0A3F7B"><input name="codepostal" type="text"
id="codepostal" size="7" maxlength="7"></td>
<td width="42%" nowrap id='codepostal_status'> </td>
</tr>
</table>
on a donc 2 éléments HTML qui contiennent un id. Le champ et
la cellule de tableau à sa droite.
Changer le statut du champ
●
La cellule qui contient le message d'erreur a un
id de “id du champ”+'_status', ce qui facilite la
tache.
<code:javascript>
function changeHTML(element, text) {
elementObject = getElement(element);
elementObject.innerHTML = text;
}
setFieldState(“zipCode”, “yellow”, “H0H 0H0”);
</code:javascript>
Changer le statut du champ (suite)
●
Définir la fonction maintenant
<code:javascript>
function setFieldState(field, state, message)
{
var messageId = field+”_status”;
stateBg = {yellow: “#cad116”, red: “#bb6969”, green: “#b6b6b6”};
var bgColor = stateBg[state];
var fgColor = “#000000”;
changeHTML(messageId, message);
setColors(getElement(field), bgColor, fgColor);
setColors(getElement(messageId), null, bgColor);
}
</code:javascript>
Les événements
●
Il existe plusieurs événements en Javascript qui sont
lancés pour les éléments '<input>' tels que le champ
de saisi texte. Ils sont :
●
onfocus
●
onblur (perte de focus)
●
onkeyup
●
onkeydown
●
onchange
●
onmouseover, onmouseout, onmousedow, onmouseup
●
Pour une liste complète consultez:
http://www.devguru.com/technologies/javascript/
Les événements (suite)
●
●
Nous sommes intéressés à plusieurs événements
notamment 'onkeyup', 'onfocus', 'onblur'. L'événement
onChange ne fonctionne pas de façon cohérente à
notre utilisation, alors on n'en prendra pas compte.
Le champ zipCode devient donc:
<input type='text'
id='zipcode'
name='zipcode'
onblur=”validate('zipcode', false)”
onkeyup=”validate('zipcode', true)”
onfocus=”validate('zipcode', true)'>
La fonction de validation
●
Notre fonction de validation doit prendre en charge
plusieurs types de validation:
●
La validation par regular expression
●
La validation par fonction javascript
●
La validation par appel AJAX
●
La façon propre de le faire serait par Objet. Toutefois
étant donné les circonstances j'utiliserai des array.
La fonction de validation (suite)
●
Le régistre d'informations de validation
<code:javascript>
var fields = new Object();
fields.zipcode = { minLength: 7, maxLength: 7,
regExp: "/^[a-zA-Z]{1}[0-9]{1}[a-zA-Z]{1}[ .-][0-9]{1}[a-zA-Z]{1}[0-9]{1}$/i",
valFunction: null,
hint: "V0A 1H0",
ajax: false,
fixed: true;
</code>
La fonction de validation (suite)
function validate(fieldId, focus){
var valInfo = fields[fieldId];
var fieldEl = getElement(fieldId);
fields[fieldId].valid = false;
var regExpGood = true;
var functionGood = true;
var lengthGood = (fieldEl.length >= valInfo.minLength && fieldEl.length <= valInfo.maxLength);
if(valInfo.regExp != null) {
eval('reg = '+valInfo.regExp);
regExpGood = reg.test(getFieldValue(field)) }
if(valInfo.function != null)
eval(“functionGood = “+valInfo.function+”(“+fieldEl.value+”);”);
if(regExpGood && functionGood && lengthGood){
setFieldState(fieldId, “green”, “ok”);
fields[fieldId].valid = true;}
else if(focus == true) setFieldState(fieldId, “yellow”, valInfo.hint);
else setFieldState(fieldId, “red”, valInfo.hint);
}
L'objet XmlHttpRequest revisité
●
Une description plus détaillée de l'objet XmlHttpRequest
Propriété
Description
open(“methode”, “url”, flag)
Ouvre la connexion avec le serveur.
méthode -> "GET" ou "POST"
url -> l'url à laquelle on va envoyer notre requête.
Si la méthode est GET, on met les paramètres dans l'url.
flag -> true si l'on veut un dialogue asynchrone, sinon, false
setRequestHeader("nom","valeur")
Assigne une valeur à un header HTTP qui sera envoyé lors de la requête.
Par exemple, pour un POST :
nom -> "Content-Type"
valeur -> "application/x-www-form-urlencoded"
send("params")
Envoie la requête au serveur.
Si la méthode est GET, on met null en paramètre.
Si la méthode est POST, on met les paramètres a envoyer, sous la forme :
"nomparam1=valeurparam1&nomparam2=valeurparam2".
abort()
Abandonne la requête.
onreadystatechange
Ici, on va lui affecter une fonction a nous qui sera exécutée à chaque
"changement d'état" de notre objet.
L'objet XmlHttpRequest revisité (suite)
●
Une description plus détaillée de l'objet XmlHttpRequest
Propriété
Description
readyState
C'est cette propriété qu'on va tester dans le onreadystatechange.
Elle représente l'état de l'objet et peut prendre plusieurs valeurs :
0 -> Non initialisé.
1 -> Ouverture (open() vient de s'exécuter).
2 -> Envoyé (send() vient de s'exécuter).
3 -> En cours (des données sont en train d'arriver).
4 -> Prêt (toutes les données sont chargées).
status
Le code de la réponse du serveur.
200 -> OK.
404 -> Page non trouvée.
statusText
Le message associé à status.
responseText
La réponse retournée par le serveur, au format texte.
responseXML
La réponse retournée par le serveur, au format dom XML.
La fonction d'appel AJAX
●
●
●
la fonctionalité dont on a besoin est très simple: appel du
script php sur le serveur et gestion de la réponse.
L'URL appelé sera:
validate.php?field=[champ]&value=[valeur]
Il retournera le nombre d'enregistrement dans la table
User qui ont ces propriétés.
La fonction d'appel AJAX (suite)
<code:javascript>
var _xmlHttp = null;
//l'objet xmlHttpRequest utilisé pour contacter le serveur
var _baseUrl = "validate.php" //l'adresse à interroger pour valider l'information
var _lastCall = "";
function callValidate(field, value){
if(_xmlHttp&&_xmlHttp.readyState!=0) _xmlHttp.abort();
_xmlHttp=getXMLHTTP();
if(_xmlHttp){
//appel à l'url distante
_lastCall = field;
var urlCall = _baseUrl+"?field="+field+"&value="+value;
addStatus("AJAX Call: "+urlCall);
_xmlHttp.open("GET",_baseUrl+"?field="+field+"&value="+encodeURI(value), true);
La fonction d'appel AJAX (suite)
_xmlHttp.onreadystatechange=function() {
if(_xmlHttp.readyState==4 &&_xmlHttp.responseText) {
var valInfo = fields[_lastCall];
addStatus("AJAX Return:"+_xmlHttp.responseText);
if(_xmlHttp.responseText == "1"){
setFieldState(_lastCall, "red", valInfo.ajaxHint);
} else {
setFieldState(_lastCall, "green", "ok");
fields[_lastCall].valid = true;
}
} };
_xmlHttp.send(null)
}
}
</code:javascript>
// envoi de la requête
Le code PHP derrière
●
le code php servira à valider qu'une adresse email est
unique et qu'un username est unique
<code:php>
$field = $_GET['field']; $value = $_GET['value'];
if(!isset($_GET['field']) || !isset($_GET['value'])) {
?>This file takes two parameters in get : field and value. The URL should look
like <?= $_SERVER['REQUEST_URI'] ?>?field=username&value=simbad<br><br>
It returns either 1 if we find a record that has that value, or 0 if it doesn't.
<?php exit;
}
$dbConn = mysql_connect("localhost", "******", "*******");
mysql_select_db("ajaxpresentation");
if($dbConn == null) die("we have a problem connecting");
Le code PHP derrière (suite)
$res = mysql_query("select id from members where $field = '$value'");
if(!$res)
{
$message = 'Invalid query: ' . mysql_error() . "\n";
$message .= 'Whole query: ' . $query;
die($message);
}
echo mysql_num_rows($res);
</code:php>
Fonction de validation Javascript
(2)
<code:javascript>
function validate(fieldId, focus)
{
if(focus == false) addStatus("validate called on:<b>"+fieldId+";</b> focus:"+focus);
var valInfo = fields[fieldId];
var fieldEl = getElement(fieldId);
var fieldObj = getFieldObject(fieldId);
fields[fieldId].valid = false;
var regExpGood = true;
var functionGood = true;
var lengthGood = (fieldEl.value.length >= valInfo.minLength && fieldEl.value.length <=
valInfo.maxLength);
if(valInfo.regExp != null) {
eval('reg = '+valInfo.regExp);
regExpGood = reg.test(fieldObj.value)
}
Fonction de validation Javascript
(2)
if(valInfo.valFunction != null)
eval("functionGood = "+valInfo.valFunction+"("+fieldEl.value+");");
if(valInfo.ajax && focus == false && regExpGood && functionGood && lengthGood) {
callValidate(fieldId, fieldObj.value);
setFieldState(fieldId, "yellow", "validating...");
} else if(regExpGood && functionGood && lengthGood){
if(valInfo.ajax || focus == true && !valInfo.fixed)
setFieldState(fieldId, "yellow", "form valid");
else {
setFieldState(fieldId, "green", "ok");
fields[fieldId].valid = true;
}
}
else if(focus == true) setFieldState(fieldId, "yellow", valInfo.hint);
else setFieldState(fieldId, "red", valInfo.hint);
Fonction de validation Javascript
(2)
if(!focus) addStatus("regExpGood:"+regExpGood+", functionGood:"+functionGood+",
lengthGood:"+lengthGood);
</code:javascript>
Le champ username
●
On désire contrôler le format du username
(alphanumérique, 6 à 12 caractères) et en deuxième lieu
on fait appel aux script de validation côté serveur.
<code:javascript>
fields.username = { minLengthObject(),
minLength: 6,
maxLength: 12,
regExp: "/^[a-zA-Z0-9]{6,12}$/i",
hint: "6 to 12 alphanumeric",
ajax: true,
ajaxHint: "username already used",
fixed: true};
</code:javascript>
Le champ username (suite)
●
Le code HTML pour le champ
// le champ
<tr bgcolor="#0A3F7B">
<td align="right" nowrap="nowrap" bgcolor="#0A3F7B">Code d'utilisateur: </td>
<td bgcolor="#0A3F7B"><input type="text"
onfocus="validate('username', true);"
onkeyup="validate('username', true);"
onblur="validate('username', false);"
name="username"
id="username"
size="12"
maxlength="18" /></td>
<td nowrap="nowrap" bgcolor="#0A3F7B" id='username_status'> </td>
</tr>
Le bouton submit
●
●
On doit rajouter du code javascript pour valider que tous
les champs soient effectivement corrects avant de
soumettre.
De plus, étant donné qu'une personne peut passer d'un
champ directement au bouton submit, il faut donner un
délai pour permettre aux événements et au AJAX de
prendre place:
<code:javascript>
function trySubmit()
{
setTimeout("submitForm()", 500);
}
Le bouton submit
function submitForm(){
if(_xmlHttp&&_xmlHttp.readyState!=0) { setTimeout(“submitForm()”, 500); exit; }
var valid = true;
for(var i in fields){
if(!fields[i].valid)
valid = false;
if(fields[i].valid == undefined)
setFieldState(i, "red", fields[i].hint);
}
if(valid) document.forms[0].submit();
else alert("Please fix errors (red fields) before submitting");
}
</code:javascript>
// le bouton :
<a href='#' onclick='trySubmit();' >[Submit] </a>
Rajouter des champs à valider
●
●
on peut aisément rajouter des champs dans le système de
validation en populant un objet à l'intérieur de l'objet 'fields'
qui contient toutes les instructions nécessaires
et rajouter le champ, l'espace pour les messages et les
appels sur événements appropriés
<code:javascript>
fields.email = { minLength: 6, maxLength: 64,
regExp: "/^[^ ]+@[a-zA-Z0-9-.]+[.][a-zA-Z0-9]{2,3}$/i",
hint: "[email protected]",
ajax: true,
ajaxHint: "courriel deja dans le système",
fixed: true};
</code:javascript>
Rajouter les champs à valider (suite)
// le champ
<tr bgcolor="#0A3F7B">
<td align="right" nowrap="nowrap">Courriel: </td>
<td bgcolor="#0A3F7B"><input type="text"
onfocus="validate('email', true);"
onkeyup="validate('email', true);"
onblur="validate('email', false);"
name="email"
id="email"
size="32"
maxlength="64" /></td>
<td nowrap="nowrap" id='email_status'> </td>
</tr>
L'espace de statut
●
il suffit d'un <DIV> auquel on applique le bon style
<div id='status' style="height:172px; overflow:auto"></div>
●
et de quelques fonctions javascript simples:
<code:javascript>
var statusLine = 1;
function addStatus(text){
prependHTML("status", statusLine+". "+text+"<br>");
statusLine++;
}
function clearStatus(){
changeHTML('status', "");
statusLine = 1;
}
L'espace de statut (suite)
function prependHTML(element, text){
elementObject = getElement(element);
text = text + elementObject.innerHTML;
elementObject.innerHTML = text;
}
</code:javascript>
●
Et ensuite d'en profiter
<code:javascript>
addStatus(“some information”);
</code>
●
Et si vous voulez, vous offrir un bouton pour vider le statut
<a href="#" onclick='clearStatus()'>[Clear] </a>
Appendix A – Behaviour
●
●
●
Behaviour est une librairie Javascript qui permet de
séparer le code de la présentation.
On associe des événements aux objets HTML de la même
façon qu'on associe des styles CSS, soit par id et class
Au lieu de produire du code spaghetti comme ceci (du site
web Backpack
<span onmouseover="notesBlock.hoverBegin(128699)"
onmouseout="notesBlock.hoverEnd(128699, true)">
<a class="trashcan" href="#"
onclick="if (confirm('Are you sure?')) {
new Ajax.Updater('notes',
'/page/2326/notes/destroy/128699', {
Appendix A – Behaviour (suite)
●
Ou comme ceci (du site web Flickr)
<div id="image_16209134_normal">
<script language="Javascript">
photo_hash['16209134'] = new Object();
photo_hash['16209134'].title = '2am on Saturday';
</script>
<h4 id="title_div16209134"
style="margin-bottom: 0px; margin-top: 0px;">
2am on Saturday
</h4>
<script type="text/javascript">initPhotosUserPageTitle_div('16209134');</script>
●
Behaviour vous permet de générer du code propre et
facile à comprendre.
Appendix A – Behaviour (suite)
<ul id="example">
<li>
<a href="/someurl">Click me to delete me</a>
</li>
</ul>
<code:javascript>
var myrules = {
'#example li' : function(el){
el.onclick = function(){ this.parentNode.removeChild(this); }
}
};
Behaviour.register(myrules);
</code:javascript>
●
Préférable, ne croyez-vous pas?
Appendix B – Outils de débogage
●
●
FireBug (extension Firefox)
–
Firebug permet de déboguer le Javascript, le dHTML et le Ajax.
C'est une combinaison de la Javascript Console, du DOM
Inspector et d'un interpréteur de commande Javascript.
–
Il contient un 'XMLHttpRequest Spy', qui capte les appels
XMLHttpRequest ainsi que leurs réponses respectives.
–
Un indicateur d'erreur s'active sur la barre d'état qui vous informe
tout de suite des erreurs dans la page courante seulement*.
Tamper Data (extension Firefox)
–
Permets de modifier les requêtes générées par Firefox avant
qu'elles soient envoyées.
–
Utile pour les WebServices & Ajax
Liens Utiles
●
Web 2.0, allez plus loin avec AJAX et XMLHttpRequest
http://siddh.developpez.com/articles/ajax/
●
AJAX – Une autocomplétion pas à pas
http://dcabasson.developpez.com/articles/javascript/ajax/ajax-autocompletion-pas-a-pas/
●
Behaviour
http://bennolan.com/behaviour/
●
Prototype – A Javascript Framework
http://prototype.conio.net/
●
Open Rico – Another Javascript Framework
http://openrico.org/rico/demos.page?demo=rico_weather
●
Scriptaculous – Another Javascript Framework
http://wiki.script.aculo.us/scriptaculous/show/Demos
Quelques mots sur moi
●
Martin Legris
(514) 448-0362 – [email protected]
●
●
Développeur, Designer Graphique & Formateur Pigiste
–
Spécialiste de PHP & Orienté Objet
–
Méthodologies : UML 2.0, eXtreme Programming, Agile
Developpement
–
Spécialiste Web 2.0 (AJAX)
–
Spécialiste ActionScript 2.0, Flash 8
http://www.newcommerce.ca
Téléchargement