JQuery数据绑定:①列表绑定(续)


其实挂MVC只在上一节有说道,我还是只写Jquery数据绑定吧。

  我不知道别人是否使用过我这种绑定方法,这是我想出来的。所以一个人的想法会不会被别人所接受那是别人的看法。我只是分享下自己的方法。

  当然,个人能力有限,愚昧的地方还望指出。

  首先 试想写这个方法或者说绑定一个列表时需要碰到哪些问题? 如何在这个方法里解决大多数列表的问题?

  Ⅰ、如何分页?

  Ⅱ、绑定的是Url请求还是Array?

  Ⅲ、列表加载后需要做什么处理?

  Ⅳ、其他的问题...

  我们把绑定Table的方法写成一个Jquery的插件。 用起来就舒服一些。 

  $("#lstTable").bindTable(....);

  Ⅰ、如何分页?

  但凡列表,都会有分页的问题。在我们这种绑定方法里分页无非是重新绑定列表,只不过请求的数据是后台给的另外一页的数据。

  那么,我们的分页只不过是把一些分页连接的点击事件变成绑定请求,类似

$(".pagelist a").click(function(){
    $("#lstTable").bindTable({pageIndex:xx});
});

  假如翻页我们写成一个$("#xx").Paper(...) 翻页后会如何记忆第一次请求传递的参数?  目前是把参数记忆在table的自定义属性里,而才callback则放在一个全局变量里。

  Ⅱ、绑定的是Url请求还是Array?

  绑定的数据源不一定是ajax请求,可能是ViewData、Model或其他自己整理好的Array,其实Url也是去获取Data,那就视绑定为已有数据而已

  已有的数据如何分页?这不和后台已分好页的数据冲突了吗? 确实有点冲突,这个.... 目前ajax数据的分页我们还是按后台来分页吧-_-

  Ⅲ、列表加载后需要做什么处理?
我们动态append to tBody的html内容是死的,里面的<a>、<input>可能没有自己的事件,除非里面已经写好了 onclick 。。 这样我们改动起来就失去了Jquery的事件绑定的优势。

  所以绑定数据后,我们需要处理所有列表共通的事件绑定,另外需要一个callback方法来处理特定的需求。

  Ⅳ、其他的问题...

  点击thead里的连接对数据排序如何处理?  翻页后前一页的已选中的checkbox如何记忆?其他还会发现... 好的方法是慢慢成熟演变的。

  以上的问题都是我在实际开发中不断碰到的总结。

  Jquery的插件的写法,随便找个插件我们就可以模仿的写下来。 类似$("##").FunctionName(..) 就是下面这种写法。

; (function($) {
   $.fn.FunctionName = function(...){};
})(jQuery);

  如果手打代码太累了-。-而且不能高亮,但是代码会比较干净。可是我还是选择了粘贴现在在用的代码(还没做到理想状态),如果把代码打成一个演变的过程可能更容易理解

  下面我们开始写bindTable这个扩展方法。

  Code

