简体   繁体   English

jQuery Draggable - 创建可拖动并开始拖动html5本机Drag and Drop api事件

[英]jQuery Draggable - Create draggable and start dragging on html5 native Drag And Drop api event

Okay, basically what I want to try to achieve, is when a dragover event fires from HTML5 Drag And Drop API , I wish to create a jQuery draggable object, and start following the mouse around, while the dragend event fires from the HTML5 Drag And Drop API . 好吧,基本上我想要尝试实现的是,当一个dragover事件从HTML5 Drag And Drop API触发时,我希望创建一个jQuery draggable对象,并开始跟随鼠标,而dragend事件从HTML5 Drag And Drop API dragend中触发HTML5 Drag And Drop API

The reason I want to do this, is the following: 我想这样做的原因如下:

  • I have an application which uses a plugin, that has a functionality, which is dependent on the jQuery.ui draggable to function (it is the FullCalendar Scheduler plugin, version 3) 我有一个使用插件的应用程序,它具有一个功能,它依赖于jQuery.ui draggable to function(它是FullCalendar Scheduler插件,版本3)
  • I want to achieve a new functionality in the application, with which the client can drag something from browser window A , and drop it in the above mentioned plugin in browser window B . 我想在应用程序中实现一个新功能,客户端可以从浏览器窗口A中拖动一些东西,并将其放在浏览器窗口B中的上述插件中。
  • As the above mentioned plugin is not working with the native HTML5 Drag and Drop API , and the jQuery.ui draggable is not capable of dragging elements from one browser window to the other, I think my only option is to mix these two plugins. 由于上面提到的插件不能使用本机HTML5 Drag and Drop API ,并且jQuery.ui draggable无法将元素从一个浏览器窗口拖动到另一个浏览器窗口,我认为我唯一的选择是混合使用这两个插件。

My proposed solution to this problem was, using the native HTML5 Drag and Drop API , and when the dragged element reaches over a dropzone , creating a new draggable element in browser window B , and simulating a mousedown event on it, so it starts following the cursor. 我提出的解决这个问题的方法是,使用原生的HTML5 Drag and Drop API ,当拖动的元素到达一个dropzone ,在浏览器窗口B中创建一个新的可拖动元素,并在其上模拟一个mousedown事件,所以它开始跟随光标。 When the dragend event would fire, I planned to plain and simply fire the mouseup event on the draggable element also, and from here on the scheduler plugin can do it's magic. dragend事件发生时,我计划简单地简单地在draggable元素上触发mouseup事件,并且从调度程序插件开始就可以实现它的魔力。

To try to test this out, with a single browser window at first, I've tried to achieve the first part of my above solution, ie: when the dragover fires, create the jQuery.ui draggable and simulate a mousedown on it, then it should start following the mouse. 为了尝试对此进行测试,首先使用单个浏览器窗口,我试图实现上述解决方案的第一部分,即:当dragover触发时,创建jQuery.ui draggable并在其上模拟mousedown ,然后它应该开始跟随鼠标。 I can't achieve this behaviour. 我无法实现这种行为。

I made a fiddle, where you can see what I tried so far (I am not posting the whole code here, as it is rather long): JSFiddle 我做了一个小提琴,你可以看到我到目前为止所尝试的内容(我不是在这里发布整个代码,因为它很长): JSFiddle

Basically, the error I am getting at the Fiddle, with both options that I tried, is a type.indexOf is not a function error. 基本上,我在小提琴中得到的错误,我尝试过的两个选项都是type.indexOf is not a function错误。

I also asked and received some help on the following question , from where the proposed solution works fine when starting the drag operation with a click event, but it isn't working with any other event type. 我还询问并获得了一些关于以下问题的帮助,当使用click事件开始拖动操作时,建议的解决方案可以正常工作,但它不适用于任何其他事件类型。 I pressume, I can simulate a mousedown.draggable event, only from a MouseEvent , and the dragend event is not a MouseEvent . 我按下,我只能从MouseEvent模拟mousedown.draggable事件,而dragend事件不是MouseEvent

Long story short, I would need help in obtaining the result I am looking for, at least for the first part of my proposed solution! 长话短说,我需要帮助才能获得我想要的结果,至少对于我提出的解决方案的第一部分!

There does not appear to be a good answer for this. 这似乎没有一个好的答案。 First, not all browsers support the same DnD terminology or functionality. 首先,并非所有浏览器都支持相同的DnD术语或功能。 Such as FireFox fires a dragenter event on drop and Chrome does not seem to detect a drop event when the object is from another window. 例如FireFox在drop上触发dragenter事件,当对象来自另一个窗口时,Chrome似乎没有检测到drop事件。

Here is my testing so far. 这是我到目前为止的测试。 To use, copy the content into a Text file and save as HTM or HTML. 要使用,请将内容复制到文本文件中并另存为HTM或HTML。 Then Open the file locally in your browser. 然后在浏览器中本地打开文件。 Open another Window and open the second HTM. 打开另一个窗口并打开第二个HTM。 now you have two windows you can drag to and from. 现在你有两个可以拖拽的窗户。

wina-1.htm WINA-1.htm

<!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"></pre>
<div class="items ui-widget">
  <div id="draggable" class="ui-widget-content idle" draggable="true">
    <p>Drag me around</p>
  </div>
  <div id="static" class="ui-widget-content">
    <p>I can't be moved</p>
  </div>
</div>
<script>

var srcEl;

function 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("Drag Start: " + e.target.nodeName + "#" + e.target.id);
  srcEl = e.target;
  if(e.dataTransfer == undefined){} else {
    e.dataTransfer.effectAllowed = "copyMove";
    log("Event dataTransfer.effectAllowed: " + 

e.dataTransfer.effectAllowed);
    log("Source Element: " + srcEl.nodeName + "#" + srcEl.id);
  }
  this.classList.add("selected");
}

