2010-05-25 15 views
12

Ho due div, uno che contiene alcune cose e l'altro con tutte le cose possibili. Cliccando su una delle div trasferirai gli oggetti all'altra div. Il codice mi è venuto in mente è:jQuery: un modo per "aggiornare" i gestori di eventi?

$("#holder > *").each(function() { 
    $(this).click(function(e) { 
     $(this).remove(); 
     $("#bucket").append(this); 
    }); 
}); 

$("#bucket > *").each(function() { 
    $(this).click(function(e) { 
     $(this).remove(); 
     $("#holder").append(this); 
     }); 
}); 

Questo funziona perfettamente, salvo che i gestori di eventi hanno bisogno di essere aggiornati una volta aggiungo o tolgo elementi. Quello che voglio dire è che, se per prima cosa clicco su un elemento, esso viene aggiunto all'altro div, ma se faccio di nuovo clic su questo elemento, non succede nulla. Posso farlo manualmente ma esiste un modo migliore per raggiungere questo obiettivo?

risposta

20

Prova jquery live events .. il $ .live (nome evento, funzione) si associa a tutti gli elementi correnti che corrispondono così come gli elementi aggiunti al Dom in futuro mediante la manipolazione di javascript.

esempio:

$("#holder > *").live("click", function(e) { 
     $(this).remove(); 
     $("#bucket").append(this); 
}); 

$("#bucket > *").live("click", function(e) { 
     $(this).remove(); 
     $("#holder").append(this); 
}); 

Importante:

Nota che $.live da allora è stato messo a nudo da jQuery (1.9 in poi) e che si dovrebbe invece usare $.on.

Suggerisco di fare riferimento a this answer per un esempio aggiornato.

+0

@ John: Grazie per la risposta. Non sono sicuro che mi manchi, ma quando sostituisco il mio codice con questo, non succede nulla. Sto usando jQuery-1.4.2.Mi sto perdendo qualcosa? Voglio dire, anche gli eventi iniziali non funzionano. – Legend

+1

Questo non funzionerà. 'jQuery.fn.live' ha bisogno di un selettore con cui lavorare ... non può funzionare con' $ (this) '... – James

+0

Immagino di sì. Sapevo che "questo" sta rovinando le cose. – Legend

1

Hai guardato la funzione live di jQuery?

+0

Grazie per i suggerimenti. Attualmente sta guardando. – Legend

+1

'live' è stato deprecato – craned

2

MODIFICA: non utilizzare dal vivo, è deprecato!

Approfitta del fatto che la bolla degli eventi. Utilizzando .on():

var = function(el1, el2) { 

var things = $('#holder, #bucket'); 
things.each(function(index) { 
    // for every click on or in this element 
    things.eq(index).on('click', '> *', function() { 
    // append will remove the element 
    // Number(!0) => 1, Number(!1) => 0 
    things.eq(Number(!index)).append(this); 
    }); 
}); 

qualsiasi click su qualsiasi elemento (esistente al momento di bind o meno) si bolla (ammesso che non è stato catturato manualmente l'evento e si fermò di propagazione). Pertanto, è possibile utilizzare quello event delegation per associare solo due eventi, uno su ciascun contenitore. Ogni click che ha superato la prova di selezione del secondo argomento (in questo caso, > *, rimuoverà che elemento e quindi aggiungere al contenitore alternativo come accesesed da things.eq(Number(!index))

+0

In realtà, non lo sarà. A meno che non intendi separare/reindirizzare quando gli elementi vengono aggiunti al DOM. Penso che tu intenda dire .live ('click', function() { –

+0

La mia comprensione è che bind non funziona con gli articoli futuri ma solo con elementi che attualmente corrispondono a un dato selettore [citazione dalla documentazione 'live' in jQuery) : "Questo nuovo elemento corrisponde anche al selettore .clickme, ma poiché è stato aggiunto dopo la chiamata a .bind(), i clic su di esso non faranno nulla." –

+0

Intendevo .live, sry per la confusione - stavo raccogliendo la mia ragazza e andavo di fretta a digitare sul mio telefono e ho digitato bind di habbit, lol –

6

Qui si va, utilizzando il più intuitivo delegate API: ..

var holder = $('#holder'), 
    bucket = $('#bucket'); 

holder.delegate('*', 'click', function(e) { 
    $(this).remove(); 
    bucket.append(this); 
}); 

bucket.delegate('*', 'click', function(e) { 
    $(this).remove(); 
    holder.append(this); 
}); 
+0

@ J-P: Ahh ... ho appena accettato la soluzione di John. +1 per l'aiuto. Solo per curiosità, c'è qualche vantaggio nell'utilizzare il delegato in diretta? – Legend

+0

@Legend, Sì, è più veloce, perché non richiede la selezione ridondante di '#header> *' e '#bucket> *' prima. – James

+0

@ J-P: ha senso. Grazie per la spiegazione. – Legend

1

in primo luogo, live è deprecato in secondo luogo, rinfrescante, non è ciò che si vuole Hai solo bisogno di collegare il gestore clicca per fonte giusta, in questo caso: il documento

Wh. it you do

$(document).on('click', <id or class of element>, <function>); 

il gestore di clic è allegato al documento. Quando la pagina viene caricata, il gestore di clic è collegato a un'istanza specifica di un elemento. Quando la pagina viene ricaricata, quell'istanza specifica viene eliminata, in modo che il gestore non stia registrando alcun clic. Ma la pagina rimane in modo da collegare il gestore di clic al documento. Semplice e facile.

Problemi correlati