Elementos da marcação HTML podem ser aninhados uns dentro de outros, criando-se uma cadeia de elementos-filhos e seus elementos-ancestrais. Neste cenário, quando se atrela um evento JavaScript (por exemplo: o evento clicar) a um determinado elemento E do DOM ele, evento, será disparado mesmo que o clique ocorre em um elemento-filho de E.
O nome usado na terminologia JavaScript para descrever esse efeito é event bubbling. Bubbling em tradução livre significa borbulhante, assim em linguagem não técnica podemos dizer que eventos JavaScript borbulham, no sentido de que são disparados por ação em elementos descendentes do elemento a que são atrelados.
No exemplo mostrado a seguir o evento clique dispara o alerta mesmo quando o clique ocorre nos elementos em
ou code
, embora ele, evento, tenha sido atrelado ao elemento div
.
<div >Nesta área experimente clicar no elementoEM
aninhado não clicando noDIV
e observe que há o disparo do alerta.Esse efeito ocorre porque o evento “borbulha” bubbles do elemento mais aninhado para seu elemento-ancestral.
Bubbling
O princípio fundamental do efeito bubbling diz o seguinte:
Depois que um evento é disparado no elemento mais distante de uma cadeia aninhada do DOM ele é disparado em seus elementos ancestrais na ordem crescente de aninhamento.Observe um exemplo com três elementos
div
aninhados:<!DOCTYPE HTML> <html> <body> <link type="text/css" rel="stylesheet" href="example.css"> <div class="d1">1 <!-- ancestral mais alto --> <div class="d2">2 <div class="d3">3 <!-- descendente mais baixo --> </div> </div> </div> </body> </html>
O efeito bubbling da JavaScript faz com que um clique no no div 3 dispare o evento a ele atrelado primeiro no elemento descendente mais baixo 3 (também chamado de target), depois no elemento 2 e finalmente no elemento 1.
um clique no no div 2 dispara o evento a ele atrelado primeiro no elemento 2 (também chamado de target) e depois no elemento 1.
um clique no no div 1 dispara o evento a ele atrelado (também chamado de target) e nada mais.
A ordem de disparo é chamada de bubbling order, pois o evento “borbulha” do elemento descendente mais baixo para seus ancestrais tal como ocorre com uma bolha de ar na água.
O exemplo mostrado a seguir é interativo e demonstra visualmente o efeito bubble. Clique os divs:
Observe a seguir os código do exemplo:
HTML
<div class="d1">1 <div class="d2">2 <div class="d3">3 </div> </div> </div>CSS
<style> .d1 { background-color: green; position: relative; width: 150px; height: 150px; text-align: center; cursor: pointer; } .d2 { background-color: blue; position: absolute; top: 25px; left: 25px; width: 100px; height: 100px; } .d3 { background-color: red; position: absolute; top: 25px; left: 25px; width: 50px; height: 50px; line-height: 50px; } </style>JavaScript
<script> var divs = document.getElementsByTagName('div') for(var i=0; i<divs.length; i++) { divs[i].onclick = function(e) { e = e || event var target = e.target || e.srcElement this.style.backgroundColor='yellow' alert("target = "+target.className+", this="+this.className) this.style.backgroundColor = '' } } </script>this e event.target
O elemento descendente mais baixo que dispara o evento é chamado de target ou elemento originário.
O navegador Internet Explorer define para target a propriedade
srcElement
e os navegadores em conformidade com o W3C definem a propriedadeevent.target
.O código JavaScript cross-browser é mostrado a seguir:
var target = event.target || event.srcElementHandlers (ações disparadas por eventos) em ancestrais:
No exemplo interativo mostrado a seguir para cada elemento div
foi definido o atributo onclick
para disparar um handler cuja saída mostra quem é target e quem é this.
Clique em um div
e observe o seguinte:
Observe a seguir os código do exemplo:
HTML
<div class="d1">1 <div class="d2">2 <div class="d3">3 </div> </div> </div>
CSS
<style> .d1 { background-color: green; position: relative; width: 150px; height: 150px; text-align: center; cursor: pointer; } .d2 { background-color: blue; position: absolute; top: 25px; left: 25px; width: 100px; height: 100px; } .d3 { background-color: red; position: absolute; top: 25px; left: 25px; width: 50px; height: 50px; line-height: 50px; } </style>
JavaScript
<script> var divs = document.getElementsByTagName('div') for(var i=0; i<divs.length; i++) { divs[i].onclick = function(e) { e = e || event var target = e.target || e.srcElement this.style.backgroundColor='yellow' alert("target = "+target.className+", this="+this.className) this.style.backgroundColor = '' } } </script>
Em navegadores em conformidade com o W3C this também pode ser obtido com uso de event.currentTarget
.
Vimos que o efeito bubbling percorre elementos aninhados no DOM de baixo para cima (do elemento filho para seus ancestrais).
É possível interromper o efeito bubbling antes que ele percorra todos os elementos aninhados.
O código para interromper o efeito em navegadores em conformidade com o W3C é mostrado a seguir:
event.stopPropagation()
Para os IE<9:
event.cancelBubble = true
E, finalmente o código cross-browser:
element.onclick = function(event) { event = event || window.event // cross-browser event if (event.stopPropagation) { // opção para poadrões W3C event.stopPropagation() } else { // opção para IE event.cancelBubble = true } }
Simplificação do código cross-browser:
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true)
Se a um elemento for atrelado vários handlers disparados pelo mesmo evento, os handelers serão independentes..
Por exemplo: se em um link existerem dois handelers disparados por click, interromper o efeito bubbling em um dos handelers não interrompe no outro. O navegador não tem qualquer compromisso com a ordem de disparo dos handelers.
En todos os navegadores, exceto nos IE<9 os eventos são processados em dois estágios.
No primeiro estágio o evento percorre a cadeia aninhada de cima para baixo (dos elementos ancestrais para os elementos descendentes) – este estágio é chamado capturing. No outro estágio ocorre o efeito bubbles como estudado. Este comportamento é padronizado pelas especificações do W3C.
Segundo esse modelo o comportamento do evento é:
Todos os métodos de manipulação de eventos simplesmente ignoram a fase caputuring. Para que o evento ocorra na fase capturing declaramos o último argumento método addEventListener
como sendo true.
Observe o código mostrado a seguir:
elem.addEventListener( type, handler, phase )
Clique em um dos divs mostrados a seguir para constatar o efeito capturing em ação (exceto IE<9):
A ordem deverá ser 1 -> 2 -> 3.
Observe o código JavaScript desse exemplo:
var divs = document.getElementsByTagName('div') for(var i=0; i<divs.length; i++) { divs[i].addEventListener("click", highlightThis, true) }
Na prática a fase capturing raramente é usada, mas
existem eventos que não “borbulham”, mas honram o efeito capturing. Por exemplo: onfocus
e onblur
.
No exemplo mostrado a seguir atrelamos handlers a ambos os estágios.
Clique em um dos divs mostrados a seguir para constatar a ordem de processamento dos eventos (exceto IE<9):
A ordem deverá ser 1 -> 2 -> 3 -> 3 -> 2 -> 1.
Observe o código JavaScript desse exemplo:
var divs = document.getElementsByTagName('div') for(var i=0; i<divs.length; i++) { divs[i].addEventListener("click", highlightThis, true) divs[i].addEventListener("click", highlightThis, false) }
addEventListener
for declarado true, aliás essa é a única maneira de disparar o evento na fase capturing.event.cancelBubble=true
(IE) ou com event.stopPropagation()
para os demais navegadores.Crédito: http://learn.javascript.ru/
Publicado segundo os termos da licença CC BY-NC-SA.
Em 2006 comecei a publicar nesse blog uma série de desafios CSS que consistiam em…
Há muito tempo que eu não publico um "Teste seu conhecimento". Esta semana, revendo algumas…
HTML5? Web universal? É comum eu me deparar com dúvidas sobre a HTML5 não só…
Quem é Tab Atkins Jr? Tab Atkins Jr, um desenvolvedor americano, trabalhou durante muitos anos…
Pessoal, a BrazilJS Conf 2013 disponibilizou para o Maujor cupons de desconto para serem oferecidos…
Ultimamente recebi vários emails de meus leitores perguntando com criar o efeito que existe no…
View Comments
Seu blog é excelente. Estou aprendendo um pouco sobre programação e a sua página é uma de minhas fontes principais para tirar duvidas.
Parabéns! ótimas dicas, estou começando a apreender um pouco sobre programação, tentando melhorar meu site! obrigado, dicas bem uteis!
Seu blog é excelente. Estou aprendendo um pouco sobre programação e a sua página é uma de minhas fontes principais para tirar duvidas.
Estou muito grato pelo que você compartilhe este artigo, eu incluído na categoria de iniciantes para jogar assuntos javascrip ou html, onde eu poderia aprender ?? se for permitido , existe um site on-line para aprender o básico sobre html ?? mendigar em responder , estou muito ansioso para ser capaz de dominar as ligações do HTML ou qualquer javascrip , obrigado
Video Bokep
Assim como o Cesar não fico comentando, mas hj concordo com ele... estou aprendendo com o livro Guia Definitivo e sou iniciante, mas sempre vejo seus conteúdo quando preciso. xD
Muito bom! Sou Programador Web e sempre acompanho os posts deste blog sem falar no site do maujor.com que para mim é essencial uma passada por lá mesmo que seja rápida! Aqui sempre há algo de novo e interessante para se aprender. Eu sempre que posso passo por aqui mas somente desta vez resolvi comentar. Este post me orientou bastante em trabalhos que eu estava desenvolvendo. Este site é e sempre será um incentivo para eu continuar crescendo e aprendendo constantemente. Parabéns a todos pela rica iniciativa de partilhar conhecimentos de qualidade de forma didática, clara e objetiva!!!
Olá, adorei as dicas, at+
Tita Carré
Excelente post! Eu mesmo já tive essa dúvida e sempre vejo gente procurando saber: como cancelar evento de clique atrelado a um elemento pai durante o clique de um elemento filho... Enfim, esse artigo esclarece bem a questão.