2010-10-16 10 views
5

quindi ho tag di ancoraggio sotto forma di <a href='[link'] rel='Tab'> e applico quanto segue al caricamento della pagina :('documento pronto' intendo)Come associare una funzione agli eventi DOM una volta sola e in modo che non vengano eseguiti una seconda volta nell'attivazione dell'evento?

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

ora il problema è che quando faccio questo e poi tramite JavaScript nuova i collegamenti sono generati, nel mio caso con il caricamento di una seconda pagina con JqGrid ci sono nuovi <a rel='neoTab'> che non esistevano quando eseguo per la prima volta jQuery("a[rel*=Tab]").click(function(e) in modo che non funzionino ... quindi posso eseguiread ogni evento che crea nuovi collegamenti ma poi i vecchi link caricheranno più schede quindi c'è un modo per selezionare tutti gli "a[rel*=Tab]" che non erano stati selezionati prima?

nota: posso e hanno già risolto questo attraverso un approccio algoritmico, come si può vedere attraverso i dettagli di seguito, penso solo che v'è una certa sintassi che non sono a conoscenza per evitare la necessità di utilizzare questo hack!

dettagli inutili:

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'); 
} 

UPDATE: come Wrikken suggerito jQuery() vivere ho controllato fuori ed è esattamente quello che mi serve, ma non riesco a farlo funzionare realmente. , in alcuni casi non funzionerà. Per tutti gli altri che hanno scritto soluzioni diverse, sei fimario con .live() se è così perché non posso usarlo qui?

CONCLUSIONE ringraziamento speciale a fudgey, patrick dw, e wrikken. Tutte le risposte sono state utili. .delegate(). ha funzionato per me, ma per qualche motivo .live() no. qualcosa sul modo in cui gli elementi della jqGrid aggiunta alla tabella. Terrò aperta la domanda per un po ' Grazie mille ancora per tutto il tuo aiuto. +1 a tutti

+0

@patrick Sì, ho finito per utilizzare delegato per ora poiché tutto veniva aggiunto a #list. poiché è l'id della tabella su cui jqGrid sta lavorando. Penso che ci sarebbero migliori soluzioni con i metodi in jqGrid, quindi aspetterò qualche risposta dagli esperti di jqGrid e intanto lo studierò di più, ma ho il codice che funziona fino ad ora. – Neo

risposta

1

Stavo per suggerire di utilizzare .one() ma sembra che si aggiungano i collegamenti dinamicamente. Quindi potrei essere meglio aggiungere un flag a un link che è già stato cliccato. Come suggerisce Patrick, delegato sarebbe meglio per questo, con queste modifiche:

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

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

// do something 

}); 
+0

fudgey - Penso che il titolo della domanda possa essere un po 'fuorviante. Con * "solo una volta" *, penso che OP si riferisca al fatto che sta cercando nell'intero DOM per trovare gli elementi '' appena creati e assegnare il 'clic'. Pertanto, i vecchi stanno ottenendo più gestori di click invece di uno. Potrei sbagliarmi, ma è quello che sto ottenendo dal corpo della domanda. : o) – user113716

+0

sì patrick hai ragione, ma fudgey è giusto così come lo sta facendo manualmente. – Neo

2

è "#list" l'elemento che contiene i generati dinamicamente <a> elementi?

In tal caso, utilizzare jQuery's .delegate() method per posizionare un gestore su di esso, quindi uno qualsiasi degli elementi 'a[rel*=Tab]' che viene fatto clic all'interno di esso attiverà il gestore.

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

Qualsiasi 'a[rel*=Tab]' elementi che vengono aggiunti al #list funzionerà automaticamente. Se #list non è il contenitore, utilizzare il selettore corretto per il contenitore.


EDIT: Mentre il metodo .delegate() di cui sopra è (a mio parere) l'approccio migliore, se si voleva assegnare singoli click gestori a solo i nuovi elementi in fase di creazione, si avrebbe bisogno di chiamare lo stesso metodo .click() rispetto ai nuovi elementi specifici.

Quindi, se si crea un nuovo <a> dopo il caricamento della pagina, devi fare qualcosa di simile:

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'); 

Naturalmente questo non è il codice esatto, ma mostra come è possibile creare un nuovo elemento, memorizzare un riferimento ad esso e assegnare il gestore click solo a quell'elemento.

Oppure, se si sta creando una struttura più grande dove il <a> è annidato, si può fare la stessa cosa, ma fare un .find() per ottenere il <a> all'interno della struttura, quindi assegnare il click.

Problemi correlati