2013-06-10 24 views
8

I have a simple table:e.stopPropagation() non funziona come previsto?

enter image description here

Il TR ha <tr onclick='alert("row");'>

e il pulsante è:

$("body").on('click',".b",function (e){ 
    alert('button'); 
    e.stopPropagation(); 
}); 

Tuttavia - Anche se ho scritto e.stopPropagation(); avverte ancora: "fila, pulsante".

Ora, so che il gestore di eventi è attaccato al body e il selettore viene controllato contro di essa (l'inizio click sul tasto e spostare fino al corpo, proprio come $.live uso da fare, ma contro document ...).

Ma il controllo dovrebbe essere per il button clic e non per il clic TR.

Sembra che, mentre sto facendo clic, si propaga alla "body" (perché ho attaccato gestore di eventi ad esso) e mentre la sua strada fino al corpo attiva il click sul TR.

Cosa sta succedendo qui? Come posso mantenere il mio codice (allegare al corpo) e avere ancora solo l'avviso del "pulsante".

P.s

so che posso fare semplicemente:

$(".b").on('click',function (e){ 
    alert('button'); 
    e.stopPropagation(); 

}); 

ma voglio sapere perché il mio lavoro attuale codice pretende molto (!).

+1

Come ti sembra di capire che il problema è che si allega il gestore di eventi per il corpo, non è chiaro che cosa' chiedendo. –

+0

@dystroy Ho collegato il gestore al corpo. sì. ma ho anche detto: "interrompere la propagazione". quindi IMHO dovrebbe solo allertare "riga". e da lì - smetti di salire. La delega –

+0

utilizza la propagazione dell'evento per raggiungere il delegato. Ecco perché un evento che non bolle (propagare) come evento onload non può essere utilizzato con delega. –

risposta

11

Il problema è che si sta collegando il gestore di eventi allo body, anche se questo è delegato all'elemento .b. Questo gestore eventi viene chiamato solo dopo che è stato chiamato il gestore eventi tr, quindi è troppo tardi per interrompere la propagazione.

come suppongo che si desidera trattare con elementi aggiunti in modo dinamico e non si può semplicemente associare il gestore di eventi per il td, posso suggerire questo:

$('body').on('click',"tr",function (e){ 
    alert('row'); 
}); 
$("body").on('click',".b",function (e){ 
    alert('button'); 
    e.stopPropagation(); 
}); 

Demonstration

+0

Grazie dystroy :-) –

5

... ma voglio sapere perché il mio attuale codice (!) Non funziona.

Da docs jQuery, il event.stopPropagation con delega evento:

Poiché il metodo .Live() gestisce gli eventi una volta che hanno propagato al la parte superiore del documento, non è possibile fermare la propagazione di eventi live . Allo stesso modo, eventi gestiti da .delegate() propagheranno agli elementi a cui sono delegati; gestori di eventi collegati su qualsiasi elemento sotto di esso nell'albero DOM sarà già stato eseguito al momento della chiamata del gestore di eventi delegato. Questi gestori, , pertanto, potrebbero impedire l'attivazione del gestore delegato tramite chiamando event.stopPropagation() o restituendo false.

live e delegate sono ora on quindi questo vale.

+0

Questa è la risposta giusta. – andreszs

0

può essere, semplicemente fissare la gestione degli eventi verso il basso il pulsante mi piace (anche con la inline javascript attaccato alla <tr> tag) -

$("td").on('click',".b",function (e){ 
    alert('button2'); 
    e.stopPropagation(); 
}); 

O - Invece di dare l'evento inline in <tr>, u può give-

$(document).on('click',".b",function (e){ 
    alert('button'); 
    e.stopPropagation(); 
}); 

$(document).on('click',"tr",function (e){ 
    alert('tr'); 
    e.stopPropagation(); 
}); 
Problemi correlati