接上一次日志哈,这一次用原来写的datalist实现了简单应用,模拟igoogle。
做的过程中发现代码很多问题,主要是流程上的问题。
主要是自己层次不够,明明已经感到这样那样的问题,都能说出来就是不知道怎么改。主要问题:
1 初始化时候参照其他jquery框架,应该达到配置最小化,却怎么都做不好
2 现在控件必须提供数据源datalist与模板template,数据源还好说,但是模板的写法真的太坑爹,现在是放在数据库里面了
以后怎么做还说不清哦
3 与.net中datalist一致,不论datalist还是item都会生成多余的标签,这里是生成的div,看上去很是别扭
4 最大问题还是,混乱!!!就像这篇文章一样,js控制力不同于服务器语言,所有整个做起来,不论事件绑定
还是其他什么定义都感觉有点混乱,流程不清,这是我主要应该改进的地方。
主要流程:
1 加载小工具模板:现在先一次性加载,以后用到一个保存一个作为全局参数
2 加载该用户的所有小工具:现在先一次性加载,以后先加载第一页,
根据页索引判断加载
3 根据用户小工具数据,初始化所有小工具外框
由于数据以及模板已经取出,此时加载速度应该非常快,左中右一次加载
**此处注意,虽说小工具外框一样,但是新增的小工具可能会在外框加载结束后再修饰外框
比如,weibo、top.....,此数据存于小工具定制列(CustomData)
4 此时进行数据异步加载,
***数据可以统一加载,但是此处先加载所有小工具每列前两名数据
在根据后台用户干预加载那些大数据小工具,加载结束后,当用户滑动鼠标便进行以下
控件加载,每次控件加载数量可配置化
5 所有控件加载结束,已加载结束控件,可能会根据后台配置要求动态刷新数据
此处需要做轮询
6 控件加载结束后,开始做控件事件绑定
***注意粒度尽量小,不要和其他模块相互影响
首页效果图:
此处点击都会触发事件,一个是异步加载选项卡数据,一个是展开摘要:
也可以延后加载,比如:开始只加载前三个模块,鼠标滑动后,再加载后面的模块:
一下是,初始化后鼠标滑动前与鼠标滑动后的效果:
分屏、分页效果
点击上面1,2,3肯定会指向不同也了,其实现在用户是我,若是用户换了也会有所不同
下面是第二页和第三页
拖动排序也实现了,之前想自己写一个拖动插件,拖动时实现了却发现插件非常困难,
局限于自己的层次,就直接用的jquery ui的拖动
下面是拖动排序的展示,保存到数据库的,最后一张是刷新后重新排序的图:
点击最大化,并实现鼠标滚动到最下边重新加载数据(滚动分页嘛):
数据库简要设计,因为我没有安装数据库,所有优点不好弄:
设计缘由:由于今后可能不止五页,做到页数动态化
NO. |
字段名称 |
说明 |
1 |
uuid |
页面唯一标识 |
2 |
pageSort |
页面排序 |
3 |
pageName |
页面标题,默认1,2,3,4,5 |
4 |
pageDes |
页面描述,鼠标划上显示 |
5 |
|
|
NO. |
字段名称 |
说明 |
1 |
uuid |
页面唯一标识 |
2 |
templateKey |
标识 |
3 |
templateValue |
模板内容 |
4 |
des |
描述 |
5 |
|
|
小工具参数化,可变参数,具有验证性
NO. |
字段名称 |
说明 |
1 |
uuid |
小模块唯一标识 |
|
author |
小工具作者 |
2 |
alias |
模块前台标识名,对应category |
3 |
title |
小模块名称 |
4 |
dataSourceUrl |
数据源链接地址 |
5 |
pageId |
当前小工具属于第几屏,对应pages 的 uuid |
6 |
colId |
当前小工具属于第几列(暂分为1,2,3列) |
7 |
sort |
当前小工具顺序 |
8 |
templateId |
当前小工具对应模板,对应templates表 |
9 |
type |
当前小工具类型,frame或者json |
|
|
|
|
|
|
参数化后
NO. |
字段名称 |
说明 |
1 |
uuid |
小模块唯一标识 |
2 |
alias |
模块前台标识名,对应category |
3 |
title |
小模块名称 |
5 |
pageId |
当前小工具属于第几屏,对应pages 的 uuid |
6 |
colId |
当前小工具属于第几列(暂分为1,2,3列) |
7 |
sort |
当前小工具顺序 |
8 |
moduleParameter |
当前小工具具有的参数对象,现在采用json对象 采用键值对,加一个描述字段 {dataSourceUrl:XXXXX ,templateId:XXXX , type:XXX } 以上是基本属性,应该是字段吧….. |
灰色部分可以不用,直接默认在第一页第一排,默认最大 其默认值在用户小工具表中体现出来
|
NO. |
字段名称 |
说明 |
1 |
uuid |
小模块唯一标识 |
2 |
moduleKey |
|
3 |
moduleValue |
|
4 |
des |
|
5 |
isTransfer |
是否形成json传向前台 |
|
|
|
|
userModules
NO. |
字段名称 |
说明 |
1 |
uuid |
小模块唯一标识 |
2 |
userId |
用户id |
3 |
moduleId |
小工具Id |
|
userPrefers |
用户偏好设置 |
|
|
|
|
NO. |
字段名称 |
说明 |
1 |
uuid |
小模块唯一标识 |
2 |
preKey |
|
3 |
preValue |
|
4 |
des |
|
5 |
isTransfer |
是否形成json传向前台 |
|
|
|
|
核心实现代码如下:原来的datalist的代码我就不发了:
1
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
|
/// <reference path="../scripts/jquery-1.4.1.js" />
/// <reference path="dataList.js" />
/// <reference path="itemTemplate.js" />
//全局变量设置
var
templateWarehouse = {};
var
userModuleData = {};
var
leftColModule, centerColModule, rightColModule;
//首页模块加载参数
var
moduleLoadPara = {};
moduleLoadPara.index = 1;
//初始化加载索引
moduleLoadPara.num = 1;
//每次索引加载个数
moduleLoadPara.isLoad =
false
;
//当前是否在加载
//---------------------------------------------------------------------------
//第一步,加载模板
function
loadTemplate() {
$.ajax({
type:
"post"
,
url:
"../Ajax.aspx?sql=select * from templates "
,
type:
"json"
,
async:
false
,
success:
function
(data) {
$.each(data,
function
(i, item) {
templateWarehouse[item.templateKey] = item.templateValue;
});
}
});
}
//加载所有模板数据
function
loadModuleData(isAsync) {
var
_isAsync =
false
;
if
(isAsync)
_isAsync = isAsync;
var
userId =
"wl"
;
$.ajax({
type:
"post"
,
url:
"../Ajax.aspx?sql=select * from modules m ,userModules um where 1=1 and m.uuid=um.moduleId and um.userId='"
+ userId +
"'"
,
type:
"json"
,
async: _isAsync,
success:
function
(data) {
userModuleData[
"1"
] = [];
userModuleData[
"2"
] = [];
userModuleData[
"3"
] = [];
userModuleData[
"4"
] = [];
userModuleData[
"5"
] = [];
$.each(data,
function
(i, item) {
var
userPrefs = item.userPrefers;
if
(
typeof
(userPrefs) ==
"string"
) {
userPrefs = eval(
"("
+ userPrefs +
")"
); ;
}
item.userPrefers = userPrefs;
userModuleData[userPrefs.pageId].push(item);
});
}
});
}
//---------------------------------------------------------------------------
//根据用户id,按要求加载其模板
function
initModuleFrame(_pageId) {
var
pageId = 1;
if
(_pageId)
pageId = _pageId;
var
$div = $(
"#main"
);
$div.html(
""
);
loadColModule(pageId,
"left_conter"
);
loadColModule(pageId,
"cell_conter"
);
loadColModule(pageId,
"right_conter"
);
}
function
loadColModule(pageId, colId) {
var
$div = $(
"#main"
);
var
colData = getColData(pageId, colId);
var
colModule =
new
dataList(colId,
"commonFrame"
);
colModule.itemElementEvent = {
_sortItems: {
elementKey:
".content"
,
eventType:
"ready"
,
funcName: itemSort
},
_itemMaxClick: {
elementKey:
".btn_close"
,
eventType:
"click"
,
funcName: itemMaxClick
},
_itemMenuClick: {
elementKey:
".btn_more"
,
eventType:
"click"
,
funcName: itemMenuClick
}
};
colModule.className =
"column"
;
colModule.dataSource = colData;
colModule.dataBind($div);
if
(colId ==
"left_conter"
) {
leftColModule = colModule;
}
else
if
(colId ==
"cell_conter"
) {
centerColModule = colModule;
}
else
if
(colId ==
"right_conter"
) {
rightColModule = colModule;
}
}
function
getColData(pageId, colId) {
var
tempData = [];
var
data = userModuleData[pageId];
$.each(data,
function
(i, item) {
var
userPrefs = item.userPrefers;
if
(userPrefs.pageId == pageId && userPrefs.colId == colId) {
tempData.push(item);
}
});
tempData = tempData.sort(
function
(a, b) {
if
(a.userPrefers.sort < b.userPrefers.sort) {
return
-1;
}
if
(a.userPrefers.sort > b.userPrefers.sort) {
return
1;
}
return
0;
});
return
tempData;
}
//---------------------------------------------------------------------------
function
loadItemMax(sender, param, e, isClick) {
var
dataSourceUrl = param.dataSourceUrl;
var
templateId = param.templateId +
"-max"
;
var
title = param.title;
var
type = param.type;
var
id = sender.id;
var
$max = $(
"#list-max"
);
var
$main = $(
"#main"
);
var
$content = $(
"#list-max #list-max-content"
);
if
(isClick)
$content.html(
""
);
var
$title = $(
"#list-max #list-max-title"
);
var
$itemList = $(
"#list-max .list"
);
var
$listMore = $(
"#list-max #list-max-more"
);
var
isLoad = $listMore.val();
$listMore.val(
"-1"
);
var
len = $itemList.length;
var
_index = len + 1;
var
itemStr =
'<fieldset class="list"><legend><span class="index">page'
+ _index.toString() +
'</span></legend><div id="itemContent'
+ _index.toString() +
'" >数据加载中......</div></fieldset>'
;
$main.hide();
$max.show();
$title.html(title);
if
(type && type ==
"s-html"
) {
var
html =
'<iframe scrolling="no" frameborder="0" src="'
+ dataSourceUrl +
'"></iframe>'
;
$content.html(html);
}
else
{
$content.append(itemStr);
$.ajax({
type:
"post"
,
url: dataSourceUrl,
type:
"json"
,
async:
true
,
success:
function
(data) {
var
$itemContent = $(
"#list-max #itemContent"
+ _index.toString() +
""
);
$itemContent.html(
""
);
var
dataNews = data;
if
(
typeof
(dataNews) ==
"string"
) {
dataNews = eval(
"("
+ data +
")"
);
}
var
listMax =
new
dataList(id +
"_max"
, templateId);
listMax.dataSource = dataNews;
listMax.dataBind($itemContent);
$listMore.val(
"1"
);
}
});
}
}
//小工具事件定义,小工具事件处理函数
function
itemMaxClick() {
var
sender =
this
;
var
param = arguments[0];
var
e = arguments[1];
loadItemMax(sender, param, e,
true
);
$(document).unbind(
"scroll"
);
$(document).bind(
"scroll"
,
function
(e) {
var
windowHeight = $(window).height();
var
windowScrollTop = $(window).scrollTop();
var
documentHeight = $(document).height();
var
$listMore = $(
"#list-max #list-max-more"
);
var
isLoad = $listMore.val();
if
((windowHeight + windowScrollTop + 100) > documentHeight && isLoad ==
"1"
) {
loadItemMax(sender, param, e);
}
});
}
//小工具事件定义,点击出现菜单栏
function
itemMenuClick() {
var
sender =
this
;
var
param = arguments[0];
var
e = arguments[1];
// alert("弹出菜单" + "--" + param.uuid1 + "--" + sender.id)
var
uuid = param.uuid1;
var
popupMenu = $(
"#popupMenu"
);
}
//定义小工具会用到的工具类
var
moduleInitTool = {};
//适用于不同模板,若是有新模板,只需根据规范添加函数即可,工厂方法
moduleInitTool.jsonModule =
function
(sender, param, e) {
var
templateId = param.templateId;
var
id = param.uuid;
var
dataSourceUrl = param.dataSourceUrl;
var
$itemContent = sender.getItemElement(
".content"
);
if
(dataSourceUrl) {
moduleLoadPara.isLoad =
false
;
$.ajax({
type:
"post"
,
url: dataSourceUrl,
type:
"json"
,
async:
true
,
success:
function
(data) {
$itemContent.html(
""
);
var
dataNews = data;
if
(
typeof
(dataNews) ==
"string"
) {
dataNews = eval(
"("
+ data +
")"
); ;
}
var
listItemNews =
new
dataList(id +
"_news"
, templateId);
listItemNews.itemElementEvent = {
clickTitle: {
elementKey:
".span2"
,
eventType:
"click"
,
funcName: titleClick
}
}
listItemNews.dataSource = dataNews;
listItemNews.dataBind($itemContent);
// if (sender.id == "right_conter_id_1")
// setInterval(function () {
// alert("重新加载" + sender.id);
// }, 5000);
moduleLoadPara.isLoad =
true
;
}
});
}
}
moduleInitTool.htmlModule =
function
(sender, param, e) {
var
id = param.uuid;
var
dataSourceUrl = param.dataSourceUrl;
var
$itemContent = sender.getItemElement(
".content"
);
if
(dataSourceUrl) {
var
html =
'<iframe scrolling="no" frameborder="0" src="'
+ dataSourceUrl +
'"></iframe>'
;
$itemContent.html(html);
}
}
moduleInitTool.weiboModule =
function
(sender, param, e) {
}
moduleInitTool.labelModule =
function
(sender, param, e) {
var
templateId = param.templateId;
var
id = param.uuid;
var
dataSourceUrl = param.dataSourceUrl;
var
customData = param.customData;
var
modulePara = param.moduleParameter;
if
(
typeof
(modulePara) ==
"string"
) {
modulePara = eval(
"("
+ modulePara +
")"
); ;
}
templateWarehouse[
"labelHeadTemplate"
] = modulePara.labelHeadTemplate;
var
$itemContent = sender.getItemElement(
".content"
);
$itemContent.html(customData);
var
lableHead = sender.getItemElement(
"#labelHead"
);
moduleLoadPara.isLoad =
false
;
$.getJSON(
"../Ajax.aspx?sql=select * from bigType"
,
function
(data) {
var
labelHeadList =
new
dataList(id +
"_head"
,
"labelHeadTemplate"
);
labelHeadList.dataSource = data;
labelHeadList.className =
"labelHead"
;
labelHeadList.itemEvent = {
_labelHeadClick: {
eventType:
"click"
,
funcName:
function
() {
var
_sender =
this
;
var
_param = arguments[0];
var
_e = arguments[1];
var
labelBody = sender.getItemElement(
"#labelBody"
);
var
bigTypeId = _param.id;
var
url =
"../Ajax.aspx?sql=select * from smallType where bigTypeId="
+ bigTypeId +
""
;
$.getJSON(url,
function
(_data) {
labelBody.html(
""
);
var
labelBodyList =
new
dataList(bigTypeId +
"_head"
, templateId);
labelBodyList.dataSource = _data;
labelBodyList.dataBind(labelBody);
});
}
}
};
labelHeadList.dataBind(lableHead);
moduleLoadPara.isLoad =
true
;
});
}
function
elementDatabind(s) {
var
sender =
this
;
var
param = arguments[0];
var
e = arguments[1];
var
type = param.type;
if
(type && type.length > 2) {
var
_funcName = type.substring(2) +
"Module"
;
// eval(_funcName);//此方法不能异步调用
var
funcName = moduleInitTool[_funcName];
if
(funcName &&
typeof
(funcName) ==
"function"
) {
funcName(sender, param, e);
}
}
}
function
titleClick() {
var
sender =
this
;
var
param = arguments[0];
var
e = arguments[1];
var
summary = sender.getItemElement(
".summary"
);
var
isShow = summary.css(
"display"
);
if
(isShow ==
"none"
) {
summary.show();
}
else
{
summary.hide();
}
}
//用于小工具排序
function
itemSort() {
var
sender =
this
;
var
html = sender.htmlElement;
// alert(html.offset().top);
$(
".column"
).sortable({
connectWith:
".column"
,
cursor:
'move'
,
opacity: 0.7,
handle:
" .title"
,
stop: sortItemsAjax
});
}
//向后台发送数据
function
sortItemsAjax() {
submitSortData(
"left_conter"
);
submitSortData(
"cell_conter"
);
submitSortData(
"right_conter"
);
}
function
submitSortData(colId) {
var
parent = $(
"#"
+ colId);
var
$children = parent.children();
$children.each(
function
(i, item) {
var
id = item.id;
var
itemId =
"#"
+ id +
" #itemId"
;
var
$uuid = $(itemId);
var
uuid = $uuid.html();
var
userPrefers = item.userPrefers;
$.ajax({
type:
"post"
,
url:
"../Ajax.aspx?sort="
+ i +
"&colId="
+ colId +
"&id="
+ uuid +
"&no=no"
,
type:
"json"
,
async:
true
,
success:
function
(data) {
}
});
});
}
//---------------------------------------------------------------------------
//总体外部流程,外部方法
function
mainProcess() {
var
$max = $(
"#list-max"
);
var
$main = $(
"#main"
);
var
$btn_Narrow = $(
"#list-max .btn_Narrow"
);
$btn_Narrow.unbind(
"click"
);
$btn_Narrow.bind(
"click"
,
function
() {
if
($max.css(
"display"
) ==
"none"
) {
$main.hide();
$max.show();
}
else
{
$(document).unbind(
"scroll"
);
var
$listMore = $(
"#list-max #list-max-more"
);
$listMore.val(
"-1"
);
$main.show();
$max.hide();
}
});
}
function
LaterEvent() {
var
commomEvent = {
_loadItems: {
elementKey:
".content"
,
eventType:
"ready"
,
funcName: elementDatabind
}
};
var
num = (moduleLoadPara.index) * (moduleLoadPara.num);
for
(
var
i = 0; i < num; i++) {
if
(leftColModule.items[i])
leftColModule.items[i].eventAdd(commomEvent);
if
(centerColModule.items[i])
centerColModule.items[i].eventAdd(commomEvent);
if
(rightColModule.items[i])
rightColModule.items[i].eventAdd(commomEvent);
}
moduleLoadPara.index++;
// leftColModule.eventAdd(commomEvent);
// centerColModule.eventAdd(commomEvent);
// rightColModule.eventAdd(commomEvent);
}
function
delayLoad() {
var
commomEvent = {
_loadItems: {
elementKey:
".content"
,
eventType:
"ready"
,
funcName: elementDatabind
}
};
$(document).unbind(
"scroll"
);
$(document).bind(
"scroll"
,
function
(e) {
if
(moduleLoadPara.isLoad) {
var
num = (moduleLoadPara.index) * (moduleLoadPara.num);
var
oldNum = (moduleLoadPara.index-1) * (moduleLoadPara.num);
for
(
var
i = oldNum; i < num; i++) {
if
(leftColModule.items[i])
leftColModule.items[i].eventAdd(commomEvent);
if
(centerColModule.items[i])
centerColModule.items[i].eventAdd(commomEvent);
if
(rightColModule.items[i])
rightColModule.items[i].eventAdd(commomEvent);
}
moduleLoadPara.index++;
}
});
}
function
pageClick() {
for
(
var
i = 1; i <= 5; i++) {
var
page = $(
"#pageIndex"
+ i.toString());
page.unbind(
"click"
);
page.bind(
"click"
,
function
(e) {
var
_p = $(
this
);
initModuleFrame(_p.text());
LaterEvent();
var
$max = $(
"#list-max"
);
var
$main = $(
"#main"
);
$main.show();
$max.hide();
$(document).unbind(
"scroll"
);
var
$listMore = $(
"#list-max #list-max-more"
);
$listMore.val(
"-1"
);
//置顶
$(
'html,body'
).animate({ scrollTop:
'0px'
}, 800);
// A:return false --->In event handler ,prevents default behavior and event bubbing 。
//return false 在事件的处理中,可以阻止默认事件和冒泡事件。
//B:event.preventDefault()---> In event handler ,prevent default event (allows bubbling) 。
//event.preventDefault()在事件的处理中,可以阻止默认事件但是允许冒泡事件的发生。
//C:event.stopPropagation()---> In event handler ,prevent bubbling (allows default behavior).
//event.stopPropagation()在事件的处理中,可以阻止冒泡但是允许默认事件的发生。
e.stopPropagation();
return
false
;
});
}
}
function
pageLoad() {
mainProcess();
loadTemplate();
loadModuleData();
initModuleFrame();
LaterEvent();
pageClick();
//置顶
$(
'html,body'
).animate({ scrollTop:
'0px'
}, 800);
delayLoad();
//5分钟更新一次模块数据
var
updateModuleData = setInterval(
"loadModuleData(true)"
, 50000);
}
//---------------------------------------------------------------------------
|
代码太多不做说明了,以后肯定会封装,
就现在看来整个应用感觉问题不少,实际用处不大吧。
后面点代码整理后再一并发出吧,如果有需要的话。