zoukankan      html  css  js  c++  java
  • 自己写一个轻量的JqueryGrid组件

    接触mvc不久,突然没有了viewstate和服务端控件处处都觉得不顺手,很多在webform时不必要考虑的问题都出现在眼前,这其中分页时查询条件保持的问题又是最让我头疼的事情,权衡再三,决定用ajax局部刷新列表的方式来解决这个问题。网上基于jquery的grid组件很多,jquerygrid,jqgrid等等,分别试用了一下,功能确实非常强大,但感觉上有点重,配置项太多,用起来依然感觉束手束脚,所以想来想去,还是用最笨的办法自己做了一个组件,很简陋,唯一的好处就是灵活,容易修改和控制。

    没图没真相,先来个截图看看:

    功能:

    1. 指定url,支持post或get方式加载数据
    2. 自定义数据查询条件
    3. 列定义时可以对数据项进行简单的转换处理。如:数据源[{ "name": "张三",  "age": 12, "sex": 1 }],渲染时希望把sex的值 1 显示为 男性
    4. 支持多选
    5. 支持分页
    6. 点击行时自动选中,多选时,点击checkbox进行选中和取消选中
    7. 能够返回选中项目的值,多选时返回选中值的数组

    根据个人的习惯和对功能的分解,定义了这样一个setting:

    var list = $('#list').GridView({
                'apiUrl': '/Student/List',  // 指定数据请求的URL路径
                'apiType': 'post',  // 请求的方式
                'columns': [    // 要显示的列,title对应表头,column对应数据项的属性名称,width指定列的宽度,func指定绑定时调用的函数名称
                    { title: '姓名', column: 'Name',  160 },
                    { title: '年龄', column: 'Age' },
                    { title: '性别', column: 'Sex',  100, 'func': 'convertToSex' }
                ],
                'valueColumn': 'StudentId', // data-value 取值的属性名
                'pageSize': 20, // 每页显示的数量
                'isMultiy': false,  // 是否支持多选
                'isTreeView': false,   // 是否支持树形
                'pager': 'pager',   // 指定包含分页的divid,主要是为了能单独控制pager中的一些数据,把pager给拆出来了,后来发现似乎用处不大
                'onRowClick': function(id) { }, // 当数据行被点击时执行的回调,参数是tr中的data-value
                'convertSource': function (data) { return data.body; }, // 使用数据源之前对数据进行转换。因为我的api返回的都是{ code: 200, body: [] }这种类型,需要在这里直接返回body
                'onDataBindComplete': function() {}, // 当数据加载完成,也就是列表渲染完成后的回调。比如说提醒用户加载完成之类的
                'getSearchData': function() { return $('#form1').serialize(); },    // 获取查询参数,这个很重要,想了很多办法,最终采用了这种方案,在查询前运行这个函数,将返回值作为ajax的查询参数
                'listCssClass': 'table',    // 列表table的样式名
                'pagerCssClass': 'pager',   // 分页最外面div的样式名
                'beforeSend': function() { }    // ajax请求之前调用的函数,原本是为了提醒一下加载已开始,请稍后之类的,现在没怎么用到
            });
    

    OK,接下来就是这个扩展的具体实现了,代码很多,但思路很简单,主要就是代码的拼接。大家自己看吧!

    (function ($) {
    
        $.fn.GridView = function (settings) {
            // 系统变量
            var self = this;
            self.selected = [];
            var pageindex = 1, pageSize = 20;
    
            if (settings.pageSize && $.isNumeric(settings.pageSize) && settings.pageSize > 0) {
                pageSize = settings.pageSize;
            }
    
            var rand = Math.floor(Math.random() * 1000);
            var table = $("<table" + (settings.listCssClass ? " class='" + settings.listCssClass + "'" : "") + " id='myList" + rand + "'></table>");
    
            var colgroup = colgroup2 = "<colgroup>"
            $.each(settings.columns, function (idx, item) {
                colgroup += "<col" + item.width ? " style='" + item.width + "px;'" : "" + ">";
                colgroup2 += "<col" + item.width ? " style='" + item.width + "px;'" : "" + ">";
            });
            colgroup += "<col style='18px;'></col>";
            colgroup += "</colgroup>";
            colgroup2 += "</colgroup>";
            var table = $("<table" + (settings.listCssClass ? " class='" + settings.listCssClass + "'" : "") + " id='myList" + rand + "'></table>");
    
            var pagerHtml = '<div' + (!settings.pagerCssClass ? '' : ' class="' + settings.pagerCssClass + '"') + '>';
            //var pagerHtml = '';
            pagerHtml += '<a class="disabled" id="first' + rand + '"><i class="fa fa-fast-backward"></i></a>';
            pagerHtml += '<a class="disabled" id="prev' + rand + '"><i class="fa fa-backward"></i></a>';
            pagerHtml += '<div class="pager-index"><b>第</b><input value="1" type="text" maxlength="4" id="index' + rand + '"><b>页</b></div>';
            pagerHtml += '<a class="disabled" id="next' + rand + '"><i class="fa fa-forward"></i></a>';
            pagerHtml += '<a class="disabled" id="last' + rand + '"><i class="fa fa-fast-forward"></i></a>';
            pagerHtml += '<div class="pager-info2"> 共计 <span class="totalCount" id="total' + rand + '">0</span> 条记录,';
            pagerHtml += '每页显示 <span class="pageSize' + rand + '">' + pageSize + '</span> 条,';
            pagerHtml += '共 <span class="totalPage" id="page' + rand + '">1</span> 页,';
            pagerHtml += '用时 <span class="loadTime" id="time' + rand + '">0</span>毫秒';
            pagerHtml += "</div></div>";
            var pagerDom = $(pagerHtml);
            var firstButton, prevButton, nextButton, lastButton, currentSpan, pageSizeSpan, totalCountSpan, totalPagesSpan, loadTimeSpan;
    
            // 临时变量
            var tbody, pager, cbAll, checkboxes, isPager = false, totalPage = 1;
    
            // 创建table
            self.append(table);
    
            // 创建thead
            addChildrenToTable();
    
            // 为tbody赋值
            tbody = $("#tbody" + rand);
    
            var colCount = settings.columns.length + 2;
            tbody.html("<tr class='empty'><td colspan='" + colCount + "'>等待加载数据...</td></tr>");
    
            // 创建分页
            if (settings.pager && $("#" + settings.pager)[0]) {
                pager = $("#" + settings.pager);
                isPager = true;
                pager.append(pagerDom);
                setPagerButtonEvent();
            }
    
            // 创建渲染函数
            self.fun = new Function("data", renderFunString());
    
            // 渲染第一列
            self.setFirstCol = function (val) {
                if (settings.isMulti) {
                    return "<td class='chk'><input type='checkbox' id='cb" + val + "' value='" + val + "'></td>"
                } else {
                    return "<td class='no'>" + val + "</td>";
                }
            }
    
            // 渲染最后一列
            self.setLastCol = function () {
                return "<td></td>";
            }
    
            // 渲染中间列
            self.setCol = function (content, width, cssClass, level) {
                var html = "<td";
                html += width ? " style='" + width + "px'" : "";
                html += cssClass && cssClass != 'undefined' ? " class='" + cssClass + "'" : "";
                html += ">";
                if (settings.isTreeView) {
                    html += level ? "<span class='block' style='" + 24 * level + "px'>" + (level > 0 ? "|—" : "") + "</span>" : "";
                }
                html += content && content != "undefined" ? content : "";
                html += "</td>";
                return html;
            }
    
            // 显示指定页码的数据
            self.show = function (index, type) {
                self.selected = [];
                if (!settings.apiUrl) {
                    return;
                }
    
                if (!type || type.toLowerCase() != "post") {
                    $.get(settings.apiUrl, getAjaxData(), function (data) {
                        var source = [];
                        if (settings.convertSource && $.isFunction(settings.convertSource)) {
                            source = settings.convertSource(data);
                        } else {
                            source = data;
                        }
                        addRowsToTbody(source);
                    });
                } else {
                    $.post(settings.apiUrl, getAjaxData(), function (data) {
                        var source = [];
                        if (settings.convertSource && $.isFunction(settings.convertSource)) {
                            source = settings.convertSource(data);
                        } else {
                            source = data;
                        }
                        addRowsToTbody(source);
                    });
                }
            };
    
            // 获取选中的ID
            self.getSelectedId = function () {
                if (self.selected.length == 0) {
                    return null;
                } else {
                    return self.selected[0];
                }
            };
    
            self.getSelectedIds = function () {
                return self.selected;
            };
    
            self.clear = function () {
                self.selected = [];
                $("tr", "#myList" + rand).removeClass("selected");
                $(":checkbox", "#myList" + rand).prop("checked", false);
            };
    
            // 为table内的元素绑定事件
            tbody.on("click", "tr", function () {
                if ($(this).hasClass("empty")) return;
                $("tr", tbody).removeClass("selected").find(":checkbox").prop("checked", false);
                $(this).addClass("selected").find(":checkbox").prop("checked", true);
                $("#cbAll" + rand).prop("checked", false);
                self.selected = [$(this).data("value")];
            });
    
            // 绑定复选框点击事件
            if (settings.isMulti) {
                cbAll = $("#cbAll" + rand);
    
                cbAll.on("click", function () {
                    if (!checkboxes) checkboxes = $(":checkbox", tbody);
    
                    if ($(this).prop("checked")) {
                        self.selected = [];
    
                        $.each(checkboxes, function (idx, item) {
                            $(this).prop("checked", true);
                            self.selected.push($(this).val());
    
                            var tr = $("#tr" + $(item).val());
                            if (!tr.hasClass("selected")) tr.addClass("selected");
                        });
                    } else {
                        checkboxes.prop("checked", false);
                        $("tr", tbody).removeClass("selected");
                        self.selected = [];
                    }
                });
    
                tbody.on("click", ":checkbox", function (event) {
                    event.stopPropagation();
    
                    if ($(this).prop("checked")) {
                        $("#tr" + $(this).val()).addClass("selected");
                    } else {
                        $("#tr" + $(this).val()).removeClass("selected");
                    }
                    if (!checkboxes) {
                        checkboxes = $(":checkbox", tbody);
                    }
    
                    self.selected = [];
    
                    var unCheckedCount = 0;
    
                    $.each(checkboxes, function () {
                        if ($(this).prop("checked")) {
                            self.selected.push($(this).val());
                        } else {
                            unCheckedCount++;
                        }
                    });
    
                    if (unCheckedCount > 0) {
                        cbAll.prop("checked", false);
                    } else {
                        cbAll.prop("checked", true);
                    }
                });
            }
    
            // 返回渲染函数的程序体
            function renderFunString() {
                var funString = "var self = this; var html = ''; $.each(data, function(idx, item) { var val = ";
                funString += (settings.valueColumn ? "item." + settings.valueColumn : "idx");
                funString += "; html += '<tr id="tr' + val + '" data-value="' + val + '">'; html += self.setFirstCol(val);";
                var level = null;
                if (settings.levelColumn) {
                    level = settings.levelColumn;
                }
                $.each(settings.columns, function (idx, item) {
                    if (item.func) {
                        funString += " html += self.setCol( " + item.func + "(item), " + item.width + ", '" + item.cssClass + "'" + (level ? " , item." + level : "") + " );";
                    } else {
                        funString += " html += self.setCol( item." + item.column + ", " + item.width + ", '" + item.cssClass + "'" + (level ? " , item." + level : "") + " );";
                    }
                });
                funString += " html += self.setLastCol(); html += '</tr>'; idx++; }); return html;";
                return funString;
            }
    
            // 将数据生成html,并插入到tbody中
            function addRowsToTbody(data) {
                if (data && data.body && data.body.length > 0) {
                    var html = self.fun(data.body);
                    tbody.html(html);
    
                    if (isPager) {
                        setPagerButton(pageSize, pageindex, data.totalCount, new Date().getTime());
                    }
                } else {
                    var colCount = settings.columns.length + 2;
                    tbody.html("<tr class='empty'><td colspan='" + colCount + "'>请求的数据为空</td></tr>");
                }
            }
    
            // 创建table
            function addChildrenToTable() {
                var body = "<thead>"
                if (settings.columns) {
                    if (settings.isMulti) {
                        body += "<th class='chk'><input type='checkbox' id='cbAll" + rand + "' /></th>";
                    } else {
                        body += "<th class='no'></th>";
                    }
    
                    $.each(settings.columns, function (idx, col) {
                        body += "<th>" + col.title + "</th>";
                    });
                    body += "<th></th>";
                    body += "</thead><tbody id='tbody" + rand + "'></tbody>";
    
                    table.append($(body));
                }
            }
    
            // 绑定分页按钮的点击事件
            function setPagerButtonEvent() {
                firstButton = $("#first" + rand);
                prevButton = $("#prev" + rand);
                nextButton = $("#next" + rand);
                lastButton = $("#last" + rand);
                currentSpan = $("#index" + rand);
    
                pageSizeSpan = $("#size" + rand);;
                totalCountSpan = $("#total" + rand);;
                totalPagesSpan = $("#page" + rand);;
                loadTimeSpan = $("#time" + rand);;
    
                firstButton.on("click", function () {
                    if (!$(this).hasClass("disabled")) {
                        pageindex = 1;
                        self.show();
                    }
                });
    
                prevButton.on("click", function () {
                    if (!$(this).hasClass("disabled")) {
                        pageindex -= 1;
                        pageindex = pageindex <= 0 ? 1 : pageindex;
                        self.show();
                    }
                });
    
                nextButton.on("click", function () {
                    if (!$(this).hasClass("disabled")) {
                        pageindex += 1;
                        self.show();
                    }
                });
    
                lastButton.on("click", function () {
                    if (!$(this).hasClass("disabled")) {
                        pageindex = totalPage;
                        self.show();
                    }
                });
    
                currentSpan.on("change", function () {
                    var nc = Number($(this).val());
                    if (nc && nc <= totalPage && nc > 0) {
                        pageindex = nc;
                        self.show();
                    } else {
                        $(this).val(pageindex);
                    }
                });
            }
    
            // 配置 Pager 按钮
            function setPagerButton(size, index, total, start) {
                if (total == 0) {
                    pager.hide();
                } else {
                    pager.show();
                }
    
                // 总页数
                var pages = Math.ceil(total / size);
                pages = (pages == 0 ? 1 : pages);
                totalPage = pages;
    
                if (pages == 1) {
                    if (!firstButton.hasClass("disabled")) {
                        firstButton.addClass("disabled");
                    }
                    if (!prevButton.hasClass("disabled")) {
                        prevButton.addClass("disabled");
                    }
                    if (!nextButton.hasClass("disabled")) {
                        nextButton.addClass("disabled");
                    }
                    if (!lastButton.hasClass("disabled")) {
                        lastButton.addClass("disabled");
                    }
                } else {
                    if (index == 1) {
                        if (!firstButton.hasClass("disabled")) {
                            firstButton.addClass("disabled");
                        }
                        if (!prevButton.hasClass("disabled")) {
                            prevButton.addClass("disabled");
                        }
                    } else {
                        if (firstButton.hasClass("disabled")) {
                            firstButton.removeClass("disabled");
                        }
                        if (prevButton.hasClass("disabled")) {
                            prevButton.removeClass("disabled");
                        }
                    }
                    currentSpan.val(index);
                    if (index == pages) {
                        if (!nextButton.hasClass("disabled")) {
                            nextButton.addClass("disabled");
                        }
                        if (!lastButton.hasClass("disabled")) {
                            lastButton.addClass("disabled");
                        }
                    } else {
                        if (nextButton.hasClass("disabled")) {
                            nextButton.removeClass("disabled");
                        }
                        if (lastButton.hasClass("disabled")) {
                            lastButton.removeClass("disabled");
                        }
                    }
                }
                totalCountSpan.text(total);
                pageSizeSpan.text(this.pageSize);
                totalPagesSpan.text(pages);
                loadTimeSpan.text((new Date().getTime() - start));
            }
    
            // 获取ajax的查询参数
            function getAjaxData() {
                var param;
                if ($.isFunction(settings.getSearchData)) {
                    param = settings.getSearchData();
                }
                if (isPager) {
                    if ($.isArray(param)) {                                             // $("form").serializationArray()
                        param.push({ "name": "pageSize", "value": pageSize });
                        param.push({ "name": "pageIndex", "value": pageindex });
                    } else if ($.isPlainObject(param)) {                                 // 自定义查询对象
                        $.extend(true, param, { "pageSize": pageSize, "pageIndex": pageindex });
                    } else {                                                             // $("form").serialization()
                        param = (param ? param + "&" : "") + "pageSize=" + pageSize + "&pageIndex=" + pageindex;
                    }
                }
                return !!param ? param : {};
            }
    
            return self;
        }
    
    })(jQuery);
    
    /*
     *使用范例:
     *==========================数据格式============================
     {
      "code": 200,
      "describe": "",
      "totalCount": 3,
      "body": [
        {
          "no": 1,
          "name": "王五",
          "family": {
            "father": "王老五",
            "mother": "陈静蓉"
          }
        },
        {
          "no": 2,
          "name": "张三",
          "family": {
            "father": "张作霖",
            "mother": "李培芳"
          }
        },
        {
          "no": 3,
          "name": "李四",
          "family": {
            "father": "李宗仁",
            "mother": "江少芬"
          }
        }
      ]
     }
    
     *==========================页面调用============================
        <script src="jquery-1.10.2.js"></script>
        <script src="myGrid.js"></script>
        <script>
    	    var list = $("#list").myGrid({
    		    apiUrl: "data.json",
    		    isMulti: false,
    		    isTree: true,
    		    cols: [
    			    { col: "no",  120, title: "编号", cssClass: "chk", level: 0 },
    			    { col: "name",  120, title: "姓名", level: 0 },
    			    { col: "family.father",  120, title: "父亲", level: 1, func: "addFix" }
    		    ],
    		    valueCol: "no",
    		    pager: "pager",
    		    pageSize: 2,
    		    cssClass: "default-list-table",
    		    convertSource: function(data) {
    			    return data;
    		    }
    	    });
    
            // 这个是用来转换数据的方法
    	    function addFix(obj) {
    		    return "000" + obj;
    	    }
    	    list.show();
        </script>

    一个修改的操作:

  • 相关阅读:
    hihocoder 1388 Periodic Signal
    HDU 5880 Family View (AC自动机)
    HDU 5889 Barricade (bfs + 最小割)
    UVa 10806 Dijkstra, Dijkstra (最小费用流)
    POJ 3169 Layout (差分约束)
    差分约束系统学习
    HDU 3062 病毒侵袭持续中 (AC自动机)
    HDU 2896 病毒侵袭 (AC自动机)
    HDU 2222 Keywords Search (AC自动机)
    项目管理工具Leangoo,截止日期终于变绿色了
  • 原文地址:https://www.cnblogs.com/diwu0510/p/6576453.html
Copyright © 2011-2022 走看看