Easy Grid 最简单的Javascript 表格控件

      表格是很常用的html控件之一, 为了使用的方便以及美观, Easy就出现了Easy.Grid ,这个表格简单易用,符号Easy的宗旨。

用户只要会html 、Javascript ,看了Easy.Grid 的Demo 就不使用,并且运用自如。演示地址:http://easy.apphb.com/unit/ui/index.htm

都是程序员就不多说了,看源码(一下常用的方法封装在Easy的核心库里):

Easy.data.Store = function (cfg) {
    var me = this;
    Easy.apply(me, cfg);
    me.callback = function () { };
    var pubs = {
        start: 0,
        load: function (params) {
            var pms = Easy.applyIf(params || {}, me.baseParams);
            me.start = pms.start;
            var mk = new Easy.UI.Mask({
                message: '正在加载数据...'
            });
            mk.show();
            me.loader = Easy.Ajax.post({
                url: me.url,
                params: pms,
                callback: function (rsp, cfg) {
                    try {
                        if (this.status == 200) {
                            me.callback();
                            var json = Easy.decode(rsp);
                            if (json.exception) {
                                alert(json.message);
                                return false;
                            }
                            me.processResponse.call(me, rsp);
                        } else {
                            me.exception.call(me, rsp, this.statue);
                        }
                    } catch (e) {
                        mk.close();
                    } finally {
                        mk.close();
                    }
                }
            });
        },
        on: function (en, fn, scope) {
            var me = this;
            (scope || me)["on" + Easy.String.toPascal(en)] = Easy.delegate(fn, scope || me, Easy.slice(arguments, 3));
        },
        fireEvent: function (eventName, scope) {
            return (scope["on" + Easy.String.toPascal(eventName)] || Easy.emptyFn).apply(scope, Easy.slice(arguments, 2));
        },
        processResponse: function (resText, option) {
            var o = Easy.decode(resText);
            if (o && !o.exception)
                me.drawRow(o);
            else {
                me.exception.call(resText, me.loader.statue);
            }
            me.fireEvent('load', me);
        },
        exception: function (resT, state) {

            me.fireEvent('exception', me);
        }
    };

    Easy.apply(me, pubs);
    return me;
}

