OVH Cloud OVH Cloud

Événement déclenché sur un objet erroné

22 réponses
Avatar
Claude Schneegans
Bonjour,

Regardez à l'adresse suivante:
http://www.contentbox.com/claude/test/testEvent.htm

Le script parcoure tous les éléments du document, et pour chaque élément
de liste LI,
il lui assigne un événement de type onmouseover

La fonction appelée par l'événement vérifie le nom de balise de l'objet,
ça devrait toujours être
un LI, mais ô surprise, des fois l'objet est le UL, et dans ce cas une
alarme est déclenchée.
Comment se peut-ce, puisqu'aucun UL n'a d'événement attaché ? Bizarre hein ?

Promenez la souris sur le menu, et tout d'un coup, pouf ! C'est un UL
qui déclenche.

Le plus curieux, c'est que Mords-y-la semble avoir le même problème.

Si c'est un comportement normal, j'aimerais bien en avoir une explication.

Merci.

Voilà le code :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
<title>Untitled</title>
<STYLE>
ul {
background-color: #B9D2FF;
margin:0px;
padding: 0;
position:absolute;
border: solid 1px #AAAAAA;
}
ul li {
width: 125px;
margin: 0;
padding: 0;
background-color: #628BFF;
color: #DFE6F5;
border: 1px outset;
list-style: none;
}
UL LI UL {
left:110px;
top:5px;
}
</STYLE>
</head>

<body>
<UL id="0">
<li id="1">item 1
<UL id="1.0">
<li id="1.1">item 1.1</li>
<li id="1.3">item 1.3</li>
<li id="1.4">item 1.4</li>
</ul></li>
<li id="2">item 2</li>
<li id="3">item 3</li>
<li id="4">item 4</li>
</ul>
<SCRIPT>
function init(m)
{
var el = m.childNodes;
for (var l = 0; l<el.length; l++)
{
if(el[l].tagName)
{
var tag = el[l].tagName.toLowerCase();
if (tag == "ul")
{
//do not attach event if UL container, but process its LIs
init (el[l]);
}
else if (tag == "li")
{
//attach event to list element ONLY
if(document.all)el[l].attachEvent('onmouseover', show);
else el[l].addEventListener("mouseover", show, false);
init (el[l]);
}
}
}
}
function show(e)
{
var li;
if (document.all)li=event.srcElement;
else li=e.target;
if (li.tagName != "LI")alert("over" + li.id + " : tag is " +
li.tagName);
}
init(document.body);
</SCRIPT>

</body>
</html>

10 réponses

1 2 3
Avatar
Jean
Bonjour,

AMHA le problème vient du fait que l'élément LI ne peut pas servir de
conteneur (<li id="1"><ul>bla bla</ul></li>),
c'est implicite, la fermeture de cet élément étant facultative :

http://www.w3.org/TR/1998/REC-html40-19980424/struct/lists.html#edef-LI


