Logo

Bölüm 6: DOM Manipülasyonu ve Olay Yönetimi

15 Haziran 2025
9 dk okuma süresi
dom-manipulasyonu-olay-yonetimi

DOM Nedir?

DOM (Document Object Model), HTML belgelerinin JavaScript tarafından manipüle edilebilir hale getirilmiş ağaç yapısıdır. DOM sayesinde JavaScript ile web sayfasının içeriğini, stilini ve yapısını dinamik olarak değiştirebiliriz.

DOM Ağaç Yapısı

<!DOCTYPE html>
<html>
<head>
    <title>Sayfa Başlığı</title>
</head>
<body>
    <div id="container">
        <h1 class="baslik">Merhaba Dünya</h1>
        <p class="metin">Bu bir paragraftır.</p>
    </div>
</body>
</html>

Bu HTML, DOM’da şu şekilde temsil edilir:

  • document (kök)
    • html
      • head
        • title
      • body
        • div#container
          • h1.baslik
          • p.metin

Element Seçimi

Temel Seçim Metodları

// ID ile seçim
let baslik = document.getElementById('baslik');
console.log(baslik);
 
// Class ile seçim (ilk bulduğu)
let ilkMetin = document.getElementsByClassName('metin')[0];
 
// Tag ile seçim
let tumParagraflar = document.getElementsByTagName('p');
 
// CSS seçici ile (ilk bulduğu)
let container = document.querySelector('#container');
let ilkBaslik = document.querySelector('.baslik');
let ilkP = document.querySelector('p');
 
// CSS seçici ile (hepsini)
let tumMetinler = document.querySelectorAll('.metin');
let tumDivler = document.querySelectorAll('div');

Gelişmiş Seçim Teknikleri

// Kombineli seçiciler
let containerIcindekiBaslik = document.querySelector('#container h1');
let metinSinifliP = document.querySelector('p.metin');
 
// Attribute seçiciler
let emailInputu = document.querySelector('input[type="email"]');
let baslikMetinli = document.querySelector('h1[title="ana-baslik"]');
 
// Pseudo seçiciler
let ilkCocuk = document.querySelector('div:first-child');
let sonCocuk = document.querySelector('div:last-child');
let nciCocuk = document.querySelector('li:nth-child(3)');
 
// Multiple seçim
let baslikVeParagraf = document.querySelectorAll('h1, p');

Element İçeriğini Değiştirme

Text İçeriği

let baslik = document.querySelector('h1');
 
// Sadece metin içeriği
baslik.textContent = 'Yeni Başlık';
console.log(baslik.textContent); // "Yeni Başlık"
 
// HTML tags ile birlikte metin
baslik.innerText = 'Görünen Metin'; // CSS ile gizli içeriği dahil etmez
 
// HTML içeriği
baslik.innerHTML = '<strong>Kalın</strong> Başlık';

HTML İçeriği Manipülasyonu

let container = document.querySelector('#container');
 
// Mevcut içeriği değiştirme
container.innerHTML = `
    <h2>Yeni Başlık</h2>
    <p>Yeni paragraf içeriği</p>
    <button onclick="alert('Tıklandı!')">Tıkla</button>
`;
 
// İçeriğe ekleme
container.innerHTML += '<div>Ek içerik</div>';
 
// Güvenli metin ekleme (XSS koruması)
let kullaniciGirdisi = '<script>alert("Hack!")</script>';
let guvenliDiv = document.createElement('div');
guvenliDiv.textContent = kullaniciGirdisi; // Script çalışmaz
container.appendChild(guvenliDiv);

Element Özellikleri (Attributes)

Attribute Yönetimi

let resim = document.querySelector('img');
 
// Attribute okuma
let src = resim.getAttribute('src');
let alt = resim.getAttribute('alt');
 
// Attribute değiştirme
resim.setAttribute('src', 'yeni-resim.jpg');
resim.setAttribute('alt', 'Yeni resim açıklaması');
 
// Attribute varlığını kontrol etme
if (resim.hasAttribute('title')) {
    console.log('Title attribute var');
}
 
// Attribute silme
resim.removeAttribute('title');
 
// Data attributeler
let element = document.querySelector('.veri-elementi');
element.setAttribute('data-kullanici-id', '123');
element.setAttribute('data-durum', 'aktif');
 
// Dataset ile erişim (daha pratik)
element.dataset.kullaniciId = '456';
element.dataset.durum = 'pasif';
console.log(element.dataset.kullaniciId); // "456"

Class Yönetimi

let element = document.querySelector('.test');
 
// Class ekleme
element.classList.add('yeni-class');
element.classList.add('class1', 'class2', 'class3');
 
// Class silme
element.classList.remove('eski-class');
 
// Class toggle (varsa sil, yoksa ekle)
element.classList.toggle('aktif');
 
// Class kontrol etme
if (element.classList.contains('gizli')) {
    element.classList.remove('gizli');
}
 
// Tüm class'ları değiştirme
element.className = 'tamamen-yeni-classlar';

Stil Değiştirme

let kutu = document.querySelector('.kutu');
 
// Tek stil özelliği
kutu.style.backgroundColor = 'red';
kutu.style.fontSize = '20px';
kutu.style.margin = '10px auto';
 
// Çoklu stil (camelCase kullanın)
kutu.style.cssText = `
    background-color: blue;
    color: white;
    padding: 20px;
    border-radius: 10px;
`;
 
// Computed style okuma
let hesaplananStil = window.getComputedStyle(kutu);
console.log(hesaplananStil.backgroundColor);
console.log(hesaplananStil.fontSize);

Element Oluşturma ve Ekleme

Yeni Element Oluşturma

// Element oluşturma
let yeniDiv = document.createElement('div');
let yeniP = document.createElement('p');
let yeniButton = document.createElement('button');
 
// İçerik ekleme
yeniDiv.textContent = 'Yeni div içeriği';
yeniP.innerHTML = 'Bu bir <strong>paragraf</strong>';
yeniButton.textContent = 'Tıkla Beni';
 
// Özellik ekleme
yeniDiv.className = 'dinamik-div';
yeniDiv.id = 'yeni-id';
yeniButton.setAttribute('data-action', 'submit');
 
// Event ekleme
yeniButton.addEventListener('click', function() {
    alert('Dinamik buton tıklandı!');
});

Element Yerleştirme

let container = document.querySelector('#container');
 
// Element ekleme
container.appendChild(yeniDiv);        // Sona ekle
container.appendChild(yeniP);
container.appendChild(yeniButton);
 
// Belirli pozisyona ekleme
let ilkElement = container.firstElementChild;
container.insertBefore(yeniDiv, ilkElement); // Başa ekle
 
// Modern metodlar (IE desteklemiyor)
container.prepend(yeniDiv);           // Başa ekle
container.append(yeniP);              // Sona ekle
ilkElement.before(yeniButton);        // Önüne ekle
ilkElement.after(yeniDiv);            // Arkasına ekle

Element Silme

let silinecekElement = document.querySelector('.silinecek');
 
// Klasik yöntem
silinecekElement.parentNode.removeChild(silinecekElement);
 
// Modern yöntem
silinecekElement.remove();
 
// Tüm çocukları silme
container.innerHTML = '';
 
// Seçici ile silme
document.querySelectorAll('.gecici').forEach(el => el.remove());

Olay Yönetimi (Event Handling)

Temel Event Listener

let button = document.querySelector('#myButton');
 
// Event ekleme
button.addEventListener('click', function() {
    console.log('Buton tıklandı!');
});
 
// Arrow function ile
button.addEventListener('click', () => {
    console.log('Arrow function ile event');
});
 
// Named function ile
function buttonClick() {
    console.log('Named function ile event');
}
button.addEventListener('click', buttonClick);
 
// Event silme
button.removeEventListener('click', buttonClick);

Event Object

