拖拽:从 Dojo 到 HTML 5

开发 前端
拖拽是 Web 2.0 应用中最流行的技术之一。本文将介绍如何在网络应用程序中使用 dojo 和 HTML5 这两种技术的拖拽功能。并将通过示例详细介绍 HTML5 的拖拽功能。

Dojo 及 HTML 5 简介

Dojo 是目前***的开源 JavaScript 工具库之一,很多开发者以及企业用户都把Dojo 作为***的 JavaScript 工具。Dojo 为 Web 应用的开发提供了大量的客户端组件,能够让你可以方便的进行 HTML DOM 操作、拖拽、AJAX 调用、定制可视化控件等来使得你的 Web 应用变成富网络应用 (RIA)。而且 Dojo 在性能、可访问性、多语言支持以及文档方面都做的非常出色,这也是企业选择 Dojo 的原因之一。

51CTO推荐专题:HTML 5 下一代Web开发标准详解

HTML 5 是***一代的 HTML,它将成为 HTML、XHTML 以及 HTML DOM 的新标准, HTML 5 是 W3C 与 WHATWG 合作的结果,目前仍外于开发中 ; 自从上一代 HTML4,Web 世界已经发生了巨大的变化,HTML 5 的到来将更大的促进 Web 的发展,HTML 5 提供了很多新的功能,主要有:

◆新的 HTML 元素,例如 section, nav, header, footer, article 等

◆用于绘画的 Canvas 元素

◆用于多媒体播放的 video 和 audio 元素

◆用于定位的 Geolocation API

◆本地存储以及离线应用

◆Web Workers

◆拖拽 API

◆文件 API

我们主要对 HTML 5 的拖拽功能进行讲解,并结合文件 API 与桌面进行交互。来与 Dojo 的 dnd 拖拽组件进行比较。

使用 Dojo 创建及定制拖拽应用

类似 Dojo 其他组件,拖拽的实现有两种方式:声明式和编程式。在这里我们使用声明式的方式做简要的介绍。

在 Dojo 拖拽实现中,有两个重要的元素 dojo.dnd.Source 和 dojo.dnd.Target。这两个元素分别标示了拖拽中的源容器 Source 和目标容器 Target。值得注意的是源容器 Source 默认也是目标容器 Target,而不需要作目标容器 Target 的声明。我们在源容器 Source 中创建一些可以拖动的元素,要让这些元素可拖动,我们要为这些元素添加 class 属性值 DojoDndItem。下面的示例代码定义了一个源容器 Source 以及一些可以拖动的元素。在这些可以拖动的元素中我们可以定义它们的拖拽类型 dndType。dndType 的值开发者可以自己定义,而目标容器 Target 元素的 accept 属性定义了该目标容器接受的拖拽类型。

清单 1. 创建拖拽的源容器和可拖拽的元素

  1. <div id="source" style="height:400px;" dojoType="dojo.dnd.Source">   
  2.   <div id="item1" class="dojoDndItem item" dndType="divItem">item1</div>   
  3.   <img src="w3c.jpg" class="dojoDndItem item" dndType="imageItem"></img>   
  4.   <a href="http://www.w3.org/TR/html5/" class="dojoDndItem item" dndType="linkItem"> 
  5.   HTML5 specification</a>   
  6.  </div>  

对于 Target 我们可以创建一个 div,然后加上属性 dojoType=”dojo.dnd.Target”和属性 accept。不在 accept 中的类型的 dojoDndItem 元素将不被这个容器接受。例如清单 2 中的目标容器只接受 divItem 和 imageItem 这两种类型,那么清单 1 中的 linkItem 将不能被拖到这个目标容器中。

清单 2. 创建拖拽的目标容器和可接受的类型

  1. <div id="target" style="height:400px;" dojoType="dojo.dnd.Target"   
  2. accept="divItem, imageItem"> 

真正 Web 应用的拖拽没有这么简单,开发者往往需要在拖拽的过程中更多的介入。这时候可以通过对 Dojo 提供的 dojo.dnd.Source 和 dojo.dnd.Target 进行继承扩展,开发满足业务需要的功能和特性。这里将不赘述。

使用 HTML 5 创建拖拽应用

在这一章中,我们将要使用 HTML 5 创建一个简单的拖拽应用,如图 1 所示,用户可以把网页上内容从左边的区域拖放到右边的区域。这个应用程序的代码可到附件中可以下载。

图 1. HTML 5 拖拽应用效果图

拖拽:从 Dojo 到 HTML5 

#p#

创建可以拖动的节点

使用 HTML 5 创建拖拽只需要对可拖拽的节点进行声明——给可以拖拽的节点添加 draggable 属性并设值为 true。如清单 3 中的 div 节点,通过添加 draggable 属性就可以拖拽了。在 HTML 5 中<img>和<a> 默认情况下是可以拖拽的,所以不需要设置 draggable 属性。

