这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
拖放 (drag-and-drop,DnD) 其实是两个动作——拖和放。所以,它涉及到两个元素。一个是被拖的元素,称为拖放源;另一个是要放的目标,称为拖放目标。本文将通过拆分这两个概念来详细介绍原生拖放,感兴趣的朋友一起学习吧
前面的话
拖放 (drag-and-drop,DnD) 其实是两个动作——拖和放。所以,它涉及到两个元素。一个是被拖的元素,称为拖放源;另一个是要放的目标,称为拖放目标。本文将通过拆分这两个概念来详细介绍原生拖放
拖放源
什么样的元素才是拖放源呢?
HTML5 为所有 HTML 元素规定了一个 draggable 属性,表示元素是否可以拖动
图像和链接的 draggable 属性自动被设置成了 true,而其他元素这个属性的默认值都是 false
[注意] 必须设置 draggable='true'才能生效,只设置 draggable 不起作用
默认情况下,文本只有在被选中的情况下才能拖动,而图像和链接在任何时候都可以拖动。而其他元素则无法被拖放
- <input value="文字可拖动">
- <img alt="图像可拖动" src="http://files.cnblogs.com/files/xiaohuochai/zan.gif">
- <a href="#">
- 链接可拖动
- </a>
- <div id="test" style="height:30px;width:300px;background:pink;">
- 元素不可拖动
- </div>
当为元素设置 draggable 属性后,普通元素也可以拖动
- <div draggable="true" style="height:30px;width:100px;background:pink;">
- </div>
兼容
IE9 - 浏览器不支持 draggable 属性,但可通过 mousedown 事件处理程序调用 dragDrop() 方法来实现拖动效果
- <div id="test" style="height:30px;width:300px;background:pink;">
- </div>
- <script>
- test.onmousedown = function() {
- this.dragDrop();
- }
- </script>
[注意] 如果让 firefox 支持 draggable 属性,必须添加一个 ondragstart 事件处理程序,并在 dataTransfer 对象使用 setData() 方法来启动效果
拖放事件
拖放源涉及到 3 个拖放事件。拖动拖放源时,依次触发 dragstart、drag 和 dragend 这 3 个事件
dragstart
按下鼠标键并开始移动鼠标时,会在被拖放的元素上触发 dragstart 事件。此时光标变成 "不能放" 符号 (圆环中有一条反斜线),表示不能把元素放到自己上面
drag
触发 dragstart 事件后,随即会触发 drag 事件,而且在元素被拖动期间会持续触发该事件
dragend
当拖动停止时 (无论是把元素放到了有效的放置目标,还是放到了无效的放置目标上),会触发 dragend 事件
- <div id="test" draggable="true" style="height:30px;width:100px;background:pink;">
- 0
- </div>
- <script>
- var timer, i = 0;
- test.ondragstart = function() {
- this.style.backgroundColor = 'lightgreen';
- }
- test.ondrag = function() {
- if (timer) return;
- timer = setInterval(function() {
- test.innerHTML = i++;
- },
- 100)
- }
- test.ondragend = function() {
- clearInterval(timer);
- timer = 0;
- this.style.backgroundColor = 'pink';
- }
- </script>
拖放目标
拖放目标是指被拖动的元素松开鼠标时被放置的目标
拖放源被拖动到拖放目标上时,将依次触发 dragenter、dragover 和 dragleave 或 drop 这四个事件
dragenter
只要有元素被拖动到放置目标上,触发 dragenter 事件
dragover
被拖动的元素在放置目标的范围内移动时,持续触发 dragover 事件
dragleave
如果元素被拖出了放置目标,触发 dragleave 事件
drop
如果元素被放到了放置目标中,触发 drop 事件
[注意]firefox 浏览器的 drop 事件的默认行为是打开被放到放置目标上的 URL。为了让 firefox 支持正常的拖放,还要取消 drop 事件的默认行为
默认情况下,目标元素是不允许被放置的,所以不会发生 drop 事件。只要在 dragover 和 dragenter 事件中阻止默认行为,才能成为被允许的放置目标,才能允许发生 drop 事件。此时,光标变成了允许放置的符号
- <div id="test" draggable="true" style="height:30px;width:130px;background:pink;float:left;">
- 拖放源
- </div>
- <div id="target" style="float:right;height: 200px;width:200px;background:lightblue;">
- 拖放目标
- </div>
- <script>
- var timer, i = 0;
- var timer1, i1 = 0;
- //兼容IE8-浏览器
- test.onmousedown = function() {
- if (this.dragDrop) {
- this.dragDrop();
- }
- }
- test.ondragstart = function() {
- this.style.backgroundColor = 'lightgreen';
- this.innerHTML = '开始拖动';
- }
- test.ondrag = function() {
- if (timer) return;
- timer = setInterval(function() {
- test.innerHTML = '元素已被拖动' + ++i + '秒';
- },
- 1000);
- }
- test.ondragend = function() {
- clearInterval(timer);
- timer = 0;
- i = 0;
- this.innerHTML = '结束拖动';
- this.style.backgroundColor = 'pink';
- }
- target.ondragenter = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- this.innerHTML = '有元素进入目标区域';
- this.style.background = 'red';
- }
- target.ondragover = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- if (timer1) return;
- timer1 = setInterval(function() {
- target.innerHTML = '元素已进入' + (++i1) + '秒';
- },
- 1000);
- }
- target.ondragleave = function() {
- clearInterval(timer1);
- timer1 = 0;
- i1 = 0;
- this.innerHTML = '元素已离开目标区域';
- this.style.backgroundColor = 'lightblue';
- }
- target.ondrop = function() {
- clearInterval(timer1);
- timer1 = 0;
- i1 = 0;
- this.innerHTML = '元素已落在目标区域';
- this.style.backgroundColor = 'orange';
- }
- </script>
dataTransfer 对象
为了在拖放操作时实现数据交换,引入了 dataTransfer 对象,它是事件对象的一个属性,用于从被拖动元素向放置目标传递字符串格式的数据
dataTransfer 对象有两个主要方法:getData() 和 setData()
getData() 可以取得由 setData() 保存的值。setData() 方法的第一个参数,也是 getData() 方法唯一的一个参数,是一个字符串,表示保存的数据类型,取值为 "text" 或 "URL"
IE 只定义了 "text" 和 "URL" 两种有效的数据类型,而 HTML5 则对此加以扩展, 允许指定各种 MIME 类型。考虑到向后兼容,HTML5 也支持 "text" 和 "URL",但这两种类型会被映射为 "text/plain" 和 "text/uri-list"
实际上,dataTransfer 对象可以为每种 MIME 类型都保存一个值。换句话说,同时在这个对象中保存一段文本和一个 URL 不会有任何问题
[注意] 保存在 dataTransfer 对象中的数据只能在 drop 事件处理程序中读取
在拖动文本框中的文本时,浏览器会调用 setData() 方法,将拖动的文本以"text"格式保存在 dataTransfer 对象中。类似地,在拖放链接或图像时,会调用 setData() 方法并保存 URL。然后,在这些元素被拖放到放置目标时,就可以通过 getData() 读到这些数据
- <div>
- 请将从这堆内容不同乱七八糟的文字中挑选一些移动到拖放目标中
- </div>
- <div id="target" style="margin-top:20px;height: 100px;width:200px;background:lightblue;">
- 拖放目标
- </div>
- <div id="result">
- </div>
- <script>
- target.ondragenter = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- this.innerHTML = '有元素进入目标区域';
- this.style.background = 'red';
- }
- target.ondragover = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- }
- target.ondragleave = function(e) {
- e = e || event;
- this.innerHTML = '元素已离开目标区域';
- this.style.backgroundColor = 'lightblue';
- }
- target.ondrop = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- result.innerHTML = '落入目标区域的文字为:' + e.dataTransfer.getData('text');
- this.innerHTML = '元素已落在目标区域';
- this.style.backgroundColor = 'orange';
- }
- </script>
当然,也可以在 dragstart 事件处理程序中调用 setData(),手动保存自己要传输的数据,以便将来使用
- <div id="test" draggable="true" data-value="这是一个秘密" style="height:30px;width:100px;background:pink;">
- 拖动源
- </div>
- <div id="target" style="margin-top:20px;height: 100px;width:200px;background:lightblue;">
- 拖放目标
- </div>
- <div id="result">
- </div>
- <script>
- //兼容IE8-浏览器
- test.onmousedown = function() {
- if (this.dragDrop) {
- this.dragDrop();
- }
- }
- test.ondragstart = function(e) {
- e = e || event;
- e.dataTransfer.setData('text', test.getAttribute('data-value'));
- }
- target.ondragenter = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- this.innerHTML = '有元素进入目标区域';
- this.style.background = 'red';
- }
- target.ondragover = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- }
- target.ondragleave = function(e) {
- e = e || event;
- this.innerHTML = '元素已离开目标区域';
- this.style.backgroundColor = 'lightblue';
- }
- target.ondrop = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- result.innerHTML = '落入目标区域的文字为:' + e.dataTransfer.getData('text');
- this.innerHTML = '元素已落在目标区域';
- this.style.backgroundColor = 'orange';
- }
- </script>
改变光标
利用 dataTransfer 对象,不仅可以传输数据,还能通过它来确定被拖动的元素以及作为放罝目标的元素能够接收什么操作。为此,需要访问 dataTransfer 对象的两个属性:dropEffect 和 effectAllowed
实际上,这两个属性并没有什么用,只是拖动源在拖动目标上移动时,改变不同的光标而已 (但是,有一种情况除外)
dropEffect
dropEffect 属性可以知道被拖动的元素能够执行哪种放置行为。这个属性有下列 4 个可能的值
"none": 不能把拖动的元素放在这里。这是除文本框之外所有元素的默认值 (此时,将无法触发 drop 事件)
"move": 应该把拖动的元素移动到放置目标
"copy": 应该把拖动的元素复制到放置目标
"link": 表示放置目标会打开拖动的元素(但拖动的元素必须是一个链接,有 URL)
在把元素拖动到放置目标上时,以上每一个值都会导致光标显示为不同的符号
[注意] 必须在 ondragover 事件处理程序中针对放置目标来设置 dropEffect 属性
effectAllowed
dropEffect 属性只有搭配 effectAllowed 属性才有用。effectAllowed 属性表示允许拖动元素的哪种 dropEffect
effectAllowed 属性可能的值如下
"uninitialized": 没有给被拖动的元素设置任何放置行为
"none": 被拖动的元素不能有任何行为
"copy": 只允许值为 "copy" 的 dropEffect
"link" 只允许值为 "link" 的 dropEffect
"move": 只允许值为 "move" 的 dropEffect
"copyLink": 允许值为 "copy" 和 "link" 的 dropEffect
"copyMove": 允许值为 "copy" 和 "move" 的 dropEffect
"linkMove": 允许值为 "link" 和 "move" 的 dropEffect
"all": 允许任意 dropEffect
[注意] 必须在 ondragstart 事件处理程序中设置 effectAllowed 属性
- <div id="test" draggable="true" style="height:30px;width:100px;background:pink;display:inline-block;">
- 拖放源
- </div>
- <br>
- <div id="target1" style="margin-top:20px;height: 100px;width:150px;background:lightblue;display:inline-block;">
- (none)拖放目标
- </div>
- <div id="target2" style="margin-top:20px;height: 100px;width:150px;background:lightblue;display:inline-block;">
- (move)拖放目标
- </div>
- <div id="target3" style="margin-top:20px;height: 100px;width:150px;background:lightblue;display:inline-block;">
- (copy)拖放目标
- </div>
- <div id="target4" style="margin-top:20px;height: 100px;width:150px;background:lightblue;display:inline-block;">
- (link)拖放目标
- </div>
- <div id="result">
- </div>
- <script>
- //兼容IE8-浏览器
- test.onmousedown = function() {
- if (this.dragDrop) {
- this.dragDrop();
- }
- }
- test.ondragstart = function(e) {
- e = e || event;
- //兼容firefox浏览器
- e.dataTransfer.setData('text', '');
- e.dataTransfer.effectAllowed = 'all';
- }
- target1.ondragenter = target2.ondragenter = target3.ondragenter = target4.ondragenter = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- this.style.background = 'red';
- }
- target1.ondragover = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- e.dataTransfer.dropEffect = 'none';
- }
- target2.ondragover = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- e.dataTransfer.dropEffect = 'move';
- }
- target3.ondragover = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- e.dataTransfer.dropEffect = 'copy';
- }
- target4.ondragover = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- e.dataTransfer.dropEffect = 'link';
- }
- target1.ondragleave = target2.ondragleave = target3.ondragleave = target4.ondragleave = function(e) {
- e = e || event;
- this.style.backgroundColor = 'lightblue';
- }
- target1.ondrop = target2.ondrop = target3.ondrop = target4.ondrop = function(e) {
- e = e || event;
- if (e.preventDefault) {
- e.preventDefault();
- } else {
- e.returnValue = false;
- }
- this.style.backgroundColor = 'orange';
- }
- </script>
以上所述是小编给大家介绍的 JavaScript 原生拖放,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 phperz 网站的支持!
来源: http://www.phperz.com/article/17/0519/331742.html