首页logo
  •  

jonllen

金龙,目前就职于一家软件公司,从事Java和.Net信息安全开发设计。

个人档案

jonllen
心情闪存 | 给他留言
妮称:jonllen
来自:中国. 湖南. 湘潭
简述:金龙,目前就职于一家软件公司,从事Java和.Net信息安全开发设计。
博客日历

博客个性化定制(2)-实现类似iGoogle首页功能

分类:JavaScript

继上一篇博客个性化定制功能后,今天我又花了足足一天时间,实现了使用js拖拽定制模块功能。主要包括三步:1.拖拽模块;2.计算坐标位置;3.完成拖拽,保存当前布局位置。

一、拖拽功能

如果只单实现简单的拖拽功能,那其实很简单,就只要注意拖拽时选中文本一些问题。由于我这里还拖拽有一些区域限制等,模块又都是从后台动态输出的,就做成一个函数类,可能实现出来就没那么通用了。拖拽的过程一般我们会用到几个事件:鼠标开始按下onmousedown事件,拖动事件onmousemove,松开鼠标完成拖拽事件onmouseup。对于几个DOM元素都有相同的事件,一般不需要每个DOM元素逐一添加事件监听,可以添加一个事件到它们公共的父元素上,这样感觉更好,然后通过事件的target或srcElement捕获触发事件源元素,这里的拖拽也是这样来实现的,onmousedown事件是监听拖拽模块的父容器元素,这个方法有点不好的就是可能获得事件发生源并不是你想要的,可能获得的是它的子元素,所以这里可能还需要额外加一个是否为parentNode的判断。onmousedown事件第一步先要判断按的元素是否为可拖拽的句柄,然后再给document添加onmousemove、onmouseup事件。onmousemove里是主要的逻辑处理的事件,先根据event事件获取鼠标位置,然后设置拖拽模块的top和left值,最后使用window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty()来取消拖拽过程中选择文本。

二、计算坐标位置

在拖拽模块过程还需要判断元素的坐标位置,因为拖动的模块只能放在指定的几个区域内,所以就需要动态判断是否在指定区域内容,在区域内的那个模块前,这些都需要根据元素的坐标来判断。先判断是否区域,区域栏为树直排列的容器,因此,只需要判断当前鼠标x坐标>=区域x坐标,并且鼠标x坐标<=区域x坐标+区域宽度即可。同理,确定区域后,判断模块是根据当前鼠标y坐标>=模块y坐标,并且鼠标y坐标<=模块y坐标+模块高度,相当于判断鼠标是否在某个元素上,依此可以定位当前拖放元素的区域模块位置,并insertBefore插入一个空元素顶位,再在onmouseup事件里把顶位的空元素替换为当前拖拽的元素,清空拖动时设置的position等样式。在拖放过程中,冒似在IE里计算还有点问题,有时候发现计算出来的位置不正确。另外还发现一个bug,在拖拽时如果用滑轮滚动页面,拖动的元素会滑落在鼠标位置,导致隔空拖动,因为拉滚动条的时候并不会触发onmousemove事件,去看了下iGoogle的首页,发现也存在这个问题,我想可能需要添加window.onscoll事件监视才能解决了。

三、保存拖拽后位置

拖拽完成onmouseup事件处理相对简单,因为在onmousemove事件中已确认拖动模块的位置了即上面所说的顶位的空元素,此时只需要replaceChild为拖拽的模块,但还有一个重要的步骤,那就是前台与后台交互,把当前客户端拖拽后的模块位置状态保存起来,或是写入进数据库。这可能就是一个比较复杂的过程了,因为这干系到数据库表存放结构等,我这里的模块表存放字段有模块ID、区域ID、排序号等,所以客户端保存的时候至少要能获取这些信息,这里我在与后台动态输出模块时就有一个约定,那就是每个模块和区域的DIV里的id或class都包含这些信息,以便客户端能用js方便取到,至于排序则是遍历模块时可自动生成一个从1开始的序号,之后在是把这些信息传递到服务端保存,发送Ajax请求这里就不罗嗦了,使用iframe也行。不过我这里两种方法都没有用,因为用户登陆进后台也可以设置所有模块的栏位和排序,前台我暂只是用Cookie来临时保存所有模块的栏位和排序,不过以后要能在前台拖拽保存所有模块的栏位和排序也很简单了,加个动态页面响应Ajax请求保存所有模块的栏位和排序写入数据库即可。

重要修复:使用添加mousewheel滚动鼠标滑轮事件修正隔空拖拽问题,但还需正确的计算出每次鼠标滑轮的距离。(2010-4-3 17:25)

事例:Drag.html

源码:(Drag.js下载)

Drag.js
标签:JavaScript 拖拽,博客个性化
  • posted@ 2010-03-21 00:07
  • update@ 2010-04-03 17:47:58
  • 阅读(13091)
  • 评论(8)

相关文章

评论
1楼 文夕 2010-03-21 18:47:08
很炫啊。不过你这最近打开速度有些慢了~
回复:是吗,难道是加了dict.hjenglish.com取词的脚本?(2010-03-22 09:19:25)
2楼 applezqp 2010-03-28 12:51:09
呃,比我做的建行的拖拽功能好啊,建行拖拽功能不知道后来有没有实现。
回复:说不上好吧,需求也都不一样,建行那个我就不知道了,不去建行工作都快2个月了,也不再过问建行事。(2010-03-28 19:02:03)
3楼 crs811 2010-03-29 23:00:29
你好,我正在学习用asp.net做页面定制作,有幸看到你的文章,觉得效果很不错啊,不过,只有Drag.js还不是完整的一个小例子,没法运行。
能否给我发个有几个简单asp.net页面的完整例子呢,谢谢啦

crs811@qq.com
回复:你是要js的拖拽效果还是要能保存在数据库内的页面模块位置?(2010-03-30 22:48:35)
4楼 crs811 2010-04-01 09:00:42
主要是js的拖拽效果(拖后的位置一般保存在本地cookie中),也可以保存在数据库中么?
若方便,能否将保存数据库的过程也顺便说一下呢,谢谢
回复:是的,那我这个周未有时间就把demo发送到你的邮箱里面去,欢迎交流。(2010-04-01 23:17:59)
5楼 zhoulong8513 2010-05-31 09:40:31
你好,能将拖拽保存到数据库的Demo给我一份吗?我的邮箱:274549431@qq.com
谢谢!
回复:没有Demo版哦~只提供思路。(2010-05-31 10:56:23)
6楼 seankerdy 2010-06-29 14:44:58
拖拽效果怎么保存在数据库内的页面模块位置能给个例子吗?不胜感激,谢谢 mail:sean_kerdy@hotmail.com
7楼 shuifeng 2010-08-23 23:45:31
能给我发个保存在数据库内的demo或是思路吗
email:liulei051610613@126.com
谢谢啦
回复:思路在文章里已经说了。(2010-08-25 09:16:50)
8楼 zhoucheng 2010-08-24 19:35:16
龙兄,我把里面源码的div的排列方式改变了一下。.container .column {}中的float去掉。3个div依次往下排。 问题在这里,Column2,column1无法拖到column3里面。 怎样改js +qq 35332796 老乡帮老乡
回复:你的意思是把3个div.column做成通栏?这个应该是CSS样式的问题,不过拖拽时也需要计算div坐标,你是不能拖拽还是只是不能拖拽到其他div.column内?(2010-08-25 09:25:03)
发表评论
*必填
回复通知我
*必填