jquery应用-实现博客个性主页布局拖拽功能

接上一篇:js应用-实现博客个性主页布局拖拽功能 已改造成JQuery插件形式,并新增了一些效果,由于jquery强大的DOM选择器和一些封装的效果,使得代码更加清晰和精简。

引用上一篇:Jquery的Interface elements for jQuery里面的拖拽布局存在一些bug,效率也比较低,GoogleUI google_drag.js有些乱,不是很容易理解,Discuz!NT Space代码满天飞,所以自己参考GoogleUI的思想,简化和优化了一些操作代码,实现了博客系统基本的拖拽布局的效果,暂时未考虑其他浏览器的兼容性问题。下一步准备改造成Jquery的插件形式,并增加一些渐隐渐现和动画效果,并逐步实现一些ajax的添加删除操作,嵌入基于JQuery的音乐播放器,图片浏览器,文本编辑器。

预览体验:

html代码:
下面的可拖拽模块的mid为其在数据库中的id号;
<div style="display:inline" mid="|"><div></div></div>
每td列最后都有一个,并隐藏起来,用来可以推拽元素到此隐藏元素的前面,或者某td列本来没有元素,
也可以拖拽到此列上面:

1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2<html xmlns="http://www.w3.org/1999/xhtml">
  3<head>
  4<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
  5<title>博客推拽布局示例</title>
  6<link href="main2.css" rel="stylesheet" type="text/css" />
  7<script src="jquery.js" language="javascript"></script>
  8<script src="dimensions.js" language="javascript"></script>
  9<script src="drag2.js" language="javascript"></script>
10<script>
11    $(document).ready(
12    function () {
13        //初始化推拽布局
14        $("#main").DragLayout({
15            onEnd: function(modules) {       
16            var order = "";
17            modules.each(function(){
18                order += $(this).attr("mid") + " ";
19            });
20           
21            $("#order").text(order);
22            //或者进行ajax提交
23            }   
24        });
25        //展开收缩效果
26        $(".control .control1").click(function(){
27            var control = $(this);
28            control.parent().next().slideToggle("slow", function(){
29                  control.text()=="+expend"?control.text("-expend"):control.text("+expend");
30            });
31        });
32        //删除模块
33        $(".control .control2").click(function(){
34            var control = $(this).parent().parent();
35            control.fadeTo(300, 0.5);
36            setTimeout( function() {control.remove()}, 400);
37        });
38        //添加模块
39        $("#add").click(function(){
40            var modules = $("#main .module")
41            var lastModule = $(modules[modules.length-1]);
42            var newModule = lastModule.clone();
43            newModule.children(".title").text("new module");
44            newModule.children(".content").text("new content");
45            newModule.attr("mid", "newid");
46            newModule.insertAfter(lastModule);
47            newModule.fadeIn(300, 0.5);
48           
49        });
50    }
51    );
52       
53
54</script>
55</head>
56
57<body>
58<div id="modules">
59    <table id="main" cellspacing="10" border="0" width="98%" align="center">
60        <tr>
61            <td id="c1">
62                <div class="module" mid="1">
63                    <div class="title">title1</div>
64                    <div class="control"><span class="control1">+expend</span> <span class="control2">×delete</span></div>
65                    <div class="content">content1</div>
66                </div>               
67                <div class="module" mid="4">
68                    <div class="title">title4</div>
69                    <div class="control"><span class="control1">+expend</span> <span class="control2">×delete</span></div>
70                    <div class="content">content4</div>
71                </div>
72                <div style="display:inline" mid="|"><div></div></div>
73            </td>
74            <td id="c2" >
75                <div class="module" mid="2">
76                    <div class="title">title2</div>
77                    <div class="control"><span class="control1">+expend</span> <span class="control2">×delete</span></div>
78                    <div class="content">content2</div>
79                </div>
80                <div style="display:inline" mid="|"><div></div></div>
81            </td>
82            <td id="c3" >
83                <div class="module" mid="3">
84                    <div class="title">title3</div>
85                    <div class="control"><span class="control1">+expend</span> <span class="control2">×delete</span></div>
86                    <div class="content">content3</div>
87                </div>
88                <div style="display:inline" mid="|"><div></div></div>
89            </td>
90        </tr>
91    </table>
92    <div id="ghost"></div>
93   
94</div>
95<div id="other">
96<input type="button" id="add" value="+ add a module" /><br/>
97new order is:<div id="order" />
98</div>
99
100
101</body>
102</html>


