Proje Detayları

Adım Adım Geliştirme

Bu bölümde, sürükle ve bırak liste uygulamasını adım adım nasıl geliştirebileceğinizi öğreneceksiniz. Her adımda, ilgili kod parçalarını ve açıklamalarını bulacaksınız.

Adım 1: Proje Yapısını Oluşturma

İlk olarak, projemiz için gerekli dosyaları oluşturalım:

  • index.html - Ana HTML dosyası
  • style.css - CSS stil dosyası
  • script.js - JavaScript kod dosyası
index.html
<!DOCTYPE html>
<html lang="tr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sürükle & Bırak Liste</title>
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
</head>
<body>
    <div class="container">
        <div class="drag-drop-container">
            <div class="drag-drop-header">
                <h1>Sürükle & Bırak Liste</h1>
                <p>Öğeleri ekleyin, sürükleyin ve kategoriler arasında taşıyın</p>
            </div>
            
            <div class="drag-drop-controls">
                <input type="text" class="drag-drop-input" id="dragDropInput" placeholder="Yeni öğe ekleyin...">
                <button class="drag-drop-btn" id="dragDropAddBtn">Ekle</button>
            </div>
            
            <div class="drag-drop-categories">
                <div class="drag-drop-category" id="todoCategory" data-category="todo">
                    <h2>Yapılacaklar</h2>
                    <ul class="drag-drop-category-list" id="todoList">
                        <!-- Liste öğeleri buraya eklenecek -->
                    </ul>
                </div>
                
                <div class="drag-drop-category" id="inProgressCategory" data-category="inProgress">
                    <h2>Devam Edenler</h2>
                    <ul class="drag-drop-category-list" id="inProgressList">
                        <!-- Liste öğeleri buraya eklenecek -->
                    </ul>
                </div>
                
                <div class="drag-drop-category" id="doneCategory" data-category="done">
                    <h2>Tamamlananlar</h2>
                    <ul class="drag-drop-category-list" id="doneList">
                        <!-- Liste öğeleri buraya eklenecek -->
                    </ul>
                </div>
            </div>
        </div>
    </div>

    <script src="script.js"></script>
</body>
</html>
style.css
/* Genel Stiller */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f5f5f5;
    color: #333;
    line-height: 1.6;
}

.container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
}

/* Sürükle & Bırak Liste Stilleri */
.drag-drop-container {
    width: 100%;
    max-width: 900px;
    margin: 0 auto;
}

.drag-drop-header {
    text-align: center;
    margin-bottom: 30px;
}

.drag-drop-header h1 {
    font-size: 2.5rem;
    color: #333;
    margin-bottom: 10px;
}

.drag-drop-header p {
    color: #666;
    font-size: 1.1rem;
}

.drag-drop-controls {
    display: flex;
    justify-content: space-between;
    margin-bottom: 20px;
}

.drag-drop-input {
    flex: 1;
    padding: 12px 15px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 1rem;
    margin-right: 10px;
    outline: none;
}

.drag-drop-input:focus {
    border-color: #4caf50;
}

.drag-drop-btn {
    background-color: #4caf50;
    color: white;
    border: none;
    padding: 12px 20px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 1rem;
    transition: background-color 0.3s;
}

.drag-drop-btn:hover {
    background-color: #388e3c;
}

.drag-drop-categories {
    display: flex;
    gap: 20px;
}

.drag-drop-category {
    flex: 1;
    background-color: #fff;
    border-radius: 8px;
    padding: 20px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}

.drag-drop-category h2 {
    margin-top: 0;
    margin-bottom: 15px;
    font-size: 1.5rem;
    color: #333;
    text-align: center;
    padding-bottom: 10px;
    border-bottom: 2px solid #f1f1f1;
}

.drag-drop-category-list {
    min-height: 200px;
    list-style-type: none;
    padding: 0;
    margin: 0;
}