清单 3. 通过添加 draggable 属性来创建源容器中可以拖动的节点

  1. <div id="source" style="height:300px;">   
  2.   <div id="item1" class="item" draggable="true">item1</div>   
  3.   <img id="item2" src="w3c.jpg" class="item"></img>   
  4.   <a id="item3" href="http://www.w3.org/TR/html5/" class="item">HTML5 specification</a>   
  5.  </div>  

创建 HTML 5 拖拽的源容器和目标容器

在 HTML 5 中,我们需要给指定的节点来绑定一些事件来使之成为具有源容器或目标容器的功能。在 HTML 5 的拖拽过程中的事件有 7 个,分别是应用在目标容器或拖动节点上的 dragstart, drag, dragend 等 3 个事件,以及应用在目标容器节点上的dragenter, dragover, dragleave 和 drop 等 4 个事件。表 1 中对这些事件的触发机制和常见的操作进行了描述。

表 1. HTML 5 拖拽过程中可以绑定的事件

HTML5

备注 : 在 Dojo 中所有 dnd 源容器或目标容器在拖拽开始时都会调用 onDndStart 事件方法,而在 HTML 5 中只有拖动的节点及源容器可以触发 dragstart 事件,其他容器包括目标容器在拖动开始时不会感知源容器及拖动节点的 dragstart 事件。

清单 4 展示给目标容器绑定 dragenter, dragover, dragleave, drop 事件的示例代码。在 dragenter 和 dragleave 事件中,我们对目标容器的背景样式进行修改使得用户感知目标容器的状态(如图 2 所示)。在 dragover 事件中我们对清单 3 中的链接元素(id 属性值为 item3)的节点进行了限制。drop 事件中我们要把拖动的节点插入到目标节点的 DOM 结构中。

