<!-- [if gte mso 9]><xml><w:WordDocument><w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel><w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery><w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery><w:DocumentKind>DocumentNotSpecified</w:DocumentKind><w:DrawingGridVerticalSpacing>7.8</w:DrawingGridVerticalSpacing><w:View>Normal</w:View><w:Compatibility></w:Compatibility><w:Zoom>0</w:Zoom></w:WordDocument></xml><![endif]-->
用dojo.dnd实现拖放功能
相信很多人都自己动手写过拖放。DHTML里做拖放的原理很简单,一般有这么三个阶段:mousedown
的时候做一些初始化,
mousemove
的时候更新拖放对象的位置,
mouseup
的时候再做一些清理工作。讲起来简单,但做起来总要花一些功夫的。
Dojo
的
dnd
模块提供了通用且功能强大的拖放支持,让我们可以不用自己造轮子,而且用起来也很方便。
废话少说,先来看看它到底有多方便。假设页面上有两个ul
,我们需要对
ul
里的
li
元素实现拖放,让它们可以自由地在两个列表间移动。如果自己手写,虽然不难但也要花点时间吧。用
Dojo
的话,除了加载模块之外,甚至连一行
javascript
语句都不需要:
这个例子用了host在google的dojo1.5版本,可以直接运行。这里唯一需要写的javascript
语句就是加载
dojo.dnd.Source
类。剩下的就是在要拖放的对象上做一些标记,用html和
CSSclass
就行了。而且
Dojo
为拖放对象添加的
CSSclass
非常丰富,让我们能自由定制它们的外观。
Fig.1: Source内部DnD
Fig.2: Source之间DnD
Fig.3: 在无法接受拖放内容的地方改变Avatar的外观
好,现在来仔细看一下dojo.dnd
模块到底是怎么一回事。
dojo.dnd包结构
打开dojo/dnd
源码文件夹,可以看到里面有很多东西:
Fig.4: dojo.dnd的目录结构
刚才用的
dojo.dnd.Source
就在Source.js里面。顾名思义,
Source
就是拖放源,一个存放可拖放对象的容器。相对的还有
dojo.dnd.Target(也在Source.js里)
,它继承了
dojo.dnd.Source
,不过只能接受从别处拖过来的东西,却不能拖出去。另一个Source的子类是AutoSource,如果你需要在运行时添加可拖放的结点(实时更新可拖放结点列表),那么它就是为你准备的。
Dojo.dnd
包中的几个主要类之间的关系大致是这样:
Fig.5: DnD包中主要类的结构
其中Container
是顶层基类,它的实例包含有一些子元素,能感知
onmouseover/onmouseout
事件,并且知道具体
over
的是哪个元素。
Selector
是
Container
的子类,让容器支持鼠标选择,可以支持单选或多选。
Avatar
就是在拖放时跟着鼠标跑的那个东西,一般会直接包含拖放对象的
dom
结点。而
Manager
(是一个
Singleton
)则统筹了整个
dnd
过程,管理拖放的起点和终点,以及负责创建、更新和销毁
Avatar
。
包里剩下的东西其实组成了一个子模块:
dojo.dnd.move
,如果你只是需要把某个
dom
结点拖来拖去,就应该用这个模块。这里只介绍
dojo.dnd
,以后再写
dojo.dnd.move
。
dojo.dnd工作流程
当你在要拖动的对象上按住鼠标左键并开始移动时,Source
会调用
Manager.startDrag
函数,标志拖放过程的开始。这个函数记录当前发起拖放的
Source
和拖放的结点,然后创建出
Avatar
,建立起一切必要的事件关联,并发布(
dojo.publish
)一个“开始拖放”(
/dnd/start
)的主题(
topic
)。
Dojo.dnd
里广泛采用主题广播的方式管理拖放过程,这样页面上所有的
Source
都能监听这些主题并作出反应。例如这个
/dnd/start
主题发布后,页面上所有的
Source
(包括刚才拖出来的那个)都将检查自己是否能够接受那些正在被拖动的结点(通过一个叫
checkAcceptance
的方法)。
这里有必要提一下默认的检查方法。Source
有一个属性叫
accept
,这是一个字符串数组,默认是
["text"]
,表示这个
Source
能够接受的东西只限于包含文本的结点。你可以自由定义
accept
里的内容,这将在下一节具体解释。
当这些结点被拖到一个Source
上时(
onmouseover
),将使
Manager
发布
/dojo/source/over
主题,更新
Avatar
上的图标,以反映是否能在这个
Source
上
Drop
。
当你释放鼠标的时候,首先触发Manager
对
onmouseup
事件的响应函数。这个函数将判断当前是否有
Source
能够接受拖放的内容,如果有,就发布
/dnd/drop/before
以及
/dnd/drop
主题;如果没有,就发布
/dnd/cancel
主题。然后销毁
Avatar
、事件句柄、以及所有与本次拖放相关的信息。所有的
Source
都会监听这些主题,并作出相应的应对。
如果某个Source
在响应/dnd/drop主题时发现自己就是
Drop
的目标,就把这次拖放的结点传给一个叫
_normalizedCreator
的私有方法,该方法负责把这些结点转换成自己可以接受的形式。这里其实有一个定制点,让用户自定义转换的方式,这也将在下一节讲到。最后
insertNodes
方法把这些新结点插进来。如果做的是“移动”而不是“复制”(拖动时按住CTRL就是复制),还需要通知作为拖放起点的
Source
删除那些拖出来的子结点。
定制dojo.dnd
定制dojo.dnd
的基本方式和
dijit
类似,就是在构造函数中传入参数对象。如果是声明式创建,就可以直接用
html
属性的方式写在
html
元素中。
Dojo.dnd
具有非常多的定制点,一一列举会过于冗长,这里只挑最常用的几个。(当然,一旦你阅读了源码,完全可以抛开一切约束,通过继承的方式任意扩展
dojo.dnd
里的内容)
1.首当其冲是
accept
数组,刚才已经讲到,只有和这个数组有交集的拖放源才能被接受。例如,一个
Source
的
accept
数组是
["text","image"]
,另一个是
["image","video"]
,那么这两个
Source
就能接受从对方那里拖过来的东西。你肯定会问:为什么这是一个数组而不是单个字符串?答:对不同的拖放结点可以再定制其拖放类型。例如一个
Source
里可以既有
text
类型的结点,也有
image
类型的结点,你可以通过
dndType
属性在这些结点上做标记:
这样,如果你拖的是标记为text
的
li
元素,那么那个
accept=["image","video"]
的
Source
就无法接受它了:
Fig.6: 运用accept和dndType精确控制拖放
2.第二重要的个人感觉就是
creator
,前面提到,通过这个函数可以任意定制拖进来的东西。这个函数接受两个参数,一个是拖进来的
dom
结点的
innerHTML
(注:
Container
里说这是一个形如
{data:data,type:type}
的对象,但在
Source
的实际使用中,传的仅仅是
data
),另一个叫
hint
字符串,目前据我所知其唯一的可能值是
"avatar"
,表示创建出的结点是在
Avatar
中使用的。它需要返回一个形如:
{node:node,data:data,type:type}
的对象。这里的
node
可以跟传进来的那个没有半点关系。
Data
表示拖动的真正内容,一般就是
node.innerHTML
。
Type
就是这个结点的
dndType
。例如我要在传进来的内容前面加一点东西,可以这样写:
效果如图:
3.
一个简单但有用的开关属性:horizontal
。如果你的拖放源是一个横向容器,请把它设为
true
。
4.
三个很有用的且互相有关联的开关属性:copyOnly
默认
false,selfAccept
默认
true
,
selfCopy
默认
false
。顾名思义,如果
copyOnly
是
true
,那么这个
Source
里的东西只能被复制而不能被移走。当
copyOnly
是
true
,且
selfAccept
是
false
的时候,在容器内
dnd
也被禁止了。当
copyOnly
是
true
,
selfAccept
是
true
,且
selfCopy
是
true
的时候,容器内
dnd
的意思是复制而不是移动。
结语
本文很粗浅地介绍了dojo.dnd
包的基本用法,如果要深入了解,强烈建议阅读源码并不断实践。
Dojo.dnd
是
dojo
的核心组件之一,功能强大且代码优雅,相信你一定能从中学到不少东西。
分享到:
相关推荐
- DND(Drag-and-Drop):`dojo.dnd`模块实现了强大的拖放功能,使得交互操作更加直观。 学习Dojo不仅需要理解其模块和包的概念,还需要熟悉其API和组件系统,以及如何利用这些工具来构建高效、响应式的Web应用。...
* dojo.dnd:拖放功能的辅助 API。 * dojo.string:字符串处理包,提供了修整、转换为大写、编码、esacpe、填充等功能。 * dojo.date:日期格式解析的有效助手。 * dojo.event:事件驱动的 API,支持 AOP 开发,以及...
dojo.dnd提供拖放功能的API,dojo.string提供了字符串处理方法,dojo.date帮助解析和操作日期,dojo.event处理事件驱动和AOP开发,dojo.back管理撤销操作的栈,dojo.rpc用于与后端服务通信,dojo.data是统一的数据...
- **包系统**:基础层,按功能划分API,如`dojo.io`处理IO操作,`dojo.dnd`实现拖放功能。 - **语言库**:提供通用语言工具,如字符串处理、日期解析等。 - **环境相关包**:处理浏览器兼容性问题,确保DOJO在不同...
4. **dojo.dnd**:实现了拖放功能的API,可以轻松创建支持拖放操作的应用程序。 5. **dojo.event**:事件管理API,支持面向切面编程(AOP)以及主题/队列功能,使事件处理更加灵活。 6. **dojo.lfx**:HTML和SVG的...
这涉及到`dojo.dnd.Source`和`dojo.dnd.Manager`模块,它们提供了拖放功能的核心。通过监听拖放事件,可以控制节点的移动、复制和删除。确保正确处理数据模型的更新,以保持视图和数据的一致性。 5. **数据库读取并...
而“dojo.dnd”模块则包含了一系列与拖放操作相关的类,如 `HtmlDragObject`。 ##### 3.2 名称约定 Dojo 在命名模块时遵循一定的规则。一般来说,函数名的首字母为小写,而类名的首字母为大写。例如,“dojo....
- **dojo.dnd**:拖放功能的API。 - **dojo.event**:事件处理API,支持AOP和DOM事件的管理。 - **dojo.lfx**:HTML和SVG动画的支持,以及动画效果的实现。 - **dojo.fx**:特效支持,通常选择与dojo.lfx一起使用。 ...
- **dojo.dnd**:实现拖放功能。 - **dojo.string**:字符串处理工具,包括大小写转换、编码解码等。 - **dojo.date**:日期格式解析。 - **dojo.event**:事件驱动API,支持主题与队列功能。 - **dojo.data**:统一...
- dojo.dnd:提供拖放功能的辅助API。 - dojo.string:处理字符串,包括修剪、大小写转换、编码、填充等。 - dojo.date:解析日期格式的工具。 - dojo.event:事件驱动的API,支持面向切面编程(AOP)开发。 - ...
- **dojo.dnd**:支持拖放功能的API。 - **dojo.string**:处理字符串的工具,如修剪、大小写转换、编码等。 - **dojo.date**:日期解析和格式化助手。 - **dojo.event**:事件驱动API,支持面向切面编程和队列管理...
2. **dojo.dnd**:辅助实现拖放功能。 3. **dojo.string**:字符串处理,如修剪、大小写转换、编码等。 4. **dojo.date**:日期解析和格式化工具。 5. **dojo.event**:事件驱动API,支持面向切面编程和队列管理。 6...
例如,`dojo.html`模块提供了一系列处理HTML内容的函数,如`dojo.html.getContentBox()`,而`dojo.dnd`模块则包含了用于HTML拖放操作的相关类。 Dojo的模块和包管理机制允许按需加载,这在优化性能和减小网络传输量...
- `dojo.dnd`:支持拖放功能。 - `dojo.string`:提供了字符串处理方法,如修剪、大小写转换等。 - `dojo.date`:用于日期格式化和解析。 - `dojo.event`:实现了事件驱动API,支持面向切面编程。 - `dojo.back...
- **dojo.dnd**:支持拖放功能。 - **dojo.string**:提供字符串处理方法,如修整、转换大小写、编码等。 - **dojo.date**:帮助解析日期格式。 - **dojo.event**:支持事件驱动的 API,可用于 AOP 开发及主题/队列...
Dojo Toolkit 支持前进后退按钮以及书签功能,这意味着即使是在动态加载内容的情况下,用户也可以像使用传统 Web 页面一样使用浏览器的历史记录功能。这对于提升用户体验至关重要。 #### 4. 事件系统 (Dojo Event ...
本文将详细介绍如何利用Dojo框架实现Drag and Drop功能,并通过一个简单的示例来展示其实现过程。 #### Dojo简介 Dojo是一个开源的JavaScript库,主要用于简化复杂的客户端脚本开发。它提供了丰富的UI控件、数据...