Probleme : innerHTML + DOM + fonctions à paramètre [Résolu]

Signaler
Messages postés
16
Date d'inscription
mercredi 17 mars 2010
Statut
Membre
Dernière intervention
10 janvier 2012
-
Messages postés
16
Date d'inscription
mercredi 17 mars 2010
Statut
Membre
Dernière intervention
10 janvier 2012
-
Bonjour tou le monde
je fais un programme qui insère des lignes de formulaire en cliquant sur un bouton(Nouveau),


La ligne contient :
zone de texte associé à un calendrier pour saisir les date:
deux liste déroulante
une zone de texte qui change de "value" quand les listes déroulantes changent.

l'insertion se passe à merveille, mais puisque j'ai utilisé innerHTML, il y a une différence entre IE et FF, sur IE ça marche quand j'insère une ligne je la remplie et je clique sur mon Bouton pour insérer une deuxième ligne, j'ai la nouvelle et c'est reparti pour la remplir, je peux à tout moment revenir sur les lignes déjà insérée et les modifier, le malheur c'est avec FireFox, la première ligne s'insère normalement, je la rempli, mais une fois je clique sur le bouton d'insertion pour insérer une nouvelle ligne, il est bien insérée mais toutes les ligne précédente sont réinitialisée, ça veut dire que tout ce que j'ai saisi disparait (les liste déroulante reviennent sur l'option selected parDefaut, les zone de texte sont vide) et le calendrier n'apparait plus quand je clique sur la zone de texte de la date (onfocus engendre l'apparition du calendrier), bref sur FF ça ne marche que sur la dernière ligne insère, les précédentes sont toutes réinitialisées.
Après lecture des tuto j'ai essayé de faire l'insertion par DOM, par contre je rencontre un gros problème :colere: , la majorité de mes fonctions qui sont associées à des évènement des objets insèré contient des paramètred alors que dans ce tuto j'ai que addEventListner(Event,fonction,true) ou addAttachment(onEvent,fonction) SANS PARAMÈTRE, après tout ce long discours ma question est :
Comment associer des fonction qui contient des paramètre à des évènement inséré?



P.S : si besoin du code je peux le copier mais je vous préviens il est troop long (surtout le calendrier)

11 réponses

Messages postés
3426
Date d'inscription
lundi 26 décembre 2005
Statut
Membre
Dernière intervention
14 janvier 2011
17
HOU LA LA !
pléthore de remarques mais isolons d'abord l'objet de ton problème à savoir innerHTML.
Prenons ta fonction inserer()
function inserer() {
  var m =  document.getElementsByTagName("label").length;
  n = Math.floor(m / 4);
  var contenu = document.getElementById("insertion").innerHTML;
  insertion.innerHTML = contenu + '<div id="ligne ' //et la suite...
}
c'est une utilisation malsaine de innerHTML que tu fais là...ce que l'on peut qualifier d'effet de bord, c'est pour cela qu'il n'est pas conseillé de l'utiliser sauf peut être lors de l'initialisation.

Le plus clean serait de créer via des document.createElement( tag_balise ) puis des oParent.appendChild(new_element) tous tes élément, code lourd mais respectueux du DOM de l'élément modifié.

Une alternative en ce qui te concerne et de créer une nouvelle DIV et de lui inclure tous les éléments via innerHTMl, puis de l'ajouter via un appendChild
cela peut donner
//-----------------
function inserer() {
  var m  = document.getElementsByTagName("label").length;
  n = Math.floor(m / 4);
  //-- Get Element parent
  var oDiv = document.getElementById("insertion");
  //-- Creation de la DIV a ajouter
  var oNew = document.createElement("div");
  //-- Affectation de l'ID
  oNew.id  = "ligne " + n;
  //-- Ajout de l'element
  oDiv.appendChild( oNew)
  //-- Ajout du contenu
  oNew.innerHTML = '<span id="calendrier' //et la suite...
}

Voila pour commencer, les autres remarques on verra après...

;O)
Messages postés
3426
Date d'inscription
lundi 26 décembre 2005
Statut
Membre
Dernière intervention
14 janvier 2011
17
j'ai oublié tu peux rajouter à la panoplie
document.getElementsByTagName(nom_balise) qui te renvoie les éléments correspondant à nom_balise
var oParent = document.getElementById("ligne " + numb);
var oSelect = oParent.getElementsByTagName("SELECT");
alert(oSelect[0].innerHTML);


Bien plus d'info sur https://developer.mozilla.org/fr/JavaScript, entre autres...

