拖放

拖放是一种常见的特性,即抓取对象以后拖到另一个位置。在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放。

拖放是在“拖放源(drag source)”和“拖放目标(drop target)”之间传输数据的用户界面。下面例子将演示如何创建自定义拖放源和自定义拖放目标,前者传输数据而不是其文本内容,后者以某种方式相应拖放数据而不是仅显示它。

浏览器支持

Internet Explorer 9、Firefox、Opera 12、Chrome 以及 Safari 5 支持拖放。

注释:在 Safari 5.1.2 中不支持拖放。

拖放事件

  1. DataTransfer 对象:退拽对象用来传递的媒介,使用一般为Event.dataTransfer。
  2. draggable 属性:就是标签元素要设置draggable=true,否则不会有效果,例如:
    <div title="拖拽我" draggable="true">列表1</div>
  3. ondragstart 事件:当拖拽元素开始被拖拽的时候触发的事件,此事件作用在被拖曳元素上
  4. ondragenter 事件:当拖曳元素进入目标元素的时候触发的事件,此事件作用在目标元素上
  5. ondragover 事件:拖拽元素在目标元素上移动的时候触发的事件,此事件作用在目标元素上
  6. ondragleave 事件:拖拽元素在目标元素上移动的时候触发的事件,此事件作用在目标元素上
  7. ondrop 事件:被拖拽的元素在目标元素上同时鼠标放开触发的事件,此事件作用在目标元素上
  8. ondragend 事件:当拖拽完成后触发的事件,此事件作用在被拖曳元素上
  9. event.preventDefault() 方法:阻止默认的些事件方法等执行。在ondragover中一定要执行preventDefault(),否则ondrop事件不会被触发。另外,如果是从其他应用软件或是文件中拖东西进来,尤其是图片的时候,默认的动作是显示这个图片或是相关信息,并不是真的执行drop。此时需要用用document的ondragover事件把它直接干掉。
  10. event.setDataTransfer.effectAllowed 属性:就是拖拽的效果。
  11. evetn.setDataTransfer.setDragImage() 方法:指定图片或者文档元素做拖动时的视觉效果。

DnD总是基于事件且Javascript API包含两个事件集,一个是在拖放源上触发,另一个在拖放目标上触发。所有传递给DnD事件处理程序的事件对象都类似鼠标事件对象,另外他拥有dataTransfer属性。这个属性引用DataTransfer对象,该对象定义DnD API的方法和属性。

拖放源时间相当简单,我们就从他们开始。任何有HTML draggable属性的文档元素都是拖放源。当用户开始用鼠标在拖放源上拖动时,浏览器并没有选择元素内容,相反,它在这个元素上触发dragstart事件,这个事件的处理程序就调用dataTransfer.setData()指定当前可用的拖放源数据(和数据类型)。这个时间处理程序也可以设置dataTransfer.effectAllowed来指定支持“移动”、“复制”和“链接”传输操作中的集中,同时他可以调用dataTransfer.setDragImage()指定图片或者文档元素做拖动时的视觉效果。

当放置数据发生时会触发dragend事件。如果拖放源支持“移动”操作,它就会检查dataTransfer.dropEffect去看看是否实际执行了移动操作。如果执行了,数据就被传输到其他地方,你就应该从拖放源中删除它。

实例

var whenReady = (function() { // This function returns the whenReady() function
var funcs = []; // The functions to run when we get an event
var ready = false; // Switches to true when the handler is triggered // The event handler invoked when the document becomes ready
function handler(e) {
// If we've already run once, just return
if (ready) return; // If this was a readystatechange event where the state changed to
// something other than "complete", then we're not ready yet
if (e.type === "readystatechange" && document.readyState !== "complete")
return; // Run all registered functions.
// Note that we look up funcs.length each time, in case calling
// one of these functions causes more functions to be registered.
for(var i = 0; i < funcs.length; i++)
funcs[i].call(document); // Now set the ready flag to true and forget the functions
ready = true;
funcs = null;
} // Register the handler for any event we might receive
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", handler, false);
document.addEventListener("readystatechange", handler, false);
window.addEventListener("load", handler, false);
}
else if (document.attachEvent) {
document.attachEvent("onreadystatechange", handler);
window.attachEvent("onload", handler);
} // Return the whenReady function
return function whenReady(f) {
if (ready) f.call(document); // If already ready, just run it
else funcs.push(f); // Otherwise, queue it for later.
}
}());
whenReady(function() {
var clock = document.getElementById("clock"); // The clock element
var icon = new Image(); // An image to drag
icon.src = "clock-icon.png"; // Image URL // Display the time once every minute
function displayTime() {
var now = new Date(); // Get current time
var hrs = now.getHours(), mins = now.getMinutes();
if (mins <) mins = "0" + mins;
clock.innerHTML = hrs + ":" + mins; // Display current time
setTimeout(displayTime, 60000); // Run again in 1 minute
}
displayTime(); // Make the clock draggable
// We can also do this with an HTML attribute: <span draggable="true">...
clock.draggable = true; // Set up drag event handlers
clock.ondragstart = function(event) {
var event = event || window.event; // For IE compatability // The dataTransfer property is key to the drag-and-drop API
var dt = event.dataTransfer; // Tell the browser what is being dragged.
// The Date() constructor used as a function returns a timestamp string
dt.setData("Text", Date() + "\n"); // Tell the browser to drag our icon to represent the timestamp, in
// browsers that support that. Without this line, the browser may
// use an image of the clock text as the value to drag.
if (dt.setDragImage) dt.setDragImage(icon, 0, 0);
};
});
</script>
<style>
#clock { /* Make the clock look nice */
font: bold 24pt sans; background: #ddf; padding: 10px;
border: solid black 2px; border-radius: 10px;
}
</style>
<h1>Drag timestamps from the clock</h1>
<span id="clock"></span> <!-- The time is displayed here -->
<textarea cols=60 rows=20></textarea> <!-- You can drop timestamps here -->

