Comment faire une bulle d'aide en javascript ?

Tout d'abord...

...une question de bon sens, avant de farcir ses pages de javascript : pourquoi utiliser une bulle d'aide en javascript, alors que la méthode TITLE fonctionne sur la plupart des navigateurs modernes en ce début 2002 (IE5+ ou NN6 sur PC-windows ou Mac, Mozilla sur Linux...) ?

Le principe

En fait, nous allons proposer deux scripts. Le premier est une mise à jour d'un script traditionnel proposé à l'origine par Dynamic Drive, et nous y voyons une application intéressante sur le plan pédagogique, en ce qu'elle combine plusieurs mécanismes différents en CSS et en javascript. Dans ce script,

  1. A la base, la bulle est un calque invisible
  2. Lors du survol d'un lien, on lit les coordonnées du pointeur de souris dans les propriétés de l'objet javascript event engendré par la détection de l'évènement 'mouseover'.
  3. On remplit alors le calque précédent par le texte de la bulle d'aide (propriété innerHTML pour IE5 ou NN6)
  4. On le déplace à l'endroit voulu dans la page et on le rend visible en jouant sur ses propriétés de style
  5. Quand la souris s'en va, on rend le calque invisible

Ce script fonctionne bien sur IE5+, NN4, NN6 et Mozilla, mais pas sur Opera parce que celui-ci n'obéit pas à innerHTML en écriture. Nous en proposerons donc une variante dans une page séparée, qui permettra de pallier cette difficulté.

Nous avons déjà consacré plusieurs articles aux applications des propriétés visibility et innerHTML pour contrôler la visibilité des calques [1] et leur contenu [2].

Le déplacement du calque se fait très simplement en remplissant les propriétés top et left de son style, tout comme la propriété visibility du même style contrôle sa visibilité. On réutilisera donc le script déjà vu dans [1] pour accéder à ces trois propriétés.

Nous allons maintenant expliquer comment on localise la souris dans la page.

L'objet javascript event

Lorsque le navigateur détecte un évènement (arrivée ou départ de la souris, clic, double clic, frappe d'une touche, etc...) il crée un objet spécial dont le nom est précisément «event» (c'est un mot réservé du javascript), et dont les différentes propriétés permettent de retrouver ce qui s'est passé. Cet objet n'est apparu qu'avec IE4 et NN4, avec évidemment des propriétés différentes, comme d'habitude ; plus tard, le modèle du W3C repris par NN6 a introduit un 3ème jeu de propriétés. Tout appel de cet objet event dans les navigateurs antérieurs crée une erreur «objet non défini».

Le plus simple pour éplucher l'objet event créé par un survol de souris est de le passer en argument dans la fonction appelée par le gestionnaire onMouseOver, soit, dans notre cas d'une bulle d'aide :
    onMouseOver="bulle('texte de la bulle',event)"... 
bulle() est la fonction javascript qui va ouvrir la bulle. L'objet event sera ensuite analysé de trois manières différentes dans cette fonction, selon que le navigateur appartient aux familles NN4, IE4+ ou compatible W3C (NN6).
Pour positionner la bulle d'aide, on a besoin de connaître la position du pointeur de souris par rapport à la page, mais aussi par rapport à la fenêtre du navigateur. Le tableau ci-dessous donne les noms des propriétés correspondantes:
  NN4 IE4+ NN6 (W3C)
position
dans la page
pageX, pageY à calculer pageX, pageY
position
(fenêtre)
n'existe pas x, y clientX, clientY
La différence entre les deux positions provient du jeu des ascenseurs; le glissement correspondant de la page étant dans les propriétés body.scrollTop et body.scrollLeft, on en déduit le positionnement dans la page pour IE4+ :
      xpage = event.x + body.scrollLeft; 
      ypage = event.y + body.scrollTop; 
(coordonnées en pixels depuis le coin en haut à gauche de la page)
L'utilisation avec Opera présente des difficultés supplémentaires. Selon le réglage des préférences, Opera fonctionne comme IE4+ ou comme NN6, mais avec des lacunes gênantes. Nous renvoyons à la lecture de notre code pour la gestion de ces lacunes. Finalement, on arrive à le faire fonctionner comme NN4, mais on peut espérer que ce fonctionnement ira en s'améliorant avec les versions futures.

Positionnement de la bulle dans la fenêtre

