HTML5之拖放API实现拖放排序

前言

HTML5 中提供了直接拖放的 API,极大的方便我们实现拖放效果,不需要去写一大堆的 js,只需要通过监听元素的拖放事件就能实现各种拖放功能。

想要拖放某个元素,必须设置该元素的 draggable 属性为 true,当该属性为 false 时,将不允许拖放。而 img 元素和 a 元素都默认设置了 draggable 属性为 true,可直接拖放,如果不想拖放这两个元素,把属性设为 false 即可。

拖放事件

拖放事件由不同的元素产生。一个元素被拖放,他可能会经过很多个元素上,最终到达想要放置的元素内。这里,我暂时把被拖放的元素称为源对象,被经过的元素称为过程对象,到达的元素我称为目标对象。不同的对象产生不同的拖放事件。

原文作者:林鑫,作者博客:https://github.com/lin-xin/blog,原文地址:http://www.cnblogs.com/linxin/archive/2017/05/02/6794542.html

源对象:

  • dragstart:源对象开始拖放。
  • drag:源对象拖放过程中。
  • dragend:源对象拖放结束。

过程对象:

  • dragenter:源对象开始进入过程对象范围内。
  • dragover:源对象在过程对象范围内移动。
  • dragleave:源对象离开过程对象的范围。

目标对象:

  • drop:源对象被拖放到目标对象内。
<div id="source" draggable="true">a元素</div>
<div id="process">b元素</div>
<div id="target">c元素</div> <script>
var source = document.getElementById('source'), // a元素
process = document.getElementById('process'), // b元素
target = document.getElementById('target'); // c元素 source.addEventListener('dragstart',function(ev){ // dragstart事件由a元素产生
console.log('a元素开始被拖动');
},false) process.addEventListener('dragenter',function(ev){ // dragenter事件由b元素产生
console.log('a元素开始进入b元素');
},false)
process.addEventListener('dragleave',function(ev){ // dragleave事件由b元素产生
console.log('a元素离开b元素');
},false) target.addEventListener('drop',function(ev){ // drop事件由c元素产生
console.log('a元素拖放到c元素了');
ev.preventDefault();
},false)
document.ondragover = function(e){e.preventDefault();}
</script>

dataTransfer 对象

在所有拖放事件中提供了一个数据传递对象 dataTransfer,用于在源对象和目标对象间传递数据。接下来认识一下这个对象的方法和属性,来了解它是如何传递数据的。

setData()

该方法向 dataTransfer 对象中存入数据。接收两个参数,第一个表示要存入数据种类的字符串,现在支持有以下几种:

  • text/plain:文本文字。
  • text/html:HTML文字。
  • text/xml:XML文字。
  • text/uri-list:URL列表,每个URL为一行。

第二个参数为要存入的数据。例如:

event.dataTransfer.setData('text/plain','Hello World');

getData()

该方法从 dataTransfer 对象中读取数据。参数为在 setData 中指定的数据种类。例如:

event.dataTransfer.getData('text/plain');

clearData()

该方法清除 dataTransfer 对象中存放的数据。参数可选,为数据种类。若参数为空,则清空所有种类的数据。例如:

event.dataTransfer.clearData();

setDragImage()

该方法通过用img元素来设置拖放图标。接收三个参数,第一个为图标元素,第二个为图标元素离鼠标指针的X轴位移量,第三个为图标元素离鼠标指针的Y轴位移量。例如:

var source = document.getElementById('source'),
icon = document.createElement('img'); icon.src = 'img.png'; source.addEventListener('dragstart',function(ev){
ev.dataTransfer.setDragImage(icon,-10,-10)
},false)

effectAllowed 和 dropEffect 属性

这两个属性结合起来设置拖放的视觉效果。

值得注意的是:IE 不支持 dataTransfer 对象。对,不管哪个 IE 版本都不支持。

实现拖放排序

上面已经熟悉了拖放 API 的使用,我们来实现个简单的拖放排序,这也是在项目中比较常见的。先来理一下思路:

  • 在一个列表中,每个元素都可以被拖放,那首先要给每个元素设置 draggable 属性为 true。
  • 监听每个元素的 dragstart 事件,对源对象做样式处理来区分。
  • 监听每个元素的 dragenter 事件,当源对象进入到当前元素里,就把源对象添加到该元素之前。这样子后面的元素就会被源对象挤下去了,实现了排序的效果。
  • 但是会发现,源对象无法排到最后一个去,只能在倒数第二。这时就要监听 dragleave 事件,当过程对象是最后一个元素时,源对象离开了过程对象,这时就把源对象添加到最后去。

主要代码如下:

var source = document.querySelectorAll('.list'),
dragElement = null; for(var i = 0; i < source.length; i++){
source[i].addEventListener('dragstart',function(ev){
dragElement = this;
},false); source[i].addEventListener('dragenter', function(ev){
if(dragElement != this){
this.parentNode.insertBefore(dragElement,this);
}
}, false) source[i].addEventListener('dragleave', function(ev){
if(dragElement != this){
if(this == this.parentNode.lastElementChild || this == this.parentNode.lastChild){
this.parentNode.appendChild(dragElement);
}
}
}, false)
}; document.ondragover = function(e){e.preventDefault();}
document.ondrop = function(e){e.preventDefault();}

完整的代码地址:drag-demo

兼容

主要是在IE中的兼容不太好,不过至少在IE10中能兼容上面的拖动排序。

而且在我简单的试验中发现,就是在 IE 中元素不设置 height 的时候,不会触发 dragleave 事件。

