Web开发中的Drag&Drop完全手册

简介:
这几天做了一些drag&drop操作方面的工作,在这里把一些注意事项记录下来,算是给自己备个忘,也给需要做类似工作的人留个树阴。这里要讨论的drag&drop是指使用IE提供的内置机制,而不是使用鼠标模拟的那种"假"drag&drop,比如移动一个div或span的效果那种。

    要实现和控制drag&drop操作,那么首先第一点要弄清楚的是,到底哪些元素是可以在Web上被drag的?实际上IE默认给我们并让我们drag的元素并不多,它们是:图片选中的文字(包括页面文字和文字控件(input, textarea)中的文字)和连接(普通连接和锚点)。除此之外,别的Web元素默认都不支持drag操作(在这些元素上面drag其实就是选择操作了),所以要实现对元素默认的drag&drop控制,只能选这3类元素来操作。

    
在BizStruct同学的斧正中提到,其实几乎所有的Html元素都是支持drag&drop的(见其回复),在此表示由衷的感谢。

    接下来,那么哪些元素又是可以接受drop操作呢?任何页面上的可见元素都是可以接受drop操作的,而它们之间的不同只是在于默认的drop事件不一样。比如,文字控件(input, textarea)的默认drop事件就是获取drag操作传过来的文字内容;iframe元素的默认drop操作是到航道drag操作传过来的URL地址。当然绝大多数的Web元素的默认是操作是do nothing,什么也不做。

    那么当进行drag&drop操作时,有那些是可控制和定制的内容呢?这里关于drag&drop提供了以下一些事件(我们把它们分为作用于来源对象目的对象来分别讨论),先讨论主要作用于来源对象的事件:
   ·ondrag —— 在整个从drag动作开始,直道drop动作结束的过程中,都会触发的一个事件。
   ·ondragstart —— 在drag动作开始时,在来源对象上触发的一个事件。
   ·ondragend —— 在drop动作结束的时候,在来源对象上出发的一个事件。

   而主要做要在目的对象上的事件:
   ·ondragenter —— 在drag动作进入某一有效目的元素时,在该目的元素上触发的一个事件。
   ·ondragover —— 在drag动作进入某一有效目的元素后,在该目的元素上触发的一个事件。
   ·ondragleave —— 在drag动作离开某一有效目的元素时,在该目的元素上触发的一个事件。
   ·ondrop —— 在任何有效目的元素上进行drop操作时,在该目的元素上触发的一个事件。

    这里的来源和目的的划分不是绝对的,比如ondragover事件,在drag操作过程中,如果鼠标进入了来源对象中,同样的也会触发这个事件。这些事件触发的顺序是:来源对象 --> ondragstart --> ondrag --> ondragend;目的对象 --> ondragenter --> ondragover --> ( ondragleave | ondrap )。由于是分别在同一个对象上触发的事件,所以这个顺序很简单。那么对于一个完整的从来源对象到目的对象的drag&drop操作来说,事件的触发序列又是怎样呢?如果src表示来源对象,des表示目的对象,那么事件触发序列为:

    src:ondragstart --> src:ondrag --> des:ondragenter --> des:ondragover --> ( des:ondragleave | des:ondrop ) --> src:ondragend.

    示例为:
Drag Source Drop Destination
     // 如果alert窗口不响应鼠标点击可以使用键盘的space键来确定窗口
<onmouseover="status=this.innerText; return true;" ondragend="alert('src:on'+event.type)" onclick="return false;">Drag Source</A>
<SPAN ondrop="alert('des:on'+event.type)" ondragleave="alert('des:on'+event.type)">Drop Destination</SPAN>

    了解了事件触发顺序后,定制drag&drop过程中鼠标的光标形状也是非常重要的一个内容。因为用户的drag&drop的整个过程都需要靠鼠标光标的形状指导其进行操作,如果不能实时的调整光标为适合的型状,drag&drop操作对用户来说将无异于朦眼寻物。IE提供了用来控制的drag&drop过程中光标形状的两个属性,它们是:effectAllowed和dropEffect。

    其属性分别为:
        ·effectAllowed: copy, link, move, copyLink, copyMove, all, none & uninitialized.
        ·dropEffect: copy, link, move, none.

    前者effectAllowed是用来控制允许drag&drop操作类型的,所以这里的effect不是显示的"效果",而是是否可以执行的"操作",并且该属性只能在ondragstart事件中进行初始化,之后再对其赋值将无效。当然如果只使用effectAllowed属性,就已经可以达到控制光标形状的作用了。只是effectAllowed属性在处理复合操作时,比如copyLink, copyMove和all,会默认显示靠前那个操作类型的鼠标类型。也就是说如果effectAllowed是copyMove,那么这是鼠标光标就是copy形状。这下就知道为什么还要弄个dropEffect属性了吧?不过这个dropEffect属性中指定的effect,只能是之前effectAllowed允许的操作类型范围中的值,否则没有效果(显示no-drop鼠标光标)。
    
    示例为:
