OVH Cloud OVH Cloud

Ajouter des elements de facon dynamique

16 réponses
Avatar
Olivier Miakinen
[ publication croisée sur fciwa et fclj, suivi sur fcl.javascript ]


Bonjour,

Je suis en train de reprendre un code JavaScript un peu vieillot, et
j'aimerais le moderniser tout en l'améliorant.


En particulier, j'essaye de faire la chose suivante : au moment de la
génération de la page HTML, rajouter N <div> dans un formulaire, chaque
<div> (appelons-le "conteneur") contenant la chose suivante :
- un <input type="checkbox"> suivi d'une ligne de texte ;
- un <button type="button"> ;
- un autre <div> (appelons-le "details") contenant des détails sur
l'ensemble.

Mon idée est que cliquer sur le bouton appelle une fonction JavaScript
qui va ouvrir ou fermer le <div> "details" en changeant sa propriété
style.display.

Je ne tiens pas particulièrement à ce que cela fonctionne sur Netscape 4
ou Internet Explorer 4, mais je voudrais que cela marche au moins sur
les navigateurs modernes (Netscape 7, Mozilla, Opera, ...) sans oublier
Internet Explorer 6.


La première version du code JavaScript générait le HTML à coups de
document.write() ou document.writeln() mais cela ne me semble pas très
propre, et j'aimerais bien utiliser plutôt des trucs du genre de
document.createElement(), xxx.appendChild(), etc. si c'était possible.
J'ai réussi à faire marcher la chose dans Netscape 7, mais cela ne
marche malheureusement pas avec IE6. Comment avancer ?


Note : si la réponse est RTFM, je veux bien, mais justement je cherche
un bon manuel. Le meilleur que j'aie trouvé jusqu'à présent est
<http://fr.selfhtml.org/> mais je n'y ai pas trouvé de spécifications
complètes. Je n'arrive pas non plus à trouver sur <http://www.w3.org>.

--
Olivier Miakinen
Non, monsieur le juge, je vous le jure : jamais je n'ai cité
Bruxelles dans ma signature.

10 réponses

1 2
Avatar
Le Fou
Olivier Miakinen <om+ a écrit

Mon idée est que cliquer sur le bouton appelle une fonction JavaScript
qui va ouvrir ou fermer le <div> "details" en changeant sa propriété
style.display.


Et document.getElementById('toto').style.display = 'none' (ou block), ça ne
fonctionne pas ?

--
A'tchao

Le Fou
http://perso.club-internet.fr/ehiller/
http://club.exocet.free.fr/
http://www.ffessm-cd84.com/

Avatar
YD
[ publication croisée sur fciwa et fclj, suivi sur fcl.javascript ]


Bonjour,

Je suis en train de reprendre un code JavaScript un peu vieillot, et
j'aimerais le moderniser tout en l'améliorant.


En particulier, j'essaye de faire la chose suivante : au moment de la
génération de la page HTML, rajouter N <div> dans un formulaire, chaque
<div> (appelons-le "conteneur") contenant la chose suivante :
- un <input type="checkbox"> suivi d'une ligne de texte ;
- un <button type="button"> ;
- un autre <div> (appelons-le "details") contenant des détails sur
l'ensemble.


Si j'ai bien compris les div sont ajoutés par script ? Dans ce cas, je
suggérerai d'en inclure un caché (display: none) et de le cloner autant
de fois que nécessaire (il existe une méthode DOM cloneNode() pour cela),
changer l'attribut id du nouveau div et l'insérer dans le document

Mon idée est que cliquer sur le bouton appelle une fonction JavaScript
qui va ouvrir ou fermer le <div> "details" en changeant sa propriété
style.display.


Cela fonctionne sur tous les navigateurs cités plus bas.

Je ne tiens pas particulièrement à ce que cela fonctionne sur Netscape 4
ou Internet Explorer 4, mais je voudrais que cela marche au moins sur
les navigateurs modernes (Netscape 7, Mozilla, Opera, ...) sans oublier
Internet Explorer 6.


