Come fermare la propagazione degli eventi con l'attributo onclick inline?


313

Considera quanto segue:

<div onclick="alert('you clicked the header')" class="header">
  <span onclick="alert('you clicked inside the header');">something inside the header</span>
</div>

Come posso fare in modo che quando l'utente fa clic sull'intervallo, non genera l' divevento click?

Risposte:


272

Usa event.stopPropagation () .

<span onclick="event.stopPropagation(); alert('you clicked inside the header');">something inside the header</span>

Per IE: window.event.cancelBubble = true

<span onclick="window.event.cancelBubble = true; alert('you clicked inside the header');">something inside the header</span>

11
Non esiste l'oggetto evento in FireFox.
Robert C. Barth,

6
L'oggetto evento è un parametro del callback. In realtà, non esiste l'oggetto evento in IE perché questo oggetto è accessibile tramite window.event invece di essere un parametro della funzione :-)
Vincent Robert,

66
Questo è semplicemente sbagliato: i gestori onclick inline non fanno passare l'evento come argomento. La soluzione corretta è Gareths, di seguito.
Benubird,

2
In Firefox, puoi avere accesso a un evento variabile nello script inline, ma window.event non è disponibile. <div onclick = "alert (event);"> </div>
Morgan Cheng

1
eventsembra essere disponibile anche negli eventi inline in IOS Safari.
Yuval A.

210

Esistono due modi per ottenere l'oggetto evento dall'interno di una funzione:

  1. Il primo argomento, in un browser conforme a W3C (Chrome, Firefox, Safari, IE9 +)
  2. L'oggetto window.event in Internet Explorer (<= 8)

Se devi supportare i browser legacy che non seguono i consigli del W3C, generalmente all'interno di una funzione utilizzeresti qualcosa del tipo seguente:

function(e) {
  var event = e || window.event;
  [...];
}

che controlla prima l'uno e poi l'altro e memorizza quello che è stato trovato nella variabile evento. Tuttavia, in un gestore di eventi inline non esiste un eoggetto da utilizzare. In tal caso, è necessario sfruttare la argumentsraccolta che è sempre disponibile e fa riferimento all'insieme completo di argomenti passati a una funzione:

onclick="var event = arguments[0] || window.event; [...]"

Tuttavia, in generale dovresti evitare i gestori di eventi in linea se devi fare qualcosa di complicato come interrompere la propagazione. Scrivere i gestori di eventi separatamente e collegarli agli elementi è un'idea molto migliore a medio e lungo termine, sia per la leggibilità che per la manutenibilità.


11
Da un listener in linea, è possibile passare l'oggetto evento come:, onclick="foo(event)"quindi nella funzione function foo(event){/* do stuff with event */}. Funziona con i modelli di eventi IE e W3C.
RobG

5
Quel "minore o uguale a otto" è in qualche modo ... ambiguo.
TechNyquist,

8
questo in realtà non risponde alla domanda.
jcomeau_ictx,

1
bella risposta a una domanda diversa. : - /
Arel,

80

Tieni presente che window.event non è supportato in FireFox e quindi deve essere qualcosa sulla falsariga di:

e.cancelBubble = true

In alternativa, è possibile utilizzare lo standard W3C per FireFox:

e.stopPropagation();

Se vuoi divertirti, puoi farlo:

function myEventHandler(e)
{
    if (!e)
      e = window.event;

    //IE9 & Other Browsers
    if (e.stopPropagation) {
      e.stopPropagation();
    }
    //IE8 and Lower
    else {
      e.cancelBubble = true;
    }
}

12
E per farlo funzionare, bisogna chiamarlo così:<div onclick="myEventHandler(event);">
DarkDust

1
Potrebbe essere "event || window.event".
a punta

1
se (e.cancelBubble) non mi sembra giusto, lo imposti su vero se è già vero
Guillaume86

e.cancelBubblerestituisce false in IE! Non può raggiungere l' e.cancelBubble = true;istruzione. Usa invece le condizioni di SoftwareARM !!
mauretto,

45

Utilizzare questa funzione, verificherà l'esistenza del metodo corretto.

function disabledEventPropagation(event)
{
   if (event.stopPropagation){
       event.stopPropagation();
   }
   else if(window.event){
      window.event.cancelBubble=true;
   }
}

20

Ho avuto lo stesso problema - js error box in IE - questo funziona bene in tutti i browser per quanto posso vedere (event.cancelBubble = true fa il lavoro in IE)