Une fois obtenues les coordonnées xpage et ypage du pointeur par rapport à la page, une première idée pour positionner la bulle est mettre ces nombres dans les propriétés left et top de son style, quelque chose comme
bulleStyle.left = xpage+15 ; bulleStyle.top = ypage+15
bulleStyle est l'objet «style» du calque-bulle, obtenu comme expliqué dans [1], et où 15 est un nombre arbitraire. De cette manière la bulle s'ouvre à droite et en bas du pointeur, avec un petit décalage (ici, de 15 pixels) dans les deux sens afin que la bulle ne s'ouvre pas par dessous le pointeur.

Avec cette manière de faire, une bulle qui s'ouvrirait trop à droite dans la fenêtre ou trop en bas n'aurait pas assez de place et serait tronquée. Ce défaut est irrémédiable pour NN4, puisqu'on a n'a alors aucun moyen d'évaluer la position du pointeur dans la fenêtre, mais on peut arranger les choses pour IE4+ et NN6.

Pour IE4+ ou NN6, comme on peut détecter la position du pointeur dans la fenêtre, on n'ouvrira la bulle de cette façon que si le pointeur est suffisamment à gauche et en haut.



En fait, les instructions de positionnement sont légèrement plus compliquées car certains navigateurs attendent une chaîne dans les propriétés left ou top, avec une unité (px) explicite, alors que d'autres attendent un simple nombre. Certains sont accommodants et font la conversion d'eux-même, mais d'autres sont très stricts. Il vaut donc mieux réécrire les lignes précédentes comme ci-dessous :
xx = xpage+15; yy=ypage+15;
if(typeof(bulleStyle.left)=='string') {
   bulleStyle.left = xx + 'px'; bulleStyle.top = yy + 'px';
} else {
   bulleStyle.left = xx ; bulleStyle.top = yy ; 

Mise en œuvre et démonstrations

Essayez Essayez Essayez
Essayez Pour la mise en œuvre :
  • recopiez le script des fonctions bulle() et couic() dans la partie <HEAD> de la page.
  • commencez la page par le bloc <DIV id="tip"...> de notre code (retouché à votre goût).
  • L'appel et la disparition des bulles sont commandées par des instructions
    onMouseOver=
          "bulle('texte de la bulle',event,
                  hauteur_bulle)"
    onMouseOut="couic()" 
    L'argument «event» est obligatoire(tel quel).
    Le 3ème argument (facultatif) est la hauteur estimée de la bulle en pixels, soit, approximativement
      1,20 x taille police x nombre de lignes + 10

Lisez aussi les commentaires dans notre script.

Essayez
Essayez Essayez Essayez

Une alternative

La nécessité d'écrire le texte de la bulle lors même de l'appel à la fonction bulle() ne facilite pas la relecture du code. Par ailleurs, cette technique ne permet pas de d'obtenir des bulles complexes contenant autre chose que du texte pur. On peut donc préférer créer chacune des différentes bulles de la page dans autant de calques séparés, qu'on rendra invisible au chargement de la page, puis qu'on fera réapparaître à côté de la souris le moment venu.

Un avantage annexe sera d'éviter le recours à innerHTML, ce qui permettra un bon fonctionnement même avec Opera-5.

Afin ne pas embrouiller nos lecteurs lors de la récupération des codes, nous avons mis cette technique en oeuvre dans une page séparée. Cliquez ici pour y aller.

Les contre-indications

Ça marche généralement bien avec IE5+, NN6+, Mozilla et Opera7 ; aussi avec NN4... à condition de passer sur un positionnement imparfait des bulles.

Pas avec les versions antérieurs d'Opera (les bulles apparaissent à peu près là où il faut, comme avec NN4, mais hélas sans le contenu attendu, parce que la propriété innerHTML ne fonctionne pas correctement). Et pas avec iCab (mac) (et peut-être d'autres que nous n'avons pas testés), mais tant que iCab ne saura pas afficher correctement les calques, on ne pourra pas le compter sérieusement dans la cour des grands...

Un gros bémol cependant : ça ne fonctionne sur IE6 que si le doctype est un HTML 4 transitional sans URL (ou s'il n'y a pas de doctype du tout), c.à.d. si IE6 reste dans son mode «compatible microsoft».

Le bon positionnement vertical dans la fenêtre dépend d'une indication correcte pour la hauteur de la bulle, si on ne veut pas que la bulle soit coupée en hauteur. Enfin, ce script ne convient qu'à des bulles ne contenant que du texte. Si on veut autre chose, on passera à notre script alternatif.

Une contre-indication notoire toutefois : il vaut mieux éviter d'ouvrir ces bulles à proximité des cases d'un formulaire, parce que ces cases peuvent réapparaître au-dessus des bulles avec IE5/6 sous Windows ; le fonctionnement sous MacOS ou de NN6/Mozilla (macOS ou Windows) reste normal, mais ces configurations sont minoritaires.

Charles