用dojo.dnd实现拖放功能-Dojo中文博客-CSDN博客
《用dojo.dnd实现拖放功能-Dojo中文博客-CSDN博客》由会员分享,可在线阅读,更多相关《用dojo.dnd实现拖放功能-Dojo中文博客-CSDN博客(17页珍藏版)》请在装配图网上搜索。
1、用 dojo.dnd 实现拖放功能 - Dojo 中文博客 - CSDN 博客 用 dojo.dnd 实现拖放功能 相信很多人都自己动手写过拖放。 DHTML 里做拖放的原理 很简单,一般有这么三个阶段: mousedown 的时候做一些 初始化, mousemove 的时候更新拖放对象的位置, mouseup 的时候再做一些清理工作。讲起来简单,但做起 来总要花一些功夫的。 Dojo 的 dnd 模块提供了通用且功 能强大的拖放支持,让我们可以不用自己造轮子,而且用起 来也很方便。 废话少说,先来看看它到底有多方便。 假设页面上有两个 ul , 我们需要对 ul 里的 li 元素实现拖
2、放, 让它们可以自由地在 两个列表间移动。如果自己手写,虽然不难但也要花点时间 吧。用 Dojo 的话,除了加载模块之外,甚至连一行 javascript 语句都不需要: view plaincopy to clipboardprint? 01.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "; 02.<html> 03. <head> 04. <meta http-equiv="Content-Type" content="text/html; charset=i
3、so-8859-1"> 05. <title>Untitled Document</title> 06. <style type="text/css"> 07. @import " es/dojo.css"; 08. @import " laro/claro.css"; 09. 10. ul{ 11. border: 3px solid #ccc; 12. padding: 2em; 13. margin: 5em; 14. float: left; 15. cursor: default; 16. } 17.
4、 .dojoDndItemOver{ 18. background: #ededed; 19. cursor: pointer; 20. } 21. .dojoDndItemSelected { 22. background: #ccf; 23. } 24. .dojoDndItemAnchor{ 25. background: #ccf; 26. } 27. </style> 28. <script type="text/javascript" src=" .xd.js" djConfig="parseOnLoad
5、: true"></script> 29. <script type="text/javascript"> 30. dojo.require("dojo.dnd.Source"); 31. </script> 32. </head> 33. <body class="claro"> 34. <ul dojoType="dojo.dnd.Source"> 35. <li class="dojoDndItem">Item 1</li> 36. <li
6、 class="dojoDndItem">Item 2</li> 37. <li class="dojoDndItem">Item 3</li> 38. <li class="dojoDndItem">Item 4</li> 39. <li class="dojoDndItem">Item 5</li> 40. </ul> 41. <ul dojoType="dojo.dnd.Source"> 42. <li cl
7、ass="dojoDndItem">Item A</li> 43. <li class="dojoDndItem">Item B</li> 44. <li class="dojoDndItem">Item C</li> 45. <li class="dojoDndItem">Item D</li> 46. <li class="dojoDndItem">Item E</li> 47. </ul>
8、 48. </body> 49.</html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "; <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>Untitled Document</title> <style type="text/css"> @import " es/dojo.
9、css"; @import " laro/claro.css"; ul{ border: 3px solid #ccc; padding: 2em; margin: 5em; float: left; cursor: default; } .dojoDndItemOver{ background: #ededed; cursor: pointer; } .dojoDndItemSelected { background: #ccf; } .dojoDndItemAnchor{ background: #ccf; } </style> <
10、;script type="text/javascript" src=" .xd.js" djConfig="parseOnLoad: true"></script> <script type="text/javascript"> </script> </head> <body class="claro"> <li class="dojoDndItem">Item 1</li> <li class="dojoDndItem">Item 2</li> <l
11、i class="dojoDndItem">Item 3</li> <li class="dojoDndItem">Item 4</li> <li class="dojoDndItem">Item 5</li> </ul> <li class="dojoDndItem">Item A</li> <li class="dojoDndItem">Item B</li> <li class="dojoDndItem">Item C</li&g
12、t; <li class="dojoDndItem">Item D</li> <li class="dojoDndItem">Item E</li> </ul> </body> </html> 这个例子用了 host 在 google 的 dojo1.5 版本,可以直接运 行。这里唯一需要写的 javascript 语句就是加载 类。剩下的就是在要拖放的对象上做一些 标记,用 html 和 CSS class 就行了。而且 Dojo 为拖放对 象添加的 CSS class 非常丰富,让我们能自由定制
13、它们的 外观。 Fig.1: Source 内部 DnD Fig.2: Source 之间 DnD Fig.3: 在无法接受拖放内容的地方改变 Avatar 的外观 好,现在来仔细看一下 dojo.dnd 模块到底是怎么一回事。 dojo.dnd 包结构 打开 dojo/dnd 源码文件夹,可以看到里面有很多东西: Fig.4: dojo.dnd 的目录结构 刚才用的 就在 Source.js 里面。顾名思义, Source 就是拖放源,一个存放可拖放对象的容器。相对的 还有 (也在 Source.js 里) ,它继承了 ,不过只能接受从别处拖过来的东西,却 不能拖出去。另一个
14、 Source 的子类是 AutoSource ,如果你 需要在运行时添加可拖放的结点(实时更新可拖放结点列 表),那么它就是为你准备的。 Dojo.dnd 包中的几个主要类之间的关系大致是这样: Fig.5: DnD 包中主要类的结构 其中 Container 是顶层基类,它的实例包含有一些子元素, 能感知 onmouseover/onmouseout 事件,并且知道具体 over 的是哪个元素。 Selector 是 Container 的子类, 让容 器支持鼠标选择,可以支持单选或多选。 Avatar 就是在拖 放时跟着鼠标跑的那个东西,一般会直接包含拖放对象的 dom 结点。而 M
15、anager (是一个 Singleton )则统筹了 整个 dnd 过程,管理拖放的起点和终点,以及负责创建、 更新和销毁 Avatar 。 包里剩下的东西其实组成了一个子模块: , 如果你只是需要把某个 dom 结点拖来拖去,就应该用这个 模块。这里只介绍 dojo.dnd ,以后再写 。 dojo.dnd 工作流程 当你在要拖动的对象上按住鼠标左键并开始移动时, Source 会调用 Manager.startDrag 函数, 标志拖放过程的开始。 这 个函数记录当前发起拖放的 Source 和拖放的结点, 然后创 建出 Avatar ,建立起一切必要的事件关联,并发布 ( dojo.
16、publish )一个 “ 开始拖放 ” ( /dnd/start )的主题( topic )。 Dojo.dnd 里广泛采用 主题广播的方式管理拖放过程,这样页面上所有的 Source 都能监听这些主题并作出反应。 例如这个 /dnd/start 主题发 布后,页面上所有的 Source (包括刚才拖出来的那个)都 将检查自己是否能够接受那些正在被拖动的结点(通过一个 叫 checkAcceptance 的方法)。 这里有必要提一下默认的检查方法。 Source 有一个属性叫 accept ,这是一个字符串数组,默认是 ["text"] ,表示这个 Source
17、能够接受的东西只限于包含文本的结点。你可以自 由定义 accept 里的内容,这将在下一节具体解释。 当这些结点被拖到一个 Source 上时( onmouseover ), 将使 Manager 发布 /dojo/source/over 主题,更新 Avatar 上的图标,以反映是否能在这个 Source 上 Drop 。 当你释放鼠标的时候,首先触发 Manager 对 onmouseup 事件的响应函数。 这个函数将判断当前是否有 Source 能够 接受拖放的内容,如果有,就发布 /dnd/drop/before 以及 /dnd/drop 主题;如果没有,就发布 /dnd/cancel
18、 主题。然 后销毁 Avatar 、事件句柄、以及所有与本次拖放相关的信 息。所有的 Source 都会监听这些主题, 并作出相应的应对。 如果某个 Source 在响应 /dnd/drop 主题时发现自己就是 Drop 的目标,就把这次拖放的结点传给一个叫 _normalizedCreator 的私有方法, 该方法负责把这些结点转 换成自己可以接受的形式。这里其实有一个定制点,让用户 自定义转换的方式, 这也将在下一节讲到。 最后 insertNodes 方法把这些新结点插进来。 如果做的是 “ 移动 ” 而不是 “ 复制 ”(拖动时按住 CT
19、RL 就是复制), 还需要通知作为拖放起点的 Source 删除那些拖出来的子 结点 定制 dojo.dnd 定制 dojo.dnd 的基本方式和 dijit 类似, 就是在构造函数中 传入参数对象。如果是声明式创建,就可以直接用 html 属 性的方式写在 html 元素中。 Dojo.dnd 具有非常多的定制 点,一一列举会过于冗长, 这里只挑最常用的几个。 (当然, 一旦你阅读了源码,完全可以抛开一切约束,通过继承的方 式任意扩展 dojo.dnd 里的内容) 1. 首当其冲是 accept 数组, 刚才已经讲到, 只有和这个数 组有交集的拖放源才能被接受。例如,一个 Sourc
20、e 的 accept 数组是 ["text", "image"] ,另一个是 ["image", "video"] ,那么这两个 Source 就能接受从对方那里拖过来 的东西。你肯定会问:为什么这是一个数组而不是单个字符 串?答:对不同的拖放结点可以再定制其拖放类型。例如一 个 Source 里可以既有 text 类型的结点,也有 image 类 型的结点, 你可以通过 dndType 属性在这些结点上做标记: view plaincopy to clipboardprint? 02. <li class="dojoDndItem" dndType="text"><
21、/li> 03. <li class="dojoDndItem" dndType="image"></li> 04.</ul> <li class="dojoDndItem" dndType="text"></li> <li class="dojoDndItem" dndType="image"></li> </ul> 这样,如果你拖的是标记为 text 的 li 元素,那么那个 accept=["image", "video"] 的 Source 就无法接受它了: Fig.6
22、: 运用 accept 和 dndType 精确控制拖放 2. 第二重要的个人感觉就是 creator ,前面提到, 通过这个 函数可以任意定制拖进来的东西。这个函数接受两个参数, 一个是拖进来的 dom 结点的 innerHTML (注: Container 里说这是一个形如 {data: data, type: type} 的对象,但在 Source 的实际使用中, 传的仅仅是 data ),另一个叫 hint 字符串,目前据我所知其唯一的可能值是 "avatar" ,表示 创建出的结点是在 Avatar 中使用的。 它需要返回一个形如: {node: node, data: dat
23、a, type: type} 的对象。这里的 node 可以跟传进来的那个没有半点关系。 Data 表示拖动的真正 内容,一般就是 node.innerHTML 。 Type 就是这个结点 的 dndType 。例如我要在传进来的内容前面加一点东西, 可以这样写: view plaincopy to clipboardprint? 02. <script type="dojo/method" event="creator" args="data, hint"> 03. var node = dojo.create("div", { 04. 05. "class":
24、 "dojoDndItem", 06. "innerHTML": "<strong style='color: darkred'>Special</strong> " + String(data) 07. }); 08. return {node: node, data: node.innerHTML, type: ["text"]}; 09. </script> 10. <li class="dojoDndItem">Item A</li> 11. <li class="dojoDndItem">Item
25、B</li> 12. <li class="dojoDndItem">Item C</li> 13. <li class="dojoDndItem">Item D</li> 14. <li class="dojoDndItem">Item E</li> 15.</ul> <script type="dojo/method" event="creator" args="data, hint"> var node = dojo.create("div", { "clas
26、s": "dojoDndItem", "innerHTML": "<strong style='color: darkred'>Special</strong> " + String(data) }); return {node: node, data: node.innerHTML, type: ["text"]}; </script> <li class="dojoDndItem">Item A</li> <li class="dojoDndItem">Item B</li> <li c
27、lass="dojoDndItem">Item C</li> <li class="dojoDndItem">Item D</li> <li class="dojoDndItem">Item E</li> </ul> 效果如图: 3. 一个简单但有用的开关属性: horizontal 。如果你的拖 放源是一个横向容器,请把它设为 true 。 4. 三个很有用的且互相有关联的开关属性: copyOnly 默 认 false, selfAccept 默认 true , selfCopy 默认 false 。
28、 顾名思义,如果 copyOnly 是 true ,那么这个 Source 里 的东西只能被复制而不能被移走。当 copyOnly 是 true , 且 selfAccept 是 false 的时候,在容器内 dnd 也被禁止了。 当 copyOnly 是 true , selfAccept 是 true ,且 selfCopy 是 true 的时候,容器内 dnd 的意思是复制而不是移动。 结语 本文很粗浅地介绍了 dojo.dnd 包的基本用法,如果要深入 了解,强烈建议阅读源码并不断实践。 Dojo.dnd 是 dojo 的 核心组件之一,功能强大且代码优雅,相信你一定能从中学 到不少东西。 本文来自 CSDN 博客,转载请标明出处: 6.aspx
- 温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。