Drag Source Drop Destination
<ondragstart="event.dataTransfer.effectAllowed='copyMove'; event.dataTransfer.dropEffect='move'" onmouseover="status=this.innerText; return true;" ondragover="event.dataTransfer.dropEffect='move'; event.returnValue=false; event.cancelBubble=true;" onclick="return false;">Drag Source</A>
<SPAN ondragover="event.dataTransfer.dropEffect='copy'; event.returnValue=false; event.cancelBubble=true;">Drop Destination</SPAN>

    查看代码时注意,你会发现在src和des的对象元素中,在ondragover事件里除了对dropEffect赋以适当的值外,还有两句话:
   event.returnValue=false ;
   event.cancelBubble=true;

    只是由于页面元素在接受dragover的时候,本身都有其默认的鼠标光标显示型状,所以为了让用户自定义的鼠标光标生效,就需要使事件event的returenValue为false值并停止当事件的冒泡(event.cancelBubble=true)。

    到目前为止,一个完整的drag&drop过程就差数据传递了,其实忙活了半天,这才是藏在所有交互操作和显示效果下面最重要的步骤。这个过程需要借助于IE提供的DHTML Data Transfer对象来完成,在window对象的属性event对象中,分别有两个Data Transfer对象各自的一个实例:一个叫dataTransfer,另一个叫clipboardData。这两个对象实例的行为非常相似,但又有一些区别,clipboardData顾名思义,它使用操作系统的剪贴板来存取数据,并有3个方法;而dataTransfer通过操作一个自己的内部剪贴板来存取数据(每次ondragend事件触发后就自动清空了),除了有和clipboardData相同的3个方法外,还有两个属性(就是前面介绍的那两个effectAllowed和dropEffect)。

    我们这里不对clipboardData作更多的讨论,继续来看dataTransfer对象。它包含3个方法,它们是:setData(sDataFormat, sText), getData(sDataFormat)和clearData([sDataFormat])。它们更详细的使用和参数请参阅MSDN,这里我只用它们来实现drag&drop的数据传递。

    示例为:
Drag Source Drop Destination
<ondragstart="event.dataTransfer.effectAllowed='copyMove'; event.dataTransfer.dropEffect='move'; event.dataTransfer.setData('TEXT', this.innerText);" onmouseover="status=this.innerText; return true;" ondragover="event.dataTransfer.dropEffect='move'; event.returnValue=false; event.cancelBubble=true;" onclick="return false;">Drag Source</A>
<SPAN ondrop="this.innerText = event.dataTransfer.getData('TEXT'); this.style.color = 'red';" ondragover="event.dataTransfer.dropEffect='copy'; event.returnValue=false; event.cancelBubble=true;">Drop Destination</SPAN>

    其实很简单,就是在src的ondragstart中,调用event.dataTransfer.setData('TEXT', this.innerText),然后再des的ondrop事件中,调用this.innerText = event.dataTransfer.getData('TEXT')就行了。


本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。

目录
相关文章
|
1月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
112 3
|
22天前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
120 45
|
3天前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
15 2
|
17天前
|
前端开发 API 开发者
Python Web开发者必看!AJAX、Fetch API实战技巧,让前后端交互如丝般顺滑!
在Web开发中,前后端的高效交互是提升用户体验的关键。本文通过一个基于Flask框架的博客系统实战案例,详细介绍了如何使用AJAX和Fetch API实现不刷新页面查看评论的功能。从后端路由设置到前端请求处理,全面展示了这两种技术的应用技巧,帮助Python Web开发者提升项目质量和开发效率。
32 1
|
20天前
|
XML 安全 PHP
PHP与SOAP Web服务开发:基础与进阶教程
本文介绍了PHP与SOAP Web服务的基础和进阶知识,涵盖SOAP的基本概念、PHP中的SoapServer和SoapClient类的使用方法,以及服务端和客户端的开发示例。此外,还探讨了安全性、性能优化等高级主题,帮助开发者掌握更高效的Web服务开发技巧。
|
23天前
|
安全 数据库 开发者
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第26天】本文详细介绍了如何在Django框架下进行全栈开发,包括环境安装与配置、创建项目和应用、定义模型类、运行数据库迁移、创建视图和URL映射、编写模板以及启动开发服务器等步骤,并通过示例代码展示了具体实现过程。
34 2
|
1月前
|
设计模式 测试技术 持续交付
开发复杂Web应用程序
【10月更文挑战第3天】开发复杂Web应用程序
39 2
WK
|
23天前
|
安全 Java 编译器
C++和Java哪个更适合开发web网站
在Web开发领域,C++和Java各具优势。C++以其高性能、低级控制和跨平台性著称,适用于需要高吞吐量和低延迟的场景,如实时交易系统和在线游戏服务器。Java则凭借其跨平台性、丰富的生态系统和强大的安全性,广泛应用于企业级Web开发,如企业管理系统和电子商务平台。选择时需根据项目需求和技术储备综合考虑。
WK
37 0
|
1月前
|
Java PHP
PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。理解其垃圾回收机制有助于开发高效稳定的PHP应用。
【10月更文挑战第1天】PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。其垃圾回收机制包括引用计数与循环垃圾回收,对提升应用性能和稳定性至关重要。本文通过具体案例分析,详细探讨PHP垃圾回收机制的工作原理,特别是如何解决循环引用问题。在PHP 8中,垃圾回收机制得到进一步优化,提高了效率和准确性。理解这些机制有助于开发高效稳定的PHP应用。
47 3
|
24天前
|
JavaScript 前端开发 Java
SpringBoot_web开发-webjars&静态资源映射规则
https://www.91chuli.com/ 举例:jquery前端框架
17 0
下一篇
无影云桌面