Bu ders için video bulunmamaktadır.

Bu derse başlamak veya ilerlemenizi kaydetmek için lütfen giriş yapın veya kayıt olun.

Ders İçeriği

Giriş: Etkileşimli Web Sayfaları

Şimdiye kadar DOM'u kullanarak HTML elemanlarını seçmeyi, içeriklerini, niteliklerini ve stillerini değiştirmeyi öğrendik. Ancak web sayfalarını gerçekten dinamik ve etkileşimli kılan şey, kullanıcının eylemlerine veya tarayıcıda gerçekleşen diğer olaylara tepki verebilme yeteneğidir. İşte burada DOM olayları (events) devreye girer.

Olaylar, web sayfasında meydana gelen eylemlerdir. Bunlar kullanıcı tarafından tetiklenebilir (örneğin bir butona tıklama, fareyi bir elemanın üzerine getirme, klavyeden bir tuşa basma) veya tarayıcı tarafından otomatik olarak tetiklenebilir (örneğin sayfanın tamamen yüklenmesi, bir resmin yüklenememesi).

JavaScript, bu olayları "dinlememizi" ve olay gerçekleştiğinde belirli bir kod bloğunu (olay dinleyici - event listener veya olay işleyici - event handler) çalıştırmamızı sağlar. Bu sayede, kullanıcı etkileşimlerine yanıt veren, formları doğrulayan, animasyonları başlatan, AJAX istekleri gönderen ve çok daha fazlasını yapan web uygulamaları oluşturabiliriz.

Bu derste, yaygın DOM olaylarını, olayları dinlemenin farklı yollarını (özellikle addEventListener), olay nesnesini (event object) ve olay akışının önemli kavramlarını (bubbling, capturing, delegation) öğreneceğiz.

Yaygın DOM Olayları

Web sayfalarında karşılaşılan yüzlerce olay türü vardır. En yaygın olanlardan bazıları şunlardır:

  • Fare Olayları (Mouse Events):
    • click: Bir elemana tıklandığında.
    • dblclick: Bir elemana çift tıklandığında.
    • mouseover / mouseout: Fare imleci bir elemanın üzerine geldiğinde / üzerinden ayrıldığında.
    • mousedown / mouseup: Fare tuşuna basıldığında / bırakıldığında.
    • mousemove: Fare imleci bir eleman üzerinde hareket ettiğinde.
  • Klavye Olayları (Keyboard Events):
    • keydown: Bir tuşa basıldığında.
    • keyup: Basılı bir tuş bırakıldığında.
    • keypress: Karakter üreten bir tuşa basıldığında (genellikle keydown tercih edilir).
  • Form Olayları (Form Events):
    • submit: Bir form gönderildiğinde (genellikle <form> elemanında dinlenir).
    • change: Bir form elemanının (<input><select><textarea>) değeri değiştiğinde (genellikle odaktan çıkıldığında tetiklenir).
    • input: Bir <input> veya <textarea> elemanının değeri her değiştiğinde (anlık olarak).
    • focus: Bir form elemanı odaklandığında.
    • blur: Bir form elemanı odaktan çıktığında.
  • Pencere/Belge Olayları (Window/Document Events):
    • load: Sayfanın tüm kaynakları (resimler, CSS dosyaları vb.) tamamen yüklendiğinde (genellikle window üzerinde dinlenir).
    • DOMContentLoaded: HTML belgesi tamamen yüklenip ayrıştırıldığında (CSS, resimler beklenmez) (genellikle document üzerinde dinlenir).
    • resize: Tarayıcı penceresi yeniden boyutlandırıldığında (window üzerinde).
    • scroll: Sayfa kaydırıldığında (window veya kaydırılabilir bir eleman üzerinde).

Olay Dinleyicileri (Event Listeners) Ekleme

Bir olayı dinlemek ve gerçekleştiğinde bir fonksiyon çalıştırmak için birkaç yöntem vardır:

1. HTML Nitelikleri (Inline Event Handlers - Önerilmez)

Olay işleyici doğrudan HTML etiketinin içine on<olayadı> niteliği olarak yazılır. Örneğin: <button onclick="alert('Tıklandı!')">Tıkla</button>.

Bu yöntem genellikle önerilmez çünkü:

  • HTML ve JavaScript kodunu birbirine karıştırır, bakımı zorlaştırır.
  • Kodun okunabilirliğini azaltır.
  • Kapsam (scope) sorunlarına yol açabilir.
  • Sadece bir tane olay işleyici atanabilir.

2. DOM Özellikleri (DOM Properties - Daha İyi Ama Sınırlı)

JavaScript kodunda, elemanın on<olayadı> özelliğine bir fonksiyon atanır.

dom_properties.js
// HTML: Bana Tıkla

let buton1 = document.getElementById("buton1");

// Olay işleyici olarak bir fonksiyon atama
buton1.onclick = function() {
    console.log("Buton 1'e tıklandı! (DOM özelliği ile)");
};

// Başka bir fonksiyon atandığında önceki üzerine yazılır
buton1.onclick = function() {
    console.log("Yeni tıklama işleyicisi!"); // Sadece bu çalışır
};

// Olay işleyiciyi kaldırmak için null atama
// buton1.onclick = null;

Bu yöntem inline niteliklerden daha iyidir çünkü HTML ve JavaScript'i ayırır. Ancak hala bir sınırlaması vardır: Bir olay türü için sadece bir tane olay işleyici atanabilir. Yeni bir atama, eskisinin üzerine yazar.

3. addEventListener() (En İyi ve Önerilen Yöntem)

Modern JavaScript'te olayları dinlemek için en esnek, güçlü ve önerilen yöntemdir. Bir elemana aynı olay türü için birden fazla dinleyici eklemeye olanak tanır.

Sözdizimi: element.addEventListener(olayTipi, dinleyiciFonksiyon, seçeneklerVeyaUseCapture);

  • olayTipi: Dinlenecek olayın adı (string, örn. "click", "mouseover", "keydown"). "on" öneki kullanılmaz.
  • dinleyiciFonksiyon: Olay gerçekleştiğinde çalıştırılacak fonksiyon. Bu fonksiyona otomatik olarak bir olay nesnesi (event object) argüman olarak geçirilir.
  • seçeneklerVeyaUseCapture (Opsiyonel):
    • Boolean: true ise olay yakalama (capturing) aşamasında dinler, false (varsayılan) ise olay köpürme (bubbling) aşamasında dinler. (Aşağıda açıklanacak).
    • Nesne: Daha fazla seçenek sunar:
      • capture: Boolean, useCapture ile aynı işlevi görür.
      • once: Boolean, true ise dinleyici olay ilk kez tetiklendikten sonra otomatik olarak kaldırılır.
      • passive: Boolean, true ise dinleyici fonksiyonun preventDefault() metodunu çağırmayacağını tarayıcıya bildirir. Bu, özellikle scroll ve touch olaylarında performansı artırabilir.
addEventListener.js
// HTML: Tıkla (addEventListener)

let buton2 = document.getElementById("buton2");

function handleClick1() {
    console.log("Buton 2 - Dinleyici 1 çalıştı!");
}

function handleClick2(event) { // Olay nesnesini alabiliriz
    console.log("Buton 2 - Dinleyici 2 çalıştı!");
    console.log("Olay Tipi:", event.type); // "click"
    console.log("Hedef Eleman:", event.target); // Butonun kendisi
}

// İlk dinleyiciyi ekle
buton2.addEventListener("click", handleClick1);

// İkinci dinleyiciyi ekle (aynı olay için birden fazla eklenebilir)
buton2.addEventListener("click", handleClick2);

// Dinleyiciyi kaldırma: removeEventListener()
// Kaldırmak için aynı fonksiyon referansını kullanmak gerekir!
// buton2.removeEventListener("click", handleClick1);

removeEventListener()

addEventListener ile eklenmiş bir olay dinleyicisini kaldırmak için kullanılır. Kaldırılacak dinleyici fonksiyonun ve seçeneklerin (veya useCapture değerinin) addEventListener ile eklenirken kullanılanlarla tam olarak aynı olması gerekir.

removeEventListener.js
let buton3 = document.createElement("button");
buton3.textContent = "Dinleyici Kaldır";
document.body.append(buton3);