;O)
Messages postés
3426
Date d'inscription
lundi 26 décembre 2005
Statut
Membre
Dernière intervention
14 janvier 2011
17
Bonjour,
si besoin du code je peux le copier mais je vous préviens il est troop long (surtout le calendrier)
plutôt que le calendrier, au moins la fonction d'insertion de ta ligne et la façon dont elle est appelée, pas plus dans un premier temps.

;O)
Messages postés
16
Date d'inscription
mercredi 17 mars 2010
Statut
Membre
Dernière intervention
10 janvier 2012

plutôt que le calendrier, au moins la fonction d'insertion de ta ligne et la façon dont elle est appelée, pas plus dans un premier temps.


je vais le coper(le calendrier inclus) car elle présente aussi les même symptômes dans FireFox pour l'utiliser suffit de cliquer sur la zone de texte

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
  
<style>
body{
background-image : url("bg-logo.jpg");
background-attachment: fixed;
}
</style>
<script language="javascript">
moisX=["","Janvier","Fevrier","Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Decembre"];
JourM=["Di","Lu","Ma","Me","Je","Ve","Sa"];

var fermable_microcal=true;
var select_old= null;

var startWeek=0;//debut de la semaine 0=dim,1=lun,...
var jourPause={0:true,6:true}; //jour de pause de la semaine
var jourFeriee={"1-1":"jour an","1-5":"fête du travail","8-5":"armistice","14-7":"fête nationale","15-8":"ascencion","1-11":"armistice","11-11":"toussain","25-12":"noel"};

//structure la date 
function strucDate(dateX) 
{return {"pos":dateX.getDay(),"jour":dateX.getDate(),"mois":dateX.getMonth()+1,"annee":dateX.getFullYear()};}


var dateS= strucDate(new Date());//date Selectionné
var dnow= strucDate(new Date());//date actuelle


//retourne le ième jour du 1er du mois
function premJourMois(mois,annee) 
{return (new Date(annee,mois-1,1).getDay());}
//retourne le jour max du mois
function JmaxMois(mois,annee) 
{return (new Date(annee,mois,0).getDate());}


/* Test une date si elle est correct...spécial killer*/
function testTypeDate(dateEntree)
{
tst=false;
try
{rc=dateEntree.split("/");nd=new Date(rc[2],(rc[1]-1),rc[0]);
tst=(rc[2]>1800&&rc[2]<2200&&rc[2]==nd.getFullYear()&&rc[1]==(nd.getMonth()+1)&&rc[0]==nd.getDate());
} catch(e) {}
return tst;
}

//selection de la zone avec la souris
function choix(koi,code)
{
if (code) 
{  select_old= koi.style.background;
   koi.style.background ='#c0c0FF';
}
else 
{
koi.style.background =select_old;
}
}


function testTravail(oldX,xx,jj,mm,aa)
{
styleX="font-family:Tahoma;font-size:10px;text-align:center;";
styleX+=(oldX)?"":"color:#e0e0e0;";
styleX+="cursor:hand;border-right:1px #e0e0e0 solid;border-bottom:1px #e0e0e0 solid;";
if (jourPause[xx]||jourFeriee[jj+"-"+mm]!=null) styleX+="background:#f0f0f0;";
if (jj==dnow.jour&&mm==dnow.mois&&aa==dnow.annee) styleX+="border:2px red solid;";
return styleX;
}

//test si année bissextile
function bissextile(annee) {
return (annee%4==0 && annee %100!=0 || annee%400==0);
}

//Retourne le nombre de jour depuis le 1er janvier (num de semaine)
function nbJAnnee(dateX){
var nb_mois=[,0,31,59,90,120,151,181,212,243,273,304,334];
j=dateX.jour ; m=dateX.mois ; a=dateX.annee;
nb=nb_mois[m]+j-1 ;
if (bissextile(a) && m>2) nb++;
return nb;
}

