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

Bu yayında, sürükle ve bırak özelliğinin temelleri açıklanmaktadır.

Sürüklenebilir içerik oluşturun

Çoğu tarayıcıda metin seçimleri, resimler ve bağlantılar varsayılan olarak sürüklenebilir. Örneğin, bir web sayfasındaki bağlantıyı sürüklediğinizde, kısayol oluşturmak veya bağlantıya gitmek için adres çubuğuna veya masaüstüne bırakabileceğiniz, başlığı ve URL'si olan 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 yapmak için söz konusu öğede draggable=true değerini ayarlayın. Resimler, dosyalar, bağlantılar, dosyalar veya sayfanızdaki işaretlemeler dahil olmak üzere neredeyse her şey için sürükleme özelliği etkinleştirilebilir.

Aşağıdaki örnek, CSS Izgarası ile düzenlenmiş sütunları yeniden düzenlemek için bir arayüz oluşturur. Sütunlara ilişkin temel işaretleme şöyle görünür: Her bir sütunun draggable özelliği true olarak ayarlanı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 öğeleri için CSS'yi burada görebilirsiniz. Sürükle özelliğiyle ilgili tek CSS cursor: move özelliğidir. 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ürükleme işlemini izlemek için aşağıdaki etkinliklerden herhangi birini dinleyebilirsiniz:

Sürükleme akışını yönetmek için bir tür kaynak öğeye (sürüklemenin başladığı yer), veri yüküne (sürüklenmekte olan şey) ve hedefe (düşüşü yakalayacak alan) ihtiyacınız vardır. Kaynak öğe hemen hemen her tür öğe olabilir. Hedef, kullanıcının bırakmaya çalıştığı verileri kabul eden bırakma alt bölgesi veya bırakma alt bölgeleri grubudur. Tüm öğeler hedef olamaz. Örneğin, hedefiniz bir resim olamaz.

Sürükleme dizisi başlatma ve sonlandırma

İçeriğinizde draggable="true" özellikleri 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ürüklemeye başladığında sütunun opaklığını% 40'a ayarlar ve ardından sürükleme etkinliği sona erdiğinde% 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ükleyin; opaklığı değişir. Kaynak öğede dragstart etkinliği olduğundan, this.style.opacity değerini% 40 olarak ayarlamak kullanıcıya bu öğenin taşınmakta olan seçim olduğuna dair görsel geri bildirim verir. Öğeyi bıraktığınızda kaynak öğe, henüz düşme davranışını tanımlamamış olsanız bile% 100 opaklığa döner.

İlave görsel işaretler ekleyin

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üklenebilir olmanın yanı sıra bırakma hedefleridir. Kullanıcılar bir sütun üzerinde sürüklenen bir öğeyi tuttuğunda kenarlığı kesik çizgiyle çizerek bu durumu anlamasına 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şleyicilerini ayarlayın, sütun sürüklendiğinde over sınıfını ekleyin ve sürüklenen öğe ayrıldığında kaldırın. dragend işleyicisinde, sürüklemenin sonundaki sınıfları da kaldırdığınızdan 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 değinilmesi gereken birkaç nokta bulunmaktadır:

  • dragover etkinliği için varsayılan işlem, dataTransfer.dropEffect özelliğinin "none" olarak ayarlanmasıdır. dropEffect özelliği bu sayfanın ilerleyen kısımlarında ele alınmıştır. Şimdilik drop etkinliğinin tetiklenmesini engellediğini unutmayın. Bu davranışı geçersiz kılmak için e.preventDefault() yöntemini çağırın. Bir başka iyi uygulama da false öğesini aynı işleyicide döndürmektir.

  • over sınıfını değiştirmek için dragover yerine dragenter etkinlik işleyici kullanılır. dragover kullanırsanız kullanıcı sürüklenen öğeyi bir sütun üzerinde tutarken etkinlik tekrar tekrar tetiklenir ve bu da CSS sınıfının tekrar tekrar geçiş yapmasına neden olur. Bu, tarayıcının birçok gereksiz oluşturma işi yapmasına neden olarak kullanıcı deneyimini etkileyebilir. Yeniden çizim sayısını en aza indirmenizi önemle tavsiye ederiz. dragover kullanmanız gerekiyorsa etkinlik işleyicinizi daraltmayı veya performansı ters çevirmeyi düşünün.

Lansmanı tamamlayın

Lansmanı işlemek üzere drop etkinliği için bir etkinlik işleyici ekleyin. drop işleyicisinde, tarayıcının düşüşler için varsayılan davranışını engellemeniz gerekir. Bu, genellikle can sıkıcı bir yönlendirmedir. 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);
  });

Kodu bu noktada çalıştırırsanız öğe yeni konuma düşmez. Bunun için DataTransfer nesnesini kullanın.

dataTransfer özelliği, sürükleme işlemiyle gönderilen verileri içerir. dataTransfer, dragstart etkinliğinde ayarlanır ve bırakma etkinliğinde okunur veya işlenir. e.dataTransfer.setData(mimeType, dataPayload) yöntemini çağırmak, 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. Bunu yapmak için ilk olarak sürükleme başladığında kaynak öğenin HTML'sini depolamanı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ırakmayı işlersiniz. Buna, kullanıcının sürüklediği aynı sütuna geri dönmediğinden emin olmak da dahildir.

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. Bu özelliğin çalışması için bir masaüstü tarayıcınızın olması gerekir. Sürükle ve Bırak API'si mobil cihazlarda desteklenmez. B sütununun üzerindeki A sütununu sürükleyip serbest bırakın ve yer değişikliklerine dikkat edin:

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 tepki verdiğini kontrol etmek için özellikler sunar.

  • dataTransfer.effectAllowed kullanıcının öğe üzerinde gerçekleştirebileceği "sürükleme türünü" 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ğerlere sahip olabilir: 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 bildirimleri kontrol eder. Kullanıcı, işaretçisini bir hedef öğenin üzerinde tuttuğunda, tarayıcının imleci ne tür bir işlem (kopyalama veya taşıma gibi) yapılacağını belirtir. Efekt şu 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 bir 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ı arayüzünde öğeleri yeniden düzenlemesini isteyen bir kullanıcı arayüzünde gerçekleşebilir. Bazı durumlarda, sürükleme hedefi ve kaynak farklı öğe türleri olabilir. Arayüzde ise kullanıcının seçili resmi bir hedefe sürükleyerek bir ürün için ana resim olarak bir resim seçmesi gerekir.

Sürükle ve Bırak, kullanıcıların masaüstünden bir uygulamaya öğe sürüklemesini sağlamak için sıklıkla kullanılır. Temel fark drop işleyicinizdedir. Dosyalara erişmek için dataTransfer.getData() kullanmak yerine, veriler dataTransfer.files özelliğinde bulunur:

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.
  }
}

Özel sürükle ve bırak bölümünde bununla ilgili daha fazla bilgi bulabilirsiniz.

Daha fazla kaynak