Easy.UI.Grid = Easy.extend(Easy.UI.Base, {
    url: "/base.ashx",
    root: 'Records',
    count: "Count",
    tpl: "",
    noPaging: false,
    mutilSelect: false,
    model: 'remote',
    rows: [],
    checkboxs: [],
    headerTDs: [],
    mutilSelectTip: "你选择了多条数据!",
    noSelectTip: "你没有选择要操作的数据!",
    constructor: function (cfg) {
        var me = this;
        Easy.apply(me, cfg);
        if (!me.store && me.model === "remote") {
            if (me.url) {
                me.store = new Easy.data.Store({
                    url: me.url,
                    baseParams: Easy.apply({
                        className: me.className,
                        methodName: me.methodName || "PageData",
                        start: 0, limit: me.limit || 17, sort: '', dir: 'desc'
                    }, me.baseParams)
                });
            }
        }
        if (me.store)
            me.store.drawRow = Easy.delegate(me.drawRow, me);
        Easy.UI.Grid.superclass.constructor.call(this);
    },
    initComponent: function () {
        var me = this;
        var tpl = "<table class='e-grid' border='0' cellpadding='0' cellspacing='0'>" +
                    "<tbody>" +
                        (Easy.isArray(me.header) ? me.header.join("\n") : me.header) +
                    "</tbody>" +
                "</table><div class='clear'></div>";
        var wrap = Easy.get(me.renderTo);
        wrap.innerHTML = tpl;
        if (wrap.firstChild && Easy.isElement(wrap.firstChild) && wrap.firstChild.tagName == "TABLE")
            me.table = wrap.firstChild;
        if (me.model === 'remote')
            me.store.load();
        me.initGrid = true;
        me.wrap = wrap;
        me.headerTDs = [];
        me.clearDiv = me.table.nextSibling;
        Easy.each(me.table.firstChild.rows[0].cells, function (td, i) {
            var w = Easy.DOM.getStyle(td, "width");
            if (Easy.DOM.hasClass(td, "e-row"))
                w = 30;
            w = w || (td.offsetWidth - 10);
            me.headerTDs.push(w);
        })
    },
    drawRow: function (rows) {
        var me = this, wrap = Easy.get(me.renderTo);
        me.data = {};
        me.getCount = function () {
            return rows[me.Count];
        };
        me.tplStr = Easy.isArray(me.tpl) ? me.tpl.join("\n") : me.tpl;
        wrap.innerHTML = "";
        me.rows = [];
        me.checkboxs = [];
        var tpl = "<table class='e-grid' border='0' cellpadding='0' cellspacing='0'>" +
                    "<tbody>" +
                        (Easy.isArray(me.header) ? me.header.join("\n") : me.header) +
                       (function () {
                           var sb = [], tmp, cutIndex = 0, orow = me.root ? rows[me.root] : rows;
                           Easy.each(orow, function (it) {
                               me.data[it["FID"]] = it;
                               tmp = me.tplStr;

                               var optn = /\{(\w+)\}[.](\w+)/i, m = optn.exec(tmp);
                               while (m != null) {
                                   tmp = tmp.replace(m[0], it[m[1]][m[2]]);
                                   m = optn.exec(tmp);
                               }
                               Easy.each(it, function (v, k) {
                                   v = v == null ? "" : v;
                                   if (Easy.isDate(v)) {
                                       v = Easy.Date.format(v, "yyyy-MM-dd hh:mm");
                                   }
                                   tmp = tmp.replace(new RegExp("{" + k + "}", "g"), v);
                               });
                               cutIndex += 1 + (me.model === 'remote' ? me.store.baseParams.start : 0);
                               if (tmp.indexOf("{fn:") > -1) {
                                   var ptn = /\{fn:(.*)\/fn\}/i, match = ptn.exec(tmp);
                                   while (match != null) {
                                       var fn = match[1];
                                       var rel = (new Function(fn));
                                       tmp = tmp.replace(match[0], rel);

                                       match = ptn.exec(tmp);
                                   }
                               }

                               tmp = tmp.replace("{rowIndex}", cutIndex).replace(/\{\w*\}/ig, " ");
                               sb.push(tmp);
                           });
                           return sb.join("");
                       })() +
                    "</tbody>" +
                "</table><div class='clear'></div>";
        wrap.innerHTML = tpl;
        if (wrap.firstChild && Easy.isElement(wrap.firstChild) && wrap.firstChild.tagName == "TABLE")
            me.table = wrap.firstChild;
        me.initEvent.call(me);
        if (!me.noPaging) {
            var p = new Easy.UI.Pagingbar(Easy.apply(me.pagingbar || {}, {
                renderTo: wrap,
                data: rows,
                pageSize: me.store.baseParams.limit,
                start: me.store.baseParams.start,
                store: me.store,
                width: wrap.scrollWidth || wrap.offsetWidth || "auto"
            }));
            p.currentPageCtl.value = Math.ceil(me.store.start / me.store.baseParams.limit + 1);
        }
        me.clearDiv = me.table.nextSibling;
        me.wrap = wrap;
        me.fireEvent("render", me);
    },
    on: function (en, fn, scope) {
        var me = this;
        if (en == "rowdblclick") {
            Easy.each(me.rows, function (r, i) {
                Easy.DOM.on(r, "dblclick", Easy.delegate(fn, scope || me, [r, i]));
            })
        }
        (scope || me)["on" + Easy.String.toPascal(en)] = Easy.delegate(fn, scope || me, Easy.slice(arguments, 3));
    },
    onRender: function () {
        var me = this, style = {};
        if (me.height) {
            style.height = Math.max(me.height - me.table.offsetHeight - 75, 0);
        }
        Easy.DOM.setStyle(me.clearDiv, style);
    },
    initEvent: function () {
        var me = this, tb = me.table.firstChild;
        var ths = tb.rows[0].cells, rows = tb.childNodes;
        me.checkboxs = [];
        for (var i = 0, len = ths.length; i < len; i++) {
            var cel = ths[i];
            if (cel && cel.sort) {
                Easy.DOM.on(cel, "click", Easy.delegate(me.sort, me, [cel.sort, cel]));
                if (me.initGrid) {
                    var sortFlag = Easy.DOM.create({
                        tag: "span",
                        cls: 'e-sort-asc'
                    }, cel);
                    Easy.DOM.addClass(cel, "e-cansort");
                }
            }
        }
        var ck = rows[0].getElementsByTagName("input")[0];
        if (ck && ck.type.toLowerCase() === "checkbox") {
            //            me.checkboxs.push(ck);
            Easy.DOM.on(ck, "click", Easy.delegate(me.selectAll, me, [ck]));
        }
        for (var i = 1, len = rows.length; i < len; i++) {
            var r = rows[i];
            me.rows.push(r);
            var ckb = r.getElementsByTagName("input")[0];
            if (ckb && ckb.type.toLowerCase() === "checkbox") {
                me.checkboxs.push(ckb)
                Easy.DOM.on(ckb, "click", Easy.delegate(me.checkClick, me, [ckb, r]));
            }
            Easy.DOM.on(r, "mouseover", Easy.delegate(me.toogleClass, me, [r, "e-row-over"]));
            Easy.DOM.on(r, "mouseout", Easy.delegate(me.toogleClass, me, [r, "e-row-over"]));
            Easy.DOM.on(r, "click", Easy.delegate(me.rowClick, me, [r, i]));
            Easy.DOM.on(r, "dblclick", Easy.delegate(me.rowDblClick, me, [r, i]));

            Easy.each(r.cells, function (c, colIndex) {
                var sp = c.firstChild;
                if (sp && sp.tagName.toLowerCase() == "span") {
                    Easy.DOM.setStyle(sp, {
                        width: me.headerTDs[colIndex] || "auto"
                    });
                }
                Easy.DOM.on(c, "click", Easy.delegate(me.cellClick, me, [c, r, colIndex, i]));
                Easy.DOM.on(c, "dblclick", Easy.delegate(me.cellDblClick, me, [c, r, colIndex, i]));
            });
        }
    },
    load: function (params) {
        this.store.load(params);
    },
    refresh: function (p) {
        this.store.load(p);
    },
    sort: function (sort, cel) {
        var me = this;
        me.initGrid = false;
        Easy.DOM.toogleClass(cel.lastChild, "e-sort-desc");
        var params = { sort: sort, dir: "desc" };
        if (Easy.DOM.hasClass(cel.lastChild, "e-sort-desc")) {
            params["dir"] = "desc";
        } else {
            params["dir"] = "asc";
        }
        me.header = me.table.firstChild.firstChild.outerHTML;
        me.load(params);
    },
    selectAll: function (ck) {
        var me = this;
        Easy.each(me.checkboxs, function (c, i) {
            c.checked = ck.checked;
            Easy.DOM[ck.checked ? "addClass" : "removeClass"](me.rows[i], "e-row-select");
        });
    },
    checkClick: function (c, r) {
        Easy.DOM.toogleClass(r, "e-row-select");
        Easy.Event.stopPropagation(window.event);
        this.fireEvent('check', this, r, c);
    },
    rowClick: function (r, i, cked) {
        if (!window.event.ctrlKey && !this.mutilSelect)
            Easy.each(this.rows, function (r) {
                Easy.DOM.removeClass(r, "e-row-select");
                r.cells(0).firstChild.checked = false;
            });
        Easy.DOM.addClass(r, "e-row-select");
        this.rows[i - 1].cells(0).firstChild.checked = cked !== false ? true : cked;
        this.fireEvent('click', this, r, i, cked);
    },
    rowDblClick: function (row, idex) {
        this.fireEvent('rowdblclick', this, row, idex);
    },
    cellClick: function (cell, row, colIndex, rowIndex) {
        this.fireEvent('cellclick', this, cell, row, colIndex, rowIndex);
    },
    cellDblClick: function (cell, row, colIndex, rowIndex) {
        this.fireEvent('celldblclick', this, cell, row, colIndex, rowIndex);
    },
    toogleClass: function (r, cls) {
        Easy.DOM.toogleClass(r, cls);
    },
    getSelection: function () {
        var me = this, sel = [];
        Easy.each(me.rows, function (r) {
            var ck = r.cells(0).firstChild;
            if (ck.checked === true) {
                sel.push(me.data[ck.value]);
            }
        });
        return sel;
    },
    getValues: function (key, canempty) {
        var me = this, v = [];
        var sls = me.getSelection.call(me);
        Easy.each(sls, function (s) {
            v.push(s[key]);
        });
        if (v.length == 0 && !canempty) {
            alert(me.noSelectTip);
            v = false;
        }
        return v;
    },
    getValue: function (key, canempty) {
        var me = this, v = [];
        var sls = me.getSelection.call(me);
        if (sls.length == 1) {
            return sls[0][key];
        } else if (!canempty) {
            alert(me[sls.length == 0 ? "noSelectTip" : "mutilSelectTip"]);
            return false;
        }
    }
});