function tekSeferlikMesaj() {
    console.log("Bu mesaj sadece bir kere görünecek!");
    // Kendini kaldır
    buton3.removeEventListener("click", tekSeferlikMesaj);
}

buton3.addEventListener("click", tekSeferlikMesaj);

// Alternatif: { once: true } seçeneği
let buton4 = document.createElement("button");
buton4.textContent = "Sadece Bir Kez Tıkla";
document.body.append(buton4);

buton4.addEventListener("click", function() {
    console.log("Bu sadece ilk tıklamada çalışır.");
}, { once: true });

Olay Nesnesi (Event Object)

Bir olay tetiklendiğinde, tarayıcı otomatik olarak bir olay nesnesi (genellikle event veya e olarak adlandırılır) oluşturur ve bu nesneyi olay dinleyici fonksiyonuna ilk argüman olarak geçirir. Bu nesne, gerçekleşen olay hakkında önemli bilgiler içerir.

Bazı önemli olay nesnesi özellikleri ve metodları:

  • event.type: Gerçekleşen olayın türünü (string, örn. "click", "keydown") döndürür.
  • event.target: Olayın ilk olarak üzerinde gerçekleştiği elemanı (olayın kaynağını) döndürür. Olay köpürmesi (bubbling) sırasında değişmez.
  • event.currentTarget: Olay dinleyicisinin o anda bağlı olduğu elemanı döndürür. Bubbling sırasında, bu olay dinleyicisinin eklendiği eleman olacaktır (this ile genellikle aynıdır).
  • event.preventDefault(): Tarayıcının olayla ilişkili varsayılan davranışını engeller. Örneğin, bir formun submit olayında sayfanın yeniden yüklenmesini veya bir bağlantının click olayında yeni sayfaya gidilmesini engellemek için kullanılır.
  • event.stopPropagation(): Olayın DOM ağacında daha yukarıya (veya aşağıya) yayılmasını (köpürme veya yakalama) durdurur.
  • Fare Olayları İçin: event.clientXevent.clientY (pencereye göre koordinatlar), event.pageXevent.pageY (sayfaya göre koordinatlar), event.button (hangi fare tuşuna basıldığı).
  • Klavye Olayları İçin: event.key (basılan tuşun adı, örn. "a", "Enter", "Shift"), event.code (fiziksel tuş kodu, örn. "KeyA", "Enter", "ShiftLeft"), event.altKeyevent.ctrlKeyevent.shiftKey (yardımcı tuşların basılı olup olmadığı - boolean).
event_object.js
// HTML: Engellenecek Link
// HTML: 

let link = document.getElementById("engelle");
let input = document.getElementById("klavye-input");

link.addEventListener("click", function(event) {
    console.log("Linke tıklandı!");
    console.log("Olay Tipi:", event.type);
    console.log("Hedef:", event.target); //  elemanı
    console.log("Varsayılan davranış engelleniyor...");
    event.preventDefault(); // Linkin açılmasını engelle
});

input.addEventListener("keydown", function(e) {
    console.log(`Tuşa basıldı: Key='${e.key}', Code='${e.code}'`);
    if (e.key === "Enter") {
        console.log("Enter'a basıldı!");
    }
    if (e.ctrlKey && e.key === 's') {
        e.preventDefault(); // Ctrl+S'in varsayılan kaydetme işlemini engelle
        console.log("Ctrl+S engellendi!");
    }
});

Olay Akışı: Bubbling ve Capturing

Bir HTML elemanına tıkladığınızda, olay sadece o eleman üzerinde gerçekleşmez. Olay, DOM ağacında belirli bir sıra izleyerek yayılır. Bu yayılma iki aşamada gerçekleşir:

  1. Yakalama Aşaması (Capturing Phase): Olay, pencereden (window) başlayarak DOM ağacında aşağı doğru, olayın hedef elemanına kadar iner. Bu aşamada olay dinleyicileri varsayılan olarak çalışmaz.
  2. Hedef Aşaması (Target Phase): Olay, doğrudan hedef elemana ulaşır.
  3. Köpürme Aşaması (Bubbling Phase): Olay, hedef elemandan başlayarak DOM ağacında yukarı doğru, pencereye (window) kadar geri çıkar. Varsayılan olarak olay dinleyicileri bu aşamada çalışır.

