OVH Cloud OVH Cloud

cloneNode et id

17 réponses
Avatar
Olivier Miakinen
Bonjour,

Je repasse de temps en temps poser des questions pour l'appli en
JavaScript dont je nettoie le code en l'améliorant. J'avais déjà
demandé comment faire pour ajouter des éléments de façon dynamique,
et on m'avait répondu « cloneNode() ».

Ce que je voudrais savoir, c'est comment la fonction se comporte sur un
n½ud (ou des sous-n½uds) avec un attribut id. En effet, par définition,
un id est unique sur l'ensemble du document, et c'est même ce qui permet
d'accéder à un élément directement par getElementById.

Pour clarifier ma pensée, voici un petit bout de code parsemé de
questions sous forme de commentaires.

{
var fieldset = document.getElementById("un_fieldset");

var ref_div = document.getElementById("div_de_reference");
// div_de_reference contient des boutons, des checkboxes, etc.

var new_div = ref_div.cloneNode();
// ai-je le droit de faire ça, sachant que cela duplique l'id,
// en l'occurrence "div_de_reference" ?

fieldset.appendChild(new_div);
// c'est peut-être ça que je n'ai pas le droit de faire
// à moins de changer d'id ?
}

...
// là il se passe plein de choses, en particulier je modifie le contenu
// de new_div, puis je retourne dans la fonction ci-dessus
...

{
var fieldset = document.getElementById("un_fieldset");

var ref_div = document.getElementById("div_de_reference");
// lequel vais-je récupérer ? celui de base ? ou son clone qui,
// je le rappelle, a vu son contenu modifié après clonage ?

var new_div = ref_div.cloneNode();
fieldset.appendChild(new_div);
// mêmes questions que précédemment : ai-je le droit de faire ça ?
}

7 réponses

1 2
Avatar
Bobe
Olivier Miakinen nous a dit le 10/12/2004 00:50:

Tu veux bien détailler dans quels cas on est obligés d'utiliser
setAttribute et dans quels cas on peut s'en dispenser ?



Dans le cas d'un document HTML, le DOM HTML est utilisable:
http://www.yoyodesign.org/doc/w3c/dom2/html/Overview.html

Utilisable aussi sur un document XHTML 1.0.

--
Bobe (Aurélien Maille)
http://webnaute.net

"la vie d'un geek est un combat perpétuel contre l'imperfection"

Avatar
Bobe
Olivier Miakinen nous a dit le 10/12/2004 00:47:

Nous sommes d'accord. Ma question était plutôt de savoir, s'il y a deux
éléments avec le même id, lequel sera récupéré par un getElementById.
Mais comme je vais changer l'id avant l'insertion la question ne se
posera pas, en fait.



Comme chaque identifiant utilisé dans le document doit être unique, la
question ne se pose pas. Se la poser revient à tenter d'imaginer le
comportement que va avoir le navigateur.

Dans l'idéal, une erreur javascript devrait être retournée, mais comme
il a été dit plus haut, ce n'est apparamment pas le cas.

--
Bobe (Aurélien Maille)
http://webnaute.net

"la vie d'un geek est un combat perpétuel contre l'imperfection"

Avatar
Sébastien
Mais ... les 2 sont possibles ?


Oui.

Avatar
Sébastien
Pourquoi avec setAttribute ?


Pourquoi pas ?
Faut bien que j'amortisse mon stage de dactylo :)

Avatar
Sébastien
Olivier Miakinen wrote:


Tu peux mettre à jour l'ID avec setAttribute( ).


Pourquoi avec setAttribute ? On travaille -- de toute évidence --
sur un document HTML ou XHTML, on peut donc utiliser l'attribut id
et écrire :
new_div.id = idString



Tu veux bien détailler dans quels cas on est obligés d'utiliser
setAttribute et dans quels cas on peut s'en dispenser ? J'aimerais bien
acquérir les bonnes pratiques dès le départ, autant qu'il m'est possible
de le faire.


Dans ce cas on peut se dispenser de setAttribute( ) parce que la
propriété id est accessible à tous les éléments d'une page (X)HTML, tout
comme title, lang, dir, className et d'autre selon les éléments sur
lesquels tu travailles.
La recommandation :
<http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html>