La première version du code JavaScript générait le HTML à coups de
document.write() ou document.writeln() mais cela ne me semble pas très
propre, et j'aimerais bien utiliser plutôt des trucs du genre de
document.createElement(), xxx.appendChild(), etc. si c'était possible.
J'ai réussi à faire marcher la chose dans Netscape 7, mais cela ne
marche malheureusement pas avec IE6. Comment avancer ?


Surprenant ! IE6 supporte les méthodes citées. Les problèmes surviennent
principalement dans l'ajout d'attributs, en particulier les gestionnaires
d'événements pour lesquels il vaut mieux utiliser une syntaxe (conforme
au DOM2 HTML si l'élément accepte ces attributs) du type
elt.onclick=function(){//le code}, plutôt que d'utiliser
setAttribute("onclick", "//le code") ou encore les méthodes dédiées aux
gestionnaires d'événements DOM2 qui ne sont pas supportées par IE6.

Note : si la réponse est RTFM, je veux bien, mais justement je cherche
un bon manuel. Le meilleur que j'aie trouvé jusqu'à présent est
<http://fr.selfhtml.org/> mais je n'y ai pas trouvé de spécifications
complètes. Je n'arrive pas non plus à trouver sur <http://www.w3.org>.


Sur w3.org je conseillerai le DOM2 Core et le DOM2 HTML pour leur
annexe "ECMAScript Language Binding". Le DOM2 Event Model est intéressant
mais n'est absolument pas implémenté dans IE6...

--
Y.D.

Avatar
ASM

En particulier, j'essaye de faire la chose suivante : au moment de la
génération de la page HTML, rajouter N <div> dans un formulaire, chaque
<div> (appelons-le "conteneur") contenant la chose suivante :
- un <input type="checkbox"> suivi d'une ligne de texte ;
- un <button type="button"> ;
- un autre <div> (appelons-le "details") contenant des détails sur
l'ensemble.


tu as donc cloneNode pour "cloner" ton div de base
et dans la foulée, avant de le placer, tu peux
jouer avec le clone pour en changer tout ce que tu veux.
Finalement tu le displaies et le visibilises

Bien sûr mon IE (5.1 vieux Mac) a un peu ses vapeurs sur ces trucs
un peu modernes pour lui, mais avec Mozilla ça baigne.

IE : On a un peu besoin de coder à l'ancienne pour les modifs du clone
et donc pour faire propre (et prèt pour le futiur-présent)
on double le code (le cracra pour IE le nodal pour les autres)

j'aimerais bien utiliser plutôt des trucs du genre de
document.createElement(), xxx.appendChild(), etc. si c'était possible.
J'ai réussi à faire marcher la chose dans Netscape 7, mais cela ne
marche malheureusement pas avec IE6. Comment avancer ?


comme dit + haut : si ça n'marche pô faut doubler le code
(à mon idée)
On le faisait bien à l'époque des NC4 et IE4 ...

je cherche un bon manuel


pourtant il m'avait semblé qu'avec cloneNode et/ou appendChild
sur Google on avait le choix de l'info

. Le meilleur que j'aie trouvé jusqu'à présent est
<http://fr.selfhtml.org/> mais je n'y ai pas trouvé de spécifications
complètes. Je n'arrive pas non plus à trouver sur <http://www.w3.org>.


Des spécifications ?
me semble que selfhtml a une page où *tout* est dit, c'est complet.
http://www.toutenligne.com/documentation/html/javascript/objets/node.htm
Ne reste qu'à apprivoiser la chose ;-)
D'ailleurs, ils disent bien que rien n'oblige à tout faire par cette voie,
si c'est plus facile ou plus vite fait autrement : faut l'faire.

Avatar
Olivier Miakinen
Olivier Miakinen <om+ a écrit

Mon idée est que cliquer sur le bouton appelle une fonction JavaScript
qui va ouvrir ou fermer le <div> "details" en changeant sa propriété
style.display.


Et document.getElementById('toto').style.display = 'none' (ou block), ça ne
fonctionne pas ?


Si fait ! Si fait ! C'est autre chose qui ne fonctionne pas. D'ailleurs
je vais répondre à YD sur ce point car c'est lui ou elle qui a signalé
un problème, ainsi qu'une ébauche de solution.


Avatar
Olivier Miakinen

Si j'ai bien compris les div sont ajoutés par script ? Dans ce cas, je
suggérerai d'en inclure un caché (display: none) et de le cloner autant
de fois que nécessaire (il existe une méthode DOM cloneNode() pour cela),
changer l'attribut id du nouveau div et l'insérer dans le document


Je n'ai pas encore essayé cela, mais je vais regarder une fois que
j'aurai réglé le premier problème.

Mon idée est que cliquer sur le bouton appelle une fonction JavaScript
qui va ouvrir ou fermer le <div> "details" en changeant sa propriété
style.display.


Cela fonctionne sur tous les navigateurs cités plus bas.


Ok.

[...]
J'ai réussi à faire marcher la chose dans Netscape 7, mais cela ne
marche malheureusement pas avec IE6. Comment avancer ?


Surprenant ! IE6 supporte les méthodes citées. Les problèmes surviennent
principalement dans l'ajout d'attributs, en particulier les gestionnaires
d'événements pour lesquels il vaut mieux utiliser une syntaxe (conforme
au DOM2 HTML si l'élément accepte ces attributs) du type
elt.onclick=function(){//le code}, plutôt que d'utiliser
setAttribute("onclick", "//le code") ou encore les méthodes dédiées aux
gestionnaires d'événements DOM2 qui ne sont pas supportées par IE6.


Eh bien voilà exactement mon problème. J'ai essayé tout un tas de trucs,
la plupart ne fonctionnant pas du tout, certains ne fonctionnant que sur
Mozilla. Des trois seuls essais qui fonctionnent sur IE (dont deux qui
fonctionnent aussi sur Mozilla), aucun ne m'a permis de passer un
paramètre variable.

element2.onclick = "Dynamique(1)"; // rien
element2.onclick = "Dynamique()"; // rien
element2.setAttribute("onclick", "Dynamique(1)"); // Moz seul
element2.setAttribute("onclick", "Dynamique"); // rien
element2.onclick = Dynamique; // les deux
element2.onclick = eval("Dynamique("+1+")"); // trop tôt
element2.onclick = eval("eval(Dynamique("+1+"))"); // trop tôt
element2.onclick = 'eval("Dynamique("'+1+'")")'; // rien
element2.setAttribute("onclick", Dynamique); // IE seul
element2.addEventListener("click", Dynamique, true); // Moz seul
element2.onclick=function(){ Dynamique(1); }; // les deux

Tu noteras que le dernier essai est celui de ta réponse. Bon, en fait,
j'ai fini par trouver une solution, mais qui me semble tellement laide
que je me demande si on ne peut vraiment pas l'améliorer :

eval("element2.onclick=function(){ Dynamique("+idx+"); }");


Avatar
YD

element2.onclick = Dynamique; // les deux


onclick attend une référence de fonction donc OK.

element2.onclick=function(){ Dynamique(1); }; // les deux

Tu noteras que le dernier essai est celui de ta réponse. Bon, en fait,
j'ai fini par trouver une solution, mais qui me semble tellement laide
que je me demande si on ne peut vraiment pas l'améliorer :

eval("element2.onclick=function(){ Dynamique("+idx+"); }");


Le problème est le passage d'un paramètre à la fonction ? Le eval est mal
considéré et, à vrai dire, au moins les 3/4 du temps inutile. C'est le cas
ici. Pour déclarer une fonction on utilise soit l'instruction function soit
le constructeur Function (avec majuscule) qui attend une chaîne de
caractères en argument. J'écrirai donc plutôt :

element2.onclick=Function("Dynamique("+idx+");");

D'un autre côté, si idx sert uniquement à repérer l'élément cliqué, c'est
un peu inutile, puisque le onclick a comme contexte (son 'this') l'objet
appelant. En écrivant ainsi :

element2.onclick=function(){Dynamique(this);};

dans Dynamique le paramètre récupéré est l'objet HTML cliqué dont on peut
interroger l'id, le parentNode et tutti quanti.

Un exemple valant mieux...

<HTML><HEAD>
<script type="text/javascript">
onload= function(){
var allBtns=document.getElementsByTagName("BUTTON");
for( var i=0; i< allBtns.length;i++)
allBtns[i].onclick=Function("Dynamique(this);");
// ou allBtns[i].onclick=function(){Dynamique(this);};
}
function Dynamique(obj){document.getElementById("witness").innerHTML=obj.id;}
</script>

</HEAD>
<BODY>
<button id='truc'>Clic...</button><br>
<button id='machin'>Clic...</button><br>
<button id='bidule'>Clic...</button><br>
<P id="witness">&nbsp;</P></BODY></HTML>


--
Y.D.

Avatar
Olivier Miakinen

[...]
Eh bien voilà exactement mon problème. [...]


En voilà un autre. Je crée un <input type="checkbox"> et je voudrais
qu'il soit coché par défaut. Chacune des cinq lignes suivantes
fonctionne avec Mozilla, mais aucune avec Internet Explorer :

element2.setAttribute("checked", "checked");
element2.setAttribute("checked", true);
element2.checked = "checked";
element2.checked = true;
eval('element2.checked = "checked"');

Avatar
Olivier Miakinen

eval("element2.onclick=function(){ Dynamique("+idx+"); }");


Le problème est le passage d'un paramètre à la fonction ? Le eval est mal
considéré et, à vrai dire, au moins les 3/4 du temps inutile.


Merci, tu confirmes mon intuition.

Pour déclarer une fonction on utilise soit l'instruction function soit
le constructeur Function (avec majuscule) qui attend une chaîne de
caractères en argument.


Après m'avoir appris l'existence de function() tu viens de m'apprendre
celle de Function(). Il faudra vraiment que je me trouve une bonne doc
pour ne pas poser de questions trop basiques dans ce groupe.

J'écrirai donc plutôt :

element2.onclick=Function("Dynamique("+idx+");");


Excellent, j'essaye tout de suite.

D'un autre côté, si idx sert uniquement à repérer l'élément cliqué, c'est
un peu inutile, puisque le onclick a comme contexte (son 'this') l'objet
appelant. En écrivant ainsi :

element2.onclick=function(){Dynamique(this);};

dans Dynamique le paramètre récupéré est l'objet HTML cliqué dont on peut
interroger l'id, le parentNode et tutti quanti.


Ça me semble très bien aussi. Il se trouve que j'aurai plusieurs
paramètres à récupérer dans un tableau à partir du 'idx', donc je
vais peut-être rester sur la première de tes propositions. Une autre
possibilité serait de mettre l'index quelque part dans l'élément,
mais je ne vois pas trop l'intérêt d'une indirection (this -> index).

Un exemple valant mieux... [...]


Un grand merci pour cela.


Avatar
Cléo
Ma contribution ...

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script language="javascript">
function toggle(elt)
{
var span2 = elt.childNodes.item(1);
if(span2.style.display=="") span2.style.display = "none";
else span2.style.display = "";
}
</script>
</head>
<body>
<div onclick="toggle(this)"><span>1</span><span>coucou</span></div>
<div onclick="toggle(this)"><span>2</span><span>coucou</span></div>
<div onclick="toggle(this)"><span>3</span><span>coucou</span></div>
</body>
</html>

J'ai testé sur ie6, netscape 7, opera 7, firefox 1.0, mozilla 1.7, k-meleon
0.8.2 ...
par contre je ne suis pas sûr que ça corresponde à ton problème ...


Amicalement.
--
Cléo.
Avatar
YD

En voilà un autre. Je crée un <input type="checkbox"> et je voudrais
qu'il soit coché par défaut. Chacune des cinq lignes suivantes
fonctionne avec Mozilla, mais aucune avec Internet Explorer :

element2.setAttribute("checked", "checked");
element2.setAttribute("checked", true);
element2.checked = "checked";
element2.checked = true;
eval('element2.checked = "checked"');


Désolé de te contredire, tout ces écritures fonctionnent dans IE !

Mais je me suis aperçu d'une bizarrerie grâce à ton problème, c'est
que cela ne fonctionne *qu'après* avoir inséré la checkbox dans l'arbre
HTML ! IE refuse de considérer cochée la case tant qu'elle n'est que
"virtuelle". Pour être plus près de ce que j'ai pu voir en déboguant, IE
positionne correctement la propriété checked à true avant, mais la
repositionne à false au moment de l'insertion dans le document...

Seule parade donc positionner le checked après le appendChild ou le
insertBefore.

--
Y.D.

1 2