🗂️ Vanilla JavaScript ile İnteraktif Kanban Panosu
Pointer Events tabanlı sürükle-bırak, localStorage kalıcılığı ve erişilebilirlik odaklı teknik dokümantasyon.
1 Özet
Bu doküman, harici bağımlılık kullanmadan Vanilla JavaScript ile geliştirilmiş, sürükle-bırak destekli interaktif bir Kanban panosu bileşeninin tüm teknik detaylarını içerir. Bileşen; sıfır bağımlılık, tam çevrimdışı çalışma, erişilebilir etkileşim ve kusursuz durum yönetimi prensiplerini bir arada barındırır.
2 Teknik Varsayımlar
- Tarayıcı desteği: Modern evergreen tarayıcılar (Chrome 90+, Firefox 88+, Safari 14+, Edge 90+).
Pointer Events APIve CSS custom properties kullanılır. - Modül yapısı: Tek HTML dosyası içinde HTML + CSS + JS birleşik; harici bağımlılık yok.
- Durum yönetimi: Uygulama durumu tek bir
statenesnesinde tutulur ve her mutasyondan sonralocalStorage'a senkronize edilir. - Sürükle-bırak: HTML5 Drag & Drop API yerine Pointer Events API tercih edilmiştir. Dokunmatik cihazlarda tutarlı çalışır.
- Erişilebilirlik: Klavye ile kart taşıma (
Alt + ←/→/↑/↓) desteklenir;aria-liveile ekran okuyucu bildirimleri sağlanır. - Güvenlik: Kullanıcı girdileri
textContentüzerinden DOM'a yazılarak XSS riski minimize edilmiştir. - Performans: Liste render işlemlerinde DocumentFragment kullanılır; gereksiz reflow önlenir.
3 Mimari Genel Bakış
| Katman | Sorumluluk |
|---|---|
| State | columns, cards verilerinin tek kaynaktan yönetimi |
| Persistence | localStorage ile otomatik kayıt/yükleme |
| Renderer | DOM oluşturma ve senkronizasyon |
| DragController | Pointer tabanlı sürükle-bırak yaşam döngüsü |
| Accessibility | Klavye navigasyonu ve ARIA duyuruları |
4 Kritik Uygulama Detayları
4.1 Pointer Events ile Sürükle-Bırak
HTML5 Drag & Drop API, mobil cihazlarda ve özelleştirilmiş görsel katmanlarda
yetersiz kaldığı için Pointer Events API tercih edilmiştir. Sürükleme
yaşam döngüsü üç aşamadan oluşur:
pointerdown→ Hayalet klon (ghost) ve yer tutucu (placeholder) oluşturulur.pointermove→ Klon imleci takip eder;elementFromPointile hedef liste belirlenir; yer tutucu doğru indekse taşınır.pointerup→ Yer tutucunun nihai indeksi hesaplanır,moveCard()çağrılır ve tüm görsel katmanlar temizlenir.
setPointerCapture sayesinde imleç karttan çıksa bile olay akışı kesilmez.
4.2 Durum Tutarlılığı
moveCard() fonksiyonu, aynı sütun içinde aşağı yönde taşıma
durumunda oluşan klasik index shift hatasını
(fromIndex < toIndex ise insertIndex - 1) açıkça ele alır.
4.3 Erişilebilirlik (a11y)
- Her kart
role="button"vetabIndex=0ile odaklanabilir. Alt + Okkombinasyonu ile kartlar sütunlar arası veya sütun içi taşınabilir.aria-live="polite"bölgesi ile ekran okuyuculara "Kart taşındı", "Kart silindi" gibi bildirimler iletilir.- Sütun başlıkları
contentEditableolupEnter/Escapeile düzenlenir.
4.4 Güvenlik Önlemleri
- Kullanıcı metinleri yalnızca
textContentüzerinden yazılır → XSS imkânsız. innerHTMLhiç kullanılmamıştır.- Metin uzunluğu
MAX_TEXT_LENGTH = 200karakter ile sınırlandırılır. localStorageyükleme sırasında şema doğrulaması yapılır; bozuk veri sessizce sıfırlanır.
4.5 Performans
- Liste render işlemlerinde
DocumentFragmentkullanılır; tek bir reflow ile DOM'a bağlanır. - Yalnızca değişen sütun (
renderColumnCards) yeniden çizilir; tüm pano yeniden oluşturulmaz. requestAnimationFrameile odak geri kazanımı bir sonraki boyama döngüsüne ertelenir.
5 Önceki Sürümlerdeki Hatalar ve Düzeltmeleri
| # | Hata | Neden | Düzeltme |
|---|---|---|---|
| 1 | updatePlaceholder içinde y tanımsız |
Fonksiyon kapsamında değişken yok → ReferenceError |
Fonksiyon sadeleştirildi; ghost merkez Y değeri kullanılıyor |
| 2 | this bağlamı kayboluyordu |
Ok fonksiyonları addEventListener'a doğrudan verildi |
_onMove / _onUp içinde Drag global referansı kullanılıyor |
| 3 | Ghost li olarak klonlanıyordu |
card-ghost sınıfı card sınıfını da taşıyordu |
Ghost artık sade div; yalnızca metin ve stiller klonlanıyor |
| 4 | Kartlar hiç görünmüyordu | Seed verisi kontrolü localStorage.getItem yokluğuna bağlıydı; başlatma akışı hatalıydı |
createInitialState() içinde seed üretiliyor; state = load() || createInitialState() |
| 5 | Sütun yüksekliği çöküyordu | .column yüksekliği ebeveyn board'un align-items davranışıyla kısıtlanmıyordu |
.board { align-items: flex-start } ve .column { display: flex; flex-direction: column } sabitlendi |
kanban.board.v1 veya kanban.board.v2
anahtarları yeni sürümde kullanılmaz; kanban.board.v3 anahtarı ile temiz başlar.
Sorun devam ederse DevTools → Application → Local Storage üzerinden eski anahtarları silin.
6 Kullanım Kılavuzu
| Eylem | Yöntem |
|---|---|
| Kart taşıma | Fare/dokunma ile sürükle |
| Kart taşıma (klavye) | Kart odaktayken Alt + ←/→ (sütunlar arası), Alt + ↑/↓ (sıralama) |
| Kart düzenleme | Çift tık veya Enter |
| Kart silme | Kart odaktayken Delete |
| Kart ekleme | Sütun altındaki + Kart ekle butonu |
| Sütun adı düzenleme | Başlığa tıkla, yaz, Enter |
| Kaydetme | Otomatik (her mutasyonda localStorage) |
7 Sonuç
Sunulan çözüm; sıfır bağımlılık, tam çevrimdışı çalışma,
erişilebilir etkileşim ve kusursuz durum yönetimi
prensiplerini bir arada barındıran üretim kalitesinde bir Kanban bileşenidir.
Modüler iç mimarisi sayesinde Persistence katmanı kolayca bir API istemcisiyle,
DragController ise sıralama kütüphaneleriyle değiştirilebilir.
Yazınızı veya özel HTML kodunuzu buraya ekleyebilirsiniz...
Yazınızı veya özel HTML kodunuzu buraya ekleyebilirsiniz...