setAttribute( ) est vraiment utile dans une page XML (pas (X)HTML) dans
laquelle tu utilises tes propres éléments.



Avatar
YD
Olivier Miakinen wrote:
[...] dans quels cas on est obligés d'utiliser
setAttribute et dans quels cas on peut s'en dispenser ? J'aimerais bien
acquérir les bonnes pratiques dès le départ, autant qu'il m'est possible
de le faire.



Dans ce cas on peut se dispenser de setAttribute( ) parce que la
propriété id est accessible à tous les éléments d'une page (X)HTML, tout
comme title, lang, dir, className et d'autre selon les éléments sur
lesquels tu travailles.
La recommandation :
<http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html>

setAttribute( ) est vraiment utile dans une page XML (pas (X)HTML) dans
laquelle tu utilises tes propres éléments.


J'ajouterai que dans le cas des navigateurs on travaille sur des objets
"préconstruits" (les éléments HTML) qui sont instanciés avec toutes leurs
propriétés. Donc si on clone ou si on crée un <input type="checkbox"> on a
accès à un objet fini avec ses propriétés.

Autrement dit, dans le cas d'un élément (X)HTML manipulé par un navigateur,
on peut se dispenser de setAttribute.

La différence est, puisqu'il y en a une, qu'avec les navigateurs Gecko, le
positionnement avec setAttribute écrit l'attribut dans la balise (visible
en observant document.body.innerHTML) alors que le positionnement par script
/ne l'écrit pas forcément/...
truc.id=aString -> écrit dans la balise
truc.checked=true -> non écrit mais pris en compte
truc.setAtttribute("checked","true") -> écrit et pris en compte

Pour ceux que ça pourrait amuser, tester dans plusieurs navigateurs :

var a=document.createElement("input");
a.type="checkbox";
a.id="cb";
document.body.appendChild(a);
a.setAttribute("checked","");//après insertion à cause d'IE !!!
onload=function(){alert(document.body.innerHTML)}

Puis remplacer a.setAttribute("checked",""); par a.checkedúlse

En déduire la méthode la plus robuste.

--
Y.D.


Avatar
YD

Oui. Il fallait bien que je me trompe au moins une fois en rédigeant mon
article. Dans le vrai code JavaScript j'ai bien mis "true".


:-)

fieldset.appendChild(new_div);
// c'est peut-être ça que je n'ai pas le droit de faire
// à moins de changer d'id ?


Exact. Il faut modifier l'id. Personnellement, j'effectue toutes les
transformations *avant* l'insertion dans le document.



[...] Ma question était plutôt de savoir, s'il y a deux
éléments avec le même id, lequel sera récupéré par un getElementById.
Mais comme je vais changer l'id avant l'insertion la question ne se
posera pas, en fait.


Je ne pense pas qu'il y ait une règle absolue, le traitement des erreurs dans
le document doit être "implementation dependent". Comme il a été dit dans le
fil, le premier rencontré dans le parcours de l'arbre est généralement
retourné.

J'ai instinctivement tendance à me méfier des variables globales, même
quand je ne le devrais pas. Après réflexion, je crois que je vais suivre
ton conseil (pas pour le fieldset, en revanche, car lui changera d'un
appel à l'autre).


Pourquoi ? Tu en utilises de toute façon ! Les fonctions javascript en font
partie. La seule précaution, que tu dois connaître, est d'effectuer leur
affectation après le chargement de la page dans un gestionnaire onload si
les variables référencent un élément HTML.

var new_div = ref_div.cloneNode();
fieldset.appendChild(new_div);
// mêmes questions que précédemment : ai-je le droit de faire ça ?


Et même réponse, manipule-le avant l'insertion. Ça évitera au navigateur de
redessiner éventuellement plusieurs fois les contrôles...


.... sauf que parfois cela ne marche pas sous IE, par exemple pour
l'histoire de l'attribut "checked" dans une checkbox...


Je n'y pensais plus au checked remis à false lors de l'insertion...
Moralité : tester et retester... (cf. autre article, mêmes jour et heure)

--
Y.D.



1 2