IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Closure qui me rend fou


Sujet :

JavaScript

  1. #1
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut Closure qui me rend fou
    Bonjour,

    Voici ce que j'aimerais faire :
    J'ai un UL que je popule dynamiquement avec des LI selon des données (ici l'array artids).
    Quand je clique sur un LI, j'aimerais avoir le "numéro" du LI (1 pour le premier, etc).

    Mais pour une raison qui m'échappe (je suspecte le bug), le code suivant ne marche pas !!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
    <title>IP</title>
    </head>
    <body bgcolor="#ffffff">
     
    <ul id="ull">
    </ul>
    <script language="javascript" type="text/javascript">
    <!--
     
    var ul = document.getElementById("ull");
    var artids = [
    	{ "firstChild" : { "data" : "a" } }
    	, { "firstChild" : { "data" : "b" } }
    	, { "firstChild" : { "data" : "c" } }
    ];
     
    for(var x = 0; x < artids.length; x++) {
    	var artid = artids[x].firstChild;
     
    	var v = "";
    	do {
    		if (artid.data) {
    			v += artid.data;
    		}
    	} while (artid = artid.nextSibling);
     
    	var liElem = document.createElement("li");
    	liElem.id = x;
    	var xCopy = x;
    	fMouseDown = function(evt) {
    //				CurrentPage.suggestChange(input, liElem);
    //				alert(evt.currentTarget.id);
    		alert(xCopy);
    	}
    	liElem.onmousedown = fMouseDown;
     
    	var txt = document.createTextNode(v);
     
    	liElem.appendChild(txt);
     
    	ul.appendChild(liElem);
    }
    </script>
     
    </body>
    </html>
    Pourtant je met bien la valeur dans une variable (xCopy) qui n'existe qu'à chaque itération de la boucle.

    Merci pour vos lumières.

  2. #2
    Rédacteur/Modérateur

    Avatar de SpaceFrog
    Homme Profil pro
    Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Inscrit en
    Mars 2002
    Messages
    39 640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2002
    Messages : 39 640
    Points : 66 669
    Points
    66 669
    Billets dans le blog
    1
    Par défaut
    ce ne serait pas a cause d'un conflit de nommage ? firstChild etant un mot réservé de javascript ? data aussi ?

  3. #3
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2008
    Messages
    23 647
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Points : 91 220
    Points
    91 220
    Billets dans le blog
    20
    Par défaut
    Pourtant je met bien la valeur dans une variable (xCopy) qui n'existe qu'à chaque itération de la boucle.
    Oui, mais xCopy est une référence à x et évolue en même temps

    Voir à ce sujet : Comment attribuer à des objets un onclick faisant appel à une variable de boucle ?

  4. #4
    Expert confirmé
    Avatar de RomainVALERI
    Homme Profil pro
    POOête
    Inscrit en
    Avril 2008
    Messages
    2 652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : POOête

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 652
    Points : 4 164
    Points
    4 164
    Par défaut
    C'est valide un id entièrement numérique ? Ca devrait mais je ne sais pas pourquoi ca me fait douter... Je vais vérifier...

    edit : un id doit commencer par une lettre, non un chiffre : serait-ce une piste ?

  5. #5
    Rédacteur
    Avatar de marcha
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2003
    Messages
    1 571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 571
    Points : 2 351
    Points
    2 351
    Par défaut
    Pour la closure, qqch comme ça devrait régler le problème

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    liElem.onmousedown = function(i) {
      return function(evt) {
        alert(i);
      }
    }(x); // appel immédiat de la fonction englobante en passant x et créant une closure (variable i différente à chaque itération et copiant x)
    Maintenant il me semble qu'il y a un autre problème, quand je lit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    } while (artid = artid.nextSibling);
    Il me semble que tu confonds le DOM et un objet JSON.

  6. #6
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2008
    Messages
    23 647
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Points : 91 220
    Points
    91 220
    Billets dans le blog
    20
    Par défaut
    Citation Envoyé par marcha
    Maintenant il me semble qu'il y a un autre problème, quand je lit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    } while (artid = artid.nextSibling);
    Il me semble que tu confonds le DOM et un objet JSON.
    Non : si l'élément a un nextSibling, l'affectation renvoie le nouvel élément et on réitère, si l'élément n'a pas de nextSibling, la propriété renvoie null, ce qui fait sortir correctement de la boucle

  7. #7
    Expert confirmé
    Avatar de RomainVALERI
    Homme Profil pro
    POOête
    Inscrit en
    Avril 2008
    Messages
    2 652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : POOête

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 652
    Points : 4 164
    Points
    4 164
    Par défaut
    Citation Envoyé par Bovino Voir le message
    Oui, mais xCopy est une référence à x et évolue en même temps
    Si x était un objet, bien entendu.
    ...mais une référence sur un entier ?

    Tu veux dire que si on a :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var a = 1;
    var b = a;
    a++;
    alert(b);
    l'alert va nous sortir un "2 ? (je sais bien que non, mais c'est ce que je comprends de ta remarque : j'ai donc du rater un truc, pardon d'avance )

  8. #8
    Rédacteur
    Avatar de marcha
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2003
    Messages
    1 571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 571
    Points : 2 351
    Points
    2 351
    Par défaut
    Citation Envoyé par Bovino Voir le message
    Non : si l'élément a un nextSibling, l'affectation renvoie le nouvel élément et on réitère, si l'élément n'a pas de nextSibling, la propriété renvoie null, ce qui fait sortir correctement de la boucle
    Oui, quand on travail avec des éléments DOM je suis d'accord, mais
    dans ce code il ne s'agit pas d'éléments DOM mais d'une structure JSON.

    Et le do while sert à rien car artid.nextSibling vaut toujours undefined,
    test ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    var artids = [
    	  { "firstChild" : { "data" : "a" } }
    	, { "firstChild" : { "data" : "b" } }
    	, { "firstChild" : { "data" : "c" } }
    ];
     
    var artid = artids[0].firstChild;
    alert(artid.nextSibling);

  9. #9
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2008
    Messages
    23 647
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Points : 91 220
    Points
    91 220
    Billets dans le blog
    20
    Par défaut
    Arf... bien vu effectivement

  10. #10
    Rédacteur/Modérateur

    Avatar de SpaceFrog
    Homme Profil pro
    Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Inscrit en
    Mars 2002
    Messages
    39 640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur Web Php Mysql Html Javascript CSS Apache - Intégrateur - Bidouilleur SharePoint
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2002
    Messages : 39 640
    Points : 66 669
    Points
    66 669
    Billets dans le blog
    1
    Par défaut
    dans ce code il ne s'agit pas d'éléments DOM mais d'une structure JSON.
    n'est ce pas justement là le souci
    "nextSibling" du json confondu avec nextSibling du DOM ???

  11. #11
    Rédacteur
    Avatar de marcha
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2003
    Messages
    1 571
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 571
    Points : 2 351
    Points
    2 351
    Par défaut
    Citation Envoyé par SpaceFrog Voir le message
    n'est ce pas justement là le souci
    "nextSibling" du json confondu avec nextSibling du DOM ???
    C'est un bug BONUS dans le code, mais ce n'est pas le
    problème de la question de base, le problème de base est
    solutionable par la réponse de Bovino qui pointe sur ton
    article SpaceFrog.

    Mais comme le sujet du post est "Closure qui me rend fou"
    Voici la version basée sur ton article avec une closure .

    Ce qui permet d'éviter de toucher au DOM en créant une fonction
    différente par passage de boucle pour mémoriser les état succesifs de i.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    // fonciton qui crée une fonction ainsi qu'une closure pour c
    function bar(c) {
        return function() { alert(c); }
    }
    function foo(){
      for (i=0;i<10;i++){
        var MonDiv=document.createElement('DIV');
        MonDiv.innerHTML="div " +i;
        // MonDiv.indice=i; // plus nécessaire
        MonDiv.onclick= bar(i); // on affecte le résultat de bar, c'est à dire une fonction
        document.body.appendChild(MonDiv);
      }
    }
    Mais usuellement ça s'écrit plus synthétiquement ainsi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    function foo(){
      for (i=0;i<10;i++){
        var MonDiv=document.createElement('DIV');
        MonDiv.innerHTML="div " +i;
        MonDiv.onclick= function(c) {
          return function() { alert(c); }
        }(i); // appel de la fonction anonyme englobante copiant i dans un c unique par boucle
        document.body.appendChild(MonDiv);
      }
    }
    J'ai utilisé c comme nom de variable pour pas réutiliser i (ce qui serait
    tout a fait fonctionnel, mais "confusing"

  12. #12
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Citation Envoyé par Bovino Voir le message
    Oui, mais xCopy est une référence à x et évolue en même temps

    Voir à ce sujet : Comment attribuer à des objets un onclick faisant appel à une variable de boucle ?
    Non, si j'ai 10 éléments, une alerte sur xCopy donnera 10 et sur x donnera 11 (dernière itération qui ne vérifie plus la condition de poursuiter).

    --

    Concernant le code DOM, c'est assez curieux...
    En réalité, je travail sur un object DOM (résultat XML) mais pour simplifier, j'ai écrit cette définition en JSON et : ça marche (a, b, c) (IE, FF) ! (avec le problème de closure).
    Je ne m'en était même pas rendu compte ^^

    --

    J'ai quand même résolu le problème en mettant le tout dans une condition paramétré pour crée un nouveau scope.
    Mais je jure que la technique "var {...}Copy" avait toujours fonctionné jusqu'à présent !

Discussions similaires

  1. Probleme SUM sur requete qui me rend fou !
    Par EDAT2 dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 12/06/2012, 19h10
  2. SDL_SetAlpha et transparence qui me rend fou
    Par nightwar dans le forum SDL
    Réponses: 5
    Dernier message: 31/03/2010, 21h31
  3. Problème de Syntaxe qui me rend fou
    Par fardon57 dans le forum Débuter
    Réponses: 2
    Dernier message: 07/12/2009, 10h57
  4. une exception qui me rend fou !
    Par ghilo dans le forum Langage
    Réponses: 5
    Dernier message: 20/08/2009, 16h48
  5. SOS - Une Association Many-To-Many qui me rend fou
    Par NexoFlex dans le forum Hibernate
    Réponses: 2
    Dernier message: 30/06/2009, 18h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo