HTML5 Sürükle ve Bırak API'sı

Bu yayında, sürükle ve bırak özelliğiyle ilgili temel bilgiler verilmektedir.

Çoğu tarayıcıda metin seçimleri, görseller ve bağlantılar varsayılan olarak sürüklenebilir. Örneğin, bir web sayfasındaki bağlantıyı sürüklerseniz kısayol oluşturmak veya bağlantıya gitmek için adres çubuğuna ya da masaüstüne bırakabileceğiniz bir başlık ve URL içeren küçük bir kutu görürsünüz. Diğer içerik türlerini sürüklenebilir hale getirmek için HTML5 sürükle ve bırak API'lerini kullanmanız gerekir.

Bir nesneyi sürüklenebilir hâle getirmek için ilgili öğede draggable=true özelliğini ayarlayın. Resimler, dosyalar, bağlantılar, sayfanızdaki işaretlemeler veya hemen hemen her şey sürüklenebilir.

Aşağıdaki örnekte, CSS Grid ile yerleştirilmiş sütunları yeniden düzenlemek için bir arayüz oluşturulmaktadır. Sütunların temel işaretlemesi şöyle görünür. Her sütunun draggable özelliği true olarak ayarlanmıştır:

<div class="container">
  <div draggable="true" class="box">A</div>
  <div draggable="true" class="box">B</div>
  <div draggable="true" class="box">C</div>
</div>

Kapsayıcı ve kutu öğelerinin CSS'sini aşağıda bulabilirsiniz. Sürükleme özelliğiyle ilgili tek CSS, cursor: move mülküdür. Kodun geri kalanı, kapsayıcı ve kutu öğelerinin düzenini ve stilini kontrol eder.

.container {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
}

.box {
  border: 3px solid #666;
  background-color: #ddd;
  border-radius: .5em;
  padding: 10px;
  cursor: move;
}

Bu noktada öğeleri sürükleyebilirsiniz ancak başka hiçbir şey olmaz. Davranış eklemek için JavaScript API'yi kullanmanız gerekir.

Sürükleme etkinliklerini dinleme

Süreci izlemek için aşağıdaki etkinliklerden herhangi birini dinleyebilirsiniz:

Sürükle ve bırak akışını işlemek için bir tür kaynak öğeye (sürüklemenin başladığı yere), veri yükü öğesine (sürüklenen öğeye) ve bir hedefe (öğenin bırakılacağı alana) ihtiyacınız vardır. Kaynak öğe neredeyse her tür öğe olabilir. Hedef, kullanıcının bırakmaya çalıştığı verileri kabul eden bırakma bölgesi veya bırakma bölgesi grubudur. Tüm öğeler hedef olamaz. Örneğin, hedefiniz resim olamaz.

Sürükleme sırasını başlatma ve sonlandırma

İçeriğinizde draggable="true" özelliklerini tanımladıktan sonra her sütun için sürükleme sırasını başlatmak üzere bir dragstart etkinlik işleyici ekleyin.

Bu kod, kullanıcı sütunu sürüklemeye başladığında sütunun opaklığını% 40'a ayarlar ve sürükleme etkinliği sona erdiğinde opaklığı% 100'e döndürür.

function handleDragStart(e) {
  this.style.opacity = '0.4';
}

function handleDragEnd(e) {
  this.style.opacity = '1';
}

let items = document.querySelectorAll('.container .box');
items.forEach(function (item) {
  item.addEventListener('dragstart', handleDragStart);
  item.addEventListener('dragend', handleDragEnd);
});

Sonuç, aşağıdaki Glitch demosunda görülebilir. Bir öğeyi sürüklediğinizde opaklığı değişir. Kaynak öğede dragstart etkinliği bulunduğundan this.style.opacity'yi% 40'a ayarlamak, kullanıcıya söz konusu öğenin taşınmakta olan mevcut seçim olduğunu görsel olarak bildirir. Öğeyi bıraktığınızda, henüz bırakma davranışını tanımlamamış olsanız bile kaynak öğe% 100 opaklığa döner.

Ek görsel ipuçları ekleme

Kullanıcının arayüzünüzle nasıl etkileşimde bulunacağını anlamasına yardımcı olmak için dragenter, dragover ve dragleave etkinlik işleyicilerini kullanın. Bu örnekte sütunlar, sürüklenebilmenin yanı sıra bırakma hedefleridir. Kullanıcı, sürüklenen bir öğeyi sütun üzerinde tuttuğunda kenar çizgisini noktalı hale getirerek bu durumu anlamaya yardımcı olun. Örneğin, CSS'nizde, bırakma hedefi olan öğeler için bir over sınıfı oluşturabilirsiniz:

.box.over {
  border: 3px dotted #666;
}

Ardından JavaScript'inizde etkinlik işleyicileri ayarlayın, sütun sürüklendiğinde over sınıfını ekleyin ve sürüklenen öğe ayrıldığında sınıfı kaldırın. dragend işleyicisinde, sürüklemenin sonunda sınıfları kaldırdığımızdan da emin oluruz.

document.addEventListener('DOMContentLoaded', (event) => {

  function handleDragStart(e) {
    this.style.opacity = '0.4';
  }

  function handleDragEnd(e) {
    this.style.opacity = '1';

    items.forEach(function (item) {
      item.classList.remove('over');
    });
  }

  function handleDragOver(e) {
    e.preventDefault();
    return false;
  }

  function handleDragEnter(e) {
    this.classList.add('over');
  }

  function handleDragLeave(e) {
    this.classList.remove('over');
  }

  let items = document.querySelectorAll('.container .box');
  items.forEach(function(item) {
    item.addEventListener('dragstart', handleDragStart);
    item.addEventListener('dragover', handleDragOver);
    item.addEventListener('dragenter', handleDragEnter);
    item.addEventListener('dragleave', handleDragLeave);
    item.addEventListener('dragend', handleDragEnd);
    item.addEventListener('drop', handleDrop);
  });
});

Bu kodda ele alınması gereken birkaç nokta vardır:

  • dragover etkinliği için varsayılan işlem, dataTransfer.dropEffect özelliğini "none" olarak ayarlamaktır. dropEffect mülküne bu sayfanın ilerleyen bölümlerinde değinilmektedir. Şimdilik, drop etkinliğinin tetiklenmesini engellediğini bilmeniz yeterlidir. Bu davranışı geçersiz kılmak için e.preventDefault() numaralı telefonu arayın. Aynı işleyicide false döndürmek de iyi bir uygulamadır.

  • dragenter etkinlik işleyicisi, dragover yerine over sınıfını etkinleştirmek/devre dışı bırakmak için kullanılır. dragover kullanıyorsanız kullanıcı sürüklenen öğeyi bir sütunun üzerinde tutarken etkinlik tekrar tekrar tetiklenir ve CSS sınıfı tekrar tekrar açılıp kapanır. Bu, tarayıcının çok fazla gereksiz oluşturma işlemi yapmasına neden olur ve kullanıcı deneyimini etkileyebilir. Yeniden çizimleri en aza indirmenizi önemle tavsiye ederiz. dragover kullanmanız gerekiyorsa etkinlik dinleyicinizi sınırlamayı veya hata ayıklama süresini azaltmayı deneyin.

Bırakmayı tamamlama

Düşüşü işlemek için drop etkinliği için bir etkinlik işleyici ekleyin. dropİşleyicide, tarayıcının bırakıldığındaki varsayılan davranışını (genellikle can sıkıcı bir yönlendirme) önlemeniz gerekir. Bunun için e.stopPropagation() numaralı telefonu arayın.

function handleDrop(e) {
  e.stopPropagation(); // stops the browser from redirecting.
  return false;
}

Yeni işleyiciyi diğer işleyicilerle birlikte kaydettiğinizden emin olun:

  let items = document.querySelectorAll('.container .box');
  items.forEach(function(item) {
    item.addEventListener('dragstart', handleDragStart);
    item.addEventListener('dragover', handleDragOver);
    item.addEventListener('dragenter', handleDragEnter);
    item.addEventListener('dragleave', handleDragLeave);
    item.addEventListener('dragend', handleDragEnd);
    item.addEventListener('drop', handleDrop);
  });

Bu noktada kodu çalıştırırsanız öğe yeni konuma bırakılmaz. Bunu yapmak için DataTransfer nesnesini kullanın.