s代码:
主要是两个对象,dragLayout对象(table元素) 包含 dragModule对象(可拖拽的元素)

1 (function($) {
  2
  3 $.fn.DragLayout = function(obj) {
  4    //得到所有可拖拽的模块
  5    this.getModules = function() {
  6        return this.find("div[@mid]");
  7    };
  8    //得到所有可推拽的模块的位置offset,在后面判断最近元素时候起作用
  9    this.getModulesPostion = function() {
10        var i = 0;   
11        var modulesPostion = {};
12        this.modules.each(function() {       
13            modulesPostion[i] = $(this).offset();
14            i++;
15                   
16        });
17       
18        return modulesPostion;       
19    };
20    //初始化模块和模块位置
21    this.init = function() {
22        this.modules = this.getModules();
23        this.modulesPostion = this.getModulesPostion();
24    };
25    //回调函数,完成事件
26    this.onEnd = obj.onEnd;
27    //初始化
28    this.init();
29    var _self = this;
30    //循环创建dragModule对象           
31    return this.modules.each(function() {       
32        new dragModule(this, _self);               
33    });
34
35 }
36
37
38 var dragModule = function(ele, parent) {
39    //对应的div拖拽元素
40    this.ele = $(ele);
41    //父对象,即dragLayout对象
42    this.parent = parent;
43    //标题栏,用于鼠标拖拽
44    this.title = $(this.ele.children()[0]);
45
46    //记录原先的邻居节点,用来对比是否被移动到新的位置
47    this.origNextSibling = this.ele.next();
48    this.init.apply(this);
49   
50 };
51
52 dragModule.prototype = {
53   
54    init : function() { with(this) {
55        var _self = this;
56        // 获取移动的时候那个灰色的虚线框
57        ghostLayer = $("#ghost");
58        //鼠标按下时推拽开始       
59        title.mousedown(function (event) {
60              _self.dragStart(event);
61        });
62       
63        title.hover(function () {
64              title.fadeIn("slow");
65        },
66            function () {
67               
68            }
69        );
70   
71        title.css("cursor","move");
72
73    }
74    },
75   
76    //开始拖拽设定一些位置信息
77    dragStart: function (evt) { with(this) {
78        var _self = this;
79        evt  = evt?evt:window.event;
80
81        //鼠标相对于浏览器的位置减去元素的位置
82        //得出鼠标相对于元素的相对位置,便于拖拽时计算元素的新位置
83        x = evt.clientX - ele.offset().left;
84        y = evt.clientY - ele.offset().top;
85       
86        //绝对位置,top和left就起作用了,就可以推拽了
87        ele.css("position","absolute").css("zIndex","100").css("top",ele.offset().top).css("left",ele.offset().left);
88       
89        //将那个灰框设定得与正在拖动的对象一样高
90        ghostLayer.css("position","relative").css("display","block").css("height",ele.innerHeight()).css("width",ele.innerWidth());
91       
92        //把灰框放到这个对象原先的位置上
93        ghostLayer.insertBefore(ele.next());
94
95        //鼠标按下再移动的事件,鼠标移动,元素也跟着走
96        $(document).mousemove(function (event) { _self.drag(event);});
97        //释放鼠标的事件
98        $(document).mouseup(function (event) { _self.dragEnd(event);});
99    }
100    },
101   
102    //拖拽时实现元素跟鼠标走
103    drag: function (evt) { with(this) {
104
105        var _self = this;
106        evt  = evt?evt:window.event;
107        //计算元素的新的位置
108        ele.css("filter","alpha(opacity=70)").css("opacity","0.7").css("left",evt.clientX - x).css("top",evt.clientY - y);
109   
110        //被拖拽到的新的元素(当然也可以是原来那个)
111        var found = null;
112        //最大的距离
113          var max_distance = 10000;
114        // 遍历所有的可拖拽的element,寻找离当前鼠标坐标最近的那个可拖拽元素,以便前面插入
115        var distance = null;
116       
117        var i = 0;
118       
119        parent.modules.each(function() {
120            //利用勾股定理计算鼠标到遍历到的这个元素的距离
121            distance = Math.sqrt(Math.pow(evt.clientX - parent.modulesPostion[i].left,2) + Math.pow(evt.clientY - parent.modulesPostion[i].top, 2));           
122            i++;
123            //如果更小,记录下这个距离,并将它作为found
124            if (distance < max_distance) {
125                max_distance = distance;
126                found = $(this);
127            }
128        });
129
130       
131        //找到落脚点就先把灰框插进去,我们看到的那个灰框停靠的特效
132        if  (found != null && ghostLayer.next() != found) {
133           
134            ghostLayer.insertBefore(found);           
135        }       
136    }
137    },
138   
139    //鼠标释放时推拽完成
140    dragEnd: function (evt) { with(this) {
141        var _self = this;
142        evt  = evt?evt:window.event;
143        //卸载事件
144        $(document).unbind("mousemove");
145        $(document).unbind("mouseup");
146       
147       
148        //把拖拽时的position=absolute和相关的那些style都消除
149       
150        ele.css("position","relative").css("filter","alpha(opacity=100)").css("opacity","1").css("zIndex","").css("left","").css("top","");
151
152        //将灰框隐藏起来
153        ghostLayer.css("display", "none");       
154       
155       
156        //如果现在的邻居不是原来的邻居了后者邻居就是它本身
157        if (ghostLayer.next() != origNextSibling && ghostLayer.next() != this.ele) {
158            //把被拖拽的这个节点插到灰框的前面
159            ele.insertBefore(ghostLayer.next());
160
161            //从新初始化可推拽元素对象,可以设定它们的新位置,为下面的拖拽操作做准备
162            parent.init();
163
164            //回调函数,拖拽完成可对dragArray进行处理
165            parent.onEnd.call(this, parent.modules);
166           
167        }
168       
169        ghostLayer.insertAfter(parent);           
170    }
171    }
172 }
173
174
175
176 })(jQuery);


css代码:

1body {}{
2font-size:12px;
3}
4
5input {}{
6border:1px solid #ccc;
7background:#f5f5f5;
8}
9
10#main {}{
11TABLE-LAYOUT:fixed; border:1px solid #ccc;
12}
13
14#main td {}{
15VERTICAL-ALIGN: top; WIDTH: 32%
16}
17
18
19#other {}{
20margin:20px;
21}
22
23.module {}{
24width:100%;
25position:relative;
26border:1px solid #ccc;
27margin-bottom:10px;
28padding:0px;
29}
30
31.module .title {}{
32float:left;
33border-top:5px solid #ccc;
34background-color:#f5f5f5;
35font-size:13px;
36color:#990000;
37width:40%;
38}
39
40.module .control {}{
41float:left;
42color:#999;
43border-top:5px solid #ccc;
44background-color:#f5f5f5;
45width:60%;
46margin:0px;
47text-align:right;
48cursor:pointer;
49}
50
51.module .content {}{
52float:left;
53padding:5px;
54border:1px solid #f5f5f5;
55width:96%;
56}
57
58.block {}{
59width:1px; height:1px; position:relative; overflow:hidden;
60}
61
62#ghost {}{
63border:2px dashed #990000;
64position:absolute;
65display:none;
66top:0px;
67left:0px;
68margin-bottom:10px;
69}


原文出处:http://www.cnblogs.com/guozili/