【jquery仿dataList】应用之——模仿igoogle【定制化、拖动排序,最大化、分屏】

接上一次日志哈,这一次用原来写的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);

}
//---------------------------------------------------------------------------

 

  

 


代码太多不做说明了,以后肯定会封装,

就现在看来整个应用感觉问题不少,实际用处不大吧。

后面点代码整理后再一并发出吧,如果有需要的话。

 

 

 

 

 

 

 

 

 

 

posted on 2012-03-07 22:34  叶小钗  阅读(4318)  评论(27编辑  收藏  举报