Article publié dans Linux Magazine 73, juin 2005.
Vous connaissez Google Suggest[1] ? Ou CPAN Suggest[2] ? Vous voudriez l'utiliser pour le tester ? Alors, lisez ce qui suit, mais attention, le code JavaScript de ac.js n'est pas libre de droits, car sous évident copyright de Google.
Un nom a été donné[3] récemment à cette technique : Ajax, contraction de Asynchronous JavaScript + XML. Pour résumer, le but de l'utilisation de méthodes de développement web de type Ajax est de mettre à jour des morceaux de pages HTML sans pour autant recharger l'intégralité de la page. Cela permet de réduire d'autant la bande passante utilisée, plutôt que de faire recharger une page à chaque mise à jour. Ça permet aussi de faire des requêtes dynamiquement à un serveur HTTP pour pré-renseigner des champs de saisie, de façon à améliorer l'ergonomie d'une application web. On peut même réaliser des formulaires dont les champs sont validés au fur et à mesure de leur saisie, comme pour une application classique.
Dans notre cas, ça va nous servir à remplir un champ devant contenir une adresse mail à partir de la frappe d'un nom, sans pour autant ouvrir un annuaire dans un autre onglet du navigateur.
Mais faisons fi des explications du fonctionnement, détaillées[4] par
ailleurs, sachez simplement que le tout se base sur une invention de
Microsoft (via un ActiveX, XMLHTTP
), reprise par Mozilla, qui a le
doux nom de XMLHttpRequest
. Cette fonction JavaScript permet de
mettre en œuvre un client HTTP (le XML n'est pas obligatoire, mais peut
être géré) asynchrone dans la page. Pourquoi asynchrone ? Parce
que s'il ne l'était pas, vous ne pourriez continuer à taper sur le
clavier en espérant une réaction à la frappe d'un caractère avant que la
dernière réaction ne se soit terminée.
Passons maintenant à la pratique, et à ce qu'il faut préparer côté serveur pour que ça fonctionne.
Nous aurons besoin d'un formulaire dont un champ devra être completé, un serveur web gérant les CGI, d'un peu de Perl, et du fichier ac.js récupéré sur Google[5], que nous allons modifier comme suit :
perl -pi.orig -e 's!(\"/*)complete(/*\")!$1cgi-bin$2!g' ac.js
Cela permettra de joindre notre CGI sous le chemin /cgi-bin/ de notre serveur web.
Notre but sera de rechercher de remplir le champ par une adresse mail
alors que nous tapons un uid
. La source de données sera un annuaire
LDAP.
Le formulaire devra comporter un champ texte comme suit :
<form method="get" name=monform action="http://localhost/cgi-bin/test.cgi"> <label for="nom">Nom :</label> <input type="text" name="nom" autocomplete=off size=50 value="*"/> <input type="submit" name="submit" id="submit"/> </form>
Ce formulaire porte un nom (monform
), et le champ qui nous intéresse est
nom
. L'action test.cgi est là pour vérifier que le tout
fonctionne correctement.
Il nous faut aussi invoquer le script de Google. Pour ça, trois lignes à ajouter après (pour que les objets du DOM soient chargés dans JavaScript) le formulaire :
<SCRIPT src="ac.js"></SCRIPT> <SCRIPT> InstallAC( document.monform, document.monform.nom, document.monform.submit, "ldap.pl", "en"); </SCRIPT>
En gros, cela installe l'auto-complétion JavaScript sur le champ
monform.nom
.
Vient ensuite le script Perl (ldap.pl) pour nourrir l'ensemble :
#!/usr/bin/perl -w use strict; use Net::LDAP; use CGI qw(:standard); my $mesg; my $ldap = Net::LDAP->new("localhost", port => 389, version => 3) or die "erreur LDAP: Can't contact master ldap server ($@)"; $mesg = $ldap->bind( "cn=Manager,dc=example,dc=com", password => 'secret' ); $mesg->code && die $mesg->error; print << "EOF"; Content-Type: text/javascript; charset=ISO-8859-1 EOF my $name=param('qu'); if (defined $name) { $name =~ s/\*//g; } else { exit 0; } $mesg = $ldap->search( base => 'ou=People,dc=example,dc=com', scope => 'sub', filter => "(uid=$name*)", attrs => [ qw(uid mail) ] ); $mesg->code && die $mesg->error; my (@a1, @a2, @a3); foreach my $entry ($mesg->all_entries) { if ($entry->get_value('mail')) { push @a1, $entry->get_value('uid'); push @a2, $entry->get_value('mail'); } } $ldap->unbind(); @a3 = "0" x scalar a1; print "sendRPCDone( frameElement, \"$name\","; print "new Array(\"", join('","', @a2), "\"), "; print "new Array(\"", join('","', @a1), "\"), "; print "new Array(\"", join('","', @a3), "\") );";
Passons la connexion à l'annuaire, déjà abordée dans ces colonnes.
Remarquez l'utilisation du module CGI
avec l'interface non-objet
(qw(:standard)
). Cela va nous permettre l'utilisation de la fonction
param pour récupérer le champ qu
demandé à notre CGI par ac.js.
Ce même script demande la création d'un appel à la fonction JavaScript
sendRPCDone
avec pour paramètre le nom de l'objet mis à jour et
surtout deux tableaux avec les résultats. Un troisième tableau
(non-vide) est demandé en paramètre sinon les résultats ne s'affichent
pas. Notez au passage sa création utilisant l'opérateur
multiplicateur en fonction du nombre d'éléments du tableau @a1
.
Vous pourrez inverser les lignes contenant les join
sur @a1
et
@a2
suivant que l'élément recherché est le mail
ou l'uid
,
l'autre étant affiché à titre indicatif.
Pour déboguer le tout, pensez à utiliser multitail
qui est très
pratique pour suivre à la fois l'access_log et l'error_log d'Apache.
Enfin, le code de Google n'est pas (encore ?) réentrant (il change régulièrement). Cela signifie que vous ne pourrez avoir sur un formulaire donné qu'un seul champ pour lequel la complétion pourra être activée.
[1] http://www.google.com/webhp?complete=1&hl=en
Google Suggest.
[2] http://cpan.teknikill.net/
CPAN Suggest.
[3] http://www.adaptivepath.com/publications/essays/archives/000385.php
Description d'Ajax.
[4] http://serversideguy.blogspot.com/2004/12/google-suggest-dissected.html
Explication détaillée du code de Google Suggest.
Le code.
(Jérôme Fenal, Paris.pm - <jfenal@free.fr>)
Envoyez vos perles à perles@mongueurs.net
, elles seront peut-être
publiées dans un prochain numéro de Linux Magazine.
Copyright © Les Mongueurs de Perl, 2001-2011
pour le site.
Les auteurs conservent le copyright de leurs articles.