button.addEventListener('click', function(event) {
    console.log('Event tipi:', event.type);           // 'click'
    console.log('Hedef element:', event.target);      // Tıklanan element
    console.log('Mouse pozisyonu:', event.clientX, event.clientY);
    
    // Varsayılan davranışı engelleme
    event.preventDefault();
    
    // Event bubbling'i durdurma
    event.stopPropagation();
});
 
// Klavye eventleri
document.addEventListener('keydown', function(event) {
    console.log('Basılan tuş:', event.key);
    console.log('Tuş kodu:', event.code);
    
    if (event.key === 'Enter') {
        console.log('Enter tuşuna basıldı');
    }
    
    if (event.ctrlKey && event.key === 's') {
        event.preventDefault(); // Ctrl+S'i engelle
        console.log('Kaydetme işlemi');
    }
});

Yaygın Event Türleri

let input = document.querySelector('#textInput');
let form = document.querySelector('#myForm');
 
// Mouse eventleri
button.addEventListener('mouseenter', () => console.log('Mouse üzerine geldi'));
button.addEventListener('mouseleave', () => console.log('Mouse ayrıldı'));
button.addEventListener('mousedown', () => console.log('Mouse basıldı'));
button.addEventListener('mouseup', () => console.log('Mouse bırakıldı'));
 
// Klavye eventleri
input.addEventListener('keydown', (e) => console.log('Tuş basıldı:', e.key));
input.addEventListener('keyup', (e) => console.log('Tuş bırakıldı:', e.key));
 
// Form eventleri
input.addEventListener('focus', () => console.log('Input odaklandı'));
input.addEventListener('blur', () => console.log('Input odağı kaybetti'));
input.addEventListener('input', (e) => console.log('Değer değişti:', e.target.value));
input.addEventListener('change', (e) => console.log('Değer tamamlandı:', e.target.value));
 
form.addEventListener('submit', function(e) {
    e.preventDefault(); // Sayfayı yenilemeyi engelle
    console.log('Form gönderildi');
});
 
// Sayfa eventleri
window.addEventListener('load', () => console.log('Sayfa tamamen yüklendi'));
window.addEventListener('resize', () => console.log('Pencere boyutu değişti'));
window.addEventListener('scroll', () => console.log('Sayfa kaydırıldı'));

Event Delegation

// Container'a tek event listener, tüm çocuklar için çalışır
let lista = document.querySelector('#liste');
 
lista.addEventListener('click', function(event) {
    if (event.target.tagName === 'LI') {
        console.log('Liste öğesi tıklandı:', event.target.textContent);
        event.target.classList.toggle('seçili');
    }
    
    if (event.target.classList.contains('sil-button')) {
        event.target.parentElement.remove();
    }
});
 
// Dinamik olarak eklenen elementler için de çalışır
function yeniOgeEkle(metin) {
    let li = document.createElement('li');
    li.innerHTML = `
        ${metin}
        <button class="sil-button">Sil</button>
    `;
    lista.appendChild(li);
}

Pratik Örnekler

Todo List Uygulaması

class TodoApp {
    constructor() {
        this.todos = [];
        this.init();
    }
    
    init() {
        this.createHTML();
        this.bindEvents();
    }
    
    createHTML() {
        document.body.innerHTML = `
            <div class="todo-app">
                <h1>Todo List</h1>
                <div class="input-container">
                    <input type="text" id="todoInput" placeholder="Yeni görev ekle...">
                    <button id="addBtn">Ekle</button>
                </div>
                <ul id="todoList"></ul>
                <div class="stats">
                    <span id="totalCount">Toplam: 0</span>
                    <span id="completedCount">Tamamlanan: 0</span>
                </div>
            </div>
        `;
        
        // CSS ekleme
        let style = document.createElement('style');
        style.textContent = `
            .todo-app { max-width: 500px; margin: 50px auto; padding: 20px; }
            .input-container { display: flex; margin-bottom: 20px; }
            #todoInput { flex: 1; padding: 10px; margin-right: 10px; }
            button { padding: 10px 15px; cursor: pointer; }
            li { padding: 10px; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; }
            .completed { text-decoration: line-through; opacity: 0.6; }
            .stats { margin-top: 20px; }
        `;
        document.head.appendChild(style);
    }
    
