HTML5 खींचें और छोड़ें एपीआई

इस पोस्ट में, 'खींचें और छोड़ें' सुविधा के बारे में बुनियादी जानकारी दी गई है.

खींचने और छोड़ने लायक कॉन्टेंट बनाएं

ज़्यादातर ब्राउज़र में, चुने गए टेक्स्ट, इमेज, और लिंक को डिफ़ॉल्ट रूप से खींचकर छोड़ा जा सकता है. उदाहरण के लिए, अगर आप किसी वेब पेज पर कोई लिंक खींचते हैं, तो आपको शीर्षक और URL है जिसे आप पता बार या डेस्कटॉप पर छोड़ सकते हैं और शॉर्टकट का इस्तेमाल करें या लिंक पर जाएं. अन्य तरह के कॉन्टेंट को खींचने और छोड़ने लायक बनाने के लिए, आपको HTML5 'खींचें और छोड़ें' एपीआई का इस्तेमाल करना होगा.

किसी ऑब्जेक्ट को खींचने और छोड़ने लायक बनाने के लिए, उस एलिमेंट पर draggable=true सेट करें. इसके बारे में किसी भी चीज़ को खींचने और छोड़ने की सुविधा हो सकती है, जैसे कि इमेज, फ़ाइलें, लिंक, फ़ाइलें या मार्कअप जोड़ा जा सकता है.

नीचे दिया गया उदाहरण उन कॉलम को फिर से व्यवस्थित करने के लिए एक इंटरफ़ेस बनाता है जिन्हें सीएसएस ग्रिड की मदद से बनाया गया है. कॉलम का बेसिक मार्कअप कुछ ऐसा दिखता है, जिसमें हर कॉलम के लिए draggable एट्रिब्यूट को true पर सेट किया गया है:

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

कंटेनर और बॉक्स एलिमेंट का सीएसएस यहां दिया गया है. सिर्फ़ सीएसएस cursor: move को खींचने और छोड़ने की सुविधा प्रॉपर्टी. बाकी कोड, कंटेनर का लेआउट और स्टाइल कंट्रोल करते हैं और बॉक्स एलिमेंट.

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

यहां से आइटम को खींचकर छोड़ा जा सकता है, लेकिन कुछ और नहीं होता. जोड़ने के लिए तो आपको JavaScript API का इस्तेमाल करना होगा.

खींचकर छोड़ने वाले इवेंट को सुनें

खींचकर छोड़ने की प्रोसेस पर नज़र रखने के लिए, इनमें से किसी भी इवेंट को सुना जा सकता है:

ड्रैग फ़्लो को हैंडल करने के लिए, आपको किसी प्रकार के सोर्स एलिमेंट की ज़रूरत होगी (जहां खींचें और छोड़ें शुरू होता है), डेटा पेलोड (खींची जा रही चीज़), और टारगेट (वह क्षेत्र जहां छोड़ा गया) और कम हो जाता है). सोर्स एलिमेंट करीब-करीब किसी भी तरह का एलिमेंट हो सकता है. कॉन्टेंट बनाने टारगेट, ड्रॉप ज़ोन या ड्रॉप ज़ोन का वह सेट है जो उपयोगकर्ता के डेटा को स्वीकार करता है छोड़ने का प्रयास कर रहा है. सभी एलिमेंट को टारगेट नहीं किया जा सकता. उदाहरण के लिए, आपका टारगेट इमेज नहीं होनी चाहिए.

ड्रैग क्रम शुरू और खत्म करना

अपने कॉन्टेंट में draggable="true" एट्रिब्यूट की जानकारी देने के बाद, किसी अटैचमेंट को अटैच करें हर कॉलम के लिए ड्रैग क्रम शुरू करने के लिए dragstart इवेंट हैंडलर.

जब उपयोगकर्ता इसे खींचना शुरू करता है, तो यह कोड कॉलम की ओपैसिटी को 40% पर सेट कर देता है, फिर खींचकर छोड़ने वाला इवेंट खत्म होने पर उसे 100% पर वापस कर दें.

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);
});

इसका नतीजा नीचे दिए गए Glitch डेमो में देखा जा सकता है. कोई आइटम खींचें और उसके ओपैसिटी में बदलाव होते हैं. सोर्स एलिमेंट में dragstart इवेंट मौजूद है, इसलिए सेटिंग this.style.opacity से 40% तक, उपयोगकर्ता को विज़ुअल फ़ीडबैक मिलता है कि वह एलिमेंट वर्तमान चुनाव को स्थानांतरित किया जा रहा है. आइटम को छोड़ने पर, सोर्स एलिमेंट ओपैसिटी यानी कि ओपैसिटी, 100% पर वापस आ जाती है. भले ही, आपने अब तक वैल्यू में गिरावट न डाली हो.