//affiche le calendrier
function view_microcal(actif,ki,source,mxS,axS)
{
if (actif)
{
//decalage du mois su on clique sur -/+
if (mxS!=-1) 
{
clearTimeout(cc);
ki.focus();
fermable_microcal=true;
dateS.mois=mxS;
dateS.annee=axS;
if (dateS.mois<1) {dateS.annee--;dateS.mois+=12;}
if (dateS.mois>12) {dateS.annee++;dateS.mois-=12;}
}
//init
Dstart=(premJourMois(dateS.mois,dateS.annee)+7-startWeek)%7;
jmaxi=JmaxMois(dateS.mois,dateS.annee);
jmaxiAvant=JmaxMois((dateS.mois-1),dateS.annee);
//si on veux ajouter le numero de la semaine ...
//idxWeek=parseInt(nbJAnnee(strucDate(new Date(dateS.mois+'-01-'+dateS.annee)))/7,10)+1;

ymaxi=parseInt((jmaxi+Dstart+1)/7,10);

//generation du tableau
//--entête
htm="\";
htm+=\"-, \";
htm+=\" "+moisX[dateS.mois]+" "+dateS.annee+", \";
htm+=\"+, \";
//--corps
htm+=\"----
\";
//affichage des jours DLMMJVS
for (x=0;x<7;x++)
htm+=\""+JourM[(x+startWeek)%7]+", \";
htm+=\"\"

//------------------------
for (y=0;y<=ymaxi;y++)
{
htm+=\"----
\";
for (x=0;x<7;x++)
{
idxP=y*7+x-Dstart+1;   //numero du jour
aa=dateS.annee;
xx=(x+startWeek)%7;
//jour du mois précedent
if (idxP<=0)
{
jj=idxP+jmaxiAvant;mm=dateS.mois-1;
if (mm==0)
{mm=12;aa--;}
htm+=\""+jj+", \";
}
else if (idxP>jmaxi) //jour du mois suivant
{
jj=idxP-jmaxi;mm=dateS.mois+1;
if (mm==13)
{mm=1;aa++;}

htm+=\""+jj+", \";}
else //jour du mois en cours
{
jj=idxP;mm=dateS.mois;
htm+=\""+jj+", \";}
}
htm+=\"\"
}//-------------------------
htm+="
"
//affiche le tableau
source.innerHTML=htm;
source.style.visibility="";
} else
{
//ferme le calendrier
if (fermable_microcal) 
   cc=setTimeout(source.id+".style.visibility='hidden'",500);
}
}

</script>
<SCRIPT LANGUAGE="JavaScript">
<!--

var i=0,j=0;
function compZero(nombre) {
    return nombre < 10 ? '0' + nombre : nombre;
}

function date() {
    var infos = new Date();
var str;
str='['+compZero(infos.getDay())+' - '+compZero(infos.getMonth())+' - '+compZero(infos.getFullYear())+']';
return str;
}


var marge = 445;
function inserer(){
var m = document.getElementsByTagName("label").length;
n = Math.floor(m/4);


var contenu = document.getElementById("insertion").innerHTML;
insertion.innerHTML = contenu+'
                                     <label>ALLEE    </label>    <select id="listeD '+n+'" onchange="afficher('+n+');" >	<option value="agadir">Agadir</option><option value="hoceima">Al Hoceima</option>		<option value="casa" selected>Casablanca</option><option value="dakhla">Dakhla</option><option value="jdida">El Jadida</option>		<option value="rachidiya">Errachidia</option>	</select>     <select id="listeA '+n+'" onchange="afficher('+n+');"><option value="agadir">Agadir</option><option value="hoceima">Al Hoceima</option><option value="casa" selected>Casablanca</option><option value="dakhla">Dakhla</option>	<option value="jdida">El Jadida</option><option value="rachidiya">Errachidia</option></select>                                                                     Supprimer
                                    <label>RETOUR</label>        <label>Casablanca</label>             <label>Casablanca</label><hr />
 ';
 

}
function afficher(numb){
var D = document.getElementById("ligne "+numb);
var i = D.childNodes[5].selectedIndex;
var j = D.childNodes[7].selectedIndex;
if(isNaN(parseInt(distance[i][j])))
D.childNodes[9].setAttribute("value","------");
else
D.childNodes[9].setAttribute("value",2*parseInt(distance[i][j])+" Km");
D.childNodes[20].innerHTML = D.childNodes[5].options[i].innerHTML;
D.childNodes[18].innerHTML = D.childNodes[7].options[j].innerHTML;


}

var distance = new Array(
new Array("----","1091 Km","511 Km","1173 Km","417 Km","661 Km"),
new Array("1091 Km","----","539 Km","2264 Km","632 Km","616 Km"),
new Array("511 Km","539 Km","----","1173 Km","417 Km","545 Km"),
new Array("1173 Km","2264 Km","1684 Km","----","1590 Km","1954 Km"),
new Array("417 Km","632 Km","417 Km","1590 Km","----","506 Km"),
new Array("661 Km","616 Km","545 Km","1954 Km","506 Km","----"));
//-->
</SCRIPT>
</HEAD>

,

----

Espace agent comptable
,

----
Nom : XXXXX, ----

----
Prénom : XXXXX, ----

----
Tél : XXXXX, ----

----
Voiture : XXXXX, ----

----
Type : XXXXX, ----

----
CV : XXXXX, ----

----

Date,
Type,
Depart,
Arrivée,
Distance,
Indemnité,
---------,

----

<form id="formulaire" name="formulaire" action="" method="get">

</form>



</HTML>
Messages postés
16
Date d'inscription
mercredi 17 mars 2010
Statut
Membre
Dernière intervention
10 janvier 2012

MAIS t'es un genie !!!!!!!!!!!!!! vraiment j'ai jamais pensé a mélanger entre DOM et innerHTML, pour moi je les considère comme ennemie ces deux là, mais vraiment je viens de tester sur ça marche sur FF et IE, tous mes respect, si tu as d'autre remarques ça me sera d'une grande utilité d'un génie comme vous, encore merci

PS: j'étais entrain de créer toute la ligne via DOM et comme tu le sait déjà c'est pas facile surtout que les deux listes déroulantes que j'ai mis sont juste a titre d'exemple, mes deux vraie liste sont assez long^^

ENCORE MERCI
Messages postés
3426
Date d'inscription
lundi 26 décembre 2005
Statut
Membre
Dernière intervention
14 janvier 2011
17
...surtout que les deux listes déroulantes que j'ai mis sont juste a titre d'exemple, mes deux vraie liste sont assez long^^...
dans ces cas il ne faut pas hésiter à créer une fonction, voir le créer en PHP, si BdD par exemple, et le cloner ensuite puis l'ajouter.

Cela vaut pour la ligne entière d'ailleurs, une ligne type masquée à l'affichage puis clonée direct et dont on modifie ensuite les IDs et/ou NAMEs si l'on doit les envoyer.
Cette solution présente l'avantage de la maintenance si une modification doit intervenir dans la ligne à ajouter.

Une autre remarque pendant que l'on y est, dans la fonction afficher(numb) il faut se méfier de l'accés aux différents éléments par D.childNodes[5], les navigateurs n'ayant pas tous la même façon de hiérarchiser le DOM, mets un espace entre deux éléments de ta ligne et tu verras que cela va planter sous FireFox
;O)
Messages postés
16
Date d'inscription
mercredi 17 mars 2010
Statut
Membre
Dernière intervention
10 janvier 2012

oui j'y avait pensé dès le début, mais le prof a exigé que ça soit en JS pour éviter le rechargement de la page, par contre le dernier point me rend perplexe car je suis déjà tombé sur problème et pour être franc les indice que j'ai mis dans childNodes[i] sont mis après parcours indice par indice jusqu'à ce que je tombe sur les objet que je cherche (j(utilise alert(Objet.childNodes[i].innerHTML), je ne sais pas comment passer d'un composant aux suivant, j'ai utilisé Noeud.nextSibiling qui donne le noeud suivant de Noeud mais elle ne fait que childNodes[i+1]. si tu as une idée comment passer d'un composant à un autre sans passer par les espacement fait moi part :)
Messages postés
3426
Date d'inscription
lundi 26 décembre 2005
Statut
Membre
Dernière intervention
14 janvier 2011
17
glisse ce petit morceau de code en début de fonction afficher(numb)
var oParent = document.getElementById("ligne " + numb);
var oChild = oParent.childNodes; // liste de tous les enfants
var szTmp = "";
for( var i 0, nb oChild.length; i < nb; i++){
  szTmp += i + '->' +oChild[i].nodeName +'->' +oChild[i].nodeType +'\n';
}
alert( szTmp);
et observes, tu peux bien sur afficher ce que bon te semble

