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/>
97
new order is:<div id="order" />
98
</div>
99
100
101
</body>
102
</html>

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

js代码:
主要是两个对象,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);
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代码:

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义