拖放

拖放是一种常见的特性,即抓取对象以后拖到另一个位置。在 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. Ubuntu gcc编译报错:format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 2 has type ‘__time_t’ [-Wformat=]

    平时用的都是Centos系统,今天偶然在Ubuntu下编译了一次代码,发现报错了: 源码: #include <stdio.h> #include <sys/time.h> # ...

  2. Java 回调机制的理解

    // 在接口中声明一个处理耗时操作结果的回调方法. // Local 实现这个接口,实现处理耗时操作结果的回调方法. // Local 获得 Remote 对象,在子线程中调用 Remote 的处理耗 ...

  3. maximum subarray problem

    In computer science, the maximum subarray problem is the task of finding the contiguous subarray wit ...

  4. stat file 查看文件的 最新的被访问时间 最近的修改时间 最近的状态改变时间

    [root@NB ~]# stat /media/6FE5-D831/git-data/IT-DOC/web收藏.txt File: `/media/6FE5-D831/git-data/IT-DOC ...

  5. CLR via C#(08)-操作符

    对于操作符,我们并不陌生,例如+,-,*,%等二元操作符,以及++,!等一元操作符.但是对于非基元类型,我们需要通过一些自定义方法才能使用这些操作符.今天主要和大家分享关于操作符重载和转换操作符的知识 ...

  6. Linux 标准目录结构

    初学Linux,首先需要弄清Linux 标准目录结构 / root --- 启动Linux时使用的一些核心文件.如操作系统内核.引导程序Grub等. home --- 存储普通用户的个人文件 ftp ...

  7. python列表分组的技巧

    今天项目上需要到的. 如,将并行部署的机器分批次. 一次十台机器,如果分3次并行部署,则第一次123,第二次456,第三次789,第四次10. #coding=utf-8 a=[1,2,3,4,5,6 ...

  8. Linux 配置NFS,文件共享

    配置:   1.设定共享主机服务器    ---(注意防火墙) 编辑ipA端的/etc/exports 文件 [root@dbrac2 ~]# cat /etc/exports /media  192 ...

  9. HR外包系统 - 账款

    01 账款-服务费,注意多币种以及收款对象和联系人的设置 02 代收代付,注意多币种以及收款对象和联系人的设置 03 账单要保存服务费计算的整个过程,便于后面出报表和数据分析 04 出报表时,要考虑 ...

  10. 在Asp.Net MVC中设定site路径所对应的默认action

    设置路由的default的Controller和Action可以达到我们预期的效果,代码如下所示: public class RouteConfig { public static void Regi ...