11546 sujets

JavaScript, DOM et API Web HTML5

Pages :
Bonjour/Bonsoir,

Je souhaite créer un champ d'aide à la saisie (quand on tape une lettre, une liste de choix s'affiche et l'utilisateur peut y naviguer avec la souris ou le clavier au choix).
Cette liste (ul et li) de résultats est placée dans une div, positionnée sous le champ texte en question.

La recherche de résultats est lancée lorsque l'utilisateur relâche une touche (onkeyup).

Sous Firefox et IE, pas de problème pour l'affichage et la recherche des résultats, tout est ok.
De même pour la navigation au clavier (flèches haut/bas, touche entrée, et surlignage de l'élément "courant"), cela fonctionne aussi bien sur Firefox que sur IE.

Par contre la navigation à la souris pose problème sous IE (6 et 7, pas pu tester sous IE 8), rien ne se passe (au survol, les couleurs de fond de l'élément courant et de l'élément précédent sont censées changer).

<div id="divAutoCompleteDelivery" class="divAutoComplete"  onmouseover='javascript:highlightLI(event);'></div>


Et la fonction associée :

function highlightLI(evnt)
{
	var evt;
	if (!evnt) 
		evt = window.event;
	else
		evt = evnt;
		
	if (highlightedIndex >  -1)
		elem[highlightedIndex].style.background = "#FFF"

	var target = evt.explicitOriginalTarget||document.activeElement;

	if (target.parentNode == "[object HTMLLIElement]")
		target.parentNode.style.background = "#CCC";
	
	for (i = 0; i < elem.length; i++)
	{
		if (elem(i).innerHTML == target.parentNode.innerHTML)
			highlightedIndex = i;
	}
}


highlightedIndex est une variable globale qui correspond à l'index de l'élément courant (initialisé à -1).
elem correspond au tableau contenant les possibilités retournées (les LI).
Dans le code ci dessus j'ai remplacé les crochets par des parenthèses (elem(i)) pour éviter la balise italique.

Parfois (quand je m'acharne sur la div avec la souris), IE me retourne une erreur : elem.length is null or not an object.

Je ne vois pas trop d'où peut bien provenir le problème en fait, si vous avez une idée, voire une solution, je prends !

Merci Smiley smile
Modifié par SynRJ (08 Jun 2009 - 09:20)
Salut,

a écrit :
si vous avez une idée, voire une solution, je prends !
Alors moi ce sera des idées. Pour la solution, il faudrait voir ta page en ligne.
onmouseover='javascript:highlightLI(event);'
Je t'épargne les conseils sur la séparation HTML/JS. Mais :
- un attribut HTML se spécifie entre guillemets doubles ("), et non (')
- "javascript:" est inutile (au mieux). Le gestionnaire d'événement onmouseover étant un gestionnaire 100% javascript, il est inutile de préciser que tu vas utiliser ce langage.
- highlightLI(event) : dans tous les cas, ce event sera l'événement mouseover (je veux dire par là que jamais il ne sera vide). Sous IE ce sera par window.event (le "window." n'a pas besoin d'être précisé du moment qu'aucune variable ne porte le même nom dans le contexte immédiat), et sous Firefox ce sera parce que les gestionnaires d'événement récupèrent automatiquement l'événement en question dans un argument appelé... event.

Donc highlightLI() recevra dans tous les cas l'événement mouseover dans son argument evnt. Le test suivant au début de la fonction est donc là aussi inutile :
if (!evnt)
    evt = window.event;
else
    evt = evnt;
On passe toujours dans le else.

var target = evt.explicitOriginalTarget||document.activeElement;
Je ne connaissais pas ces propriétés et suis donc allé jeter un coup d'oeil rapide dans la doc. Il semblerait que la première soit spécifique à Firefox et la deuxième soit destiné à HTML5. J'ai vraiment survolé, alors je me plante peut-être. Mais sinon : target sera undefined sous IE (ce qui peut constituer une solution, sait-on jamais Smiley smile )

if (target.parentNode == "[object HTMLLIElement]")
Plus simple, et certainement plus sûr sûr niveau compatibilité :
if (target.parentNode.tagName.toLowerCase() == "li")

if (elem[i[#000]].innerHTML == target.parentNode.innerHTML)
Pourquoi ne pas faire simplement :
if (elem[i[#000]] == target.parentNode)
a écrit :
lors moi ce sera des idées. Pour la solution, il faudrait voir ta page en ligne.

Ça risque malheureusement d'être difficile sachant que l'appli sur laquelle je bosse est une appli intranet (avec identification requise). J'ai remplacé les apostrophes par des guillemets, je les avais probablement mises pour éviter d'échapper en permanence les guillemets.

Concernant le "javascript:", je l'avais rajouté en dernière minute, pour voir si ça fonctionnait différemment avec/sans. Il a été enlevé depuis.

if (!evnt)
    evt = window.event;
else
    evt = evnt;

Il me semble que j'avais fait ce test parce que j'avais lu qu'IE ne prenait pas en compte le passage de l'objet event en paramètre. Après avoir mis des alert dans le if et dans le else, FF passe dans le else, et IE aussi, effectivement.

var target = evt.explicitOriginalTarget||document.activeElement;

Si je fais un alert(target), j'obtiens l'objet survolé sous FF (object HTMLLi, HTMLDiv, Text), sous IE j'obtiens toujours object.
Si je fais un alert(target.parentNode.tagName) j'obtiens LI sous FF, et SPAN sous IE, pourtant mon texte est directement dans les LI, il n'y a pas de SPAN. =/


if (target.parentNode.tagName.toLowerCase() == "li")

Effectivement, et ça limite le risque d'erreur.

if (elem(i) == target.parentNode)

Je n'avais pas pensé que ça pourrait marcher, voila pourquoi =D
Modifié par SynRJ (05 Jun 2009 - 10:00)
a écrit :
J'ai remplacé les apostrophes par des guillemets, je les avais probablement mises pour éviter d'échapper en permanence les guillemets
Il suffit d'utiliser les simples quotes (') en javascript, et comme ça tu n'échappes rien.

a écrit :
j'avais lu qu'IE ne prenait pas en compte le passage de l'objet event en paramètre
Et c'est bien le cas. Seulement, en Javascript, quand tu invoques une variable, elle est cherchée dans le contexte actuel. Si elle n'y est pas trouvée, elle est cherchée dans les contextes parents, jusqu'au contexte racine (window). Donc si tu dis event dans IE et qu'aucune variable de ce nom n'existe, c'est comme si tu disais window.event. C'est mal expliqué, je m'en rends compte, mais c'est difficile en peu de lignes Smiley smile

a écrit :
Si je fais un alert(target), j'obtiens l'objet survolé sous FF (object HTMLLi, HTMLDiv, Text), sous IE j'obtiens toujours object.
Essaye alert(target.tagName), c'est un peu plus parlant pour savoir à quel élément tu as affaire...

Et si, au lieu d'utiliser ces propriétés bizarres (explicitOriginalTarget et activeElement), tu utilisais le bon vieux target ? Que t'affiche l'alerte suivante :
alert(evt.target.tagName);

a écrit :
Si je fais un alert(target.parentNode.tagName) j'obtiens LI sous FF, et SPAN sous IE, pourtant mon texte est directement dans les LI, il n'y a pas de SPAN. =/
Ah, ça c'est rigolo Smiley smile Sans voir ta page complète (en ligne), il est malheureusement impossible de te dire d'où vient ce span.
Modifié par marcv (05 Jun 2009 - 13:47)
alert(evt.target.tagName);

Avec evt l'objet event et le target "de base" (sans les propriétés bizarres), FF me renvoie la même chose que précédement (DIV, LI, ...), IE me renvoie une erreur (target.tagName is null or not an object).
Ah oui, c'est vrai que IE fonctionne pas avec target. Essaye ça :
var targetTest = evt.target || evt.srcElement;
alert(targetTest.tagName);
Est-ce que ça te donne la même chose dans les deux browsers ?
Ouyeah. Avec le target défini comme tu l'as fait, cela fonctionne.

Je vais adapter le reste et reporter les modifications sur le clic de la souris (pour sélectionner un des choix de la liste).
Je vous tiens au courant, merci.
Ah bah voila ! (c'est un "Ah bah voila" du genre "zut")

En fait, dans ma seconde fonction, qui gère la perte de focus du champ d'aide à la saisie (événement onblur), j'ai besoin des "propriétés bizarres".
evt.target || evt.srcElement
me renvoie, dans le cas du onblur, l'élément input (donc le champ texte).

Ce que j'aimerais obtenir, c'est l'élément qui a déclenché le perte de focus (l'élément sur lequel je clique), d'où mes bidules bizarroides, qui soit-dit en passant fonctionnent bien sous FF :

var target = evt.explicitOriginalTarget||document.activeElement;

a écrit :
Si je fais un alert(target), j'obtiens l'objet survolé sous FF (object HTMLLi, HTMLDiv, Text), sous IE j'obtiens toujours object.


Donc en fait du coup ma question revient à : existe-t-il un moyen d'obtenir l'élément qui déclenche la perte de focus sous Internet Explorer ?
Modifié par SynRJ (05 Jun 2009 - 11:32)
Et tant que j'y suis, j'ai une fonction qui prend pour paramètre un entier. Sous FF, ça marche, sous IE si je fais un alert(parametre), j'obtiens undefined. Faut que je passe le paramètre en chaine et ensuite que je le parse en int ?

Edit : après essai du parseInt(parametre), ça marche toujours sur FF, par contre IE me renvoie NaN.
Modifié par SynRJ (05 Jun 2009 - 12:04)
a écrit :
existe-t-il un moyen d'obtenir l'élément qui déclenche la perte de focus sous Internet Explorer ?
Euh, là aucune idée.
a écrit :
j'ai une fonction qui prend pour paramètre un entier. Sous FF, ça marche, sous IE si je fais un alert(parametre), j'obtiens undefined
Si ta fonction reçoit undefined sous IE c'est qu'elle reçoit rien. Ton problème se situe avant l'appel à la fonction.
J'appelle la fonction comme ceci (dans un bouton radio):
onclick="fieldsStateChange('vendor', value, 6);"
Les alerts des autres paramètres fonctionnent, c'est juste le dernier, entier, qui ne passe pas.
Bon j'ai trouvé, c'était un problème lié à la génération de code par Lotus Domino (ça produit vraiment quelque chose d'innommable...).

Quelqu'un a une idée pour la récupération de l'objet "cliqué" lors de la perte de focus d'un champ sous Internet Explorer ?
Ou éventuellement une autre méthode pour identifier si le clic qui provoque le onblur se situe sur la div (et sur quel élément li) ou à l'extérieur.

Petit complément :
alert(evt.explicitOriginalTarget + " " + document.activeElement);
me renvoie :
FF : [object Text] [object HTMLBodyElement]
IE : undefined [ object]

Et document.activeElement.tagName me retourne div.
Modifié par SynRJ (05 Jun 2009 - 13:50)
a écrit :
Ou éventuellement une autre méthode pour identifier si le clic qui provoque le onblur se situe sur la div (et sur quel élément li) ou à l'extérieur.
Ça c'est possible : tu mets un onclick sur la div en question, et l'élément cliqué sera dans la propriété target/srcElement de l'évenement.
Ça ne posera pas un soucis au niveau du onblur du champ texte ?

Car il me semble avoir essayé et constaté que le onblur du champ s'exécutait avant le onclick de la div =/

Je vais retenter.

Edit : Effectivement j'avais essayé, et le onblur se déclenche avant le onclick.
Modifié par SynRJ (05 Jun 2009 - 14:04)
Bon, le problème est en partie réglé en ajoutant le onblur et le onclick directement sur la div et en attrapant srcElement pour IE.

En partie seulement parce que la div a du mal à perdre le focus (cliquer "ailleurs" ne suffit généralement pas).

Edit :
A l'affichage, si je force le focus avec div.focus(), cela fonctionne pour IE (mais ça ne sert à rien, car le champ perd alors le focus, et on ne peut plus taper dedans sans recliquer, j'ai l'impression de tourner en rond Smiley eek ) , par contre FF ne semble pas le prendre en compte et ne déclenche jamais onblur quand je clic en dehors de la div.
Modifié par SynRJ (05 Jun 2009 - 14:24)
Salut,

ben c'est un peu normal puisque d'après les spécifications rares sont les élément qui reçoivent le focus (ce sont les mêmes pour blur) :
a écrit :
A, AREA, LABEL, INPUT, SELECT, TEXTAREA et BUTTON
Pour résumer ce sont les mêmes qui reçoivent l'attention lorsqu'on navigue au clavier (tabulations). Smiley cligne
Modifié par Heyoan (05 Jun 2009 - 14:33)
a écrit :
A, AREA, LABEL, INPUT, SELECT, TEXTAREA et BUTTON

J'ai beau cliquer sur n'importe quel élément de la liste ci dessus(sauf un bouton ou un lien qui me rafraichit ou change de page Smiley langue ), le onblur ne veut pas se déclencher sous FF. Sous IE il se déclenche dès que je clique en dehors de la div (que ce soit sur un autre div, une cellule de tableau, un champ, n'importe quoi !).

Smiley sweatdrop

Edit : Ah bah nan en fait, sous IE il ne se déclenche pas non plus.
Modifié par SynRJ (05 Jun 2009 - 14:44)
SynRJ a écrit :
J'ai beau cliquer sur n'importe quel élément de la liste ci dessus(sauf un bouton ou un lien qui me rafraichit ou change de page Smiley langue ), le onblur ne veut pas se déclencher sous FF.
Encore une fois c'est normal puisque onblur ne se déclenche que quand un élément avait le focus et qu'il le perd... or un DIV ne peut pas avoir le focus (bon : à part avec IE visiblement).
Oui mais du coup la solution ce serait quoi ?
De repérer l'élément positionné sous le clic, de tester si c'est la DIV ou non, comme j'avais tenté de le faire au début (avec le onblur sur le champ, mais là c'est le onclick qui ne fonctionnait pas sous IE) ?
Bon alors après avoir lu ton sujet (tout à l'heure je n'avais lu que ton dernier message Smiley langue ) il me semble que tu te simplifierais la vie en n'utilisant pas des éléments DIV / UL / LI mais des éléments SELECT et OPTION. Smiley murf
Pages :