    bindEvents() {
        let input = document.getElementById('todoInput');
        let addBtn = document.getElementById('addBtn');
        let todoList = document.getElementById('todoList');
        
        // Ekleme
        addBtn.addEventListener('click', () => this.addTodo());
        input.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') this.addTodo();
        });
        
        // Tıklama delegasyonu
        todoList.addEventListener('click', (e) => {
            let li = e.target.closest('li');
            if (!li) return;
            
            let id = parseInt(li.dataset.id);
            
            if (e.target.classList.contains('complete-btn')) {
                this.toggleTodo(id);
            } else if (e.target.classList.contains('delete-btn')) {
                this.deleteTodo(id);
            }
        });
    }
    
    addTodo() {
        let input = document.getElementById('todoInput');
        let text = input.value.trim();
        
        if (!text) return;
        
        let todo = {
            id: Date.now(),
            text: text,
            completed: false
        };
        
        this.todos.push(todo);
        input.value = '';
        this.render();
    }
    
    toggleTodo(id) {
        let todo = this.todos.find(t => t.id === id);
        if (todo) {
            todo.completed = !todo.completed;
            this.render();
        }
    }
    
    deleteTodo(id) {
        this.todos = this.todos.filter(t => t.id !== id);
        this.render();
    }
    
    render() {
        let todoList = document.getElementById('todoList');
        
        todoList.innerHTML = this.todos.map(todo => `
            <li data-id="${todo.id}" class="${todo.completed ? 'completed' : ''}">
                <span>${todo.text}</span>
                <div>
                    <button class="complete-btn">${todo.completed ? 'Geri Al' : 'Tamamla'}</button>
                    <button class="delete-btn">Sil</button>
                </div>
            </li>
        `).join('');
        
        this.updateStats();
    }
    
    updateStats() {
        let total = this.todos.length;
        let completed = this.todos.filter(t => t.completed).length;
        
        document.getElementById('totalCount').textContent = `Toplam: ${total}`;
        document.getElementById('completedCount').textContent = `Tamamlanan: ${completed}`;
    }
}
 
// Uygulamayı başlat
new TodoApp();
class ModalSystem {
    constructor() {
        this.createModal();
        this.bindEvents();
    }
    
    createModal() {
        let modalHTML = `
            <div id="modalOverlay" class="modal-overlay">
                <div class="modal-content">
                    <div class="modal-header">
                        <h3 id="modalTitle">Başlık</h3>
                        <button id="modalClose">&times;</button>
                    </div>
                    <div class="modal-body" id="modalBody">
                        İçerik
                    </div>
                    <div class="modal-footer" id="modalFooter">
                        <button id="modalOk">Tamam</button>
                        <button id="modalCancel">İptal</button>
                    </div>
                </div>
            </div>
        `;
        
        document.body.insertAdjacentHTML('beforeend', modalHTML);
        
        // CSS
        let style = document.createElement('style');
        style.textContent = `
            .modal-overlay {
                display: none;
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,0.5);
                z-index: 1000;
            }
            .modal-content {
                background: white;
                margin: 10% auto;
                width: 90%;
                max-width: 500px;
                border-radius: 8px;
                overflow: hidden;
            }
            .modal-header {
                padding: 15px;
                background: #f8f9fa;
                border-bottom: 1px solid #dee2e6;
                display: flex;
                justify-content: space-between;
                align-items: center;
            }
            .modal-body { padding: 20px; }
            .modal-footer {
                padding: 15px;
                text-align: right;
                border-top: 1px solid #dee2e6;
            }
            .modal-footer button { margin-left: 10px; padding: 8px 16px; }
        `;
        document.head.appendChild(style);
    }
    