function dragOver(e){
  e.preventDefault();
  log("Drag Over: " + e.target.nodeName + (e.target.id != "" ? "#" + 

e.target.id : ""));
  return false;
}

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("selected");
}

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);
});
</script>
</body>
</html>

As you can see, this is using raw JavaScript. 如您所见,这是使用原始JavaScript。 I was tinkering with jQuery UI, and I kept the stylesheet just for easy theming. 我正在修改jQuery UI,我保留样式表只是为了方便他们。 We have a section to print out log details, a draggable, and a static item. 我们有一个部分用于打印日志详细信息,可拖动项和静态项。

winb-1.htm winb-1.htm

<!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"></pre>
  <div id="dropzone"></div>
<script>
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").prop

("scrollHeight"));
  }

  function dragEnter(e){
    e.preventDefault();
    log("Drag Enter triggered: " + $(e.target).prop("nodeName") + 

($(e.target).attr("id").length ? "#" + $(e.target).attr("id") : ""));
  }

  function dragOver(e){
    log("Drag Over triggered: " + $(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: " + $(e.target).attr("id"));
    return false;
  }

  function dragEnd(e){
    log("Drag End Triggered: " + $(e.target).prop("nodeName") + 

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

});
</script>
</body>
</html>

Window B uses jQuery as the intention was to convert the element into a jQuery UI Draggable. Window B使用jQuery,目的是将元素转换为jQuery UI Draggable。

First thing to know, there is no way to do in transit. 首先要知道的是,在运输过程中无法做到。 Since the Source element is not a part of the target DOM, it cannot be done. 由于Source元素不是目标DOM的一部分,因此无法完成。 It can be added and initialized as a Draggable in the drop event. 它可以在drop事件中添加并初始化为Draggable。 Essentially what will happen is a new element will be created at that time assigned all the data. 基本上会发生什么是在那时分配所有数据的新元素。

Second, data transfer is unreliable and I would avoid DataTransfer as your data container. 其次,数据传输是不可靠的,我会避免使用DataTransfer作为您的数据容器。 I would advise using localStorage. 我建议使用localStorage。 This is similar to a cookie and is a lot more reliable. 这类似于cookie,更可靠。

For example, I created the following Data object: 例如,我创建了以下Data对象:

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

Here are some example functions: 以下是一些示例函数:

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

In theory, this should all work. 从理论上讲,这应该都有效。 In practice, I have hit a ton of roadblocks. 在实践中,我遇到了很多障碍。 I would suggest something like a click-to-copy type of action. 我会建议像点击复制类型的操作。 Where the User clicks an item in Window A (selecting it) and then clicks where they want it to be in Window B. Again using localStorage, the item could be cloned into the new location. 用户单击窗口A中的项目(选择它),然后单击他们希望它在窗口B中的位置。再次使用localStorage,可以将项目克隆到新位置。

wina-3.htm WINA-3.htm

<!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"></pre>
<div class="items ui-widget">
  <div id="draggable" class="ui-widget-content idle" draggable="true">
    <p>Click on me</p>
  </div>
  <div id="static" class="ui-widget-content">
    <p>I can't be moved</p>
  </div>
</div>
<script>
var intv;

function 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 collectData(el){
  return {
    id: el.id,
    type: el.nodeName,
    attr: {
      id: el.id,
      class: el.className,
      width: el.width,
      height: el.height
    },
    content: el.innerText
  };
}

function 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 : "");
  if(e.target.classList.contains("selected")){
    log("Deselect element: " + trg);
    e.target.classList.remove("selected");
  } else {
    log("Element Selected: " + trg);
    e.target.classList.add("selected");
    saveData("select-data", collectData(e.target));
  }
  intv = setInterval(function(){
    if(getData("select-data") == null){
      document.getElementsByClassName("selected")[0].classList.remove("selected");
      log("Unselected");
      clearInterval(intv);
    }
  }, 1000);
}

log("Init");

var item = document.getElementById("draggable");
item.addEventListener('click', selElem);
</script>
</body>
</html>

winb-3.htm winb-3.htm

<!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"></pre>
  <div id="dropzone"></div>
<script>
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").prop

("scrollHeight"));
  }

  function getData(k){
    console.log("Getting Data: '" + k + "'", localStorage.getItem(k));
    return JSON.parse(localStorage.getItem(k));
  }

  function clearData(k){
    log("Clear Data");
    localStorage.setItem(k, null);
  }

  function makeEl(dObj, pObj){
    console.log(dObj, pObj);
    return $("<" + dObj.type + ">", dObj.attr).html("<p>" + dObj.content + 

"</p>").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")){
      log("Click Detected - Collecting Data");
      d = getData("select-data");
      console.log("Data", d);
      d.attr.id = "clone-" + ($("#dropzone .cloned").length + 1);
      log("Making Element: " + d.type + "#" + d.attr.id);
      item = makeEl(d, trg);
      item.removeClass("selected").addClass("cloned").position({
        my: "center",
        of: e
      }).draggable();
      clearData("select-data");
      return true;
    }
    return false;
  }

  log("Init");

  $("#dropzone").on({
    mouseup: handleDrop,
    click: handleDrop
  });
});
</script>
</body>
</html>

I know this is not the answer you're looking for, and for that you need to try to ask the real question. 我知道这不是你正在寻找的答案,为此你需要尝试提出真正的问题。 You seem to keep asking around the question. 你似乎一直在问这个问题。

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM