JavaScript
Transcription
JavaScript
Techniques à Objets et Internet Le Web et sa programmation Jean-François Perrot Université Pierre et Marie Curie (Paris 6) Cours n° 6 : Introduction à Javascript-4 • Objets en Javascript • Application au contrôle des formulaires Jean-François Perrot JavaScript 4 1 Sommaire Objets : 3 - 8 Communication : 9 - 20 Le modèle objet de la page : 21 - 26 window et document : 27 - 36 Conclusion : 37 - 38 Jean-François Perrot JavaScript 4 2 1 "Objets" en JavaScript • Avec les objets COM de Visual Basic et les (vrais) objets Java, encore une autre notion d'objet informatique... • Les objets de Javascript sont en fait des "tableaux associatifs" (c-à-d. des tableaux indexés par des chaînes), avec une une syntaxe pointée (y compris l'instruction with, absente en Java) pour les utiliser et une primitive new pour les créer. • Comme les "vrais" objets ils ont des propriétés (champs = données) et des comportements (méthodes = procédures) – propriétés et comportements sont traités de la même façon car en Javascript les fonctions sont des données ! • Mais il n'y a ni classes, ni héritage... Jean-François Perrot JavaScript 4 3 "Objets" prédéfinis en JavaScript • La notation pointée permet de manipuler aisément une grande quantité d'objets dont le type est prédéfini : String, Date, etc. • Dans le jargon (le "métalangage") employé pour parler de JavaScript, on dit "l'objet String", " l'objet Date", etc. (et même de "l'objet Math" !!!). Il vaudrait certes mieux parler de classes, mais il n'y a pas de classes en JavaScript... On préfère donc dire "n'importe quoi" ! • Exemple : les chaînes de caractères sont des "objets" "abc".length --> 3 // length est une "propriété" "abc".toUpper() --> "ABC" // toUpper est une "méthode" "abc".toUpper().length --> 3 Jean-François Perrot JavaScript 4 4 2 <html> <head> <title> Essai de date </title> </head> <body> <p>Debut</p> <p> <script type="text/javascript"> var aujourdHui = new Date(); var var var var var var var leQuantieme = aujourdHui.getDate(); leJourDeLaSemaine = aujourdHui.getDay(); leMois = aujourdHui.getMonth(); lAnnee = aujourdHui.getFullYear(); lHeure = aujourdHui.getHours(); laMinute = aujourdHui.getMinutes(); laSeconde = aujourdHui.getSeconds(); Les Dates en JavaScript date.html document.write("<h3> Nous sommes le jour : " + leQuantieme); document.write(" du mois : " + leMois); document.write(" de l\'année : " + lAnnee + ".<br /> />"); document.write("Ce jour est un : " + leJourDeLaSemaine + ".<br /> />"); document.write("Il est : " + lHeure + " heures "); document.write(laMinute + " minutes " + laSeconde + " secondes </h3>"); document.write("<h1>Bonne Année, Heureux Siècle, Excellent _ Millénaire </h1>"); </script> </p><p>Fin</p> </body></html> Jean-François Perrot JavaScript 4 5 Une Date particulière Jean-François Perrot JavaScript 4 6 3 Constantes & fonctions "mathématiques" • Comme en Java, un certain nombr />e de constantes (p.ex. PI) et de fonctions à caractère "mathématique" sont regroupées en un "module" appelé Math. Par analogie avec Java, on emploie la notation pointée " Math.xxx" pour les désigner : Math.abs(-5) --> 5 ; Math.max(5, 7) --> 7 ; Math.PI --> 3.1416... ; Math.random() --> ??? • Puisqu'il n'y a pas de classes en JavaScript, on ne peut pas parler comme en Java de la classe Math et de ses attributs et méthodes de classe (alias static members). On est donc amené pour expliquer cette notation à proférer une monstruosité : the Math Object... que je préfère ne pas traduire en français ! Jean-François Perrot JavaScript 4 7 Couleurs en JavaScript • La notation normale pour désigner une couleur en Javascript est une chaîne en format RGB (6 chiffres hexadécimaux RRGGBB représentant les trois composantes rouge, vert, bleu, chacune entre 0 et 255). rouge = "FF0000", vert = "00FF00", bleu = "0000FF" • On peut ainsi affecter par programme les différentes couleurs qui apparaissent dans une page. Par exemple, la couleur de fond : document.bgColor="FF0000" • La valeur numérique fait aussi bien l'affaire que la chaîne en hexadécimal : document.bgColor=14102802... Jean-François Perrot JavaScript 4 8 4 Problème de communication • La réalisation de scripts un tant soit peu élaborés requiert l'écriture de fonctions. – Ces fonctions sont normalement déclarées dans l'en-tête de la page. – Dans l'en-tête aucun des noms des différents composants qui apparaissent dans le corps n'est connu ! – Toute l'information communiquée aux fonctions est donc portée par les arguments. • Conclusions : – il faut pouvoir passer comme arguments les objets adéquats. – il faut choisir les fonctions à placer dans l'en-tête en conséquence ! Jean-François Perrot JavaScript 4 9 Problèmes de communication exemple Exercice "faire défiler les photos en cliquant", en plaçant la photo courante dans un lien et en utilisant l'événement Click pour recalculer son chemin d'accès. Dans l'état actuel de nos connaissances : Le nom de la photo n'est pas connu dans l'en-tête, par conséquent on ne peut pas l'utiliser dans une fonction auxiliaire. L'essentiel du travail doit donc s'écrire dans le handler onClick : – incrémentation du numéro courant (qui est nécessairement contenu dans une variable globale) – affectation du nouveau chemin à la propriété photo.src – sans oublier de renvoyer faux pour inhiber l'ouverture du lien ! Le calcul du chemin à partir du numéro courant, en revanche, se fait avantageusement par une fonction... Jean-François Perrot JavaScript 4 10 5 <html> <head> <title>PourExplorer</title> <script type="text/javascript"> Idée de solution var k = 0; function chemin(i) {... Photo2.html } function avancer(photo) {... } Idée : recourir à </script> onLoad </head> <body onLoad="avancer(flip);"> Moyen : le nom <p>Debut</p> <p> flip est connu <a onclick= 'if ( confirm(" Voulez-vous changer ? ") ) { dans tout le avancer(flip); document, } c'est-à-dire entre return false;'> <img name="flip" /> les balises </a> <body> et </p><p>Fin</p> </body> </body> </html> Défilé des photos Jean-François Perrot JavaScript 4 11 Défilé des photos détail de la solution Jean-François Perrot <script type="text/javascript"> var k = 1; // le numéro var res = "../Jour2pm/PhotJPG/"; function chemin(i) { if (i <10) { return(res + "0"+i+".jpg"); } else { return(res + i+".jpg"); } } function avancer(photo) { if ( k == 13 ) k = 0; k++; photo.src = chemin(k); } </script> JavaScript 4 12 6 Utilisation du "modèle-objet" • Le fond du problème de communication : un nom est connu dans le contexte d'un objet. – Exemple : le nom flip est connu dans le contexte de l'objet document • Les objets de JavaScript servent à construire un "modèleobjet" pour les pages Web et pour les fenêtres des navigateurs où elles s'affichent. • Nous allons explorer (en partie) ce modèle. – d'abord, le modèle des formulaires – ensuite celui des fenêtres et des documents – enfin celui de la composition et des cadres Jean-François Perrot JavaScript 4 13 Le formulaire comme "objet" Chaque balise <form...>...</form> donne naissance à un "objet" form. • Un tel objet possède les propriétés suivantes : – individuellement, en tant qu'objet, chacun de ses éléments nommés (propriété = le nom) – collectivement, le tableau de ses éléments (elements) – son nom (name) – son action (action) = l'URL où le formulaire envoie son contenu (en principe un script CGI) – et quelques autres propriétés de service... • Il réagit aux événements Submit et Reset par les handlers onsubmit et onreset. • Il a deux méthodes submit()et reset() simulant lesdits événements. Jean-François Perrot JavaScript 4 14 7 Exemple de formulaires nommés (1) • Utilité d'avoir plusieurs formulaires dans la même page : – un formulaire envoie au serveur CGI les valeurs de tous ses champs. – on peut souhaiter différencier la structure utilisée pour saisir l'information et le format employé pour l'envoyer : le formulaire de saisie va renseigner un second formulaire chargé de l'expédition. • Exemple : le formulaire ci-contre employé pour synthétiser l'information en une ligne : M. (Mme ou Melle) <Prénom> <Nom>, [musicien] [sportif] Jean-François Perrot JavaScript 4 15 Exemple de formulaires nommés (2) <form onsubmit= "Synthese.leResume.value = synthetiser(this); return false;"> <p> Nom : <input type="text" name="leNom"/> </p> <p> Prénom : <input type="text" name="lePrenom"/> </p> <p> Sexe : <br /> <input type="radio" name="leSexe" value="M"/> M <br /> <input type="radio" name="leSexe" value="F"/> F <br /> </p> <p> Âge : <input type="text" name="Age"/> </p> <p> Activités favorites : <br /> <input type="checkbox" name="laMusique" value="Oui" checked="checked"/> Musique <br /> <input type="checkbox" name="leSport" Deuxform.html value="Oui"/> Sport <br /></p> <input type="submit" value="Envoi"/> <br /> </p> </form> <form name="Synthese"> <p> en somme : <input type="text" name="leResume" size="60"/> </p> </form> Jean-François Perrot JavaScript 4 16 8 Exemple de formulaires nommés (3) Jean-François Perrot JavaScript 4 La fonction de synthèse Deuxform.html <head> <title>Essai avec deux formulaires</title> <script type="text/javascript"> function synthetiser(formulaire) { var res=""; with (formulaire) { // deux conventions preliminaires var mus; if ( leSexe[0].checked ) { mus = "musicien"; } else { mus = "musicienne"; } var sport; if ( leSexe[0].checked ) { sport = "sportif"; } else { sport = "sportive"; } Jean-François Perrot 17 // calcul de la chaine-resultat if ( leSexe[0].checked ) { res += "M. "; } else { if ( parseInt(Age.value) < 20 ) { res += "Melle "; } else { res += "Mme "; } } // terminé pour M., Mme ou Melle res += lePrenom.value; res += " "; res += leNom.value; if ( laMusique.checked ) { res += ", "+mus; if ( leSport.checked ) { res += " et "+sport+"."; } else { res += "."; } } else { if ( leSport.checked ) { res += ", "+sport+"."; } else { res += "."; } } // et c'est tout ! }// fin du with return res; } </script> </head> JavaScript 4 18 9 Exemple de formulaires nommés (4) Commentaire • La solution retenue a pour principe de communiquer à la fonction synthetiser l'objet formulaire tout entier : synthetiser(this) • Elle a l'avantage de ne modifier le formulaire original que dans la balise <form...> (ajout d'un handler onSubmit). • Elle a l'inconvénient d'invoquer un pseudo-submit : nécessité d'un return false dans le handler pour inhiber l'envoi au serveur. • Il serait plus naturel d'utiliser un push button pour déclencher l'action de synthèse : <input type="button" value="Envoi" onClick = "Synthese.leResume.value= synthetiser(???")> Jean-François Perrot JavaScript 4 19 De l'élément au formulaire Le problème est alors de passer du bouton au formulaire ! • Chaque objet-élément elt d'un formulaire "connaît" l'objet-formulaire dont il fait partie (il détient son adresse comme propriété). • Ce dernier est accessible sous le nom de propriété form : le formulaire dont fait partie elt est elt.form. • Application à notre exemple : <input type="button" value="Envoi" onClick = "Synthese.leResume.value= synthetiser(this.form)"> Jean-François Perrot JavaScript 4 20 10 Objets "fenêtres" vs. objets "documents" • JavaScript distingue dans le fonctionnement d'une page – ce qui concerne son cadre (la fenêtre : dimensions, position, bordures, affichage de différents attributs, outils et autres) – ce qui concerne son contenu (le document : ce qui est affiché dans la page). • Ces deux ordres de préoccupations sont pris en compte par deux genres d'objets : les fenêtres (Window) et les Documents. • La difficulté est de savoir exactement à qui on doit s'adresser pour réaliser telle ou telle tâche... Jean-François Perrot JavaScript 4 21 La fenêtre comme "objet fondamental" (1) L'espace des noms L'unité fondamentale dans le modèle-objet de JavaScript est la fenêtre du navigateur, représentée par un "objet Window". (1) Toutes les entités JavaScript lui appartiennent (on dit qu'il définit l'espace des noms - name space) • Toutes les fonctions (standard comme alert, confirm, etc. ou définies par l'utilisateur) sont en fait des méthodes de l'objet Window où elles sont déclarées. • Toutes les variables globales sont en fait des propriétés de l'objet Window où elles sont déclarées. • Il s'ensuit que deux fonctions ou deux variables globales différentes pourront porter le même nom, à condition d'être déclarées dans des fenêtres différentes. Jean-François Perrot JavaScript 4 22 11 La fenêtre comme "objet fondamental" (2) La hiérarchie de composition (2) La fenêtre est la racine de l'arbre d'objets représentant la page : • p. ex. elle détient comme propriété l'objet document... • esquisse de cet arbre : elements[ ] forms[ ] Button Checkbox Hidden Password Radio Reset Select Submit Text textarea navigator La fenêtre Window history location anchors[ ] links[ ] images[ ] document applets[ ] options[ ] Pour chaque objet o dans la page, il y a un chemin unique de la fenêtre à o. Jean-François Perrot JavaScript 4 23 Questions de désignation : contexte • Tout fragment de code JavaScript s'exécute dans le contexte d'un objet. – tous les objets dont les noms sont connus dans ce contexte peuvent être désignés directement : ainsi par exemple : alert("bla bla") • Exemple : soit un handler d'un objet Button, élément d'un formulaire : – la place du bouton dans l'arbre des objets de la page est La fenêtre document form button – dans le handler, on peut donc utiliser les noms définis dans la fenêtre, dans le document, dans le formulaire qui contient le bouton, et enfin dans le bouton lui-même. Jean-François Perrot JavaScript 4 24 12 Ex. Désignations <html> <head> <script type="text/javascript"> var vb = "la value de ce bouton est : " var frc = "le formulaire contient " var elts = " elements\n" var dc = "le document contient " var frs = " formulaires\n" var tlf = "la taille de la fenêtre est : " var pxs = " pixels" </script></head> <body> <form> <p> <textarea name="Aff" rows=5 cols=50> </textarea></p> <input type="button" value="Pour voir" Designation.html onClick = "Aff.value=vb+value+'\n'+frc+elements.length+elts+dc+ forms.length+frs+tlf+innerHeight+' x '+innerWidth+pxs"> </form> </body> </html> La fenêtre Jean-François Perrot document form button JavaScript 4 25 Questions de désignation : ambiguïté ? • Quid si le même nom est défini à deux niveaux différents ? – l'évolution du système tend à éliminer ces situations • C'est la désignation la plus locale qui prime, mais il vaut mieux lever l'ambiguïté, en désignant explicitement l'objet visé – l'objet Window représentant la fenêtre active est accessible par la propriété implicite window, aussi appelée self – dans notre exemple, les noms complets seraient : window.document.forms[0].elements[1].value window.document.forms[0].elements.length window.document.forms.length window.innerHeight window.innerWidth Jean-François Perrot JavaScript 4 26 13 Deux fonctionnalités des objets Window (il y en a bien d'autres !) • La status line gérée à travers deux propriétés – status (déjà vu) pour messages transitoires – defaultStatus pour messages permanents • La gestion du temps : – setTimeout(uneChaînedeCode, unDélai) exécute l'action spécifiée par la chaîne uneChaînedeCode après unDélai compté en millisecondes : setTimeout("alert('Avez-vous fini ?')", 5000) SetTimeout.html Jean-François Perrot JavaScript 4 27 Exemple : une horloge <html> <head> <script type="text/javascript"> function showtime(){ var now = new Date() var hours = now.getHours() var minutes = now.getMinutes() var seconds = now.getSeconds() var timevalue = "" + ((hours > 12) ? hours - 12 : hours) timevalue += ((minutes < 10) ? ":0" : ":") + minutes timevalue += ((seconds < 10) ? ":0" : ":") + seconds timevalue += (hours >= 12) ? " P.M." : " A.M." document.clock.face.value = timevalue <body onLoad="showtime()"> defaultStatus = timevalue <form name="clock"> setTimeout("showtime()",1000) <input type="text" } name="face" size="15" /> </script> </form> </head> Showtime.html </body> </html> Jean-François Perrot JavaScript 4 28 14 Fenêtres : ouverture et fermeture • Les objets Window possèdent (entre autres) une méthode open() et une méthode close() – les objets Document aussi, avec des significations différentes ! Il faut donc préciser... • window.close() ferme la fenêtre courante – setTimeout("window.close()", 5000) • window.open()ouvre une nouvelle fenêtre !!! – il lui faut comme arguments • une URL où trouver un document à y charger (éventuellt. vide) • un nom désignant la fenêtre en question (voir plus loin) • différentes caractéristiques optionnelles – renvoie comme résultat un pointeur sur la fenêtre créée. Jean-François Perrot JavaScript 4 29 Application : solution du problème "document.write" • Nous avons vu que "document.write" ne pouvait pas être employé à bon droit dans des handlers d'événements associés à des formulaires. • La bonne solution est d'écrire dans le document d'une nouvelle fenêtre ! function montrer(clr) {// nouvelle version améliorée var newwin = window.open("", "nov","width=350, height=100"); newwin.document.write ("<p><B><FONT SIZE=7 COLOR=" +clr+">Démonstration</FONT></B></p>"); newwin.document.close(); // pour réutilisation newwin.setTimeout("window.close()", 5000); } Jean-François Perrot JavaScript 4 30 15 La fenêtre comme cible (target) pour un lien ou pour un formulaire • Les liens et les formulaires peuvent avoir un champ target qui spécifie la fenêtre où –le contenu du lien (URL) sera affiché –le retour du script CGI sera écrit • La valeur de ce champ doit être un nom de fenêtre au sens de window.open() –mais, contrairement à l'usage, ce nom doit être donné par une constante de chaîne "The target property cannot be assigned the value of a JavaScript expression or variable." dit la doc ! –si la fenêtre ainsi désignée n'est pas encore créée, elle le sera... Jean-François Perrot JavaScript 4 <html> <head> <title>DefileNouvFen</title> <script type="text/javascript"> var k = 0; var res = "../../PHOTOS-JPG/"; function chemin(i) { if (i <10) { return(res + "0"+i+".jpg"); } else { return(res + i+".jpg"); } } function chemsuiv() { if ( k == 13 ) k = 0; k++; return chemin(k); } </script> </head> Jean-François Perrot 31 Le défilé des photos dans une fenêtre à part Le code JavaScript 4 Photo3.html <body> <p>Debut</p> <p> <a href="" onclick = "href=chemsuiv();" target="photo"> Photo suivante </a> </p> <p>Fin</p> </body> </html> 32 16 Le défilé des photos dans une fenêtre à part -----------Le spectacle ! Jean-François Perrot JavaScript 4 33 Rediriger le résultat d'un formulaire <form action="http://www-poleia.lip6.fr/~jfp/php/photo.cgi" target="photo"> Jean-François Perrot JavaScript 4 34 17 Le document comme "objet" • Un objet document représente le contenu d'une page html simple (c-à-d. non composée, voir plus loin). Il se matérialise dans le code html par la balise <body...>...</body> et par son contenu. • Il possède une série de propriétés, qui traduisent les diverses indications portées dans le code. • Son activité principale est l'écriture d'un contenu codé (la plupart du temps) comme un texte html, par la méthode write(...). • L'objet représentant le document courant est connu sous le nom de document. En fait c'est la propriété document de l'objet window actif (= la fenêtre courante). On a donc pratiquement les équivalences : document = window.document = self.document Jean-François Perrot JavaScript 4 35 Quelques propriétés des objets document • Propriétés descriptives : couleurs – bgColor = la couleur de fond (html : affaire de style...) – etc. • Propriétés stucturelles : tous les éléments nommés sont accessibles comme propriétés du document (avec leurs noms), et en outre on peut accéder aux éléments essentiels du contenu (même non nommés), en autant de tableaux anchors links images forms • Ex. :Au lieu de désigner un formulaire par son nom, on peut le trouver par son indice dans le tableau forms Dans l'exemple "à 2 formulaires" Synthese == forms[1] Idem, dans le "défilé des photos", flip == images[0] Jean-François Perrot JavaScript 4 36 18 Solution complète au problème de communication • Chaque objet de la page peut être désigné en tout endroit du code – par son nom (s'il a un attribut name) – par son numéro (index) dans la collection dont il fait partie (elements d'un formulaire, images, links, et c. d'un document) Ex. Ex flip = images[0] • Selon la "distance" qui sépare le lieu de déclaration du ieu d'invocation, il faudra compléter ce nom par un fragment de chemin : Ex. dans l'en-tête, flip est inconnu, et son synonyme images[0] aussi : seul window est accessible, il faut donc dire (window).document.flip ou (window).document.images[0] Jean-François Perrot JavaScript 4 37 Note sur l'interprétation • L'exemple de la référence document.flip dans l'en-tête met en évidence le caractère interprété de JavaScript : – au moment où cette référence est lue (au cours du traitement de l'en-tête de la page par le navigateur) le nom flip n'est pas encore déclaré (il ne le sera que lorsque le cops de la page aura été traité) – JavaScript doit donc "faire confiance" à l'objet document en faisant l'hypothèse que ce dernier possèdera effectivement un attribut nommé flip. • Cette "mise en attente" interdit une compilation (génération de code assembleur) qui supposerait que l'on traduise flip en un déplacement en mémoire. • Après le traitement de l'en-tête, JavaScript conserve donc la "forme abstraite" document.flip et ne pourra l'interpréter qu'à l'exécution… en détectant peut-être une erreur, trop tard ! Jean-François Perrot JavaScript 4 38 19