更重要的一点是在 ios 和安卓上,完全不兼容。不过还好,有一个插件能让它在移动端完美兼容。
插件地址:ios-html5-drag-drop-shim

只需要在原有的代码中引入该插件,即可在移动端上实现拖动了。

<script>
var iosDragDropShim = { enableEnterLeave: true }
</script>
<script src="vendor/ios-drag-drop.js"></script>

HTML5 进阶系列:拖放 API 实现拖放排序(转载)的更多相关文章

  1. HTML5 进阶系列:indexedDB 数据库

    前言 在 HTML5 的本地存储中,有一种叫 indexedDB 的数据库,该数据库是一种存储在客户端本地的 NoSQL 数据库,它可以存储大量的数据.从上篇:HTML5 进阶系列:web Stora ...

  2. HTML5 进阶系列:拖放 API 实现拖放排序

    前言 HTML5 中提供了直接拖放的 API,极大的方便我们实现拖放效果,不需要去写一大堆的 js,只需要通过监听元素的拖放事件就能实现各种拖放功能. 想要拖放某个元素,必须设置该元素的 dragga ...

  3. HTML5拖放API实现拖放排序的实例代码

    想要拖放某个元素,必须设置该元素的 draggable 属性为 true,当该属性为 false 时,将不允许拖放.而 img 元素和 a 元素都默认设置了 draggable 属性为 true,可直 ...

  4. HTML5 进阶系列:文件上传下载

    前言 HTML5 中提供的文件API在前端中有着丰富的应用,上传.下载.读取内容等在日常的交互中很常见.而且在各个浏览器的兼容也比较好,包括移动端,除了 IE 只支持 IE10 以上的版本.想要更好地 ...

  5. HTML5 进阶系列:canvas 动态图表

    前言 canvas 强大的功能让它成为了 HTML5 中非常重要的部分,至于它是什么,这里就不需要我多作介绍了.而可视化图表,则是 canvas 强大功能的表现之一. 现在已经有了很多成熟的图表插件都 ...

  6. HTML5权威指南--标签新变化,文件API,拖放API(简要学习笔记一)

    1.标签元素更加语义化   2.内容类型仍然为“text/html”    扩展符仍然为html或者htm.    <1>DOCTYPE 声明<!DOCTYPE html>就可 ...

  7. 我拖拖拖--H5拖放API基础篇

    不要搞错,本文不是讲如何拖地的.看过<javascript精粹>朋友应该知道,他实现拖放的过程比较复杂,现在时代不同了,我们用H5的新的拖放API就能非常方便的实现拖放效果了.最近在园子见 ...

  8. html5的新特性——拖放API

    在HTML5之前只能使用鼠标事件模拟出"拖放"效果:HTML5专门为拖放提供了7个事件句柄.  被拖动的源对象可以触发的事件: (1)ondragstart:源对象开始被拖动 (2 ...

  9. HTML5 十大新特性(七)——拖放API

    拖放API是H5专门为了鼠标拖放而新提供了7个事件,可以分成三个部分来讲. 一.拖动的源对象(source)可以触发的事件 dragstart:拖动开始 drag:拖动进行中 dragend:拖动结束 ...

随机推荐

  1. set 利用lower_bound实现key索引

    set中数据类型为结构体T,T中有两个成员key和val定义如下: struct T{ int key,val; T(int k,int v):key(k),val(v){} bool operato ...

  2. P2757 导弹的召唤(数据加强)

    传送门 LIS的O(nlgn)模板题.加强"导弹拦截" #include <cstdio> #include <cstring> #include < ...

  3. npm模块管理器入门

    什么是 NPM npm 是 Node 官方提供的包管理工具,他已经成了 Node 包的标准发布平台,用于 Node 包的发布.传播.依赖控制.npm 提供了命令行工具,使你可以方便地下载.安装.升级. ...

  4. 自动化运维工具——ansible详解(一)

    ansible 简介 ansible 是什么? ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.chef.func.fabric)的优点,实现了批量系统 ...

  5. 初学PHP心得(第一天)

    我是PHP初学者,听说女生挺适合学这门语言的.所以,我就下定决心,来好好的探究下它,希望它能成为我开启IT道路的第一道关卡. 今天心血来潮,来记录下一天的成果和收获吧.既然想法有了,那就要去实现它.于 ...

  6. ctrl+z 以后怎么恢复挂起的进程

    (1) CTRL+Z挂起进程并放入后台 (2) jobs 显示当前暂停的进程 (3) bg %N 使第N个任务在后台运行(%前有空格) (4) fg %N 使第N个任务在前台运行 默认bg,fg不带% ...

  7. saltstack_grains

    1. [root@kylin1 grains]# cd /srv/salt/_grains/ [root@kylin1 _grains]# ls cpu.py [root@kylin1 _grains ...

  8. Linux下RabbitMq安装

    在大多数大公司,像应用服务器软件的安装.部署都是运维的事情,其实自己去尝试部署一下,也是有收获的. 有机会正好尝试了Linux下的rabbitMq安装过程,做了记录,希望有用到的人可以做下参考. 安装 ...

  9. session与cookie的区别与联系

    session与cookie是在做项目中很常用的会话技术,session与cookie也是面试中被问到频率最高的问题,有一次我去面试,面试官就怼着我session与cookie一直问(头都大了),下面 ...

  10. python 正则表达式之零宽断言

    零宽断言:用于查找特定内容之前或之后的内容,但并不包括特定内容本身.对于零宽断言来说,我认为最重要的一个概念是位置,零宽断言用于指定一个位置,这个位置应该满足一定的条件(它附近满足什么表达式),并且这 ...