JavaScript Event Bubbling ve Capturing
Merhabalar. Bu yazımda JavaScript'te bulunan Bubbling ve Capturing özelliklerinden bahsedeceğim. Öncelikle bu kavramların Türkçe karşılıklarını vererek işe başlayalım; Bubble kabarcık, bubbling ise kabarcıklanma anlamlarına geliyor. Capturing ise yakalamak demek. Bu kavramları açıkladıktan sonra bubbling ve capturing özelliklerinin kullanıldığı addEventListener konusuna geçiş yapabiliriz.
JavaScript addEventListener
addEventListener, bir elemana herhangi bir olayda ne yapacağını belirten metottur. Örneğin; id değeri baslik olan elemana tıklanınca şunu yap, mouse ile üzerine gelince şunu yap gibi. Kullanımı ise aşağıdaki gibidir.
element.addEventListener(event, function, useCapture);
Bu ifadede yer alan kavramları açıklayalım;
element: İşlem yapılacak olan elementi belirtir. Yani olay yakalayıcı eklenecek olan elemanı. Örneğin; id değeri baslik olan veya class değeri icerik olan eleman gibi
event: Hangi olayda işlemin gerçekleştirileceğini belirler. Örneğin; tıklama, fare ile üzerine gelme gibi.
function: Yapılacak olan işlemi belirtir. Bu kısma daha önce tanımladığımız bir fonksiyonu yazabileceğimiz gibi istediğimiz işlemleri yapabileceğimiz bir fonksiyon ifadesi de yazabiliriz.
useCapture: Olayın bubbling (kabarcıklanma) veya capturing (yakalama) olduğunu belirten parametredir. Opsiyoneldir yani zorunlu değildir. Boolean (true/false) bir değer alır. Hiçbir değer yazılmazsa false değerini alır. Eğer false ise olayın bubbling (kabarcıklanma), true ise olayın capturing (yakalama) olduğunu belirtir.
İşte bütün bu karışıklık da zaten bu useCapture parametresinden kaynaklanmaktadır. Isınma turunu atlattıysak hızımızı biraz daha arttıralım ve bu karmaşıklığın neden kaynaklandığını bir örnek üzerinden açıklayalım.
İç içe geçmiş üç tane div ekliyorum. Id değerleri dıştan içe doğru bir, iki ve uc olsun. Siz dilerseniz farklı elemanları ve farklı id değerlerini kullanabilirsiniz.
<div id="bir">
<div id="iki">
<div id="uc"></div>
</div>
</div>
Olayın daha net anlaşılabilmesi için bu üç div'e ayrı ayrı stiller veriyorum.
#bir { float: left; width: 300px; height: 300px; background-color: green }
#iki { float: left; width: 250px; height: 250px; background-color: yellow; margin: 25px 0 0 25px }
#uc { float: left; width: 200px; height: 200px; background-color: orange; margin: 25px 0 0 25px}
Bu işlemlerin ardından aşağıdaki görünüme sahip bir HTML dosyası elde ediyorum. Aşağıdaki gördüğünüz alanlardan yeşil olanın id değeri bir, sarı olanın id değeri iki ve son olarak turuncu olanın ise id değeri uc olduğunu belirtelim.
Şimdi bu üç div'e de ayrı ayrı addEventListener ile click olayı ekleyelim. Önce elemanları getElementById ile seçelim.
var bir = document.getElementById("bir")
var iki = document.getElementById("iki")
var uc = document.getElementById("uc")
bir.addEventListener("click", function(){
alert("Birinci elemana tıkladınız. (Yeşil Alan)");
})
iki.addEventListener("click", function(){
alert("İkinci elemana tıkladınız. (Sarı Alan)");
})
uc.addEventListener("click", function(){
alert("Üçüncü elemana tıkladınız. (Turuncu Alan)");
})
Üç elaman için de tıklama olayına basit bir alert yani uyarı verdirme işlemi yaptık. Hangi elemana tıklanıyorsa o elemana ait uyarı mesajı gelecektir. Örneğin; id değeri bir olan elemana tıklanınca "Birinci elemana tıkladınız. (Yeşil Alan)" şeklinde bir uyarı gelecektir.
Gelelim Bubbling(Kabarcıklanma) ve Capturing(Yakalama) karmaşasına. Yazımın en başında belirttiğim gibi bu div'ler iç içe geçmiş durumda. En dışta id değeri bir, ortada id değeri iki ve en içte de id değeri uc olan eleman bulunuyor. Haliyle ben en içteki eleman olan uc'e yani turuncu alana tıkladığım zaman aslında hem iki hem de bir id değerli elemanlara da tıklamış oluyorum. Peki yukarı yazdığım click olaylarından önce hangisi çalışmalı?
İşte bütün mesela bu noktada. Yani halk arasında çok tipik bir soru var ya "Yumurta mı tavuktan çıkar, yoksa tavuk mu yumurtadan?" şeklinde, işte bu da tam öyle bir soru ve bu soruya cevap verenler iki farklı görüşü savunmuş.
Bir grup click olayının turuncu > sarı > yeşil yani uc > iki > bir sırasıyla çalışması gerektiğini savunmuş. Yani içten dışa doğru çalışması gerektiğini belirtmiş. İşte biz bu duruma kabarcıklanma yani bubbling diyoruz.
Diğer bir grup ise click olayının yeşil > sarı > turuncu yani bir > iki > uc sırasıyla çalışması gerektiğini savunmuş. Yani dıştan içe oğru çalışması gerektiğini belirtmiş. İşte biz bu duruma da capturing yani yakalama diyoruz.
Bu iki grup arasında derin fikir ayrılıkları oluşunca iki tarafı da memnun edebilmek için addEventListener metoduna üçüncü bir parametre ekleyip buna useCapture adını vermişler ve bu sorunu çözmüşler.
Eğer addEventListener metotlarını yukarıdaki gibi bırakırsanız useCapture parametresi false olacağından bubling (kabarcıklanma) özelliğini seçmiş olursunuz ve tıklama olayları içten dışa doğru çalışır.
Ama aşağıdaki gibi useCapture parametresine true değeri verirseniz bu sefer de capturing (yakalama) özelliğini seçmiş olursunuz ve click olayı dıştan içe doğru çalışır.
bir.addEventListener("click", function(){
alert("Birinci elemana tıkladınız. (Yeşil Alan)");
}, true)
iki.addEventListener("click", function(){
alert("İkinci elemana tıkladınız. (Sarı Alan)");
}, true)
uc.addEventListener("click", function(){
alert("Üçüncü elemana tıkladınız. (Turuncu Alan)");
},true)
İşte JavaScript'teki bubling (kabarcıklanma) ve capturing (yakalama) karmaşasının izahı bu şekilde. Çalışmaya ait dosyayı bu linkten indirebilirsiniz.
Soru, görüş ve önerilerinizi yorum olarak belirtebilirsiniz. Hayırlı çalışmalar dilerim.