Pour la fin du script (ceci n'a aucun rapport avec le problème), je
mettrais :
if (li.tagName.toUpperCase() !== "LI")
au lieu de
if (li.tagName != "LI")

Amicalement,

Bonjour,

Regardez à l'adresse suivante:
http://www.contentbox.com/claude/test/testEvent.htm

Le script parcoure tous les éléments du document, et pour chaque élément de
liste LI,
il lui assigne un événement de type onmouseover

La fonction appelée par l'événement vérifie le nom de balise de l'objet, ça
devrait toujours être
un LI, mais ô surprise, des fois l'objet est le UL, et dans ce cas une
alarme est déclenchée.
Comment se peut-ce, puisqu'aucun UL n'a d'événement attaché ? Bizarre hein
?

Promenez la souris sur le menu, et tout d'un coup, pouf ! C'est un UL qui
déclenche.

Le plus curieux, c'est que Mords-y-la semble avoir le même problème.

Si c'est un comportement normal, j'aimerais bien en avoir une explication.

Merci.

Voilà le code :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
<title>Untitled</title>
<STYLE>
ul {
background-color: #B9D2FF;
margin:0px;
padding: 0;
position:absolute;
border: solid 1px #AAAAAA;
}
ul li {
width: 125px;
margin: 0;
padding: 0;
background-color: #628BFF;
color: #DFE6F5;
border: 1px outset;
list-style: none;
}
UL LI UL {
left:110px;
top:5px;
}
</STYLE>
</head>

<body>
<UL id="0">
<li id="1">item 1
<UL id="1.0">
<li id="1.1">item 1.1</li>
<li id="1.3">item 1.3</li>
<li id="1.4">item 1.4</li>
</ul></li>
<li id="2">item 2</li>
<li id="3">item 3</li>
<li id="4">item 4</li>
</ul>
<SCRIPT>
function init(m)
{
var el = m.childNodes;
for (var l = 0; l<el.length; l++)
{
if(el[l].tagName)
{
var tag = el[l].tagName.toLowerCase();
if (tag == "ul")
{
//do not attach event if UL container, but process its LIs
init (el[l]);
}
else if (tag == "li")
{
//attach event to list element ONLY
if(document.all)el[l].attachEvent('onmouseover', show);
else el[l].addEventListener("mouseover", show, false);
init (el[l]);
}
}
}
}
function show(e)
{
var li;
if (document.all)li=event.srcElement;
else li=e.target;
if (li.tagName != "LI")alert("over" + li.id + " : tag is " +
li.tagName);
}
init(document.body);
</SCRIPT>

</body>
</html>


--
Jean - JMST
Belgium

Avatar
Claude Schneegans
le problème vient du fait que l'élément LI ne peut pas servir de
conteneur



Euh ? Servir de conteneur pour quoi au juste ?
Aussi, je sais que pour un LI la fermeture est facultative, mais
naturellement, si je les enlève,
ça ne change rien. Le problème ne vient donc pas de là.

C'est quand même fatigant de se dire que lorsqu'un événement assigné à
un objet est déclenché, il faut
à chaque fois vérifier s'il provient bien de cet objet.


Avatar
Jean
le problème vient du fait que l'élément LI ne peut pas servir de
conteneur



Euh ? Servir de conteneur pour quoi au juste ?


... d'autres éléments ...

Aussi, je sais que pour un LI la fermeture est facultative, mais
naturellement, si je les enlève,


Vous avez mal compris AMHA.
Quand la fermeture d'un élément est facultative celà implique que
celui-ci ne peut pas servir de conteneur (au risque d'avoir des
résultats aléatoire de la part de l'analyseur html ... vous aurez
toujours un rendu dans le browser ... mais totalement imprévisible).
Pour prendre un exemple probablement plus clair, ce que vous faites
avec ce LI actuellement c'est comme si vous utilisiez une balise IMG
comme conteneur par ex. ...

Vous devez donc *remplacer* ce LI par un autre élément (donc avec
fermeture de balise obligatoire) pouvant servir de conteneur (span,
div, ...).

ça ne change rien. Le problème ne vient donc pas de là.



Ben hum ... :-)

C'est quand même fatigant de se dire que lorsqu'un événement assigné à un
objet est déclenché, il faut
à chaque fois vérifier s'il provient bien de cet objet.


Pas si on suit la norme :-) AMHA

--
Jean - JMST
Belgium



Avatar
Claude Schneegans
Quand la fermeture d'un élément est facultative celà implique que
celui-ci ne peut pas servir de conteneur


Ah bon ? Et depuis quand ?
Un LI peut contenir une autre liste, même une table, en fait n'importe
quoi, c'est en toutes lettres dans le standard HTML.

Le fait qu'une fermeture soit facultative vient seulement du fait que la
fermeture est impliquée automatiquement par le contexte;
dans le cas d'un LI, celui-ci est automatiquement fermé par le premier </UL>