ज़्यादा विज़ुअल संकेत जोड़ें

आपके इंटरफ़ेस के साथ इंटरैक्ट करने का तरीका समझने में उपयोगकर्ता की सहायता करने के लिए, dragenter, dragover, और dragleave इवेंट हैंडलर. इस उदाहरण में, कॉलम खींचने और छोड़ने लायक होने के अलावा, उनका टारगेट कम हो जाता है. इन कामों में उपयोगकर्ता की मदद करें इसे समझने के लिए, बॉर्डर को डैश वाली बनाएं. ऐसा तब करें, जब वे खींचे गए आइटम को कॉलम. उदाहरण के लिए, अपनी सीएसएस में, over वे एलिमेंट जो ड्रॉप टारगेट हैं:

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

इसके बाद, अपने JavaScript में इवेंट हैंडलर सेट अप करें. इसके बाद, over क्लास जोड़ें कॉलम को ऊपर की ओर खींचकर छोड़ा जाता है. इसके बाद, बनाए गए एलिमेंट के बाहर जाने पर, कॉलम को हटा दिया जाता है. तय सीमा में dragend हैंडलर के आखिर में हम यह भी पक्का करते हैं कि खींचें.

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);
  });
});

इस कोड में कुछ बातें बताई गई हैं:

  • डिफ़ॉल्ट कार्रवाई dragover इवेंट के लिए, dataTransfer.dropEffect प्रॉपर्टी को "none". इस पेज पर dropEffect प्रॉपर्टी के बारे में बाद में बताया गया है. अभी के लिए, बस ध्यान रखें कि यह drop इवेंट को ट्रिगर होने से रोकता है. इसे बदलने के लिए व्यवहार, e.preventDefault() को कॉल करें. वापस जाना एक अच्छा तरीका है false उसी हैंडलर में.

  • इसके बजाय, over क्लास को टॉगल करने के लिए, dragenter इवेंट हैंडलर का इस्तेमाल किया जाता है dragover. dragover का इस्तेमाल करने पर, इवेंट बार-बार ट्रिगर होता है, जबकि उपयोगकर्ता खींचे गए आइटम को कॉलम पर रखता है, जिसकी वजह से सीएसएस क्लास टॉगल होती है बार-बार. इससे ब्राउज़र कई गै़र-ज़रूरी रेंडरिंग का काम कर देता है, इससे उपयोगकर्ता अनुभव पर असर पड़ सकता है. हमारा सुझाव है कि आप और अगर आपको dragover का इस्तेमाल करना है, तो अपने इवेंट लिसनर को थ्रॉट करना या उसे डिकोड करना.

लॉन्च को पूरा करें

लॉन्च की प्रोसेस पूरी करने के लिए, drop इवेंट के लिए इवेंट लिसनर जोड़ें. drop में हैंडलर के लिए, आपको ब्राउज़र के डिफ़ॉल्ट व्यवहार को रोकना होगा. आम तौर पर, लोगों को रीडायरेक्ट करने से आपको परेशानी होती है. ऐसा करने के लिए, e.stopPropagation() पर कॉल करें.

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

नए हैंडलर को दूसरे हैंडलर के साथ ज़रूर रजिस्टर करें:

  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);
  });

अगर इस पॉइंट पर कोड चलाया जाता है, तो आइटम नई जगह पर नहीं जाता. यहां की यात्रा पर हूं इसके लिए, DataTransfer का इस्तेमाल करें ऑब्जेक्ट है.

खींचकर छोड़ने की कार्रवाई में भेजा गया डेटा dataTransfer प्रॉपर्टी में सेव होता है. dataTransfer अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है को dragstart इवेंट में सेट किया जाता है और ड्रॉप इवेंट में पढ़ा या मैनेज किया जाता है. कॉल से जुड़ी सुविधा e.dataTransfer.setData(mimeType, dataPayload) से आपको ऑब्जेक्ट का MIME सेट करने की सुविधा मिलती है टाइप और डेटा पेलोड की जानकारी.