拖放目标比拖放源更棘手。任何元素都可以是拖放目标,这不需要像拖放源一样设置HTML属性,只需要简单地定义合适的时间监听程序。有4个事件在拖放目标上触发。当拖放对象进入文档元素时,浏览器在这个元素上触发dragenter事件。拖放目标应该使用dataTransfer.types属性确定拖放对象的可用数据是否是它能理解的格式。如果检查成功,拖放目标必须让用户和浏览器都知道它对防止感兴趣。可以通过改变他的边框或者背景颜色来向用户反馈。令人吃惊的是,拖放目标通过取消事件来告知浏览器它对防止感兴趣。如果元素不取消浏览器发送给它的draggenter事件,浏览器将不会把它作为这次拖放的拖放目标,并不会向它在发送任何事件。但如果拖放目标取消了dragenter事件,浏览器将发送dragover事件表示用户继续在目标元素上拖动对象。再一次令人吃惊的是,拖放目标必须监听且取消所有这些事情来表明它对放置感兴趣。如果拖放目标向指定它只允许移动、复制和链接操作,它应该使用dragover事件处理程序来设置dataTransfer.dropEffect

如果用户移动拖放对象离开通过取消事件表明有兴趣的拖放目标,那么在拖放目标上将触发dragleave事件。这个事件的处理程序应该恢复元素的边框或者背景颜色或者取消任何其他为相应dragenter事件而执行的可视化反馈。遗憾的是,dragenter和draleave事件会冒泡,如果拖放目标内部嵌套元素,想知道dragleave事件表示拖放对象从拖放目标离开到目标外的事件还是到目标内的事件非常困难。

最后,如果用户把拖放队形放置在拖放目标上,拖放目标上会触发drop事件。这个事件的处理程序应该使用dataTransfer.getData()获取传输的数据并做一些适当的处理。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<style type="text/css">
*{padding: 0px;margin:0px;}
.droppable{
background: yellow;
}
.dnd{margin:20px;border:2px solid blue;padding: 20px;}
</style>
<script type="text/javascript">
window.onload = function(){
var lists = document.getElementsByTagName('ul');
var regexp = /\bdnd\b/;
for (var i=0;i<lists.length;i++)
if (regexp.test(lists[i].className)) dnd(lists[i]);
function dnd(list){
var original_class = list.className;
var entered = 0;
list.ondragenter = function(e){
e = e || window.event;
var from = e.relatedTarget;
entered++;
if ((from &&!isChild(from,list)) || entered ==1) {
var dt = e.dataTransfer;
var types = dt.types;
if (!types ||(types.contains&&types.contains("text/plain"))||(types.indexOf &&types.indexOf("text/plain")!=-1)) {
list.className = original_class + " droppable";
return false;
}
return;
}
return false;
};
list.ondragover = function(e){return false;} list.ondragleave = function(e){
e = e || window.event;
var to = e.relatedTarget;
entered--;
if (to && !isChild(to,list) || entered <= 0) {
list.className = original_class;
entered = 0;
}
return false;
}; list.ondrop = function(e){
e = e || window.event;
var dt = e.dataTransfer;
var text = dt.getData("Text");
if (text) {
var item = document.createElement("li");
item.draggable = true;
item.appendChild(document.createTextNode(text));
list.appendChild(item);
list.className = original_class;
entered = 0;
return false;
}
}; var items = list.getElementsByTagName("li");
for (var i=0;i<items.length;i++)
items[i].draggable = true;
list.ondragstart = function(e){
var e = e || window.event;
var target = e.target || e.srcElemnt;
if (target.tagName !=="LI") return false;
var dt = e.dataTransfer;
dt.setData("Text", target.innerText || target.textContent);
dt.effectAllowed = "move";
}; list.ondragend = function(e){
e = e || window.event;
var target = e.target || e.srcElemnt;
if (e.dataTransfer.dropEffect ==="move") target.parentNode.removeChild(target);
} function isChild(a,b){
for(; a; a = a.parentNode) if (a === b) return true;
return false;
}
}
}
</script>
</head>
<body>
<ul class="dnd">
<li>测试测试测试测试-1</li>
<li>测试测试测试测试-2</li>
<li>测试测试测试测试-3</li>
<li>测试测试测试测试-4</li>
</ul>
<ul class="dnd">
<li>测试测试测试测试-5</li>
<li>测试测试测试测试-6</li>
<li>测试测试测试测试-7</li>
<li>测试测试测试测试-8</li>
</ul>
<ul class="dnd">
<li>测试测试测试测试-9</li>
<li>测试测试测试测试-10</li>
<li>测试测试测试测试-11</li>
<li>测试测试测试测试-12</li>
</ul>
</body>
</html>