Même chose pour l'OPTION qui est implicitement fermée par une autre
OPTION ou la fermeture du SELECT.
Une OPTION ne peut contenir une liste, mais ça n'a rien à voir avec la
fermeture facultative.

Avatar
Jean
Quand la fermeture d'un élément est facultative celà implique que
celui-ci ne peut pas servir de conteneur


Ah bon ? Et depuis quand ?


Pour moi ... depuis toujours :-)

Un LI peut contenir une autre liste, même une table, en fait n'importe quoi,
c'est en toutes lettres dans le standard HTML.



Non les LI sont des éléments de listes ... les listes ce sont des OL,
UL, DIR, ... qui elles ont une fermeture obligatoire.

Le fait qu'une fermeture soit facultative vient seulement du fait que la
fermeture est impliquée automatiquement par le contexte;


... je dirais plutôt par l'analyseur ...

dans le cas d'un LI, celui-ci est automatiquement fermé par le premier </UL>

Même chose pour l'OPTION qui est implicitement fermée par une autre OPTION ou
la fermeture du SELECT.
Une OPTION ne peut contenir une liste, mais ça n'a rien à voir avec la
fermeture facultative.


C'est la même chose que pour les LI comme je k'expliquais précédemment.

J'insiste : vous avez mal compris :-)
Si vous strucurez vos documents avec de telles libertés vous risquez de
repasser souvent ici en pensant être victime d'un bug qui n'en n'est
pas un ... sinon écrire au w3c pour qu'il change la norme ... et aux
éditeurs de browser pour qu'ils l'adopte :-)

--
Jean - JMST
Belgium


Avatar
Claude Schneegans
Un LI peut contenir une autre liste, même une table, en fait n'importe
quoi, c'est en toutes lettres dans le standard HTML.


Non les LI sont des éléments de listes ... les listes ce sont des OL,
UL, DIR, ... qui elles ont une fermeture obligatoire.



Si je me réfère au lien cité par vous-même, je lis :

« Lists may also be nested:
DEPRECATED EXAMPLE: (Ce qui est "deprecated" ici, c'est l'attribut start)

<UL>
<LI> ... Level one, number one...
<OL>
<LI> ... Level two, number one...
<LI> ... Level two, number two...
<OL start="10">
<LI> ... Level three, number one...
</OL>
<LI> ... Level two, number three...
</OL>
<LI> ... Level one, number two...
</UL>

Il n'y a pas une liste dans un LI ici ?

J'insiste : vous avez mal compris



Ah bon...
Moi je crois que vous confondez entre :

Container tags: require or optionally require a closing tag.
Ex : H1, B, I, TABLE, TR, TD, UL, OL etc. (fermeture obligatoire);
ou encore : P, LI, OPTION, etc. (fermeture facultative);
et :
Non-container tags: Must not have a closing tag.
Ex: BR, HR, IMG
De plus, les UL, OL et autres sont AUSSI appelés « liste elements », au
même titre que le LI.
Voir par exemple : http://www.fuzzylu.com/docs/html/p000gloss.htm

Et de plus, et de toute façon, je ne vois pas ce que cela peut avoir à
voir avec le déclenchement inopiné
d'événements sur des objets, que ceux-cis soient « container » ou non.
Un événement de type « onmouseon » est légal sur un objet LI comme sur
un UL.
Ce qui est anormal, c'est qu'un événement déclaré pour un LI se retrouve
de temps en temps sur un UL.


Avatar
Jean
Un LI peut contenir une autre liste, même une table, en fait n'importe
quoi, c'est en toutes lettres dans le standard HTML.


Non les LI sont des éléments de listes ... les listes ce sont des OL,
UL, DIR, ... qui elles ont une fermeture obligatoire.



Si je me réfère au lien cité par vous-même, je lis :