var callbackList = [];
$.fn.bindTable = function(args) {
    if (this.length == 0) {
        return this;
    }
    var id = this.attr("id");
    //定义需要的参数
    var url, pagesize, pageindex, data, ispage, callback, listName, isappend;
    //检查传递的参数
    switch (typeof (args)) {
        case "string": //只传url
            url = args;
            args = [];
            args.url = url;
            break;
        case "number": //只传pagesize
            pagesize = args;
            args = [];
            args.pagesize = pagesize;
            break;
        case "function"://只传callback
            callback = args;
            args = [];
            args.callback = callback;
            callbackList.id == undefined;
            break;
        case "undefined"://啥也没传
        default:
            args = args || "";
            break;
    }
    url = args.url || this.attr("datasource"); //绑定的数据源为url请求 datasource是table的一个自定义属性
    callback = args.callback || callbackList[id]; //绑定后的Function
    if (args.data == undefined && args.url == undefined && pageindex == 1) {
        dataList[id] = [];
    }
    data = args.data || dataList[id]; //绑定的数据源为已请求好的JsonData

    pageRequest = args.pageRequest || false; //是否为分页请求
    pagesize = args.pagesize || parseInt(this.attr("pagesize")) || Math.round(Math.round((window.screen.height - 500) / 26) / 5) * 5; //分页
    isappend = args.isappend || false; //是否把数据填充到现在的列表
    if (pageRequest) {
        pageindex = args.pageindex || 1;
    }
    else {
        pageindex = 1;
    }

    listName = args.list || "list";//请求的数据源的格式是Array还是Dictionary 例如{recourCount:xx,list:[]}

    ispage = args.ispage || this.attr("ispage");//是否分页

    if (url == undefined && data == undefined)//如果url请求和data都没有则不执行绑定
        return this;

    if (args.callback != undefined)//如果请求中有callback 清掉callbackList.id
        callbackList[id] = undefined;
    if (args.url != undefined)//如果是url请求 清掉data和dataList.id
    {
        data = undefined;
        dataList[id] = undefined;
    }
    // 其实上面一大串都是来处理参数的。用一个args就是一个可变参数。
   // pagesize是根据分辨率来决定的5的倍数。后台分页也要根据前台传值来决定pageszie
   // callbackList是用来存放该列表绑定后的处理方法,由于翻页传递参数只需要传递pageIndex pagesize和recordcount 所以 callback等其他参数需要来记忆。

 

    //如果是ajax请求
    if (data == undefined) {
        url = url.replace(/&?(pageindex|pagesize|_)=\w+/ig, "");//过滤url的翻页参数

        if (ispage != "0") {
            if (url.indexOf("?") == -1) url += "?";
            url += "&pageindex=" + pageindex + "&pagesize=" + pagesize;//加上翻页的参数,就是因为要加上,所以上面先过滤
        }
        $.ajax({
            url: url,
            async: false,//这里用了同步请求,IE6下会卡一下,如果用异步,则需要把后面的代码做成一个单独的方法。
            success: function(d) {
                if (d == "")
                    data = undefined;
                else
                    data = eval("(" + d + ")");
            }
        });
    }
   
    //如果不是添加,先把tbody置空
    if (!isappend) {
        $(".pagelist", this).empty().hide();
        $("tbody:eq(0)", this).empty();
    }
    if (data == undefined)//ajax请求失败
    {
        return this;
    }

    //声明一个Array用来绑定
    var dataSource = [];
    if (data[listName] === undefined) {
        dataSource = data;
    }
    else if (data[listName] != null) {
        dataSource = data[listName];
    }
    //翻页需要的recordCount
    var recordCount = data.recordCount || dataSource.length;

    var isAjaxRequest = (url != undefined); //是否为ajax请求
    var currentPageData = [];//当前页要绑定的数据,主要是为了使非ajax数据方便分页。
    if (!isAjaxRequest) {
        var loop = pagesize * pageindex;
        if (loop >= recordCount) loop = recordCount;

        for (var i = (pageindex - 1) * pagesize; i < loop; i++) {
            currentPageData.push(dataSource[i]);
        }
    }
    else
        currentPageData = dataSource;

    //替换模板创建到列表
    if ($("tbody", this).length == 0)
        this.append("<tbody></tbody>");

    //没有数据的显示
    if (!isappend) {
        if (currentPageData.length == 0) {
            $("tbody", this).html("<tr><td colspan='" + $("thead th:visible", this).length + "'>暂时没有数据</td></tr>");
            $("tfoot", this).empty().hide();
            return this;
        }
    }
    $("tr:contains('暂时没有数据')", this).remove();
    $("tbody", this).append(replaceTemplate(getTemplate(id), currentPageData));//这里执行数据替换
   
    //执行callback,callback可以是string或Function callback主要用于绑定后的列表处理
    if (callback != undefined) {
        if (typeof (callback) == "function") {
            callback(dataSource);
        }
        else {
            try {
                eval(callback)();
            } catch (e) { }
        }
        if (ispage != "0") {
            callbackList[id] = callback;
        }
    }

    //如果分页 创建分页到tfoot
    if (ispage != "0" || $("tfoot", this).length > 0) {
        this.attr("datasource", url);
        if (!isAjaxRequest) {
            dataList[id] = data;
        }
        this.pageHtml(recordCount, pagesize, pageindex);
    }
   //这里把排序、分页、事件绑定都写死在里面了,这样有些丑陋,如果我要做实例的话,会重写这个方法。
 //
    this.bindSort();//排序
    this.setPageLink();//设置分页的链接
    setLink(id); //设置其他连接,这里以后还需要修改。
   
    //设置th里的全选为非选中状态
    try {
        $("thead th input[type='checkbox']", this).attr("checked", "");
    } catch (e) { }
    return this;
};

