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

jQuery Discussion :

Transmission d'arguments sur une fonction anonyme


Sujet :

jQuery

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Points : 138
    Points
    138
    Par défaut Transmission d'arguments sur une fonction anonyme
    Bonjour,
    je n'arrive pas a transmettre correctement une variable dans une fonction anonyme.

    voilà le code simplifié:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    bouton = $('<input type="button" value="essai" />');
     x='ok';
    alert(x);
    bouton.click(function(x){
       //return function(x) {
             alert(x);
       //}
    });

    Je cree un bouton en Jquery, je lui joint un evenement click et j'ajoute le tout au DOM.
    Je n'ai pas tout mis concernant la création et l'ajout du bouton mais ça marche de ce coté là.

    Le problème c'est que lorsque je clique sur le bouton j'ai une alerte qui m'affiche "[object Object]" au lieu de "ok".

    A savoir aussi, le tout se trouve dans une boucle While, c'est pourquoi j'ai aussi tenté d'utiliser une autre fonction anonyme imbriqué pour que la variable x contienne la bonne valeur et non pas celle en fin de boucle.

    voici le code un peu plus complet de ce que je veux au final:
    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
    boutons = $('<div id="popMessage_boutons"></div>');
    var i=0;
    while (i < ù.boutons.length) {
        bouton = $('<input type="button" value="' + ù.boutons[i].caption + '" />');
        if (ù.boutons[i].callback) {
            x = ù.boutons[i].callback;
            alert(x);
            bouton.click(function(x){
                //return function(x) {
                    alert(x);
                    fondOpaque('clear');
                    $('#popMessage').animate({opacity: 0}, 200,'swing',function() {
                        this.remove();
                        window[x]();
                    });
                //}
            }); 
        } else {
            bouton.click(function(){ ù.closeMessage() });
        }
        boutons.append(bouton);
        i++;
    } 
    popup.append(boutons);
    $(ù.destination).append(popup);

  2. #2
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    Dans le code suivant
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var x = 'Ok';
    alert(x); // [ Ok ]
    bouton.click(function( x ) {
        alert(x); // [ ??? ]
    });
    Tu définis une variable x avec pour valeur 'Ok'. Après tu définis une fonction qui prend un argument x que tu affiches dans le corps de ta fonction.
    Le x de départ n'a rien à voir avec le x dans ta fonction, parce que tu l'as déclaré comme argument, il masque le x declaré dans la portée englobante.

    Soit tu utilises une cloture
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var x = 'Ok';
    alert(x); // [ Ok ]
    bouton.click(function() { // ou bouton.click(function( e ) {
        alert(x); // [ Ok ]
    });
    où tu captures ta variable x de niveau supérieur, et tu affiches bien sa valeur

    Soit tu lis la doc de jQuery pour voir quel argument la méthode click passe à ta fonction anonyme et qui sera lié à x dans ta fonction et tu vois s'il est possible de lui passer le x de départ.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Points : 138
    Points
    138
    Par défaut
    d'accord avec ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var x = 'Ok';
    alert(x); // [ Ok ]
    bouton.click(function( x ) {
        alert(x); // [ ??? ]
    });
    le 'x' dans la fonction est différent de celui en dehors et finalement c'est ce que je veux. Sauf qu'avec ce code 'x' est déclaré mais pas initialisé et c'est là mon problème.

    J'ai essayé avec ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var x = 'Ok';
    alert(x); // [ Ok ]
    bouton.click(function() { // ou bouton.click(function( e ) {
        alert(x); // [ Ok ]
    });
    Alors je ne comprends pas trop a quoi sert le 'e' dans l'argument de la fonction, j'ai essayé avec et sans et le resultat est identique. Je peux accéder à la valeur 'x' tel quel est hors de la fonction et donc dans mon cas j'y accède à la fin de la boucle While ce qui fait que sa valeur ne correspond plus a ce qu'elle devrait etre. Il faut absolument que je capture la valeur de x au moment où j'attache la fonction au bouton.

    Ensuite, regarder dans la doc de Jquery, je vois pas trop le rapport puisque c'est une fonction que je lui donne en argument et ça passe. Les details de la fonction ne sont pas pris en compte par jquery (y compris les arguments je pense).
    J'ai quand meme jeté un coup d'oeil et j'ai rien vu.

    J'ai modifié mon code d'essai pour qu'il soit un peu plus clair:
    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
     
    var table = ['b1','b2'];
    var x;
     
    cadre = $('<div id="popMessage_boutons"></div>');
    var i=0;
    while (i < table.length) {
       bouton = $('<input type="button" value="' + table[i] + '" class="popMessagebouton" />');
     
          x = table[i];
     
          bouton.click(function(){
             alert(x);
          }); 
     
       cadre.append(bouton);
       i++;
    } 
     
    popup.append(cadre);
    $(ù.destination).append(popup);
    Avec ce code, je crée 2 boutons, "b1" et "b2".
    Lorsque je clique sur un bouton il doit m'afficher son nom ("b1" ou "b2).

    actuellement les 2 boutons m'affichent le message "b2". (y compris si je met le "e" dans les argument de la fonction)

  4. #4
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    Dans une cloture, tu captures une référence à une variable, pas sa valeur. Donc effectivement, dans ta boucle, toutes les fonctions vont avoir la même valeur pour x, celle obtenue en fin de boucle. Pour éviter ça, il faut passer x en argument. Cela permet de garder une référence sur l'argument, qui contient la valeur de x, qui est différente à chaque appel. En code on peut traduire ça par :
    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
    var table = ['b1','b2'];
    var x;
    var i=0;
    while (i < table.length) {
        bouton = ...
        x = table[i];
        bouton.click(handlerFactory(x));
        i++;
    }
    // renvoie une fonction liée à la valeur de x au travers de son argument xval
    function handlerFactory ( xval ) {
        return function( e ) {
            alert(xval);
        }
    }
    On passe x à handlerFactory, on recopie donc sa valeur dans xval qui est lié à la fonction anonyme que l'on retourne. Et comme à chaque appel la référence à xval sera différente, on est tout bon.

    C'était pour le principe, on peut faire plus simple avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var table = ['b1','b2'];
    var x;
    var i=0;
    while (i < table.length) {
        bouton = ...
        x = table[i];
        bouton.click((function( xval, e ) {
            alert(xval);
        }).bind(null,x));
        i++;
    }
    en utilisant Function.prototype.bind on va créer une fonction dont le contexte d'appel (this) sera null et le premier paramètre aura la valeur de x.

    Maintenant : qu'est-ce qu'il m"embrouille avec son argument e ?
    Et bien, dans la doc jQuery, on peut lire
    .click( handler )
    handler
    Type: Function( Event eventObject )
    A function to execute each time the event is triggered.
    que effectivement, .click prend une fonction en argument, ET que cette fonction prend un évènement comme argument. L'évènement en question est une encapsulation de l'évènement DOM qui a été déclenché (MouseEvent par exemple). Donc notre fonction peut prendre un argument, un évènement d'où le e.

    Juste après, depuis la version 1.4.3
    .click( [eventData ], handler )
    eventData
    Type: Anything
    An object containing data that will be passed to the event handler.

    handler
    Type: Function( Event eventObject )
    A function to execute each time the event is triggered.
    on a une deuxième forme pour enregistrer un gestionnaire d'évènement (ta fonction anonyme). Dans ce cas, .click prend deux arguments, des données à transmettre et le gestionnaire d'évènement. Je ne connais pas jQuery, mais je mettrais bien un p'tit billet sur le fait que les données passées dans le premier argument se retrouvent dans l'évènement au travers de la propriété data. Dans ce cas, ton code deviendrait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var table = ['b1','b2'];
    var x;
    var i=0;
    while (i < table.length) {
        bouton = ...
        x = table[i];
        bouton.click(x,function( e ) { // ou éventuellement : bouton.click({ data:x },function( e ) {...
            alert(e.data);
        });
        i++;
    }
    Il ne te reste plus qu'à tester ...

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    175
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Seine et Marne (Île de France)

    Informations forums :
    Inscription : Octobre 2009
    Messages : 175
    Points : 138
    Points
    138
    Par défaut
    C'est bon, ça fonctionne
    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
     
    var table = ['b1','b2'];
    var x;
     
    cadre = $('<div id="popMessage_boutons"></div>');
    var i=0;
    while (i < table.length) {
       bouton = $('<input type="button" value="' + table[i] + '" class="popMessagebouton" />');
     
          x = table[i];
     
          bouton.click({nbr : x},function(event){
             alert(event.data.nbr);
          }); 
     
       cadre.append(bouton);
       i++;
    } 
     
    popup.append(cadre);
    $(ù.destination).append(popup);
    Merci infiniment pour toutes ces explications limpides, ça m'a permis de mieux comprendre certains principes du javascript et de découvrir le passage d'argument avec jquery.

  6. #6
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Points : 22 933
    Points
    22 933
    Billets dans le blog
    125
    Par défaut
    On peut aussi utiliser deux autres méthodes :
    • un attribut data-* ;
    • une écriture appropriée pour conserver directement la valeur.


    Exemple :
    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
    $( function(){ // forme abrégée de $(document).ready(function(){
     
        var jObjCadre = $( "<div/>", {
            "id" : "popMessage_boutons"
        }).appendTo( "body" );
     
        $.each( [ "b1", "b2" ], function( i, nbr ){
     
            $( "<input/>", {
                "type" : "button",
                "class" : "popMessagebouton",
                "value" : nbr,
                "data-nbr" : nbr,
                "on" : {
                    "click" : function( event ){
                        console.log( "$( this ).val() = ", $( this ).val() );
                        console.log( '$( this ).data( "nbr" ) = ', $( this ).data( "nbr" ) );
                        console.log( "nbr = ", nbr );
                    }
                }
            }).appendTo( jObjCadre );
     
        });
     
    });

    Blog

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Match sur les argument d une fonction.
    Par gomisse dans le forum Langages fonctionnels
    Réponses: 4
    Dernier message: 03/03/2015, 21h55
  2. Réponses: 13
    Dernier message: 17/09/2014, 18h09
  3. transmission d'arguments surchargés à une sous fonction
    Par epeedelorage dans le forum Général JavaScript
    Réponses: 19
    Dernier message: 24/07/2012, 18h52
  4. Réponses: 2
    Dernier message: 22/06/2011, 15h21
  5. Récupération d'arguments sur une fonction
    Par p0Kep0K dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 21/09/2005, 09h17

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