HTML5拖放事件(Drag-and-Drop,DnD)的更多相关文章

  1. HTML5 拖放(Drag 和 Drop)功能开发——基础实战

    随着HTML5的普及度越来越高,现在写代码也遇到一些了,经过同事的点播开展了一次Dojo活动用以技术交流,我也乘此机会将HTML5的拖放功能整理了一下. 简介 拖拽(Drag/Drop)是个非常普遍的 ...

  2. HTML5拖放(drag and drop)与plupload的懒人上传

    HTML5拖放能够将本地的文件拖放到页面上,plupload又是很好的文件上传插件,而今天就将两者结合,做了个文件拖拽上传的功能. 简述HTML5拖放 拖放是HTML5标准的一部分,任何元素都能够拖放 ...

  3. HTML5 拖放(Drag 和 Drop)

    拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. <!DOCTYPE HTML> <html> <hea ...

  4. HTML5 拖放(Drag 和 Drop)详解与实例

    简介 拖放是一种常见的特性,即抓取对象以后拖到另一个位置. 在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放. 先点击一个小例子:在用户开始拖动 <p> 元素时执行 JavaSc ...

  5. HTML5 拖放(Drag 和 Drop)详解与实例(转)

    公司要开一个技术分享会,给我们出了几个简单的题去实现,其中有如何实现表格中列之间的拖拽,我知道html5中有个新方法可以实现,但是没有认真学习,现在闲了去学学,发现关于drag和drop的文章有很多, ...

  6. HTML5 拖放(Drag 和 Drop)功能开发——浅谈dataTransfer对象

    [前言] 之前我已经为大家介绍过一篇有关HTML5中原生拖拽的相关知识了.今天为大家介绍HTML5拖拽中的其他一些关于dataTransfer对象的知识和应用. dataTransfer对象 之前的一 ...

  7. 原生拖拽,拖放事件(drag and drop)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Blazor 使用拖放(drag and drop)上传文件

    在很多上传文件的应用实例中, 都可以看到[拖放文件到此上传]这种骚功能 ,今天我们就来试试Blazor能不能完成这个想法. 简述HTML5拖放 拖放是HTML5标准的一部分,任何元素都能够拖放,也能够 ...

  9. HTML5 CSS3 专题 : 拖放 (Drag and Drop)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/31413767 本来准备写一个支持多图片拖拽上传的例子,但是为了更好的理解,先介绍 ...

  10. HTML5 学习05—— 拖放(Drag 和 Drop)

    拖放(Drag 和 drop)是 HTML5 标准的组成部分.即抓取对象以后拖到另一个位置. 例:将w3cschool图标拖动到矩形框中. <script> function allowD ...

随机推荐

  1. osg绘制一个球体

    //By smells2 at Lab 2012-02-21#include <osg/Group>#include <osg/Geode>#include <osg/S ...

  2. 128. Longest Consecutive Sequence(leetcode)

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  3. 瞧一瞧迷一般的SQLDA

    With static SQL, host variables used in embedded SQL statements are known at application compile tim ...

  4. NYOJ之猴子吃桃问题

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAskAAAIMCAIAAACIcqa9AAAgAElEQVR4nO3dO3Li3BaG4TMJcgbi1A

  5. hadoop2.x NameNode 的共享存储实现

    过去几年中 Hadoop 社区涌现过很多的 NameNode 共享存储方案, 比如 shared NAS+NFS.BookKeeper.BackupNode 和 QJM(Quorum Journal ...

  6. C# 一些常用的技巧代码

    1.字符串风格成字符数组: 比如将字符串:23$123$45$转换成int[]这样的数组,你该怎么转换?其实你不用写那么的for循环,只需要一句话: int [] Relst =Array.Conve ...

  7. Tiny Rss Reader - 迷你RSS阅读器

    发布新软件 TinyRss: Windows平台上的一个小巧的Rss阅读器. 用户界面: 项目地址: https://github.com/movsb/tinyrss.git 测试下载: http:/ ...

  8. document.location.reload();与location.href='xxx'的区别

    document.location.reload();会重新加载页面,onload事件会被触发. location.href='xxx'刷新页面,onload事件不会触发.

  9. SublimeText 插件

    Markdown 预览 想要预览,可以配置下面的快捷方式. { "keys": ["alt+m"], "command": "ma ...

  10. 手机web页面制作时的注意事项

    一.手机页面的标准头规范 字符编码使用utf-:指定页面手机内存缓存中的存储时间段 device-width:通知浏览器使用设备的宽度作为可视区的宽度 initial-scale - 初始的缩放比例 ...