Code

    //==========================================================================
    //设置分页连接,只针对翻页的<a>做处理。
    //==========================================================================
    $.fn.setPageLink = function() {
        var id = this.attr("id");
        $("tfoot .pagelist a", this).unbind("click").click(function() {
            var thisPageIndex = $(this).attr("href");
            thisPageIndex = thisPageIndex.substring(thisPageIndex.lastIndexOf("#") + 1);
            $("#" + id).bindTable({ pageindex: thisPageIndex, pageRequest: true });
        });
        return this;
    };
    //==========================================================================
    //表格分页(这个程序的样式写的比较死,如果想要比较丰富的翻页样式,还要写一堆代码-_-)
    //==========================================================================
    $.fn.pageHtml = function(recordCount, pageSize, pageIndex) {

        pageIndex = parseInt(pageIndex);
        pageSize = parseInt(pageSize);
        recordCount = parseInt(recordCount);

        var pageCount = parseInt(recordCount / pageSize);

        if (recordCount % pageSize > 0)
            pageCount++;
        if (pageIndex > pageCount)
            pageIndex = pageCount;

        if (pageCount <= 1) {
            $(".pagelist", this).empty().hide();
            return this;
        }
        var isShowCount = this.attr("isShowCount");
        var isShowPageList = this.attr("isShowPageList");

        var html = "<div class='pagelist'>";
        if (isShowCount != "0") {
            html += "<span>共" + recordCount + "条 第" + pageIndex + "页/共" + pageCount + "页,每页" + pageSize + "条</span>";
        }

        if (pageIndex == 1) {
            html += "<span>首页</span>";
            html += "<span>上一页</span>";
        }
        else {
            html += "<a href=\"#1\">首页</a>";
            html += "<a href=\"#" + (pageIndex - 1) + "\">上一页</a>";
        }
        if (isShowPageList != "0") {

            var listSize = 5; //显示 1 2 3 4
            var loopSize = 5; //循环上限
            var listIndex = 0; //当前list的索引
            if (pageIndex % listSize > 0)
                listIndex = parseInt(pageIndex / listSize);
            else
                listIndex = parseInt(pageIndex / listSize) - 1;

            if (listSize > pageCount)//总页数不到一个页码数
                loopSize = pageCount;
            else
                loopSize = listSize;

            //
            if ((listIndex + 1) * listSize >= pageCount && listSize < pageCount) {
                loopSize = pageCount % listSize;
                if (loopSize == 0)
                    loopSize = listSize;
            }

            for (var i = 1; i <= loopSize; i++) {
                var pageText = i + (listIndex * listSize);
                if (pageText == pageIndex)
                    html += "<span class='currentPage'>" + pageText + "</span>";
                else
                    html += "<a href='#" + pageText + "'>" + pageText + "</a>";
            }
            if (loopSize == listSize && pageCount > listSize) {
                var nextList = (listIndex + 1) * listSize + 1;
                if (nextList <= pageCount)
                    html += "<a href=\"#" + ((listIndex + 1) * listSize + 1) + "\"></a>";
            }
        }
        if (pageCount == pageIndex) {
            html += "<span>下一页</span>";
            html += "<span>末页</span>";
        }
        else {
            html += "<a href=\"#" + (pageIndex + 1) + "\">下一页</a>";
            html += "<a href=\"#" + pageCount + "\">末页</a>";
        }
        html += "</div>";

        if ($("tfoot", this).length == 0)
            this.append("<tfoot></tfoot>");

        $("tfoot:eq(0)", this).show().html("<tr><td colspan=\"" + $("thead th:visable", this).length + "\">" + html + "</td></tr>");

        //翻页需要存储数据到table的属性中
        this.attr("pagesize", pageSize);
        this.attr("ispage", "1");
        return this;
    };
    //==========================================================================
    //表格排序(排序目前只是对ajax请求绑定排序,显存的目前还没排序。)
    //==========================================================================
    $.fn.bindSort = function() {

        var url = this.attr("datasource");

        if (url == undefined)
            return this;

        if (url.indexOf('?') == -1)
            url += "?";

        url = url.replace(/&?(sort|desc)=\w+/ig, "");
        var id = this.attr("id");

        $("th a", this).each(function() {
            var sort = $(this).attr("sort");
            var desc = $(this).attr("desc")
            if (sort == undefined || sort == "")
                return;

            //加载设置样式
            if (desc != undefined && sort != $("#" + id).attr("sort")) {
                $(this).text($(this).text().replace("▼", "").replace("▲", "")); //使用文字样式
            }
            //$(this).removeClass("sort" + Math.abs(desc - 1));//使用图片样式
            //设置点击
            $(this).unbind("click").click(function() {

                desc = Math.abs(desc - 1) || 0;

                $(this).attr("desc", desc);

                //点击后设置样式
                $("#" + id).attr("sort", sort);
                $(this).text($(this).text().replace("▼", "").replace("▲", "") + (desc == 1 ? "▼" : "▲")); //使用文字样式
                //$(this).removeClass("sort" + Math.abs(desc - 1)).addClass("sort" + desc);//使用图片样式

                //刷新Table数据
                $("#" + id).bindTable({
                    url: url + "&sort=" + sort + "&desc=" + desc
                });
            });
        });
        return this;
    };


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3