Örneğin, bir butonun içindeki bir <span> elemanına tıklarsanız, olay önce window -> html -> body -> ... -> button -> span şeklinde iner (capturing), sonra span üzerinde tetiklenir (target), sonra span -> button -> ... -> body -> html -> window şeklinde yukarı çıkar (bubbling).

addEventListener metodunun üçüncü parametresi (veya seçenekler nesnesindeki capture özelliği) hangi aşamada dinleme yapılacağını belirler:

  • false veya { capture: false } (Varsayılan): Köpürme (Bubbling) aşamasında dinler.
  • true veya { capture: true }: Yakalama (Capturing) aşamasında dinler.
bubbling_capturing.js
// HTML:
// 
//   Dış Div
//   İç Buton
// 

let disDiv = document.getElementById("disDiv");
let icButon = document.getElementById("icButon");

// Bubbling dinleyicileri (varsayılan)
disDiv.addEventListener("click", function(e) {
    console.log("Dış Div Bubbling (Hedef: " + e.target.id + ")");
});
icButon.addEventListener("click", function(e) {
    console.log("İç Buton Bubbling (Hedef: " + e.target.id + ")");
});

// Capturing dinleyicileri
disDiv.addEventListener("click", function(e) {
    console.log("Dış Div Capturing (Hedef: " + e.target.id + ")");
}, true); // veya { capture: true }
icButon.addEventListener("click", function(e) {
    console.log("İç Buton Capturing (Hedef: " + e.target.id + ")");
}, true);

// İç Buton'a tıklandığında konsol çıktısı:
// Dış Div Capturing (Hedef: icButon)
// İç Buton Capturing (Hedef: icButon)
// İç Buton Bubbling (Hedef: icButon)
// Dış Div Bubbling (Hedef: icButon)

Olay Yayılmasını Durdurma: event.stopPropagation()

Bazen bir olayın daha fazla yayılmasını (yukarı veya aşağı) engellemek isteyebiliriz. Örneğin, içteki bir elemana tıklandığında dıştaki elemanın tıklama olayının tetiklenmesini istemeyebiliriz. Bunun için olay dinleyici fonksiyonu içinde event.stopPropagation() metodu çağrılır.

stopPropagation.js
// Önceki HTML ve Dış Div Bubbling dinleyicisi aynı kalsın.

icButon.addEventListener("click", function(e) {
    console.log("İç Buton Bubbling - Yayılma durduruluyor!");
    e.stopPropagation(); // Olayın Dış Div'e köpürmesini engelle
});

// İç Buton'a tıklandığında konsol çıktısı:
// İç Buton Bubbling - Yayılma durduruluyor!
// (Dış Div Bubbling çalışmaz)

Olay Yetkilendirme (Event Delegation)

Eğer çok sayıda elemana (örneğin bir listedeki tüm <li> elemanlarına) aynı olay dinleyicisini eklemek isterseniz, her birine ayrı ayrı addEventListener eklemek performans açısından verimsiz olabilir. Ayrıca, listeye sonradan eklenen yeni elemanlar için tekrar dinleyici eklemeniz gerekir.

Olay Yetkilendirme (Event Delegation), bu sorunu çözmek için kullanılan yaygın bir tekniktir. Fikir şudur: Olay dinleyicisini her bir çocuğa ayrı ayrı eklemek yerine, ortak bir ebeveyn elemana (örneğin <ul> listesine) eklersiniz. Olay köpürmesi (bubbling) sayesinde, çocuk elemanlardan birinde gerçekleşen olay ebeveyne kadar ulaşacaktır. Ebeveyndeki dinleyici fonksiyonu içinde event.target özelliğini kullanarak olayın aslında hangi çocuk eleman üzerinde başladığını kontrol edebilir ve sadece ilgili çocuk eleman için işlem yapabilirsiniz.

