Como parar a propagação de eventos com o atributo embutido onclick?

313

Considere o seguinte:

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

Como posso fazer para que, quando o usuário clicar no intervalo, ele não dispara o divevento de clique?

Sam
fonte

Respostas:

272

Use event.stopPropagation () .

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

Para o IE: window.event.cancelBubble = true

<span onclick="window.event.cancelBubble = true; alert('you clicked inside the header');">something inside the header</span>
James
fonte
11
Não existe o objeto de evento no FireFox.
Robert C. Barth
6
O objeto de evento é um parâmetro do retorno de chamada. Na verdade, não existe tal coisa como o objeto de evento no IE, porque esse objeto é acessível através window.event vez de ser um parâmetro da função :-)
Vincent Robert
66
Isso está errado - os manipuladores onclick inline não passam o evento como argumento. A solução correta é Gareths, abaixo.
Benubird
2
No Firefox, você pode ter acesso a um evento variável no script embutido, mas o window.event não está disponível. <div onclick = "alert (event);"> </div>
Morgan Cheng
1
eventparece estar disponível também em eventos embutidos no IOS Safari.
Yuval A.
210

Existem duas maneiras de obter o objeto de evento de dentro de uma função:

  1. O primeiro argumento, em um navegador compatível com W3C (Chrome, Firefox, Safari, IE9 +)
  2. O objeto window.event no Internet Explorer (<= 8)

Se você precisar dar suporte a navegadores herdados que não seguem as recomendações do W3C, geralmente dentro de uma função você usaria algo como o seguinte:

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

que verificaria primeiro um e depois o outro e armazenaria o que fosse encontrado na variável de evento. No entanto, em um manipulador de eventos embutido, não há um eobjeto a ser usado. Nesse caso, você deve tirar proveito da argumentscoleção que está sempre disponível e se refere ao conjunto completo de argumentos passados ​​para uma função:

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

No entanto, de um modo geral, você deve evitar manipuladores de eventos em linha se precisar de algo complicado, como interromper a propagação. Escrever seus manipuladores de eventos separadamente e anexá-los a elementos é uma idéia muito melhor a médio e longo prazo, tanto para facilitar a leitura quanto a manter a manutenção.

Gareth
fonte
11
De um ouvinte em linha, você pode passar o objeto evento como: onclick="foo(event)", em seguida, na função function foo(event){/* do stuff with event */}. Isso funciona nos modelos de eventos IE e W3C.
RobG
5
Que "menor ou igual a oito" é um tanto ... ambíguo.
TechNyquist
8
isso realmente não responde à pergunta.
jcomeau_ictx
1
resposta pura a uma pergunta diferente. : - /
Arel 28/10
80

Lembre-se de que o window.event não é suportado no FireFox e, portanto, deve ser algo parecido com:

e.cancelBubble = true

Ou você pode usar o padrão W3C para FireFox:

e.stopPropagation();

Se você quiser ser chique, faça o seguinte:

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

    //IE9 & Other Browsers
    if (e.stopPropagation) {
      e.stopPropagation();
    }
    //IE8 and Lower
    else {
      e.cancelBubble = true;
    }
}
Robert C. Barth
fonte
12
E para fazê-lo funcionar, é preciso chamar isso assim:<div onclick="myEventHandler(event);">
DarkDust
1
Pode ser "evento || window.event".
Pointy
1
if (e.cancelBubble) não parece certo para mim, você defini-lo como true se ele já é verdade
Guillaume86
e.cancelBubbleretorna falso no IE! Não pode alcançar a e.cancelBubble = true;instrução. Em vez disso, use a condição do SoftwareARM !!
mauretto
45

Use esta função, ele testará a existência do método correto.

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

Eu tive o mesmo problema - caixa de erro js no IE - isso funciona bem em todos os navegadores, tanto quanto eu posso ver (event.cancelBubble = true faz o trabalho no IE)

onClick="if(event.stopPropagation){event.stopPropagation();}event.cancelBubble=true;"
MSC
fonte
1
Obrigado @MSC exatamente o que eu precisava!
DannyC
1
Script embutido. Ele faz responder à pergunta
Cesar
10

Isso funcionou para mim

<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>
Matías Contreras Selman
fonte
Tem certeza de que esse snippet de código exato funcionou para você? Porque parece que há um problema de citação de string no manipulador onclick da div externa ...?!
Nicole Nicole
7

Para páginas da Web do ASP.NET (não MVC), você pode usar o Sys.UI.DomEventobjeto como invólucro do evento nativo.

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

ou, passe o evento como um parâmetro para a função interna:

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

e em alguma função:

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

De acordo com esta página , no IE você precisa:

event.cancelBubble = true

ajh1138
fonte
2

Como não posso comentar por causa do Karma, escrevo a resposta como um todo: De acordo com a resposta de Gareth (var e = argumentos [0] || window.event; [...]) usei esse oneliner on-line no onclick para um hack rápido:

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

Sei que é tarde, mas queria que você soubesse que isso funciona em uma linha. Os chavetas retornam um evento que tem a função stopPropagation anexada nos dois casos, então tentei encapsulá-los entre chavetas, como no if e .... funciona. :)

user3611941
fonte
1

Isso também funciona - No link HTML, use onclick com retorno como este:

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

E então a função comfirmClick () deve ser como:

function confirmClick() {
    if(confirm("Do you really want to delete this task?")) {
        return true;
    } else {
        return false;
    }
};
Rajendra
fonte
2
Não é isso que a pergunta significa.
jzonthemtn
jbird @ Isso é exatamente o que a pergunta significava. É uma maneira (mais antiga) diferente de cancelar um evento de borbulhar na árvore dom (está nas especificações do nível 1 da API do dom).
G1_13
@ gion_13 Mas a ação do clique não é algo que o usuário precisa confirmar. Na pergunta, queremos apenas que o onclick da criança () seja acionado e não o onclick do pai (). Colocar um prompt do usuário entre eles não é útil. Espero que você possa ver essa diferença.
precisa saber é o seguinte
1
O confirmnão é relevante. Estou me referindo ao valor de retorno . citação: No link HTML, use onclick com retorno como este
gion_13
retornando falsos cancela seguindo o link, ele não cancelar a propagação no meu cromo
commonpike
1

Por que não apenas verificar qual elemento foi clicado? Se você clicar em algo, window.event.targetserá atribuído ao elemento que foi clicado e o elemento clicado também poderá ser transmitido como argumento.

Se o destino e o elemento não forem iguais, foi um evento que se propagou.

function myfunc(el){
  if (window.event.target === el){
      // perform action
  }
}
<div onclick="myfunc(this)" />
cs01
fonte
Obrigado companheiro, esta parece ser a solução mais limpa aqui. Em uma nota lateral, você deve considerar que isso só corresponde quando o elemento clicado é o elemento superior superior real.
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>
commonpike
fonte
0

A melhor solução seria lidar com o evento por meio de uma função javascript, mas para usar uma solução simples e rápida usando o elemento html diretamente e uma vez que o "event" e o "window.event" sejam descontinuados e não sejam universalmente suportados ( https://developer.mozilla.org/pt-BR/docs/Web/API/Window/event ), sugiro o seguinte "código rígido":

<div onclick="alert('blablabla'); (arguments[0] ? arguments[0].stopPropagation() : false);">...</div>
jose.serapicos
fonte