2010-10-16 1 views
5

donc j'ai les balises d'ancrage sous forme de <a href='[link'] rel='Tab'> et je demande ce qui suit à la charge de la page « document prêt » :(Je veux dire)Comment lier la fonction aux événements DOM une fois et une seule fois afin qu'ils ne s'exécutent pas une seconde fois dans le déclenchement de l'événement?

jQuery("a[rel*=Tab]").click(function(e) { 
       e.preventDefault();//then I do some stuff to open it in jq ui tab} 

maintenant le problème est que quand je fais cela et plus tard par javascript nouveau les liens sont générés, dans mon cas avec le chargement d'une deuxième page avec JqGrid il y a de nouveaux <a rel='neoTab'> qui n'existaient pas quand je lance jQuery("a[rel*=Tab]").click(function(e) pour qu'ils ne fonctionnent pas ... donc je peux exécuter jQuery("a[rel*=Tab]").click(function(e) à chaque événement qui crée de nouveaux liens mais alors les anciens liens chargeraient plusieurs onglets alors est-il possible de sélectionner tous les "a[rel*=Tab]" qui n'étaient pas sélectionnés avant? Je peux et ai déjà résolu cela par une approche algorithmique comme vous pouvez le voir à travers les détails ci-dessous, je pense juste qu'il y a quelques syntaxes que je ne connais pas pour éviter le besoin d'utiliser ce hack!

Détails: Unnecessary

var neoTabitStat = 0; 
var openTabs = new Array(); 
openTabs[0] = 'inbox'; 
if(!(currentBox=='inbox'||currentBox=='outbox')) {var currentBox = 'inbox';} 

function initNeoTab(a){ 
    if(neoTabitStat==0) { 
     jQuery("a[rel*="+a+"]").click(function(e) { 
      e.preventDefault(); 
      tabIt(jQuery(this).attr('href')+'&nohead=1',jQuery(this).attr('title'),jQuery(this).attr('data-hovercard')); 
     }); 
    neoTabitStat++; 
    } 
} 

function tabIt(a,b,c) { 
    c = typeof(c) != 'undefined' ? c : 0; 
    lastOpen = openTabs.length; 
    if(lastOpen<6) { 
     if(openTabs.indexOf(c)<0) { 
      openTabs[lastOpen] = c; 
      jQuery("#tabs").tabs("add" , a , b, lastOpen+1); 
     } 
     $tabs.tabs('select', openTabs.indexOf(c)); 
    }else{ 
     var tabErrDig = jQuery('<div style="display:hidden">You have opened the maximum amount of tabs please close one to open another tab.</div>').appendTo('body'); 
     tabErrDig.dialog({width:500,title:'Maximum Tabs Opened',modal: true, 
       buttons: { 
        Ok: function() { 
         jQuery(this).dialog("close"); 
        } 
       } 
     }); 
    } 
} 

jQuery(document).ready(function() { initNeotab('nameOfrelAttr4existingLinks'); } 
myGrid = jQuery("#list").jqGrid({/*alot of stuff...*/} , gridComplete: function() { initNeotab('nameOfrelAttr4generatedLinks'); 
} 

MISE À JOUR: comme suggéré Wrikken jQuery() vivre je l'ai vérifié et il est exactement ce que je dois, mais je ne peux pas le faire pour réellement travailler. , cela ne fonctionnera pas dans certains cas. Pour tout le monde qui a écrit des solutions différentes, êtes-vous familier avec .live() si oui, pourquoi est-ce que je ne peux pas l'utiliser ici?

CONCLUSION grâce à fudgey, patrick dw et wrikken. Toutes les réponses ont été utiles. .delegate(). travaillé pour moi, mais pour une raison quelconque .live() n'a pas. quelque chose sur la façon jqGrid ajouter des éléments à la table. Je vais garder la question ouverte pendant un moment. Merci encore beaucoup pour toute votre aide. 1 à tous

+0

@patrick oui J'ai fini par utiliser delegate pour le moment car tout était ajouté à #list. car c'est l'identifiant de la table sur laquelle travaille jqGrid. Je pense qu'il y aurait de meilleures solutions avec les méthodes de jqGrid donc je vais attendre quelques réponses de la part des experts de jqGrid et en attendant l'étudier moi-même, mais j'ai le code qui marche jusqu'à présent. – Neo

Répondre

1

J'allais suggérer d'utiliser .one() mais il semble que vous ajoutiez des liens dynamiquement. Donc, je pourrais être préférable d'ajouter un drapeau à un lien qui a déjà été cliqué. Comme Patrick suggère, délégué serait le meilleur pour cela, avec ces modifications:

jQuery("#list").delegate('a[rel*=Tab]', 'click', function() { 

if ($(this).is('.alreadyClicked')) { return false; } 
$(this).addClass('alreadyClicked'); 

// do something 

}); 
+0

fudgey - Je pense que le titre de la question peut être un peu trompeur. Par * "une seule fois" *, je pense qu'OP fait référence au fait qu'il cherche dans tout le DOM afin de trouver les nouveaux éléments "" et d'assigner le "clic". Par conséquent, les anciens obtiennent plusieurs gestionnaires 'click' au lieu d'un. Je peux me tromper, mais c'est ce que je comprends du corps de la question. : o) – user113716

+0

oui patrick tu as raison mais fudgey a raison aussi bien qu'il le fait manuellement. – Neo

2

est "#list" l'élément qui contient les éléments <a> générées dynamiquement?

Si tel est le cas, utilisez jQuery's .delegate() method pour y placer un gestionnaire, de sorte que l'un des éléments 'a[rel*=Tab]' sur lequel il a cliqué déclenche le gestionnaire.

jQuery("#list").delegate('a[rel*=Tab]', 'click', function() { 
    //... 
}); 

Tous les 'a[rel*=Tab]' éléments qui sont ajoutés à #list fonctionne automatiquement. Si #list n'est pas le conteneur, utilisez le sélecteur correct pour le conteneur.


EDIT: Bien que la méthode .delegate() ci-dessus est (à mon avis) la meilleure approche, si vous ne voulez assigner click individuels gestionnaires uniquement les nouveaux éléments que vous les créez, vous devez appeler la même méthode .click() par rapport aux nouveaux éléments spécifiques.

Donc, si vous créez un nouveau <a> après le chargement de la page, vous feriez quelque chose comme ceci:

var $newA = $('<a rel="someTab">some text</a>'); 

// Assign click handler to only the newly created element 
$newA.click(function(e) { 
     e.preventDefault(); 
     //then I do some stuff to open it in jq ui tab 
}); 

$newA.appendTo('#list'); 

Bien sûr, ce n'est pas votre code exact, mais montre comment vous pouvez créer un nouvel élément, stocker une référence et affecter le gestionnaire click uniquement à cet élément.

Ou si vous créez une structure plus grande où le <a> est imbriquée, vous pouvez faire la même chose, mais faire un .find() pour obtenir le <a> intérieur de la structure, puis attribuez-lui la click.

Questions connexes