jQuery Draggable - создайте перетаскиваемый объект и начните перетаскивать его на собственное событие API Drag And Drop html5 - PullRequest
0 голосов
/ 22 июня 2019

Хорошо, в принципе, я хочу попытаться добиться, когда событие dragover запускается из HTML5 Drag And Drop API, я хочу создать объект jQuery draggable и начать следовать за мышью, пока dragendсобытие запускается из HTML5 Drag And Drop API.

Причина, по которой я хочу это сделать, заключается в следующем:

  • У меня есть приложение, которое использует плагин, который имеет функциональность, котораязависит от jQuery.ui draggable для работы (это плагин FullCalendar Scheduler, версия 3)
  • Я хочу добиться новой функциональности в приложении, с помощью которой клиент может перетащить что-то из браузера окно A , и поместите его в вышеупомянутый плагин в окне браузера B .
  • Поскольку вышеупомянутый плагин не работает с собственным HTML5 Drag and Drop API, а jQuery.ui draggable не способен перетаскивать элементы из одного окна браузера в другое, я думаю, что мой единственный вариант - смешать эти два плагина.

Мое предлагаемое решение этой проблемы было с использованием собственного HTML5 Drag and Drop APIи когда тащатэлемент достигает dropzone, создавая новый перетаскиваемый элемент в окне браузера B и имитируя событие mousedown, поэтому он начинает следовать за курсором.Когда сработало событие dragend, я планировал просто и просто запустить событие mouseup для элемента draggable, и с этого момента плагин планировщика может творить чудеса.

Чтобы попытатьсяпротестируйте это сначала с помощью одного окна браузера, я попытался выполнить первую часть моего решения, а именно: когда срабатывает dragover, создайте jQuery.ui draggable и смоделируйте на нем mousedown, затемон должен начать следовать за мышью.Я не могу добиться такого поведения.

Я сделал скрипку, где вы можете увидеть то, что я пробовал до сих пор (я не публикую здесь весь код, так как он довольно длинный): JSFiddle

По сути, ошибка, которую я получаю на Fiddle, с обоими опробованными опциями - это ошибка type.indexOf is not a function.

Я также спрашивал и получал некоторую помощь по следующим вопросам вопрос , откуда предложенное решение прекрасно работает при запуске операции перетаскивания с событием click, но оно не работает с любым другим типом события.Я нажимаю, я могу смоделировать событие mousedown.draggable, только из MouseEvent, и событие dragend не является MouseEvent.

Короче говоря, мне нужна помощь в получении результатаЯ ищу, по крайней мере, первую часть предложенного мной решения!

1 Ответ

0 голосов
/ 25 июня 2019

Похоже, нет хорошего ответа на это.Во-первых, не все браузеры поддерживают одинаковую терминологию или функциональность DnD.Например, FireFox запускает событие dragenter при выпадении, а Chrome, похоже, не обнаруживает событие drop, когда объект находится в другом окне.

Вот мое тестирование до сих пор.Чтобы использовать, скопируйте содержимое в текстовый файл и сохраните как HTM или HTML.Затем откройте файл локально в вашем браузере.Откройте другое окно и откройте второй HTM.теперь у вас есть два окна, которые вы можете перетащить в и из.

wina-1.htm

<code><!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Window A</title>
  <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <style>
  .items {
    position: relative;
  }
  .items > div {
    margin-right: 5px;
    width: 150px;
    height: 150px;
    padding: 0.5em;
    border-radius: 6px;
    display: inline-block;
  }
  #log {
    width: 100%;
    height: 5em;
    overflow-y: auto;
  }
  [draggable].idle {
    background-color: rgba(255,0,0,0.75); 
  }
  [draggable].selected {
    background-color: rgba(255,0,0,0.95);
  }
  </style>
</head>
<body>
<pre id="log">

Тащите меня вокруг

Я не могу быть перемещен

var srcEl;функция log (s) {var now = new Date ();var t = now.getHours () + ":" + now.getMinutes () + ":" + now.getSeconds () + "."+ now.getMilliseconds ();var l = document.getElementById ("log");l.append (t + ":" + s + "\ r \ n");l.scrollTop = l.scrollHeight;} function dragStart (e) {log ("Начало перетаскивания:" + e.target.nodeName + "#" + e.target.id);srcEl = e.target;if (e.dataTransfer == undefined) {} ​​else {e.dataTransfer.effectAllowed = "copyMove";log («Событие dataTransfer.effectAllowed:» + e.dataTransfer.effectAllowed);log ("Исходный элемент:" + srcEl.nodeName + "#" + srcEl.id);} this.classList.add ("selected");} function dragOver (e) {e.preventDefault ();log ("Перетаскивание:" + e.target.nodeName + (e.target.id! = ""? "#" + e.target.id: ""));вернуть ложь;} function dragLeave (e) {log ("Drag Leave:" + e.target.nodeName + (e.target.id! = ""? "#" + e.target.id: ""));} function dragStop (e) {log ("Drag End:" + e.target.nodeName + "#" + e.target.id);this.classList.remove ( "выбрано");} log ("Init");var item = document.getElementById ("draggable");item.addEventListener ('dragstart', dragStart, false);item.addEventListener ('dragover', dragOver, false);item.addEventListener ('dragleave', dragLeave, false);window.addEventListener ('dragleave', dragLeave, false);var items = document.querySelectorAll ('. items> div');[] .forEach.call (items, function (el) {el.addEventListener ('dragover', dragOver, false);});

