Aie! Il a quelques navigateurs (dont Opera 5)
où nos bulles ne fonctionnent pas...
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...) ?
Pour avoir des bulles d'aides là où
TITLE ne fonctionne pas ? Par exemple, pour
NN4, moribond, mais encore disparu ? Ou pour le (presque) tout nouveau
Opera, toujours bugué pour TITLE (du moins pour
Opera5-mac) ?
Parce que la bulle déclenchée par un TITLE
n'arrive pas assez vite, surtout sur Explorer (le navigateur dominant
du moment), et qu'on peut souhaiter des réactions plus
nerveuses ?
Parce qu'on estime que la petite bulle
déclenchée par TITLE est trop discrète
et qu'on voudrait quelque chose de plus vigoureux ?
Pour faire des «bulles d'aide» bien tarabiscotées,
par exemple avec des figures... Pourquoi pas,
n'est-ce-pas, quand on peut faire compliqué ?
Pour maîtriser la mise en page d'un texte complexe dans la
bulle, chose impossible avec un TITLE ?
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,
A la base, la bulle est un calque invisible
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'.
On remplit alors le calque précédent par le texte de la bulle
d'aide (propriété innerHTML pour IE5 ou NN6)
On le déplace à l'endroit voulu dans la page et on le rend
visible en jouant sur ses propriétés de style
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)"...
où 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+ :
(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
où 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.
Pour le positionnement horizontal, nous utilisons la largeur
bulleWidth de la bulle (une variable javascript fixée
à 150 dans notre script, mais qu'on peut changer à volonté).
Dès que xfenetre dépasse cette
largeur (augmentée de notre décalage de 15 pixels), on ouvre la bulle
sur la gauche en prenant bulleStyle.left = xpage - bulleWidth - 15
Cette méthode n'est pas directement applicable au positionnement vertical
parce qu'il n'y a pas moyen de connaître avec certitude la hauteur de la bulle.
Nous avons
choisi d'inclure cette hauteur en argument facultatif dans notre script.
La valeur prise par défaut devrait suffire pour des bulles de deux lignes
examinées sans grossissement. Au delà, il conviendrait d'ajouter ce
troisième argument de manière empirique, par essais et
erreurs ; on peut partir de la valeur suivante :
  hauteur = 1,20 x taille police x nombre
de lignes et ajouter une dizaine de pixels pour faire bon poids.
Cette procédure suppose évidemment que le visiteur n'ajoute
aucun effet de zoom sur les caractères, mais il n'y a aucun moyen d'en tenir
compte (à notre connaissance).
De toute manière, pour voir la totalité d'une bulle d'aide
qui aurait été ainsi tronquée, le visiteur n'aura qu'à
retoucher l'ascenseur vertical de la page.
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 ;
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
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.