si tu as une idée comment passer d'un composant à un autre sans passer par les espacement fait moi part
comme indiqué ci dessus avec un test sur le nodeType, si 1 on prend en compte SiNON on fait rien, par exemple.

le mieux, me semble t-il, reste une ID et/ou NAME, si transmit, et la récupération traditionnelle.
;O)
Messages postés
16
Date d'inscription
mercredi 17 mars 2010
Statut
Membre
Dernière intervention
10 janvier 2012

très bonne méthode, j'ai fait la connaissance de nodeType qui retourne soit 1 soit 3 (dans mon cas) merci , il reste plus que faire une fonction qui peut même me retourner si je suis un input ou un select, merci énormément tu me sauve la vie.
Messages postés
3426
Date d'inscription
lundi 26 décembre 2005
Statut
Membre
Dernière intervention
14 janvier 2011
17
nodeType peut prendre les valeurs de 1 à 12.

...et observes, tu peux bien sur afficher ce que bon te semble ...
tu peux mettre oChild[ i].tagName

penses à mettre en Réponse acceptées !certains point pouvant aider d'autres personnes.

;O)
Messages postés
16
Date d'inscription
mercredi 17 mars 2010
Statut
Membre
Dernière intervention
10 janvier 2012

Merci enormément encore, je vais mettre resolu, passe une superbe soirée