« Lists may also be nested:
DEPRECATED EXAMPLE: (Ce qui est "deprecated" ici, c'est l'attribut start)

<UL>
<LI> ... Level one, number one...
<OL>
<LI> ... Level two, number one...
<LI> ... Level two, number two...
<OL start="10">
<LI> ... Level three, number one...
</OL>
<LI> ... Level two, number three...
</OL>
<LI> ... Level one, number two...
</UL>

Il n'y a pas une liste dans un LI ici ?



Ben non ... l'exemple est assez clair pourtant :-)
C'est une UL qui contient une OL qui elle même contient une OL.
Les LI sont les éléments de la liste UL et des deux listes OL ...

J'insiste : vous avez mal compris



Ah bon...
Moi je crois que vous confondez entre :

Container tags: require or optionally require a closing tag.
Ex : H1, B, I, TABLE, TR, TD, UL, OL etc. (fermeture obligatoire);
ou encore : P, LI, OPTION, etc. (fermeture facultative);
et :
Non-container tags: Must not have a closing tag.
Ex: BR, HR, IMG
De plus, les UL, OL et autres sont AUSSI appelés « liste elements », au même
titre que le LI.
Voir par exemple : http://www.fuzzylu.com/docs/html/p000gloss.htm

Et de plus, et de toute façon, je ne vois pas ce que cela peut avoir à voir
avec le déclenchement inopiné
d'événements sur des objets, que ceux-cis soient « container » ou non.
Un événement de type « onmouseon » est légal sur un objet LI comme sur un UL.
Ce qui est anormal, c'est qu'un événement déclaré pour un LI se retrouve de
temps en temps sur un UL.


Pas si le parser ne s'y retrouve plus AMHA :-)

--
Jean - JMST
Belgium



Avatar
Claude Schneegans
Ben non ... l'exemple est assez clair pourtant :-)
C'est une UL qui contient une OL qui elle même contient une OL.

Les LI sont les éléments de la liste UL et des deux listes OL ...

Erreur : l'OL n'est pas contenue directement dans l'UL, mais dans le LI
du UL, et le 2e OL
est contenu dans le LI du premier OL. C'est parce que les </LI> ont été
omis que vous
confondez, c'est pour ça que moi je les mets toujours, ça rend la
structure plus claire.

On trouve partout des exemples de "nested lists", il suffit de chercher :
http://css.maxdesign.com.au/listutorial/sub01.htm
http://www.simplebits.com/notebook/2003/10/19/styling_nested_lists.html
http://www.webdevtips.com/webdevtips/html/nested_lists.shtml
http://www.howtocreate.co.uk/tutorials/jsexamples/listCollapseExample.html
.....
Tous avec les fermetures des LI pour que ce soit plus clair.

... je crois qu'un coup d'oeil à ces "tutorials" vous serait des plus
profitables ;-))

La question reste donc ouverte : pourquoi ces faux évènements sur les UL
auxquels on n'a rien demandé ?

Avatar
Jean
Ben non ... l'exemple est assez clair pourtant :-)
C'est une UL qui contient une OL qui elle même contient une OL.

Les LI sont les éléments de la liste UL et des deux listes OL ...

Erreur : l'OL n'est pas contenue directement dans l'UL,


mais si :-)

mais dans le LI du UL,


mais non :-)

et le 2e OL
est contenu dans le LI du premier OL.


mais non :-)

C'est parce que les </LI> ont été omis que vous
confondez,


ben ... si je me trompe ... je mange mon chapeau ... promis (et tant
pis pour moi) :-)

c'est pour ça que moi je les mets toujours,


Là nous sommes d'accord ... conformité xml oblige ...

ça rend la structure plus claire.



ben non ... je rajoute les fermetures :

<UL>
<LI> ... Level one, number one...</LI>
<OL>
<LI> ... Level two, number one...</LI>
<LI> ... Level two, number two...</LI>
<OL start="10">
<LI> ... Level three, number one...</LI>
</OL>
<LI> ... Level two, number three...</LI>
</OL>
<LI> ... Level one, number two...</LI>
</UL>