清单 4. 创建目标容器的事件

  1. var target = dojo.byId('target');   
  2.  dojo.connect(target, 'dragover', function(e){   
  3.   // doesn't allows link item (id = “item3”) to drop   
  4.   if (e.dataTransfer.getData('id') != "item3"){   
  5.     e.preventDefault();   
  6.   }   
  7.  });   
  8.  
  9.  dojo.connect(target, 'dragenter', function(e){   
  10.   //add style   
  11.   dojo.addClass(target, "over");   
  12.  });   
  13.  
  14.  dojo.connect(target, 'dragleave', function(){   
  15.   //remove style   
  16.   dojo.removeClass(target, "over");   
  17.  });   
  18.  
  19.  dojo.connect(target, 'drop', function(e){   
  20.   //remove style if drop is successful   
  21.   dojo.removeClass(target, "over");   
  22.       
  23.   // stops the browser from redirecting   
  24.   if (e.stopPropagation) e.stopPropagation();   
  25.       
  26.     
  27.   var itemId = e.dataTransfer.getData('id');   
  28.   var dragItem = dojo.byId(itemId);   
  29.   e.target.appendChild(dragItem);     
  30.     
  31.  }  

图 2. 当拖动节点到目标容器是时对目标容器进行高亮显示

HTML 5

从清单 4 中我们在目标容器上对事件对象的 dataTransfer 属性进行了 getData 操作——取出了关键字 id 对应的数据。在 HTML 5 拖拽过程中,用户可以在表 1 定义的事件里通过 event.dataTransfer 得到 DataTransfer 对象 ( 详见 W3C 网站上的接口定义)并对其进行定制传输数据、定制拖拽影像等操作。例如我们可以在 dragstart 事件中通过 setData 方法初始化数据(代码详见附件)。表 2 中列出了这各数据对象的方法及常用的用途。

表 2. DataTransfer 的常用方法

HTML 5

与桌面进行交互

除了在网页中对一些页面上的元素进行拖拽以外,HTML 5 扩充的 API 还允许网页与文件系统进行交互,比如从文件系统拖一个或几个文件到网页中,或是从网页拖到文件系统中。以前者为例,当我们从桌面或其它文件夹拖动文件到网页上某个目标结点时,我们可以通过 DataTransfer 的 files 属性得到这些文件数量以及文件的属性及内容。DataTransfer.files.length 的大小即为拖动文件的数量,当没有拖动文件时,files.length 的大小即为 0,可用来判断是否有文件拖动。

清单 5. 通过 dataTransfer.files 拿到文件对象

  1. var files = e.dataTransfer.files;   
  2.   var msg = "";   
  3.   for (var i = 0; i < files.length; i++) {   
  4.    console.log ("Name: " + files[i].name + ", fileSize: " + files[i].size);   
  5.    var dataReader = new FileReader();   
  6.    dataReader.onload = function(){   
  7.      msg += ("content: " + dataReader.result);   
  8.    }   
  9.   dataReader.readAsText(files[i]);   
  10.  }  

从清单 5 中的代码中我们可以看到 files 中存储了若干 file 对象,通过这个对象可以获取文件名,文件大小等。然后我们可以通过 FileReader 获取文件的内容。获取内容的 FileReader 并不是 HTML 5 拖拽的功能,而是借助了 File API 。它可以以文本,二进制,以及 dataURL 的形式读取,实现读取文件内容实现文件上传等,在我们的示例代码 HTML 5dndfile.html 中我们演示了通过 readAsText 方法读取文本文件和通过 readAsDataURL 方法读取图像文件的使用。

与桌时行交互时,我们只需要对将清单 5 中给出的代码稍加修改加到目标容器的 drop 事件中,其它事件不用修改。例如清单 6 所示。

清单 6. 在目标容器的 drop 事件读取文本文件的内容

  1. dojo.connect(textdiv, 'drop', function(e){   
  2.   if (e.stopPropagation){   
  3.     e.stopPropagation(); // stops the browser from redirecting   
  4.   }   
  5.   var files = e.dataTransfer.files;   
  6.   var msg = "";   
  7.   for (var i = 0; i < files.length; i++) {   
  8.     msg += ("Name: " + files[i].fileName + ", fileSize: " + files[i].fileSize);   
  9.     var dataReader = new FileReader();   
  10.     dataReader.onload = function(){   
  11.       msg += ("content: " + dataReader.result);   
  12.       textdiv.textContent = msg;   
  13.     }   
  14.     dataReader.readAsText(files[i]);   
  15.   }   
  16.  });  

这样当我们拖动一个文本文件到指定的目标区域时,我们就可以看到文件内容。

Dojo 和 HTML 5 拖拽功能的比较和选择

Dojo 实现了一套完整的拖拽框架和事件机制,并提供了默认的实现,用户可以通过声明的方式快速实现拖拽,而且还可以通过继承默认的 Source、Target 以及 Avatar 实现拖拽定制化。从使用经验上来看,Dojo 更倾向于完整的 DOM 节点操作,而数据的传输往往是通过绑在 DOM 节点上的属性实现的。

HTML 5 的拖拽现在还在规范的定制和完善中,各个主流浏览器对该规范的支持也是各有千秋,基本上还处于发展的阶段。本文中提供的示例仅在 Firefox 3.6 以上版本测试通过。HTML 5 作为新时代的 HTML 协议,拖拽事件中的 DataTransfer 接口体现了拖拽过程中以数据传输为中心的发展前景。与此同时,跟 File API 的结合可以使得 Web 应用的数据交互通过拖拽操作延伸到最终用户的桌面及文件系统上。另外 HTML 5 还可以实现在不同浏览器窗口之间的拖拽操作,也是拖拽过程传输数据的一种应用。

小结

对比 Dojo 和 HTML 5,我们不难发现在使用 Dojo 比 HTML 5 可以更容易地开发出体验效果非常好的拖拽应用;而 HTML 5 作为 HTML 的新规范,注重了拖拽过程中数据传输的重要性。两者如果可以融合则可以互补其短。通过实验,笔者发现 Dojo dnd 与 HTML 5 拖拽暂时不能在同一结点上同时使用,由于 Dojo 是在 HTML4 规范基础上的工具包,它们之间可能因在事件上的冲突会导致 HTML 5 拖拽不可用。但是我们有理由相信,随着 HTML 5 规范的发展,将会有支持 HTML 5 拖拽的工具包出现,届时开发者可以更为便捷的开发出更为丰富的 Web 应用。

原文链接:http://www.ibm.com/developerworks/cn/web/1102_guoqing_draganddrop/

【编辑推荐】

  1. 初学者必知的HTML 5入门级技巧
  2. 12个精妙有趣的HTML 5应用
  3. HTML 5新的 Input 类型
  4. 20个HTML 5和CSS3的免费网站模板与教程
  5. 用Dojo实现Ajax请求:XHR、跨域、及其他
责任编辑:陈贻新 来源: developerWorks
相关推荐

2011-02-25 10:19:23

ibmdwHTML5Web开发

2012-04-24 09:48:49

HTML5

2011-08-01 16:43:51

ibmdwHTML5Dojo

2011-09-08 09:38:46

HTML5 WidgeDojo

2011-04-25 14:20:49

DojoHTML 5

2011-04-22 15:02:19

HTML5Dojo

2012-05-17 13:17:26

HTML5

2010-07-23 10:08:44

Dojo 1.5

2011-08-18 09:05:50

HTML 5

2013-06-06 10:42:25

2015-03-19 14:50:27

编程拖拽编程合格程序员

2012-05-28 10:01:19

2015-12-02 11:18:32

2020-09-09 15:30:07

5GCPRI接口

2012-01-18 10:49:05

ibmdw

2013-03-25 17:16:11

2011-11-24 21:12:35

ibmdw

2011-10-03 20:23:34

2019-09-27 10:25:39

5G浪潮云计算

2011-11-15 09:10:24

HTML 5
点赞
收藏

51CTO技术栈公众号