.drag-drop-item {
    background-color: #f9f9f9;
    padding: 15px;
    margin-bottom: 10px;
    border-radius: 4px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    cursor: move;
    transition: all 0.3s;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.drag-drop-item:hover {
    background-color: #f1f1f1;
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}

.drag-drop-item.dragging {
    opacity: 0.5;
    background-color: #e0e0e0;
}

.drag-drop-item-content {
    flex: 1;
}

.drag-drop-item-actions {
    display: flex;
    gap: 10px;
}

.drag-drop-item-actions button {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 1rem;
    color: #666;
    transition: color 0.3s;
}

.drag-drop-item-actions button:hover {
    color: #333;
}

.drag-drop-item-actions .edit-btn:hover {
    color: #2196f3;
}

.drag-drop-item-actions .delete-btn:hover {
    color: #f44336;
}

.drag-drop-item-handle {
    cursor: move;
    color: #999;
    margin-right: 10px;
}

.drag-drop-category.highlight {
    background-color: #e8f5e9;
    border: 2px dashed #4caf50;
}

.drag-drop-empty {
    text-align: center;
    padding: 20px;
    color: #999;
    font-style: italic;
}

/* Responsive Tasarım */
@media (max-width: 768px) {
    .drag-drop-categories {
        flex-direction: column;
    }
    
    .drag-drop-category {
        margin-bottom: 20px;
    }
}

Adım 2: JavaScript Kodunu Yazma

Şimdi, uygulamanın işlevselliğini sağlayacak JavaScript kodunu yazalım:

script.js
// DOM elementlerini seçme
const dragDropInput = document.getElementById('dragDropInput');
const dragDropAddBtn = document.getElementById('dragDropAddBtn');
const todoList = document.getElementById('todoList');
const inProgressList = document.getElementById('inProgressList');
const doneList = document.getElementById('doneList');
const categories = document.querySelectorAll('.drag-drop-category');

// Değişkenler
let draggedItem = null;
let items = JSON.parse(localStorage.getItem('dragDropItems')) || {
    todo: [
        { id: 1, content: 'JavaScript öğrenmek' },
        { id: 2, content: 'Proje geliştirmek' }
    ],
    inProgress: [
        { id: 3, content: 'DOM manipülasyonu çalışmak' }
    ],
    done: [
        { id: 4, content: 'HTML öğrenmek' }
    ]
};
let nextId = 5; // Başlangıç ID'si

// Sayfa yüklendiğinde
document.addEventListener('DOMContentLoaded', () => {
    // Öğeleri yükle
    loadItems();
    
    // Yeni öğe ekleme
    dragDropAddBtn.addEventListener('click', addItem);
    dragDropInput.addEventListener('keypress', (e) => {
        if (e.key === 'Enter') {
            addItem();
        }
    });
    
    // Sürükleme olayları için kategorileri ayarla
    setupDragAndDrop();
});

// Öğeleri yükleme fonksiyonu
function loadItems() {
    // Tüm listeleri temizle
    todoList.innerHTML = '';
    inProgressList.innerHTML = '';
    doneList.innerHTML = '';
    
    // Yapılacaklar listesi
    if (items.todo.length === 0) {
        todoList.innerHTML = 'Henüz öğe yok';
    } else {
        items.todo.forEach(item => {
            const listItem = createListItem(item);
            todoList.appendChild(listItem);
        });
    }
    
    // Devam edenler listesi
    if (items.inProgress.length === 0) {
        inProgressList.innerHTML = 'Henüz öğe yok';
    } else {
        items.inProgress.forEach(item => {
            const listItem = createListItem(item);
            inProgressList.appendChild(listItem);
        });
    }
    
    // Tamamlananlar listesi
    if (items.done.length === 0) {
        doneList.innerHTML = 'Henüz öğe yok';
    } else {
        items.done.forEach(item => {
            const listItem = createListItem(item);
            doneList.appendChild(listItem);
        });
    }
}

// Liste öğesi oluşturma fonksiyonu
function createListItem(item) {
    const listItem = document.createElement('li');
    listItem.className = 'drag-drop-item';
    listItem.draggable = true;
    listItem.dataset.id = item.id;
    
    listItem.innerHTML = `
        
        ${item.content}
        
            
            
        
    `;
    
    // Düzenleme butonu için olay dinleyicisi
    listItem.querySelector('.edit-btn').addEventListener('click', () => {
        editItem(item.id);
    });
    
    // Silme butonu için olay dinleyicisi
    listItem.querySelector('.delete-btn').addEventListener('click', () => {
        deleteItem(item.id);
    });
    
    // Sürükleme olayları
    listItem.addEventListener('dragstart', dragStart);
    listItem.addEventListener('dragend', dragEnd);
    
    return listItem;
}

// Yeni öğe ekleme fonksiyonu
function addItem() {
    const content = dragDropInput.value.trim();
    
    if (content !== '') {
        // Boş öğe mesajını kaldır
        const emptyMessage = todoList.querySelector('.drag-drop-empty');
        if (emptyMessage) {
            todoList.removeChild(emptyMessage);
        }
        
        // Yeni öğe oluştur
        const newItem = {
            id: nextId++,
            content: content
        };
        
        // Öğeyi yapılacaklar listesine ekle
        items.todo.push(newItem);
        
        // Öğeyi DOM'a ekle
        const listItem = createListItem(newItem);
        todoList.appendChild(listItem);
        
        // Giriş alanını temizle
        dragDropInput.value = '';
        
        // LocalStorage'a kaydet
        saveItems();
    }
}

// Öğe düzenleme fonksiyonu
function editItem(id) {
    // Tüm kategorilerde öğeyi bul
    let category = '';
    let itemIndex = -1;
    
    for (const cat of ['todo', 'inProgress', 'done']) {
        const index = items[cat].findIndex(item => item.id === id);
        if (index !== -1) {
            category = cat;
            itemIndex = index;
            break;
        }
    }
    
    if (category && itemIndex !== -1) {
        const item = items[category][itemIndex];
        const newContent = prompt('Öğeyi düzenleyin:', item.content);
        
        if (newContent !== null && newContent.trim() !== '') {
            // Öğeyi güncelle
            item.content = newContent.trim();
            
            // DOM'u güncelle
            const listItem = document.querySelector(`.drag-drop-item[data-id="${id}"]`);
            if (listItem) {
                listItem.querySelector('.drag-drop-item-content').textContent = newContent.trim();
            }
            
            // LocalStorage'a kaydet
            saveItems();
        }
    }
}

// Öğe silme fonksiyonu
function deleteItem(id) {
    // Tüm kategorilerde öğeyi bul
    let category = '';
    let itemIndex = -1;
    
    for (const cat of ['todo', 'inProgress', 'done']) {
        const index = items[cat].findIndex(item => item.id === id);
        if (index !== -1) {
            category = cat;
            itemIndex = index;
            break;
        }
    }
    
    if (category && itemIndex !== -1) {
        // Öğeyi diziden kaldır
        items[category].splice(itemIndex, 1);
        
        // DOM'dan kaldır
        const listItem = document.querySelector(`.drag-drop-item[data-id="${id}"]`);
        if (listItem) {
            listItem.parentElement.removeChild(listItem);
        }
        
        // Eğer liste boşsa, boş mesajı göster
        if (items[category].length === 0) {
            const list = document.getElementById(`${category}List`);
            list.innerHTML = 'Henüz öğe yok';
        }
        
        // LocalStorage'a kaydet
        saveItems();
    }
}

// LocalStorage'a kaydetme fonksiyonu
function saveItems() {
    localStorage.setItem('dragDropItems', JSON.stringify(items));
}

// Sürükleme başlangıç olayı
function dragStart(e) {
    draggedItem = this;
    setTimeout(() => {
        this.classList.add('dragging');
    }, 0);
    
    // Veri transferi
    e.dataTransfer.setData('text/plain', this.dataset.id);
    e.dataTransfer.effectAllowed = 'move';
}

// Sürükleme bitiş olayı
function dragEnd() {
    this.classList.remove('dragging');
    draggedItem = null;
    
    // Tüm kategorilerdeki vurgulamayı kaldır
    categories.forEach(category => {
        category.classList.remove('highlight');
    });
}

// Sürükle ve bırak işlevselliğini ayarlama
function setupDragAndDrop() {
    categories.forEach(category => {
        // Sürükleme üzerinde olayı
        category.addEventListener('dragover', (e) => {
            e.preventDefault();
            category.classList.add('highlight');
        });
        
        // Sürükleme dışına çıkma olayı
        category.addEventListener('dragleave', () => {
            category.classList.remove('highlight');
        });
        
        // Bırakma olayı
        category.addEventListener('drop', (e) => {
            e.preventDefault();
            category.classList.remove('highlight');
            
            const id = parseInt(e.dataTransfer.getData('text/plain'));
            const targetCategory = category.dataset.category;
            
            // Öğeyi eski kategorisinden bul ve kaldır
            let sourceCategory = '';
            let itemIndex = -1;
            let item = null;
            
            for (const cat of ['todo', 'inProgress', 'done']) {
                const index = items[cat].findIndex(item => item.id === id);
                if (index !== -1) {
                    sourceCategory = cat;
                    itemIndex = index;
                    item = items[cat][index];
                    break;
                }
            }
            
            if (sourceCategory && itemIndex !== -1 && item) {
                // Öğeyi eski kategorisinden kaldır
                items[sourceCategory].splice(itemIndex, 1);
                
                // Öğeyi yeni kategoriye ekle
                items[targetCategory].push(item);
                
                // DOM'u güncelle
                loadItems();
                
                // LocalStorage'a kaydet
                saveItems();
            }
        });
    });
}

Adım 3: Dokunmatik Cihaz Desteği Ekleme

Mobil cihazlarda sürükle ve bırak işlevselliğini desteklemek için aşağıdaki kodu ekleyelim:

touch-support.js
// Dokunmatik cihaz desteği için ek kod
// Bu kodu script.js dosyasının sonuna ekleyin

// Dokunmatik cihaz kontrolü
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;

if (isTouchDevice) {
    // Dokunmatik cihazlar için alternatif sürükleme yöntemi
    setupTouchDragAndDrop();
}

function setupTouchDragAndDrop() {
    // Tüm liste öğeleri için uzun basma olayı ekle
    document.addEventListener('DOMContentLoaded', () => {
        // Öğeler yüklendiğinde dokunmatik olayları ekle
        addTouchEventsToItems();
    });
}

function addTouchEventsToItems() {
    const items = document.querySelectorAll('.drag-drop-item');
    
    items.forEach(item => {
        // Uzun basma için zamanlayıcı
        let touchTimer;
        let touchStartX, touchStartY;
        let isTouching = false;
        
        // Dokunma başlangıcı
        item.addEventListener('touchstart', (e) => {
            touchStartX = e.touches[0].clientX;
            touchStartY = e.touches[0].clientY;
            
            // Uzun basma algılama (500ms)
            touchTimer = setTimeout(() => {
                isTouching = true;
                item.classList.add('dragging');
                
                // Seçilen öğeyi göster
                const clone = item.cloneNode(true);
                clone.style.position = 'fixed';
                clone.style.top = `${touchStartY - 30}px`;
                clone.style.left = `${touchStartX - 30}px`;
                clone.style.width = `${item.offsetWidth}px`;
                clone.style.opacity = '0.8';
                clone.style.zIndex = '1000';
                clone.id = 'touchDragClone';
                document.body.appendChild(clone);
                
                // Kategorileri vurgula
                categories.forEach(category => {
                    category.classList.add('highlight');
                });
            }, 500);
        });
        
        // Dokunma hareketi
        item.addEventListener('touchmove', (e) => {
            if (isTouching) {
                e.preventDefault(); // Sayfanın kaydırılmasını engelle
                
                const touchX = e.touches[0].clientX;
                const touchY = e.touches[0].clientY;
                
                // Klonu hareket ettir
                const clone = document.getElementById('touchDragClone');
                if (clone) {
                    clone.style.top = `${touchY - 30}px`;
                    clone.style.left = `${touchX - 30}px`;
                }
                
                // Hangi kategorinin üzerinde olduğunu kontrol et
                categories.forEach(category => {
                    const rect = category.getBoundingClientRect();
                    
                    if (
                        touchX >= rect.left &&
                        touchX <= rect.right &&
                        touchY >= rect.top &&
                        touchY <= rect.bottom
                    ) {
                        category.classList.add('highlight');
                    } else {
                        category.classList.remove('highlight');
                    }
                });
            }
        });
        
        // Dokunma bitişi
        item.addEventListener('touchend', (e) => {
            clearTimeout(touchTimer);
            
            if (isTouching) {
                const touchX = e.changedTouches[0].clientX;
                const touchY = e.changedTouches[0].clientY;
                
                // Klonu kaldır
                const clone = document.getElementById('touchDragClone');
                if (clone) {
                    document.body.removeChild(clone);
                }
                
                // Hangi kategorinin üzerinde bırakıldığını kontrol et
                categories.forEach(category => {
                    const rect = category.getBoundingClientRect();
                    
                    if (
                        touchX >= rect.left &&
                        touchX <= rect.right &&
                        touchY >= rect.top &&
                        touchY <= rect.bottom
                    ) {
                        // Öğeyi bu kategoriye taşı
                        const id = parseInt(item.dataset.id);
                        const targetCategory = category.dataset.category;
                        
                        // Öğeyi eski kategorisinden bul ve kaldır
                        let sourceCategory = '';
                        let itemIndex = -1;
                        let itemObj = null;
                        
                        for (const cat of ['todo', 'inProgress', 'done']) {
                            const index = items[cat].findIndex(i => i.id === id);
                            if (index !== -1) {
                                sourceCategory = cat;
                                itemIndex = index;
                                itemObj = items[cat][index];
                                break;
                            }
                        }
                        
                        if (sourceCategory && itemIndex !== -1 && itemObj) {
                            // Öğeyi eski kategorisinden kaldır
                            items[sourceCategory].splice(itemIndex, 1);
                            
                            // Öğeyi yeni kategoriye ekle
                            items[targetCategory].push(itemObj);
                            
                            // DOM'u güncelle
                            loadItems();
                            
                            // LocalStorage'a kaydet
                            saveItems();
                        }
                    }
                });
                
                // Tüm vurgulamaları kaldır
                categories.forEach(category => {
                    category.classList.remove('highlight');
                });
                
                item.classList.remove('dragging');
                isTouching = false;
            }
        });
        
        // Dokunma iptali
        item.addEventListener('touchcancel', () => {
            clearTimeout(touchTimer);
            
            if (isTouching) {
                // Klonu kaldır
                const clone = document.getElementById('touchDragClone');
                if (clone) {
                    document.body.removeChild(clone);
                }
                
                // Tüm vurgulamaları kaldır
                categories.forEach(category => {
                    category.classList.remove('highlight');
                });
                
                item.classList.remove('dragging');
                isTouching = false;
            }
        });
    });
}

// Yeni öğe eklendiğinde veya öğeler yüklendiğinde dokunmatik olayları ekle
function loadItems() {
    // ... mevcut kod ...
    
    // Dokunmatik cihaz desteği için
    if (isTouchDevice) {
        addTouchEventsToItems();
    }
}

Adım 4: Uygulamayı Test Etme

Şimdi uygulamanızı test etme zamanı! Aşağıdaki adımları izleyin:

  1. Tüm dosyaları (index.htmlstyle.cssscript.js) aynı klasöre kaydedin.
  2. HTML dosyasını bir web tarayıcısında açın.
  3. Giriş alanına metin yazarak ve "Ekle" butonuna tıklayarak yeni öğeler ekleyin.
  4. Öğeleri sürükleyerek farklı kategoriler arasında taşıyın.
  5. Düzenleme ve silme butonlarını kullanarak öğeleri düzenleyin veya silin.
  6. Sayfayı yenileyin ve öğelerin localStorage sayesinde korunduğunu doğrulayın.
  7. Mobil cihazda veya dokunmatik ekranda uzun basma ile sürükleme işlevini test edin.

İpucu: Tarayıcınızın geliştirici araçlarını (genellikle F12 tuşu ile açılır) kullanarak JavaScript hatalarını ayıklayabilirsiniz. Ayrıca, responsive tasarımı test etmek için tarayıcının ekran boyutunu değiştirebilirsiniz.

Projeyi Geliştirme

Temel sürükle ve bırak liste uygulamasını başarıyla oluşturduktan sonra, aşağıdaki özelliklerle projenizi geliştirebilirsiniz:

1. Öğe Önceliği ve Renk Kodlaması

Öğelere öncelik seviyesi ekleyin ve farklı öncelikleri renk kodlarıyla gösterin:

priority.js
// Öğe veri yapısını güncelle
let items = JSON.parse(localStorage.getItem('dragDropItems')) || {
    todo: [
        { id: 1, content: 'JavaScript öğrenmek', priority: 'high' },
        { id: 2, content: 'Proje geliştirmek', priority: 'medium' }
    ],
    inProgress: [
        { id: 3, content: 'DOM manipülasyonu çalışmak', priority: 'medium' }
    ],
    done: [
        { id: 4, content: 'HTML öğrenmek', priority: 'low' }
    ]
};

// Liste öğesi oluşturma fonksiyonunu güncelle
function createListItem(item) {
    const listItem = document.createElement('li');
    listItem.className = `drag-drop-item priority-${item.priority || 'medium'}`;
    listItem.draggable = true;
    listItem.dataset.id = item.id;
    
    listItem.innerHTML = `
        
        ${item.content}
        
            
                
            
            
            
        
    `;
    
    // Düzenleme butonu için olay dinleyicisi
    listItem.querySelector('.edit-btn').addEventListener('click', () => {
        editItem(item.id);
    });
    
    // Silme butonu için olay dinleyicisi
    listItem.querySelector('.delete-btn').addEventListener('click', () => {
        deleteItem(item.id);
    });
    
    // Öncelik butonu için olay dinleyicisi
    listItem.querySelector('.priority-btn').addEventListener('click', (e) => {
        togglePriority(item.id);
    });
    
    // Sürükleme olayları
    listItem.addEventListener('dragstart', dragStart);
    listItem.addEventListener('dragend', dragEnd);
    
    return listItem;
}

// Öncelik değiştirme fonksiyonu
function togglePriority(id) {
    // Tüm kategorilerde öğeyi bul
    let category = '';
    let itemIndex = -1;
    
    for (const cat of ['todo', 'inProgress', 'done']) {
        const index = items[cat].findIndex(item => item.id === id);
        if (index !== -1) {
            category = cat;
            itemIndex = index;
            break;
        }
    }
    
    if (category && itemIndex !== -1) {
        const item = items[category][itemIndex];
        const currentPriority = item.priority || 'medium';
        
        // Önceliği değiştir (döngüsel: low -> medium -> high -> low)
        if (currentPriority === 'low') {
            item.priority = 'medium';
        } else if (currentPriority === 'medium') {
            item.priority = 'high';
        } else {
            item.priority = 'low';
        }
        
        // DOM'u güncelle
        const listItem = document.querySelector(`.drag-drop-item[data-id="${id}"]`);
        if (listItem) {
            // Sınıfları güncelle
            listItem.className = `drag-drop-item priority-${item.priority}`;
            
            // Öncelik butonunu güncelle
            const priorityBtn = listItem.querySelector('.priority-btn');
            priorityBtn.dataset.priority = item.priority;
        }
        
        // LocalStorage'a kaydet
        saveItems();
    }
}

// CSS'e öncelik stilleri ekle
/*
.priority-high {
    border-left: 4px solid #f44336;
}

.priority-medium {
    border-left: 4px solid #ff9800;
}

.priority-low {
    border-left: 4px solid #4caf50;
}

.priority-btn[data-priority="high"] {
    color: #f44336;
}

.priority-btn[data-priority="medium"] {
    color: #ff9800;
}

.priority-btn[data-priority="low"] {
    color: #4caf50;
}
*/

2. Öğe Etiketleri

Öğelere etiketler ekleyerek daha iyi kategorilendirme yapın:

tags.js
// Öğe veri yapısını güncelle
let items = JSON.parse(localStorage.getItem('dragDropItems')) || {
    todo: [
        { id: 1, content: 'JavaScript öğrenmek', priority: 'high', tags: ['öğrenme', 'kodlama'] },
        { id: 2, content: 'Proje geliştirmek', priority: 'medium', tags: ['proje'] }
    ],
    inProgress: [
        { id: 3, content: 'DOM manipülasyonu çalışmak', priority: 'medium', tags: ['öğrenme'] }
    ],
    done: [
        { id: 4, content: 'HTML öğrenmek', priority: 'low', tags: ['öğrenme', 'tamamlandı'] }
    ]
};

// Liste öğesi oluşturma fonksiyonunu güncelle
function createListItem(item) {
    const listItem = document.createElement('li');
    listItem.className = `drag-drop-item priority-${item.priority || 'medium'}`;
    listItem.draggable = true;
    listItem.dataset.id = item.id;
    
    // Etiketleri oluştur
    let tagsHTML = '';
    if (item.tags && item.tags.length > 0) {
        tagsHTML = '';
        item.tags.forEach(tag => {
            tagsHTML += `${tag}`;
        });
        tagsHTML += '';
    }
    
    listItem.innerHTML = `
        
        
            ${item.content}
            ${tagsHTML}
        
        
            
            
                
            
            
            
        
    `;
    
    // Düzenleme butonu için olay dinleyicisi
    listItem.querySelector('.edit-btn').addEventListener('click', () => {
        editItem(item.id);
    });
    
    // Silme butonu için olay dinleyicisi
    listItem.querySelector('.delete-btn').addEventListener('click', () => {
        deleteItem(item.id);
    });
    
    // Öncelik butonu için olay dinleyicisi
    listItem.querySelector('.priority-btn').addEventListener('click', () => {
        togglePriority(item.id);
    });
    
    // Etiket butonu için olay dinleyicisi
    listItem.querySelector('.tag-btn').addEventListener('click', () => {
        editTags(item.id);
    });
    
    // Sürükleme olayları
    listItem.addEventListener('dragstart', dragStart);
    listItem.addEventListener('dragend', dragEnd);
    
    return listItem;
}

// Etiketleri düzenleme fonksiyonu
function editTags(id) {
    // Tüm kategorilerde öğeyi bul
    let category = '';
    let itemIndex = -1;
    
    for (const cat of ['todo', 'inProgress', 'done']) {
        const index = items[cat].findIndex(item => item.id === id);
        if (index !== -1) {
            category = cat;
            itemIndex = index;
            break;
        }
    }
    
    if (category && itemIndex !== -1) {
        const item = items[category][itemIndex];
        const currentTags = item.tags ? item.tags.join(', ') : '';
        
        const newTags = prompt('Etiketleri virgülle ayırarak girin:', currentTags);
        
        if (newTags !== null) {
            // Etiketleri güncelle
            item.tags = newTags.split(',')
                .map(tag => tag.trim())
                .filter(tag => tag !== '');
            
            // DOM'u güncelle
            loadItems();
            
            // LocalStorage'a kaydet
            saveItems();
        }
    }
}

// CSS'e etiket stilleri ekle
/*
.drag-drop-item-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-top: 5px;
}

.tag {
    background-color: #e0e0e0;
    color: #333;
    padding: 2px 8px;
    border-radius: 12px;
    font-size: 0.8rem;
}
*/

3. Sürükle ve Bırak Sıralama

Aynı kategori içinde öğeleri sürükleyerek yeniden sıralama özelliği ekleyin:

reordering.js
// Sürükle ve bırak işlevselliğini ayarlama fonksiyonunu güncelle
function setupDragAndDrop() {
    // Kategori listeleri
    const lists = document.querySelectorAll('.drag-drop-category-list');
    
    lists.forEach(list => {
        // Sürükleme üzerinde olayı
        list.addEventListener('dragover', (e) => {
            e.preventDefault();
            const afterElement = getDragAfterElement(list, e.clientY);
            const draggable = document.querySelector('.dragging');
            
            if (afterElement == null) {
                list.appendChild(draggable);
            } else {
                list.insertBefore(draggable, afterElement);
            }
        });
    });
    
    // Kategoriler
    categories.forEach(category => {
        // Sürükleme üzerinde olayı
        category.addEventListener('dragover', (e) => {
            e.preventDefault();
            category.classList.add('highlight');
        });
        
        // Sürükleme dışına çıkma olayı
        category.addEventListener('dragleave', () => {
            category.classList.remove('highlight');
        });
        
        // Bırakma olayı
        category.addEventListener('drop', (e) => {
            e.preventDefault();
            category.classList.remove('highlight');
            
            const id = parseInt(e.dataTransfer.getData('text/plain'));
            const targetCategory = category.dataset.category;
            
            // Öğeyi eski kategorisinden bul ve kaldır
            let sourceCategory = '';
            let itemIndex = -1;
            let item = null;
            
            for (const cat of ['todo', 'inProgress', 'done']) {
                const index = items[cat].findIndex(item => item.id === id);
                if (index !== -1) {
                    sourceCategory = cat;
                    itemIndex = index;
                    item = items[cat][index];
                    break;
                }
            }
            
            if (sourceCategory && itemIndex !== -1 && item) {
                // Öğeyi eski kategorisinden kaldır
                items[sourceCategory].splice(itemIndex, 1);
                
                // Öğeyi yeni kategoriye ekle
                items[targetCategory].push(item);
                
                // Yeni sıralamayı kaydet
                updateItemsOrder();
                
                // LocalStorage'a kaydet
                saveItems();
            }
        });
    });
}

// Sürüklenen öğenin bırakılacağı konumu belirleyen fonksiyon
function getDragAfterElement(container, y) {
    const draggableElements = [...container.querySelectorAll('.drag-drop-item:not(.dragging)')];
    
    return draggableElements.reduce((closest, child) => {
        const box = child.getBoundingClientRect();
        const offset = y - box.top - box.height / 2;
        
        if (offset < 0 && offset > closest.offset) {
            return { offset: offset, element: child };
        } else {
            return closest;
        }
    }, { offset: Number.NEGATIVE_INFINITY }).element;
}

// Öğelerin yeni sıralamasını kaydetme fonksiyonu
function updateItemsOrder() {
    // Tüm kategoriler için
    for (const cat of ['todo', 'inProgress', 'done']) {
        const list = document.getElementById(`${cat}List`);
        const newOrder = [];
        
        // Listedeki tüm öğeleri al
        const listItems = list.querySelectorAll('.drag-drop-item');
        
        // Her öğe için
        listItems.forEach(item => {
            const id = parseInt(item.dataset.id);
            
            // Öğeyi items dizisinde bul
            const itemObj = items[cat].find(i => i.id === id);
            
            if (itemObj) {
                newOrder.push(itemObj);
            }
        });
        
        // Yeni sıralamayı kaydet
        items[cat] = newOrder;
    }
}

Geliştirme Zorlukları

Sürükle ve bırak liste uygulamanızı daha da geliştirmek için aşağıdaki zorlukları deneyebilirsiniz:

  1. Tarih ve Hatırlatıcılar: Öğelere son tarih ekleyin ve yaklaşan son tarihleri vurgulayın.
  2. Alt Görevler: Her öğeye alt görevler ekleyerek daha karmaşık görev yönetimi sağlayın.
  3. Filtreleme ve Arama: Etiketlere veya içeriğe göre öğeleri filtreleme ve arama özelliği ekleyin.
  4. Çoklu Kullanıcı Desteği: Farklı kullanıcılar için farklı listeler oluşturun.
  5. Veri Dışa/İçe Aktarma: Listeleri JSON formatında dışa ve içe aktarma özelliği ekleyin.

Sonuç ve Öğrenilen Dersler

Bu projede, JavaScript'in Drag & Drop API'sini kullanarak sürükle ve bırak işlevselliğine sahip bir liste uygulaması geliştirdik. Bu süreçte şunları öğrendik:

  • HTML5 Drag & Drop API'sini kullanmayı
  • Sürüklenebilir öğeler oluşturmayı ve yönetmeyi
  • Sürükleme olaylarını (dragstart, dragover, drop vb.) kullanmayı
  • Öğeleri dinamik olarak eklemeyi, düzenlemeyi ve silmeyi
  • Kategoriler arasında öğe taşıma işlevselliği eklemeyi
  • Yerel depolama (localStorage) kullanarak verileri kalıcı hale getirmeyi
  • Dokunmatik cihazlar için sürükle ve bırak desteği eklemeyi
  • Kullanıcı deneyimini geliştirmek için görsel geri bildirimler eklemeyi

Bu proje, modern web uygulamalarında yaygın olarak kullanılan sürükle ve bırak işlevselliğini nasıl uygulayacağınızı öğrenmenize yardımcı olmuştur. Öğrendiğiniz teknikleri ve kavramları kullanarak, daha karmaşık ve tam özellikli liste uygulamaları, kanban panoları veya diğer sürükle ve bırak tabanlı arayüzler geliştirebilirsiniz.