onClick="if(event.stopPropagation){event.stopPropagation();}event.cancelBubble=true;"

1
Grazie @MSC esattamente quello di cui avevo bisogno!
DannyC,

1
Script in linea. Risponde alla domanda
Cesar, il

10

Questo ha funzionato per me

<script>
function cancelBubble(e) {
 var evt = e ? e:window.event;
 if (evt.stopPropagation)    evt.stopPropagation();
 if (evt.cancelBubble!=null) evt.cancelBubble = true;
}
</script>

<div onclick="alert('Click!')">
  <div onclick="cancelBubble(event)">Something inside the other div</div>
</div>

Sei sicuro che questo esatto frammento di codice abbia funzionato per te? Perché sembra che ci sia un problema con le citazioni di stringa nel gestore onclick del div esterno ...?!
Nicole,

7

Per le pagine Web ASP.NET (non MVC), è possibile utilizzare l' Sys.UI.DomEventoggetto come wrapper di eventi nativi.

<div onclick="event.stopPropagation();" ...

oppure, passa l'evento come parametro alla funzione interna:

<div onclick="someFunction(event);" ...

e in qualche funzione:

function someFunction(event){
    event.stopPropagation(); // here Sys.UI.DomEvent.stopPropagation() method is used
    // other onclick logic
}


2

Non posso commentare a causa del Karma, quindi scrivo questa come una risposta completa: secondo la risposta di Gareth (var e = argomenti [0] || window.event; [...]) ho usato questo oneliner in linea sul clic per un hack rapido:

<div onclick="(arguments[0] || window.event).stopPropagation();">..</div>

So che è tardi ma volevo farti sapere che funziona in una riga. Le parentesi graffe restituiscono un evento a cui è associata la funzione stopPropagation in entrambi i casi, quindi ho cercato di incapsularle in parentesi graffe come in un if e .... funziona. :)


1

Questo funziona anche - Nel link HTML usa onclick con return in questo modo:

<a href="mypage.html" onclick="return confirmClick();">Delete</a>

E quindi la funzione comfirmClick () dovrebbe essere come:

function confirmClick() {
    if(confirm("Do you really want to delete this task?")) {
        return true;
    } else {
        return false;
    }
};

2
Non è questo il significato della domanda.
jzonthemtn,

@jbird Questo è esattamente il significato della domanda. È un modo diverso (più vecchio) per annullare un evento dal gorgogliare dell'albero del dom (è nelle specifiche di livello 1 di dom api).
gion_13,

@ gion_13 Ma l'azione del clic non è qualcosa che l'utente deve confermare. Nella domanda, vogliamo solo che onclick () del bambino si attivi e non onclick del genitore (). Inserire un prompt utente tra quelli non è utile. Spero che tu possa vedere questa differenza.
jzonthemtn,

1
Non confirmè rilevante. Mi riferisco al valore di ritorno . quote: Nel link HTML usa onclick con return in questo modo
gion_13

restituendo false annulla seguendo il link, non annulla la propagazione sul mio chrome
commonpike

1

Perché non controllare semplicemente quale elemento è stato cliccato? Se fai clic su qualcosa, window.event.targetviene assegnato all'elemento su cui è stato fatto clic e l'elemento cliccato può anche essere passato come argomento.

Se il target e l'elemento non sono uguali, si è propagato un evento.

function myfunc(el){
  if (window.event.target === el){
      // perform action
  }
}
<div onclick="myfunc(this)" />

Grazie amico, questa sembra essere la soluzione più pulita qui. In una nota a margine devi considerare che questo corrisponde solo quando l'elemento selezionato è l'elemento più in alto effettivo.
Simon Mattes,

0
<div onclick="alert('you clicked the header')" class="header">
  <span onclick="alert('you clicked inside the header'); event.stopPropagation()">
    something inside the header
  </span>
</div>

0

La soluzione migliore sarebbe gestire l'evento tramite una funzione javascript, ma per utilizzare una soluzione semplice e rapida usando direttamente l'elemento html e una volta che "event" e "window.event" sono obsoleti e non universalmente supportati ( https://developer.mozilla.org/en-US/docs/Web/API/Window/event ), suggerisco il seguente "codice reale":

<div onclick="alert('blablabla'); (arguments[0] ? arguments[0].stopPropagation() : false);">...</div>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.