接上一次日志哈,這一次用原來寫的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 |
|
|
小工具模板表 templates(基本字段)
| NO. |
字段名稱 |
說明 |
| 1 |
uuid |
頁面唯一標識 |
| 2 |
templateKey |
標識 |
| 3 |
templateValue |
模板內容 |
| 4 |
des |
描述 |
| 5 |
|
|
小工具表 modules(基本字段)
小工具參數化,可變參數,具有驗證性
| 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 } 以上是基本屬性,應該是字段吧….. |
| 灰色部分可以不用,直接默認在第一頁第一排,默認最大 其默認值在用戶小工具表中體現出來
|
||
小工具參數moduleParameter
| NO. |
字段名稱 |
說明 |
| 1 |
uuid |
小模塊唯一標識 |
| 2 |
moduleKey |
|
| 3 |
moduleValue |
|
| 4 |
des |
|
| 5 |
isTransfer |
是否形成json傳向前台 |
|
|
|
|
|
|
||
用戶小工具設置表(用戶參數設置)
userModules
| NO. |
字段名稱 |
說明 |
| 1 |
uuid |
小模塊唯一標識 |
| 2 |
userId |
用戶id |
| 3 |
moduleId |
小工具Id |
|
|
userPrefers |
用戶偏好設置 |
|
|
|
|
|
|
||
用戶小工具參數偏好userModulePre
| NO. |
字段名稱 |
說明 |
| 1 |
uuid |
小模塊唯一標識 |
| 2 |
preKey |
|
| 3 |
preValue |
|
| 4 |
des |
|
| 5 |
isTransfer |
是否形成json傳向前台 |
|
|
|
|
|
|
||
最終表設計



核心實現代碼如下:原來的datalist的代碼我就不發了:
/// <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() + '" style=" margin:10px 10px 10px 10px;">數據加載中......</div></fieldset>';
$main.hide();
$max.show();
$title.html(title);
if (type && type == "s-html") {
var html = '<iframe scrolling="no" style="width:100%;height:200px" 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" style="width:100%;height:200px" 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);
}
//---------------------------------------------------------------------------
代碼太多不做說明了,以后肯定會封裝,
就現在看來整個應用感覺問題不少,實際用處不大吧。
后面點代碼整理后再一並發出吧,如果有需要的話。