dataTransfer mülkü, sürükleme işleminde gönderilen verileri tutar. dataTransfer dragstart etkinliğinde ayarlanır ve bırak etkinliğinde okunur veya işlenir. e.dataTransfer.setData(mimeType, dataPayload) çağrısı, nesnenin MIME türünü ve veri yükünü ayarlamanıza olanak tanır.

Bu örnekte, kullanıcıların sütunların sırasını yeniden düzenlemesine izin vereceğiz. Bunun için önce sürükleme işlemi başladığında kaynak öğenin HTML'sini saklamanız gerekir:

function handleDragStart(e) {
  this.style.opacity = '0.4';

  dragSrcEl = this;

  e.dataTransfer.effectAllowed = 'move';
  e.dataTransfer.setData('text/html', this.innerHTML);
}

drop etkinliğinde, kaynak sütunun HTML'sini, verileri bıraktığınız hedef sütunun HTML'sine ayarlayarak sütun bırakma işlemini gerçekleştirirsiniz. Bu, kullanıcının sürüklediği sütuna geri bırakmadığını kontrol etmeyi de içerir.

function handleDrop(e) {
  e.stopPropagation();

  if (dragSrcEl !== this) {
    dragSrcEl.innerHTML = this.innerHTML;
    this.innerHTML = e.dataTransfer.getData('text/html');
  }

  return false;
}

Sonucu aşağıdaki demoda görebilirsiniz. Bunun için masaüstü tarayıcınız olmalıdır. Sürükle ve bırak API'si mobil cihazlarda desteklenmez. A sütununu sürükleyip B sütununun üzerine bırakın ve sütunların nasıl yer değiştirdiğini görün:

Diğer sürükleme özellikleri

dataTransfer nesnesi, sürükleme işlemi sırasında kullanıcıya görsel geri bildirim sağlamak ve her bir bırakma hedefinin belirli bir veri türüne nasıl yanıt verdiğini kontrol etmek için özellikleri gösterir.

  • dataTransfer.effectAllowed kullanıcı öğe üzerinde hangi "sürükleme türünü" gerçekleştirebileceğini kısıtlar. dragenter ve dragover etkinlikleri sırasında dropEffect öğesini başlatmak için sürükle ve bırak işleme modelinde kullanılır. Özellik şu değerleri alabilir: none, copy, copyLink, copyMove, link, linkMove, move, all ve uninitialized.
  • dataTransfer.dropEffect, kullanıcının dragenter ve dragover etkinlikleri sırasında aldığı geri bildirimi kontrol eder. Kullanıcı işaretçisini bir hedef öğenin üzerinde tuttuğunda, tarayıcı imleci kopyalama veya taşıma gibi ne tür bir işlemin yapılacağını gösterir. Etki, aşağıdaki değerlerden birini alabilir: none, copy, link, move.
  • e.dataTransfer.setDragImage(imgElement, x, y), tarayıcının varsayılan "hayalet resim" geri bildirimini kullanmak yerine sürükleme simgesi ayarlayabileceğiniz anlamına gelir.

Dosya yükleme

Bu basit örnekte hem sürükleme kaynağı hem de sürükleme hedefi olarak bir sütun kullanılmaktadır. Bu durum, kullanıcıdan öğeleri yeniden düzenlemesini isteyen bir kullanıcı arayüzünde gerçekleşebilir. Bazı durumlarda, sürükleme hedefi ve kaynağı farklı öğe türleri olabilir. Örneğin, kullanıcının bir ürünün ana resmi olarak bir resmi seçip hedefe sürüklemesi gereken bir arayüzde.

Sürükle ve bırak, kullanıcıların masaüstündeki öğeleri bir uygulamaya sürüklemesine olanak tanımak için sıklıkla kullanılır. Temel fark, drop işleyicinizdedir. Dosyalara erişmek için dataTransfer.getData() yerine dataTransfer.files mülkü kullanılır ve verilerini içerir:

function handleDrop(e) {
  e.stopPropagation(); // Stops some browsers from redirecting.
  e.preventDefault();

  var files = e.dataTransfer.files;
  for (var i = 0, f; (f = files[i]); i++) {
    // Read the File objects in this FileList.
  }
}

Bu konu hakkında daha fazla bilgiyi Özel sürükle ve bırak bölümünde bulabilirsiniz.

Diğer kaynaklar