इस उदाहरण में, हम उपयोगकर्ताओं को कॉलम का क्रम बदलने की सुविधा देंगे. ऐसा करने के लिए, सबसे पहले आपको सोर्स एलिमेंट का एचटीएमएल सेव करना होगा. शुरू होगा:

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

  dragSrcEl = this;

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

drop इवेंट में, सोर्स कॉलम के एचटीएमएल को उस टारगेट कॉलम के एचटीएमएल में बदल दें जिस पर आपने डेटा छोड़ा था. यह इसमें यह जांच की जाती है कि उपयोगकर्ता उसी कॉलम पर वापस नहीं आ रहा है, जो यहां से लिया गया.

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

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

  return false;
}

नीचे दिए गए डेमो में आप नतीजे देख सकते हैं. यह सुविधा काम करे, इसके लिए ज़रूरी है कि डेस्कटॉप ब्राउज़र. 'खींचें और छोड़ें' एपीआई मोबाइल पर काम नहीं करता. खींचें और B कॉलम के ऊपर A कॉलम को छोड़ें और देखें कि वे जगह कैसे बदलते हैं:

खींचकर छोड़ने वाली ज़्यादा प्रॉपर्टी

dataTransfer ऑब्जेक्ट, प्रॉपर्टी को दिखाता है, ताकि उपयोगकर्ता को खींचने की प्रोसेस के दौरान उपयोगकर्ता और यह कंट्रोल कर सकते हैं कि ड्रॉप टारगेट एक खास तरह का डेटा है.

  • dataTransfer.effectAllowed 'खींचें और छोड़ें' को प्रतिबंधित करता है उपयोगकर्ता, एलिमेंट पर काम कर सके. इसका इस्तेमाल किया जा चुका है को खींचें और छोड़ें प्रोसेसिंग मॉडल में, dropEffect को शुरू करने के लिए dragenter और dragover इवेंट. प्रॉपर्टी में ये चीज़ें हो सकती हैं ये वैल्यू दी गई हैं: none, copy, copyLink, copyMove, link, linkMove, move, all, और uninitialized.
  • dataTransfer.dropEffect dragenter और dragover के दौरान उपयोगकर्ता को मिलने वाले फ़ीडबैक को कंट्रोल करता है इवेंट. जब उपयोगकर्ता अपने पॉइंटर को किसी टारगेट एलिमेंट के ऊपर रखता है, तो ब्राउज़र का कर्सर बताता है कि किस तरह की कार्रवाई होने वाली है, जैसे कि कर सकते हैं. इनमें से कोई एक वैल्यू, लागू हो सकती है: none, copy, link, move.
  • e.dataTransfer.setDragImage(imgElement, x, y) इसका मतलब है कि ब्राउज़र की डिफ़ॉल्ट 'घोस्ट इमेज' का इस्तेमाल करने के बजाय सुझाव, राय या शिकायत खींचकर छोड़ने के लिए आइकॉन सेट कर सकते हैं.

फ़ाइल अपलोड करें

इस आसान उदाहरण में, ड्रैग सोर्स और ड्रैग टारगेट, दोनों के तौर पर कॉलम का इस्तेमाल किया गया है. यह ऐसा यूज़र इंटरफ़ेस (यूआई) में हो सकता है जिसमें उपयोगकर्ता से आइटम का क्रम बदलने के लिए कहा जाता है. कुछ स्थितियों में, ड्रैग टारगेट और सोर्स, एलिमेंट के अलग-अलग टाइप के हो सकते हैं, जैसा कि इंटरफ़ेस में हो सकता है जहां उपयोगकर्ता को प्रॉडक्ट के लिए, एक इमेज को मुख्य इमेज के तौर पर चुनना होगा. इसके लिए, चुनी हुई इमेज को टारगेट पर खींचें और छोड़ें.

'खींचें और छोड़ें' सुविधा का अक्सर इस्तेमाल इसलिए किया जाता है, ताकि उपयोगकर्ता अपने डेस्कटॉप से आइटम खींचकर एक ऐप्लिकेशन खोलें. मुख्य अंतर आपके drop हैंडलर में है. का उपयोग करने के बजाय फ़ाइलों को ऐक्सेस करने के लिए dataTransfer.getData() करते हैं, तो उनका डेटा dataTransfer.files प्रॉपर्टी:

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

इस बारे में ज़्यादा जानकारी यहां देखी जा सकती है अपनी पसंद के मुताबिक खींचें और छोड़ें.

ज़्यादा रिसॉर्स