如何一次拖放多个html元素?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (372)

是否有HTML5的默认方式将-multiple-元素拖放到同一页面上的另一个html元素中?

看起来HTML5属性draggable适用于一个元素:“可以拖动我,但需要多个输入设备同时选择另一个可拖动元素。”

作为一种解决方法,可以使用js将标识符添加到选定的元素,并获取某个事件上的所有选定元素并按照我们的要求进行操作。但这真的是“正确”的方式吗?

drop处理文件拖放时,当检查事件时,有多个文件的界面。而且还有items财产 - 至少在Chrome中。

浏览器之间存在差异。

在Chrome中

drop事件包含该items属性

dataTransfer: DataTransfer
    items: DataTransferItemList
        length: 0

Items 似乎是0,不管你是否拖动一个项目。

在Firefox中

drop事件包含该mozItemCount属性

dataTransfer: DataTransfer
    mozItemCount: 1

mozItemCount 似乎至少是1。

$(function(){
  // Copied from: http://www.html5rocks.com/en/tutorials/dnd/basics/
  var cols_ = document.querySelectorAll('.column');
  var dragSrcEl_ = null;

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

    dragSrcEl_ = this;

    this.style.opacity = '0.4';

    // this/e.target is the source node.
    $(this).addClass('moving');
  };

  handleDragOver = function(e) {
    if (e.preventDefault) {
      e.preventDefault(); // Allows us to drop.
    }

    e.dataTransfer.dropEffect = 'move';

    return false;
  };

  handleDragEnter = function(e) {
    $(this).addClass('over');
  };

  handleDragLeave = function(e) {
    // this/e.target is previous target element.

    $(this).removeClass('over');
  };

  handleDrop = function(e) {
    // this/e.target is current target element.
    console.log(e.dataTransfer);

    if (e.stopPropagation) {
      e.stopPropagation(); // stops the browser from redirecting.
    }

    // Don't do anything if we're dropping on the same column we're dragging.
    if (dragSrcEl_ != this) {
      dragSrcEl_.innerHTML = this.innerHTML;
      this.innerHTML = e.dataTransfer.getData('text/html');
    }

    return false;
  };

  handleDragEnd = function(e) {
    // this/e.target is the source node.
    this.style.opacity = '1';

    [].forEach.call(cols_, function (col) {
      $(col).removeClass('over');
      $(col).removeClass('moving');
    });
  };

  [].forEach.call(cols_, function (col) {
    col.setAttribute('draggable', 'true');  // Enable columns to be draggable.
    col.addEventListener('dragstart', this.handleDragStart, false);
    col.addEventListener('dragenter', this.handleDragEnter, false);
    col.addEventListener('dragover', this.handleDragOver, false);
    col.addEventListener('dragleave', this.handleDragLeave, false);
    col.addEventListener('drop', this.handleDrop, false);
    col.addEventListener('dragend', this.handleDragEnd, false);
  });
});

.column {
  height: 150px;
  width: 150px;
  float: left;
  border: 2px solid #666666;
  background-color: #ccc;
  margin-right: 5px;
  border-radius: 10px;
  box-shadow: inset 0 0 3px #000;
  text-align: center;
  cursor: move;
  margin-bottom: 30px;
}
.column header {
  color: #fff;
  text-shadow: #000 0 1px;
  box-shadow: 5px;
  padding: 5px;
  background: linear-gradient(left center, rgb(0,0,0), rgb(79,79,79), rgb(21,21,21));
  border-bottom: 1px solid #ddd;
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
}
.column {
 transition: transform 0.2s ease-out;
}
.column.over {
  border: 2px dashed #000;
}
.column.moving {
  opacity: 0.25;
  transform: scale(0.8);
}
.column .count {
  padding-top: 15px;
  font-weight: bold;
  text-shadow: #fff 0 1px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
 
<div class="cols">
  <div class="column">
    <header>C</header>
  </div>
  <div class="column">
    <header>B</header>
  </div>
  <div class="column">
    <header>A</header>
  </div>
</div>

所以它看起来像正在准备多个项目拖放,但似乎没有任何默认。

提问于
用户回答回答于

首先,Chrome 的items长度和files长度都在工作。总是得到0的长度,因为拖放数据存储中的信息受保护,除了丢弃事件。因此,当记录对象并事后查看时,无法访问信息。但是如果你像这样记录它:

console.log(e.dataTransfer.items.length);

然后将可以访问实际长度。

这并不是说它会给你拖动元素的数量,有几个原因可以解释为什么:

首先,本机drag and drop API也用于从浏览器拖到其他应用程序,反之亦然。因此,这里有很多功能处理这些情况。

其他的事情是拖放API可以让你访问浏览器拖动事物时默认行为的东西。例如,在浏览器中拖动链接将打开链接。当你使用API​​时,你正在访问这些行为。

这个API的很多行为都是这个的结果,从这个意义上讲,并不是真的打算拖拽DOM元素。为此,其他图书馆可能更适合或仅仅通过它提供的不同事件来管理内容本身。

由于可以从其他应用程序拖放元素,因此很多信息都与此有关。例如dataTransferItem,你可以访问一个fileList对象。这只在将文件从操作系统拖到浏览器时才起作用。所以你有一些文件,并拖动不同的文件。但这与拖拽无关DOM elements

也可以从浏览器中拖动。例如,如果要将HTML内容拖到Word非常有用。但是,要传输的信息比简单的DOM元素更复杂。在这种情况下,你正在拖动items,但这些items不是每个说的DOM元素。它们是可以转移的不同类型的东西。

可以传输的东西的类型在实现上有很大的不同,但基本上你可以有纯文本,HTML内容和链接。所以项目的长度将是可用类型的长度。例如,在下面的jsfiddle中,在Chrome上,可以拖动图像,链接和纯文本(对于这一个,只需选择文本)的结果 :

 console.log(e.dataTransfer.items.length, 
e.dataTransfer.getData('text/plain'), 
e.dataTransfer.getData('text/uri-list'), 
e.dataTransfer.getData('text/html'));

当draggin灰色目标上的每个元素是这样的:

输入中的纯文本:

length: 1 
 plain text: text 
 link:  
 html content: 

从图像:

length: 2 
    plain text:  
     link: http://www.exiv2.org/include/img_1771.jpg 
     html content: <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><img id="image1" src="http://www.exiv2.org/include/img_1771.jpg">

来自链接:

length: 3 
 plain text: http://google.com/ 
 link: http://google.com/ 
 html content: <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><a href="http://google.com/">link 1</a>

你会看到,这html不完全是你的网页上。这是为了允许传输到其他应用程序并保持最佳格式。

所以一般来说,这API可以让你干预默认行为,拖拽几乎任何你可以在浏览器中拖动操作系统的东西。从这个意义上说,它非常复杂,但大多数功能与在同一页面内拖动DOM元素无关。

事实上,几乎所有通过拖放进行的DOM操作都是在不使用此API的情况下进行的。例如jquery-ui draggable根本不依赖于这个API

所属标签

可能回答问题的人

  • 不吃貓的鱼oo

    5 粉丝466 提问6 回答
  • Richel

    8 粉丝0 提问4 回答
  • 御姐万岁

    6 粉丝507 提问3 回答
  • 人生的旅途

    10 粉丝484 提问3 回答

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励