Avantajları:

  • Daha az olay dinleyici eklenir, bu da performansı artırır ve bellek kullanımını azaltır.
  • Ebeveyne sonradan eklenen yeni çocuk elemanlar için otomatik olarak çalışır (tekrar dinleyici eklemeye gerek kalmaz).
  • Kod daha basit ve yönetilebilir olabilir.
event_delegation.js
// HTML:
// 
//   Ürün 1 Sil
//   Ürün 2 Sil
//   Ürün 3 Sil
// 
// Yeni Ürün Ekle

let urunListesi = document.getElementById("urun-listesi");
let ekleButonu = document.getElementById("ekle-btn");

// Olay dinleyicisini ebeveyn olan 
    'ye ekle urunListesi.addEventListener("click", function(event) { // Olayın bir "sil-btn" sınıfına sahip butonda mı başladığını kontrol et if (event.target.classList.contains("sil-btn")) { console.log("Sil butonuna tıklandı!"); // Tıklanan butonun ait olduğu öğesini bul ve kaldır let listItem = event.target.closest("li"); // En yakın
  • ebeveynini bulur if (listItem) { console.log(listItem.textContent.split(" ")[0] + " " + listItem.textContent.split(" ")[1] + " siliniyor..."); listItem.remove(); } } }); // Yeni ürün ekleme fonksiyonu (yeni eklenenler için de silme çalışacak) ekleButonu.addEventListener("click", function() { let yeniUrunNo = urunListesi.children.length + 1; let yeniLi = document.createElement("li"); yeniLi.innerHTML = `Ürün ${yeniUrunNo} Sil`; urunListesi.append(yeniLi); console.log(`Ürün ${yeniUrunNo} eklendi.`); });

Alıştırmalar

  1. Bir butona tıklandığında, sayfanın arka plan rengini rastgele bir renge değiştiren bir kod yazın.
  2. Bir metin kutusuna (<input type="text">) yazı yazıldığında, yazılan metni anlık olarak bir paragraf (<p>) içinde gösterin (input olayını kullanın).
  3. Bir resmin üzerine fare ile gelindiğinde resmin kenarlığını (border) değiştiren, fare çekildiğinde eski haline döndüren bir kod yazın.
  4. Bir form oluşturun (isim ve e-posta alanları içeren). Form gönderildiğinde (submit olayı), varsayılan gönderme işlemini engelleyin (preventDefault()) ve girilen değerleri konsola yazdırın.
  5. Bir <ul> listesi oluşturun. Olay yetkilendirme (event delegation) kullanarak, listedeki herhangi bir <li> öğesine tıklandığında o öğenin metnini konsola yazdırın.

Bu derste, JavaScript ile web sayfalarını etkileşimli hale getirmenin temelini oluşturan DOM olaylarını öğrendik:

  • Olaylar: Kullanıcı veya tarayıcı tarafından tetiklenen eylemlerdir (click, keydown, load, submit vb.).
  • Olay Dinleyicileri: Olayları yakalayıp tepki veren fonksiyonlardır. En iyi yöntem addEventListener() kullanmaktır.
  • addEventListener(type, listener, options): Bir elemana olay dinleyici ekler. Birden fazla dinleyici eklenebilir. removeEventListener() ile kaldırılır.
  • Olay Nesnesi (event): Olay hakkında bilgi içerir (type, target, key, clientX vb.) ve varsayılan davranışı engellemek (preventDefault()) veya yayılmayı durdurmak (stopPropagation()) için metodlar sunar.
  • Olay Akışı: Olaylar önce yakalama (capturing) aşamasında aşağı iner, sonra köpürme (bubbling) aşamasında yukarı çıkar. Dinleyiciler varsayılan olarak bubbling aşamasında çalışır.
  • Olay Yetkilendirme (Event Delegation): Çok sayıda eleman için olayları yönetmenin verimli bir yoludur. Dinleyici ebeveyne eklenir ve event.target ile olay kaynağı kontrol edilir.

DOM olaylarını anlamak ve etkili bir şekilde kullanmak, modern web geliştirmenin vazgeçilmez bir parçasıdır.

Bir sonraki bölümde, JavaScript'in daha ileri konularına, özellikle eşzamansız (asynchronous) işlemlere ve AJAX'a giriş yapacağız.