看了这么长的源码后, 看看这个grid的到底能出现什么效果呢, 现在看看效果,

效果图如下:

 

看到效果后我们看看穿件这个grid的代码:

 

var grid = new Easy.UI.Grid({
       id: "roleGrid",
       renderTo: 'grid',
       baseParams: {
           className: "RoleServer",
           methodName: "PageData"
       },
       header: ["<tr class='e-header'>",
                            "<td class='e-checkbox'><input type='checkbox' /></td>",
                            "<td style='width:150px;' sort='FName'><span>名 称</span></td>",
                            "<td style='width:200px;' sort='FOrgID'><span>所属组织</span></td>",
                            "<td style='width:150px;' sort='FSort'><span>排 序</span></td>",
                            "<td><span>说明</span></td>",
                        "</tr>"],
       tpl: ["<tr>",
                            "<td><input type='checkbox' value='{FID}' /></td>",
                            "<td><span>{FName}</span></td>",
                            "<td><span>{OrgName}</span></td>",
                            "<td><span style='width:100px;'>{FSort}</span></td>",
                            "<td><span>{FRemark}</span></td>",
                        "</tr>"]
});

 穿件这个grid的代码仅此而已,  效果还可以的吧 !

posted @ 2011-10-27 15:37  EasyJS Framework  阅读(3199)  评论(6编辑  收藏  举报
我没读过多少书,没有文采,请海涵!