2013-03-19 1 views
2

Ok, je suis en train de rééditer mon message car je pense que cela pourrait être plus clair.Comment empêcher une fonction d'être exécutée plus d'une fois sur un événement jquery .live

J'ai une page ASP.net avec un gridview etc. Sur les lignes de résultat de la vue quadrillée est une image qui, une fois cliquée, ouvre une fenêtre contextuelle modale (essentiellement une div masquée qui est affichée sur clic). Ce modal, tel qu'il apparaît est rempli dynamiquement par un ajax/json avec un tableau à 2 colonnes, la colonne 1 seulement les lignes de texte, la colonne 2 combinaison de listes déroulantes vides et les cases à cocher (tous ces éléments sont ajoutés au DOM AFTER le chargement de la page principale). J'essaie de remplir les listes de contrôle avec leur disponible via ajax/json quand ils sont cliqués par l'utilisateur, et je veux seulement que cela se produise sur le premier clic seulement et peu importe combien de fois l'utilisateur clique sur cette liste déroulante là après (même après être sorti de foyer et de retour) je ne veux pas voir plus de reprises de la même apparence.

Voici le code qui fonctionne actuellement lorsque vous cliquez sur la liste déroulante, c'est-à-dire que la liste déroulante est remplie. problème Te est si je lâche focus et puis re-cliquez sur le menu déroulant, il se repeuple une liste double de:

<code> 
    $('#FSSiteName').live('focus', function() { 
     var $this = $(this); 
     getFSSites(); 
     //i thought the below line would stop it happening again when i click on the dropdown 
    $this.unbind('focus'); 
}); 

function getFSSites() { 
      var ddSites = $("#FSSiteName"); 
      $.ajax({ 
       type: "POST", 
       url: "Circuits_OrderManagementTracker.aspx/getTheSitesList", 
       data: "{}", 
       contentType: "application/json; charset=utf-8", 
       dataType: "json", 
       success: function (response) { 
        var xmlDoc = $.parseXML(response.d); 
        var xml = $(xmlDoc); 
        var FSSitesReturned = xml.find("Table"); 

        $.each(FSSitesReturned, function (index, FSSitesReturned) { 
         dbname = $(this).find("SiteNames").text() 
         ddSites.append('<option>' + dbname + '</option>'); 
        }); 
       }, 
       failure: function (msg) { 
        alert(msg); 
       } 
      }); 
     } 
</code> 

J'ai changé au code ci-dessous des suggestions par vos bons mêmes, mais quand je fais la ci-dessous ma liste déroulante n'est plus peuplée et j'ai aussi essayé .one() qui annonce le même effet.

<code> 
     $('#FSSiteName').on('click', function() { 
      var $this = $(this); 
      //run your alert here if it´s necessary 
      //alert('Focused for the first time :)'); 
      getFSSites(); 
      //unbind the event to prevent it from being triggered again 
      $this.off('click'); 
     }); 
</code> 

Espérons que cela soit un peu plus clair pour tous ceux qui souhaitent aider.

+0

avez-vous essayez '.one()': http://api.jquery.com/one/? – varnie

+0

Construisez-vous un cadre pour la réutilisation? Si ce n'est pas le cas, je vous recommande de tirer parti de celui qui fait tout cela pour vous comme [Telerik's Kendo] (http://www.kendoui.com) –

+0

.one() ne le déclenchera qu'une fois par élément de contexte, et non par délégué . –

Répondre

1

Le contraire de live() est die() mais both are deprecated, vous devez utiliser à la place on() et off.

+0

en fait, '.one()' est mieux adapté dans ce scénario. – Flater

+0

@Flater utilisant n'importe lequel de .on() ou .one() a fonctionné pour moi car ils semblaient empêcher getFSSites() de fonctionner. Je peux seulement supposer à ce stade que c'est parce que .Live() prend sur le #FSSiteName nouvellement ajouté au DOM et les autres ne les voient pas simplement? – MoiD101

+0

N'a pas dit que cela ne fonctionne pas :) Mais '.one()' a été spécifiquement créé pour être exécuté une seule fois, sans avoir à se désengager le gestionnaire vous-même. – Flater

0

D'accord avec le commentaire de Varnie pour utiliser .one au lieu de .live(). Live() est destiné à être utilisé avec des éléments ajoutés dynamiquement au DOM; les éléments qui n'existent pas lorsque la page est chargée pour la première fois dans le navigateur. Puisque votre élément a un sélecteur d'identifiant, pas un sélecteur de classe, je suppose que vous n'avez pas besoin d'utiliser .live() /. On() du tout.

+0

Salut Steve, j'utilise live() parce que les éléments sont en effet ajoutés dynamiquement lorsque le modal contextuel apparaît et donc les listes déroulantes vides. le problème est que .on() ne fonctionne pas seulement en direct semble remplir la liste déroulante. J'ai essayé .one() et cela semble arrêter les listes dynamiquement remplies. Im juste un peu à nouveau pour le comprendre et vous conseiller est apprécié – MoiD101

+0

Serait-il possible pour vous de poster votre code complet sur un site comme jsfiddle ou plnkr? –

+0

Salut Steve Je ne pense pas dans son intégralité, mais je vais modifier mon OP pour être plus clair et montrer plus de code ... – MoiD101

1

C'est simple d'utiliser on et off.

sur() -> ajouter un gestionnaire d'Evend off() -> supprimer un gestionnaire d'événements

$("#item li").on('click', function() { 
    $(this).text('ITEM CLICKED') 
    alert('CLICKED'); 

    //remove the event 
    $(this).off("click") 
}); 

voir cet exemple: http://jsfiddle.net/jMxxa/

documentation Jquery pour et désactiver:

sur:http://api.jquery.com/on/ off:http://api.jquery.com/off/

+0

merci Kesymaru mais si j'utilise le .on et .off la liste ne devient plus peupler dynamiquement? #FSSiteName n'est pas présent sur la page de chargement son seul ajouté dynamiquement lorsque le popup est chargé et la table est ajoutée dynamiquement – MoiD101

0

Salut à tous merci pour votre aide, ce qui est vraiment l'un des meilleurs sites que je l'ai appris à connaître comme un apprenant.J'ai moi-même mis en place une solution qui semble faire l'affaire, mais étant si nouveau pour le codage, j'apprécierais la rétroaction si j'ai fait quelque chose qui n'est pas idéal et qu'il existe une solution plus simple.

i re édité mon OP pour être plus clair voir ci-dessus et qui se tient encore, mais je l'ai changé une partie de mon code pour vérifier simplement si le menu déroulant était vide et il fonctionne voir ok:

<code> 
     $('#FSSiteName').live('click', function() { 
      var $this = $(this); 
      //Check if the dropdown has any options and if no add some 
      if ($this.find('option').length <= 1) { 
       getFSSites(); 
      } 
      else { 
       //Do Nothing!! 
      }    
     }); 

</code> 
Questions connexes