jQuery Draggable-创建可拖动对象并开始在html5本机拖放API事件上进行拖动 [英] jQuery Draggable - Create draggable and start dragging on html5 native Drag And Drop api event

查看:169
本文介绍了jQuery Draggable-创建可拖动对象并开始在html5本机拖放API事件上进行拖动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,基本上,我想尝试实现的是,当从HTML5 Drag And Drop API触发dragover事件时,我希望创建一个jQuery draggable对象,并开始跟随鼠标,而dragend HTML5 Drag And Drop API触发事件.

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.

我要这样做的原因如下:

The reason I want to do this, is the following:

  • 我有一个使用插件的应用程序,该插件的功能取决于jQuery.ui draggable的功能(它是FullCalendar Scheduler插件,版本3)
  • 我想在应用程序中实现一项新功能,客户端可以使用该功能从浏览器窗口A 中拖动某些内容,并将其拖放到浏览器窗口B中的上述插件中.
  • 由于上述插件无法与本机HTML5 Drag and Drop API一起使用,并且jQuery.ui draggable无法将元素从一个浏览器窗口拖到另一个浏览器窗口,我认为我唯一的选择是混合使用这两个插件. /li>
  • 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)
  • 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.
  • 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,并且当拖动的元素到达dropzone时,在浏览器窗口B 中创建一个新的可拖动元素,并模拟一个mousedown事件,因此它开始跟随光标.当dragend事件将触发时,我计划在draggable元素上简单地触发mouseup事件,并且从此处在Scheduler插件上可以做到这一点.

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

要尝试对此进行测试,首先使用单个浏览器窗口,我尝试实现上述解决方案的第一部分,即:当dragover触发时,创建jQuery.ui draggable并模拟mousedown,然后应该跟随鼠标开始.我无法实现这种行为.

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

基本上,我在小提琴上遇到的错误(同时尝试了两个选项)是type.indexOf is not a function错误.

Basically, the error I am getting at the Fiddle, with both options that I tried, is a type.indexOf is not a function error.

我还询问了以下

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. I pressume, I can simulate a mousedown.draggable event, only from a MouseEvent, and the dragend event is not a 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!

推荐答案

似乎没有很好的答案.首先,并非所有浏览器都支持相同的DnD术语或功能.例如FireFox会在放置时触发dragenter事件,并且当对象来自另一个窗口时,Chrome似乎无法检测到drop事件.

There does not appear to be a good answer for this. First, not all browsers support the same DnD terminology or functionality. 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.

到目前为止,这是我的测试.若要使用,请将内容复制到文本文件中并另存为HTM或HTML.然后在浏览器中本地打开文件.打开另一个窗口,然后打开第二个HTM.现在您可以在两个窗口之间来回拖动.

Here is my testing so far. To use, copy the content into a Text file and save as HTM or HTML. Then Open the file locally in your browser. Open another Window and open the second HTM. now you have two windows you can drag to and from.

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>

如您所见,这使用的是原始JavaScript.我正在修补jQuery UI,并且保留了样式表只是为了便于主题化.我们有一个部分可以打印日志详细信息,可拖动的内容和静态项目.

As you can see, this is using raw JavaScript. I was tinkering with jQuery UI, and I kept the stylesheet just for easy theming. We have a section to print out log details, a draggable, and a static item.

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>

窗口B使用jQuery的目的是将元素转换为jQuery UI Draggable.

Window B uses jQuery as the intention was to convert the element into a jQuery UI Draggable.

首先要知道的是,在运输过程中没有办法.由于Source元素不是目标DOM的一部分,因此无法完成.可以在drop事件中添加它并将其初始化为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. It can be added and initialized as a Draggable in the drop event. Essentially what will happen is a new element will be created at that time assigned all the data.

第二,数据传输不可靠,因此我会避免将DataTransfer用作您的数据容器.我建议使用localStorage.这类似于Cookie,并且可靠性更高.

Second, data transfer is unreliable and I would avoid DataTransfer as your data container. I would advise using localStorage. This is similar to a cookie and is a lot more reliable.

例如,我创建了以下数据对象:

For example, I created the following Data object:

{
  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,可以将该项克隆到新位置.

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.

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

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

希望这会有所帮助.

这篇关于jQuery Draggable-创建可拖动对象并开始在html5本机拖放API事件上进行拖动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