是否有HTML5默认的方式将多个元素拖放到同一页面上的另一个html元素中?
似乎HTML5属性draggable
,这适用于一个元素说:"你可以拖动我,但你需要多个输入设备选择另一个可拖动的元素在同一时间。"
作为一种变通方法,我们可以使用js为选定的元素添加标识符,并在某个事件中获取所有选定的元素,然后做我们想做的事情。但这真的是"正确"的方式吗?
当您检查drop
事件时,在处理文件拖放时,有一个用于多个文件的接口。还有items
属性-至少在Chrome中。
不同浏览器有不同。
在Chrome drop
事件包含items
属性
dataTransfer: DataTransfer
items: DataTransferItemList
length: 0
Items
似乎是0,无论你是否拖动一个项目。
drop
事件包含mozItemCount
属性
dataTransfer: DataTransfer
mozItemCount: 1
mozItemCount
似乎至少为1。
这里有一个小的演示
在这里您可以看到您的开发人员工具控制台:
来源:http://www.html5rocks.com/en/tutorials/dnd/basics/
$(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>
所以看起来供应商正在为多个项目的拖放做准备,但似乎没有默认值。如果我说错了,请纠正我。
我读这些文章是为了更好地理解他们
- https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_and_drop
- http://html5doctor.com/native-drag-and-drop/
:
- MDN的数据传输接口
- MDN多次拖放的非标准方法
DataTransferItemList
的定义首先,items
长度以及files
长度在Chrome中工作。你总是得到0长度,因为拖放数据存储中的信息是受保护的,除了拖放事件。因此,当你记录对象并在之后查看它时,你无法访问该信息。但是如果你像这样记录:
console.log(e.dataTransfer.items.length);
那么你就可以访问实际的长度。请看这里关于protected mode
:
https://html.spec.whatwg.org/multipage/interaction.html the-drag-data-store
这并不是说它会告诉你被拖动元素的数量,有几个原因可以解释为什么:
首先是本机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'));
当拖动灰色目标上的每个元素时,如下所示:
来自输入的纯文本:
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>
请看这里:http://jsfiddle.net/ztj6t2ff/9/
您将看到html
并不完全是您的页面上的内容。这是为了允许传输到其他应用程序并尽可能保持最佳格式。
所以一般来说,这个API
允许你干扰默认的拖动行为,几乎任何你可以在浏览器中拖动的操作系统。从这个意义上说,它非常复杂,但是大多数特性与在同一页面中拖动DOM元素无关。
事实上,几乎所有通过拖放的DOM操作都是在不使用这个API的情况下进行的。例如,jquery-ui draggable
根本不依赖于这个API。