Les LI "Level one" sont des éléments de la liste UL.
Les LI "Level two" sont des éléments de première la liste OL.
Les LI "Level three" sont des éléments de la seconde liste OL.

Les LI ne contiennent rien ... et les 2 OL sont contenues dans l'UL ...
Vous faites vos fermetures autrement ? ...

On trouve partout des exemples de "nested lists", il suffit de chercher :
http://css.maxdesign.com.au/listutorial/sub01.htm
http://www.simplebits.com/notebook/2003/10/19/styling_nested_lists.html
http://www.webdevtips.com/webdevtips/html/nested_lists.shtml
http://www.howtocreate.co.uk/tutorials/jsexamples/listCollapseExample.html
.....
Tous avec les fermetures des LI pour que ce soit plus clair.



Bon ... d'abord ce n'est pas parcequ'on le lit partout que c'est vrai
:-) (c'est un lieu commun) et je préfère un lien issu d'un standard
pour confirmer.

Ensuite ... ce n'est pas parceque je le dis que c'est vrai (hum ... là
je prèche un converti :-) ) ...

Je dois dire que pour moi les LI ont tjrs été des éléments de liste et
que de plus ceux ci devaient être inclu dans un bloc de liste (ol, ul,
dir, menu ...) ... je n'aurais donc jamais eu l'idée de mettre une
liste dans un élément de liste (dans une LI racine) ... *mais* ce qui
me fait douter à présent (là je me rapproche d'un méa culpa :-) ) c'est
que les LI ont une propriété innerHTML ... donc en théorie ... c'est
bien possible.
J'aurais donc été plus strict que la norme.
Dans l'absolu, méa culpa donc ... :-)

... je crois qu'un coup d'oeil à ces "tutorials" vous serait des plus
profitables ;-))



Ben ... ouvrons les yeux,croisons les doigts :-)

La question reste donc ouverte : pourquoi ces faux évènements sur les UL
auxquels on n'a rien demandé ?


Admettons que je raconte des âneries depuis le début.
N'empêche ... si le problème survient autant dans IE que Mozilla ...
vous admettrez qu'il y a de fortes chances qu'il y ait quelque chose de
non conforme à la norme (mais bon ... les apparences peuvent être
trompeuses).

N'empêche aussi qu'en remplacant la LI (<li id="1">) par une SPAN ou
(pour conserver votre code tel quel, sans modifications dans la feuille
de style) en englobant les listes dans une SPAN par ex., le code donne
le résultat escompté et fonctionne correctement (cf code ci dessous).
Ca me rappelle un problème avec les TABLE et IE4 ... mais je ne sais
plus ce que c'était (et ça n'a peut être rien à voir). :

<!---8<--->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
<title>Untitled</title>
<style>
ul {
background-color: #B9D2FF;
margin:0px;
padding: 0;
position:absolute;
border: solid 1px #AAAAAA;
}
ul li {
width: 125px;
margin: 0;
padding: 0;
background-color: #628BFF;
color: #DFE6F5;
border: 1px outset;
list-style: none;
}
ul li ul {
left:110px;
top:5px;
}
</style>
</head>

<body>
<span>
<ul id="0">
<li id="1">item 1
<ul id="1.0">
<li id="1.1">item 1.1</li>
<li id="1.3">item 1.3</li>
<li id="1.4">item 1.4</li>
</ul>
</li>
<li id="2">item 2</li>
<li id="3">item 3</li>
<li id="4">item 4</li>
</ul>
</span>
<script>
function init(m){
var el = m.childNodes;
for(var l=0;l<el.length;l++){
if(el[l].tagName){
var tag = el[l].tagName.toLowerCase();
if (tag == "ul"){
//do not attach event if UL container, but process its LIs
init (el[l]);
}else if(tag=="li"){
//attach event to list element ONLY
if(document.all)el[l].attachEvent('onmouseover', show);
else el[l].addEventListener("mouseover", show,
false);
init (el[l]);
}
}
}
}
function show(e){
var li;
if (document.all)li=event.srcElement;
else li=e.target;
if (li.tagName.toUpperCase()!== "LI"){
alert("over" + li.id + " : tag is " + li.tagName)
}
}
init(document.body);
</script>
</body>
</html>
<!---8<--->

--
Jean - JMST
Belgium


Avatar
Claude Schneegans
ben non ... je rajoute les fermetures :

<UL>
<LI> ... Level one, number one...</LI>
<OL>
<LI> ... Level two, number one...</LI>
<LI> ... Level two, number two...</LI>
<OL start="10">
<LI> ... Level three, number one...</LI>
</OL>
<LI> ... Level two, number three...</LI>
</OL>
<LI> ... Level one, number two...</LI>
</UL>

Les LI "Level one" sont des éléments de la liste UL.
Les LI "Level two" sont des éléments de première la liste OL.
Les LI "Level three" sont des éléments de la seconde liste OL.

Les LI ne contiennent rien ... et les 2 OL sont contenues dans l'UL ...
Vous faites vos fermetures autrement ? ...

Bon, alors si je soumets votre code au valideur officiel du W3C :

http://validator.w3.org/check
Voici ce qu'il me sort :
« Line 11, column 7: document type does not allow element "OL" here;
assuming missing "LI" start-tag

<OL>

Line 14, column 21: document type does not allow element "OL" here;
assuming missing "LI" start-tag

<OL start="10"> »

Ce qui montre bien qu'une liste, OL ou UL, c'est pareil, ne peut
contenir directement d'autre éléments
UL ou OL : il faut un LI pour les contenir.

Par contre, si je remets les fermetures des LI au bon endroit, c-à-dire
APRÈS les fermetures des listes,
donc, le code a l'air de :

<UL>
<LI> ... Level one, number one...
<OL>
<LI> ... Level two, number one...</LI>
<LI> ... Level two, number two...
<OL start="10">
<LI> ... Level three, number one...</LI>
</OL></LI>
<LI> ... Level two, number three...</LI>
</OL></LI>
<LI> ... Level one, number two...</LI>
</UL>

la réponse est claire :
« The uploaded file was tentatively found to be Valid. »

C.Q.F.D

Bon ... d'abord ce n'est pas parcequ'on le lit partout que c'est vrai
:-) (c'est un lieu commun) et je préfère un lien issu d'un standard
pour confirmer.


Comme le validateur du W3C par exemple ;-)

Je dois dire que pour moi les LI ont tjrs été des éléments de liste et
que de plus ceux ci devaient être inclu dans un bloc de liste (ol, ul,
dir, menu ...) ... je n'aurais donc jamais eu l'idée de mettre une
liste dans un élément de liste (dans une LI racine) ...


La vraie façon dont il faut voir les choses, c'est que
1º une liste ne *PEUT PAS* contenir autre chose que des éléments de
liste <LI>, donc pas de texte ni d'autre liste;
2º un élément de liste LI *PEUT* contenir n'importe quoi, y compris
d'autres listes.

(là je me rapproche d'un méa culpa :-) )


Vous brûlez mon vieux ;-)

Admettons que je raconte des âneries depuis le début.


Oui, mais là je sens que ça change ;-)

ou (pour conserver votre code tel quel, sans modifications dans la
feuille de style) en englobant les listes dans une SPAN par ex., le
code donne le résultat escompté et fonctionne correctement (cf code ci
dessous).


En effet, et c'est bizarre, quel est le rapport ?
Avec une DIV, ça marche aussi, et avec une balise B également, mais avec
un P ça bug encore.
Et toujours de la même façon chez Mords-zy-la...

1 2 3