    bindEvents() {
        let overlay = document.getElementById('modalOverlay');
        let closeBtn = document.getElementById('modalClose');
        let cancelBtn = document.getElementById('modalCancel');
        
        // Kapatma eventleri
        closeBtn.addEventListener('click', () => this.close());
        cancelBtn.addEventListener('click', () => this.close());
        
        // Overlay tıklama ile kapatma
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) this.close();
        });
        
        // ESC ile kapatma
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape' && overlay.style.display === 'block') {
                this.close();
            }
        });
    }
    
    show(options = {}) {
        let {title = 'Başlık', body = 'İçerik', onOk = null, onCancel = null} = options;
        
        document.getElementById('modalTitle').textContent = title;
        document.getElementById('modalBody').innerHTML = body;
        
        let okBtn = document.getElementById('modalOk');
        let cancelBtn = document.getElementById('modalCancel');
        
        // Eski event listener'ları temizle
        okBtn.replaceWith(okBtn.cloneNode(true));
        okBtn = document.getElementById('modalOk');
        
        // Yeni event listener'lar
        if (onOk) {
            okBtn.addEventListener('click', () => {
                onOk();
                this.close();
            });
        }
        
        if (onCancel) {
            cancelBtn.addEventListener('click', () => {
                onCancel();
                this.close();
            });
        }
        
        document.getElementById('modalOverlay').style.display = 'block';
    }
    
    close() {
        document.getElementById('modalOverlay').style.display = 'none';
    }
}
 
// Modal sistemi kullanımı
let modal = new ModalSystem();
 
// Test butonu oluştur
document.body.insertAdjacentHTML('beforeend', `
    <button id="testModal" style="margin: 20px; padding: 10px;">Modal Aç</button>
`);
 
document.getElementById('testModal').addEventListener('click', () => {
    modal.show({
        title: 'Emin misiniz?',
        body: 'Bu işlemi gerçekleştirmek istediğinizden emin misiniz?',
        onOk: () => alert('İşlem onaylandı!'),
        onCancel: () => alert('İşlem iptal edildi!')
    });
});

Pratik Egzersizler

Egzersiz 1: Dinamik Form Validator

// Bir form validation sistemi oluşturun:
// 1. Gerçek zamanlı doğrulama
// 2. Hata mesajları gösterme
// 3. Başarılı gönderim kontrolü
// 4. Farklı input türleri için özel kurallar
 
function formValidatorOlustur(formSelector) {
    // Bu sistemi tamamlayın
}

Egzersiz 2: Resim Galerisi

// Bir resim galerisi oluşturun:
// 1. Thumbnail'lar ve büyük görünüm
// 2. Klavye navigasyonu (ok tuşları)
// 3. Zoom özelliği
// 4. Slideshow modu
 
function resimGalerisiOlustur(resimler) {
    // Bu sistemi tamamlayın
}

Egzersiz 3: Çok Fonksiyonlu Dropdown

// Gelişmiş dropdown menü:
// 1. Arama özelliği
// 2. Çoklu seçim
// 3. Gruplama
// 4. Custom styling
 
function dropdownOlustur(container, options) {
    // Bu sistemi tamamlayın
}
Ipucu

Performance İpucu: DOM manipülasyonu pahalıdır. Çok sayıda değişiklik yapacaksanız, documentFragment kullanın veya innerHTML ile toplu güncelleme yapın.

Sıradaki Bölüm

Bir sonraki bölümde Asenkron JavaScript öğreneceksiniz. Promise, async/await ve AJAX ile modern web uygulamalarının dinamik veri alışverişini keşfedeceksiniz.

Öğrendikleriniz:

  • ✅ DOM element seçimi ve manipülasyonu
  • ✅ Element oluşturma, ekleme ve silme
  • ✅ Attribute ve style yönetimi
  • ✅ Event handling ve delegation
  • ✅ Pratik web uygulaması geliştirme
  • ✅ Modern DOM API’larını kullanma

Artık JavaScript ile interaktif web sayfaları oluşturabiliyorsunuz! Sırada external API’lardan veri çekmeyi ve asenkron işlemleri öğrenmek var. 🌐