Méthode |
Internet Explorer |
Firefox |
Opera |
Google Chrome |
Safari |
---|---|---|---|---|---|
Dynamic Script Loading |
Oui |
Oui |
En
partie |
Oui |
Oui |
Javascript possède une propriété intéressante qui est celle de pouvoir charger un fichier .js à partir d'un autre et ce à n'importe quel moment. Ainsi il est possible de charger une autre page de script à partir d'une première en insérant un élément <script />, comme le montre cet exemple :
type="text/javascript"
<!--
document.write("<script type=\"text\/javascript\" src=\"external.js\"><\/script>");
//-->
Javascript permet donc nativement, et depuis toujours, d'utiliser le principe de l'AJAX en appelant un fichier .js après que la page HTML a été chargée. Il est aussi possible d'appeler une page PHP, identifiée comme étant un fichier JS, ce qui permettra une bonne interaction avec le serveur. C'est ce que nous allons voir plus en détail ici.
On va faire quelque chose de très simple pour commencer : on va créer un élément <script /> qui appellera un fichier JS et celui-ci qui répondra avec un alert. C'est basique, mais il faut que vous compreniez la base avant d'aller plus loin.
Le script donné ci-dessus marche bien, mais utilise la vieille méthode write(), ce qui est plutôt déconseillée et qui de plus ne nous est pas d'un grand intérêt. Pour ajouter un élément <script />, nous allons utiliser le DOM :
var DSLScript = document.createElement("script");
DSLScript.src = "DynamicScriptLoading_1.js";
DSLScript.type = "text/javascript";
document.body.appendChild(DSLScript);
Ce script crée et insère un élément <script /> avec un attribut src pointant vers la page JS (DynamicScriptLoading_1.js dans mon exemple), dans le body de la page HTML.
Ce petit bout de code, une fois placé appelle le fichier JS exactement comme si l'élément <script /> avait été écrit en HTML "brut". Le script contenu dans ce fichier JS est alors exécuté.
On va ajouter une fonction, appelée callback qui sera appelée par le fichier JS dès que ce dernier sera chargé. C'est en quelque sorte la réponse que le script de départ attend.
function callback(sMessage) {
alert(sMessage);
}
Le fichier JS (DynamicScriptLoading_1.js) contient juste l'appel de cette fonction :
callback("Hello world !");
En clair, on obtient quelque chose comme ça :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
xmlns="http://www.w3.org/1999/xhtml"
Dynamic Script Loading
type="text/javascript"
<!--
function send() {
var DSLScript = document.createElement("script");
DSLScript.src = "DynamicScriptLoading_1.js";
DSLScript.type = "text/javascript";
document.body.appendChild(DSLScript);
document.body.removeChild(DSLScript);
}
function callback(sMessage) {
alert(sMessage);
}
//-->
type="button" value="Envoyer la requête" onclick="send()"
Dès qu'on clique sur le bouton, la fonction send() est appelée. Cette dernière ajoute un élément <script /> lequel va charger un fichier JavaScript. Et pour finir, ce fichier JavaScript va appeler la fonction callback.
Pourquoi y a-t'il un
document.body.removeChild()
?
En réalité ce type de chargement n'est pas asynchrone. Lorsque l'élément <script /> est inséré via appendChild(), le fichier JS est chargé. Quand il est chargé, removeChild() est exécutée pour supprimer l'élément <script /> qui ne nous est plus d'aucune utilité.
Je pense que vous avez compris le principe de base. On va pouvoir ajouter des variables et du PHP .
Maintenant, au lieu d'appeler un fichier JS, nous allons appeler une page PHP. PHP, comme vous le savez, permet de récupérer des variables transmises via l'URL (méthode GET). C'est ce que nous allons faire !
La transmission des variables se fait comme à l'accoutumée :
DynamicScriptLoading_2.php?variable1=valeur1&variable2=valeur2
Le script JS ne change presque pas. Ajouter simplement deux variables dans l'URL à placer dans l'élément <script /> :
DSLScript.src = "DynamicScriptLoading_2.php?Pseudo=Thunderseb&Prenom=Sebastien";
Pour ce qui est de la page PHP, c'est un peu plus « spécial », la voici :
<?php header("Content-type: text/javascript"); ?>
var sMessage = "Bonjour <?php echo $_GET['Prenom'] ?>, alias <?php echo $_GET['Pseudo'] ?> !";
callback(sMessage);
Gardez à l'esprit que c'est « comme » un fichier JavaScript,
donc, tout ce qui n'est pas dans des balises <?php ?> est du code JavaScript !
Le code PHP peut
être placé n'importe où, exactement comme si vous le placiez dans une page HTML, ce qui permet d'incorporer
dans le code JavaScript.
Le code que je vous ai donné n'est pas super pratique à utiliser. Le mieux serait d'en faire des fonctions facilement déployables, acceptant un certain nombre de variables, une fonction de callback différente (qu'on ne soit pas obligé de l'appeler « callback »)...
Voici une fonction send générique :
function send(sUrl, oParams) {
for (sName in oParams) {
if (sUrl.indexOf("?") != -1) {
sUrl += "&";
} else {
sUrl += "?";
}
sUrl += encodeURIComponent(sName) + "=" + encodeURIComponent(oParams[sName]);
}
var DSLScript = document.createElement("script");
DSLScript.src = sUrl;
DSLScript.type = "text/javascript";
document.body.appendChild(DSLScript);
document.body.removeChild(DSLScript);
}
La fonction send reçoit, en plus de l'URL du fichier à charger, les variables à transmettre (c'est-à-dire à concaténer dans l'URL). L'argument oParams est un objet contenant une liste de clés/valeurs utilisant la notation JSON, comme ceci :
var oParams = {
"Pseudo": "Thunderseb",
"Prenom": "Sebastien",
"callback": "messageFromServer"
};
La valeur de la clé callback est tout simplement le nom de la fonction de callback à déclencher une fois la page PHP chargée. La notation JSON vous paraît peut-être étrange, mais c'est pratique pour transmettre une liste du type clé/valeur en une seule fois.
Et pour parcourir une telle structure, on utilise une boucle for associée au mot clé in, comme pour lister un tableau associatif. La fonction globale encodeURIComponent permet de coder les caractères spéciaux, pour ne pas avoir de problèmes lors de la transmission.
Le script de la page PHP peut alors être transformé de cette façon, de manière à appeler la fonction de callback (dont le nom est transmis dans la variable $_GET['callback']);
<?php header("Content-type: text/javascript"); ?>
var sMessage = "Bonjour <?php echo $_GET['Prenom'] ?>s alias <?php echo $_GET['Pseudo'] ?> !";
<?php echo $_GET['callback'] ?>(sMessage);
Et voilà, on a fait le tour de cette méthode. Elle est pratique, rapide et facile à déployer, mais comporte cependant un certain nombre de limitations. Par exemple, on ne sait utiliser que des requêtes GET, et non POST. Il n'y a non plus aucun moyen de savoir si la transmission s'est bien déroulée : si la page a renvoyé une erreur 404, on ne le sait pas.
Cela dit, Dynamic Script Loading est certainement le moyen le plus intéressant pour récupérer des données au format JSON. Voyons ça plus en détail !
JSON, ou JavaScript Object Notation est un format de structuration de données, un peu comme le XML. Mais la syntaxe est identique à la syntaxe objet de JavaScript. Ce tutoriel n'était pas un tutoriel de JSON, je ne reviendrai pas sur la structure du format.
Comme l'illustre l'exemple ci-dessus, il est très facile de récupérer une variable, et cette variable peut très bien être un objet JSON. Deux avantages de l'importation d'un objet JSON via Dynamic Script Loading peuvent être les suivants :
Facilité de mise en place
L'objet récupéré est de type object, et non de type string. Il n'y a donc pas besoin d'utiliser eval ou l'objet natif JSON pour parser la chaîne de caractères, ce qui est plutôt bénéfique. Eval is evil .
Tout d'abord, voici un exemple de code JSON, que je vais placer dans un fichier .js (ou .json, ça revient au même) :
var oSoftwares = {
"Adobe": [
"Acrobat",
"InDesign",
"Photoshop"
],
"Macromedia": [
"Dreamweaver",
"Flash",
"FreeHand"
],
"Microsoft": [
"Office",
"Visual C++",
"Windows Media Player"
]
};
callback(oSoftwares);
La fonction callback va donc servir à récupérer l'objet JSON oSoftwares. Il suffira ensuite de traiter ces données et de les afficher. Voici donc ma fonction callback :
function callback(oJson) {
var tree = "", nbItems;
for (sItem in oJson) {
tree += sItem + "\n";
nbItems = oJson[sItem].length;
for (var i=0; i<nbItems; i++) {
tree += "\t" + oSoftwares[sItem][i] + "\n";
}
}
alert(tree);
}
Bien évidemment, il n'y a pas besoin de faire appel à la fonction send compliquée vue ci-dessus, puisque je ne souhaite pas envoyer de variables au fichier JavaScript.
Voici donc le code complet de l'exemple :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
xmlns="http://www.w3.org/1999/xhtml"
http-equiv="Content-Type" content="text/html; charset=utf-8"
Techniques AJAX - Dynamic Script Loading - JSON Statique
type="text/javascript"
<!--
function send(sUrl) {
var DSLScript = document.createElement("script");
DSLScript.src = sUrl;
DSLScript.type = "text/javascript";
document.body.appendChild(DSLScript);
document.body.removeChild(DSLScript);
}
function callback(oJson) {
var tree = "", nbItems;
for (sItem in oJson) {
tree += sItem + "\n";
nbItems = oJson[sItem].length;
for (var i=0; i<nbItems; i++) {
tree += "\t" + oSoftwares[sItem][i] + "\n";
}
}
alert(tree);
}
function getInfo() {
send("DynamicScriptLoading_JSON_1.js");
}
//-->
id="main"
type="button" value="Récupérer les données" onclick="getInfo();"
Il n'y a rien de bien compliqué non plus. La différence avec le code précédent est que la page appelée est une page PHP qui renvoie du code JavaScript, dont voici le code :
<?php
header("Content-type: text/javascript");
echo 'var oSoftwares = {
"Adobe": [
"Acrobat",
"InDesign",
"Photoshop"
],
"Macromedia": [
"Dreamweaver",
"Flash",
"FreeHand"
],
"Microsoft": [
"Office",
"Visual C++",
"WMedia Player"
]
};';
echo $_GET['callback'] ?>(oSoftwares);
Et voici le fichier HTML. Pour différer un tantinet de l'exemple précédent, j'ai incorporé le script de gestion avec les variables, c'est plus distrayant :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
xmlns="http://www.w3.org/1999/xhtml"
http-equiv="Content-Type" content="text/html; charset=utf-8"
Techniques AJAX - Dynamic Script Loading - JSON Dynamique
type="text/javascript"
<!--
function sendDSL(sUrl, oParams) {
for (sName in oParams) {
if (sUrl.indexOf("?") != -1) {
sUrl += "&";
} else {
sUrl += "?";
}
sUrl += encodeURIComponent(sName) + "=" + encodeURIComponent(oParams[sName]);
}
var DSLScript = document.createElement("script");
DSLScript.src = sUrl;
DSLScript.type = "text/javascript";
document.body.appendChild(DSLScript);
document.body.removeChild(DSLScript);
}
function callback(oJson) {
var tree = "", nbItems;
for(sItem in oJson) {
tree += sItem + "\n";
nbItems = oJson[sItem].length;
for(var i=0; i<nbItems; i++) {
tree += "\t" + oSoftwares[sItem][i] + "\n";
}
}
alert(tree);
}
function getInfo() {
var oParams = { "callback": "callback" };
sendDSL("DynamicScriptLoading_JSON_2.php", oParams);
}
//-->
id="main"
type="button" value="Récupérer les données" onclick="getInfo();"
Le Dynamic Script Loading est donc un moyen simple et efficace de récupérer des données sous forme de variables (données textuelles) et d'objets JavaScript (données formatées en JSON).
Facilité de mise en place
Intégration parfaite avec les données JSON
Un peu tordu à utiliser
Limité à du texte et à du JSON. On peut récupérer aussi des données XML, mais ça implique des méthodes de création avec DOMImplementation (ce qui est assez inutile)
Seulement des requêtes GET