Как вы видите, это использует сырой JavaScript.Я работал с пользовательским интерфейсом jQuery и сохранял таблицу стилей просто для удобства.У нас есть раздел для распечатки данных журнала, перетаскиваемого объекта и статического элемента.

winb-1.htm

<code><!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Window B</title>
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <style>
.drag-item {
  width: 100px;
  height: 100px;
  background-color: red;
}

body {
  position: relative;
}

div.drag-helper {
  width: 100px;
  height: 100px;
  background-color: red;
  z-index: 1002;
  position: relative;
}

#log {
  width: 100%;
  height: 5em;
  line-height: 1em;
  font-size: 1em;
  overflow-y: auto;
}

#dropzone {
  background-color: green;
  width: 95%;
  height: 340px;
}
  </style>
</head>
<body>
  <pre id="log">
jQuery (function ($) {function log (s) {var now = new Date (); var t = now.getHours () + ":" + now.getMinutes () + ":" +now.getSeconds () + "." + now.getMilliseconds (); $ ("# log"). append (t + ":" + s + "\ r \ n"). scrollTop ($ ("# log"..target) .attr ("id"). length? "#" + $ (e.target) .attr ("id"): ""));} function dragOver (e) {log ("Сработало перетаскивание через:"+ $ (e.target) .prop (" nodeName ") + ($ (e.target) .attr (" id "). length?" # "+ $ (e.target) .attr (" id "): "")); e.dataTransfer.dropEffect = 'move'; e.preventDefault ();} function handleDrop (e) {if (e.stopPropagation) {e.stopPropagation ();} log ("Drop Triggered:"+1$ (e.target) .attr ("id"). length? "#" + $ (e.target) .attr ("id"): ""));} log ("Init"); $ ("#dropzone "). on ({dragenter: dragEnter, dragover: dragOver, drop: handleDrop, mouseup: handleDrop, dragend: dragEnd});$ (window) .on ({dragenter: dragEnter, dragover: dragOver, drop: handleDrop, dragend: dragEnd});});

Окно B использует jQuery, поскольку предполагалось преобразовать элемент в jQuery UI Draggable.

Первое, что нужно знать, в пути нет пути. Поскольку элемент Source не является частью целевого DOM, это невозможно сделать. Его можно добавить и инициализировать как Draggable в событии drop. По сути, то, что произойдет, будет создан новый элемент в то время, назначенные все данные.

Во-вторых, передача данных ненадежна, и я бы не использовал DataTransfer в качестве контейнера данных. Я бы посоветовал использовать localStorage. Это похоже на cookie и намного надежнее.

Например, я создал следующий объект данных:

{
  id,
  type,
  attr: {
    id,
    class,
    width,
    height
  },
  content
}

Вот несколько примеров функций:

function collectData(obj){
  return {
    id: obj.attr("id"),
    type: obj.prop("nodeName"),
    attr: {
      id: obj.attr("id"),
      class: obj.attr("class"),
      width: obj.width(),
      height: obj.height()
    },
    content: obj.text().trim()
  };
}

function saveData(k, d){
  localStorage.setItem(k, JSON.stringify(d));
}

function getData(k){
  return JSON.parse(localStorage.getItem(k));
}

function makeEl(d, pObj){
  return $("<" + d.type +">", d.attr).html("<p>" + d.content + "</p>").appendTo(pObj);
}

$("#draggable").on('dragstart', function(e){
  saveData("drag-data", collectData($(this)));
});

$("#dropzone").on('drop', function(e){
  var item = makeEl(getData('drag-data'), $(this));
  item.addClass("clone").position({
    my: "center",
    of: e
  }).draggable();
});

Теоретически это должно работать. На практике я столкнулся с кучей препятствий. Я бы предложил что-то вроде действия типа «нажми и скопируй». Когда пользователь щелкает элемент в окне A (выбирая его), а затем щелкает, где он хочет, чтобы он находился в окне B. Снова используя localStorage, элемент может быть клонирован в новом месте.

Wina-3.htm

<code><!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Draggable - Default functionality</title>
  <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <style>
  .items {
    position: relative;
  }
  .items > div {
    margin-right: 5px;
    width: 150px;
    height: 150px;
    padding: 0.5em;
    border-radius: 6px;
    display: inline-block;
  }
  #log {
    width: 100%;
    height: 5em;
    overflow-y: auto;
  }
  [draggable].idle {
    background-color: rgba(255,0,0,0.5); 
  }
  [draggable].selected {
    background-color: rgba(255,0,0,0.95);
  }
  </style>
</head>
<body>
<pre id="log">

Нажмите на меня

Я не могу быть перемещен

var intv; журнал (ы) функций { var now = new Date (); var t = now.getHours () + ":" + now.getMinutes () + ":" + now.getSeconds () + "." + now.getMilliseconds (); var l = document.getElementById ("log"); l.append (t + ":" + s + "\ r \ n"); l.scrollTop = l.scrollHeight; } function collectData (el) { вернуть { id: el.id, тип: el.nodeName, attr: { id: el.id, class: el.className, ширина: эл. ширина, высота: высота }, содержание: el.innerText }; } функция saveData (k, v) { localStorage.setItem (k, JSON.stringify (v)); } function getData (k) { return JSON.parse (localStorage.getItem (k)); } function clearData (k) { localStorage.setItem (k, null); } function selElem (e) { var trg = e.target.nodeName + (e.target.id! = ""? "#" + e.target.id: ""); если (e.target.classList.contains ( "выбранные")) { log ("Отменить выбор элемента:" + trg); e.target.classList.remove ( "выбрано"); } еще { log («Выбранный элемент:» + trg); e.target.classList.add ( "выбрано"); saveData ("select-data", collectData (e.target)); } intv = setInterval (function () { if (getData ("select-data") == null) { document.getElementsByClassName ( "выбрано") [0] .classList.remove ( "выбрано"); войти ( "невыбранный"); clearInterval (INTV); } }, 1000); } войти ( "INIT"); var item = document.getElementById ("draggable"); item.addEventListener ('click', selElem);

winb-3.htm

<code><!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Window B</title>
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <style>
.drag-item {
  width: 100px;
  height: 100px;
  background-color: red;
}

body {
  position: relative;
}

#log {
  width: 100%;
  height: 5em;
  line-height: 1em;
  font-size: 1em;
  overflow-y: auto;
}

#dropzone {
  background-color: green;
  width: 95%;
  height: 340px;
  position: relative;
}

.cloned {
  position: absolute;
  width: 150px;
  height: 150px;
  padding: 0.5em;
  border-radius: 6px;
  display: inline-block;
  background-color: rgba(255,0,0,0.75);
}
  </style>
</head>
<body>
  <pre id="log">
jQuery (функция ($) { журнал (ы) функций { var now = new Date (); var t = now.getHours () + ":" + now.getMinutes () + ":" + now.getSeconds () + "." + now.getMilliseconds (); $ ("# log"). append (t + ":" + s + "\ r \ n"). scrollTop ($ ("# log"). prop ( "ScrollHeight")); } function getData (k) { console.log ("Получение данных: '" + k + "'", localStorage.getItem (k)); return JSON.parse (localStorage.getItem (k)); } function clearData (k) { журнал («Очистить данные»); localStorage.setItem (k, null); } function makeEl (dObj, pObj) { console.log (dObj, pObj); return $ ("<" + dObj.type + ">", dObj.attr) .html ("

" + dObj.content + "

") appendTo (PObj). } function handleDrop (e) { if (e.stopPropagation) { e.stopPropagation (); } var trg = $ (e.target); log ("Drop Triggered:" + trg.prop ("nodeName") + "#" + trg.attr ("id")); var d, item; if (e.target.id == "dropzone" && (e.type == "click" || e.type == "MouseUp")) { журнал («Обнаружен клик - сбор данных»); d = getData ("select-data"); console.log («Данные», д);d.attr.id = "clone-" + ($ ("# dropzone .cloned"). length + 1);log ("Создание элемента:" + d.type + "#" + d.attr.id);item = makeEl (d, trg);item.removeClass ("selected"). addClass ("cloned"). position ({my: "center", of: e}). draggable ();clearData ( "Select-данные");вернуть истину;} вернуть ложь;} log ("Init");$ ("# dropzone"). on ({mouseup: handleDrop, click: handleDrop});});

Я знаю, что это не тот ответ, который вы ищете, и для этого вам нужно попытаться задать реальный вопрос.Вы, кажется, продолжаете задавать вопросы.

Надеюсь, это поможет.

...