将GridViewExtenderTest测试页面添加到版本库 修改GridViewExtender.js 部分按照jslint的规则修改
netwjx authored at 2011-10-24 10:38:43
10.99 KiB
X
;
(function () {
    var w = window, d = document, bindedEvents = [], objectData;

    // 对象字典,可以将html元素和js变量关联起来,而不用在html元素中引用js元素
    function ObjectDict() {
        this.__data = [];
    }
    ObjectDict.prototype.get = function (n) {
        var i, d;
        for (i = 0; i < this.__data.length; i++) {
            d = this.__data[i];
            if (d[0] === n) {
                return d[1];
            }
        }
    };
    ObjectDict.prototype.set = function (n, v) {
        this.__data.push([n, v]);
        return this;
    };

    // 标签数组,提供类似html class属性的容器,使用push remove增删元素,使用last访问到末尾的元素,push会自动避免重复元素被加入
    function TagArray(equal) {
        this.__equal = equal;
    }
    TagArray.prototype = [];
    TagArray.prototype.push = function () {
        var i, j, args = [];
        for (i = 0; i < arguments.length; i++) {
            if (this.has(arguments[i])) {
                continue; // 已有的不添加
            }
            if (args.length > 0) {
                try {
                    for (j = 0; j < args.length; j++) {
                        if (this.__equal(arguments[i], args[j])) {
                            throw ''; // push参数中重复的不添加
                        }
                    }
                    args.push(arguments[i]);
                } catch (e) { }
            } else {
                args.push(arguments[i]);
            }
        }
        return Array.prototype.push.apply(this, args);
    };
    TagArray.prototype.remove = function (obj) {
        var i, s = 0, r = [];
        while (true) {
            i = this.has(obj, s);
            if (!i) {
                break;
            }
            s = i[0];
            r.push(this.splice(i[0], 1)[0]);
        }
        return r;
    };
    TagArray.prototype.has = function (obj, start) {
        var i;
        start = start || 0;
        for (i = start; i < this.length; i++) {
            if (this.__equal(obj, this[i])) {
                return [i, this[i]];
            }
        }
        return false;
    };
    TagArray.prototype.last = function () {
        if (this.length > 0) {
            return this[this.length - 1];
        }
    };

    function jsArray(arylike, s, n) {
        var ary, i;
        if (Object.prototype.toString.call(arylike) === '[object Array]') {
            return arylike;
        }
        if (typeof arylike.length === 'number') {
            if (typeof s === 'undefined') {
                s = 0;
            }
            if (s < 0) {
                s = arylike.length - s;
            }
            if (typeof n === 'undefined') {
                n = arylike.length;
            }
            if (n < 0) {
                n = arylike.length - n;
            }
            try {
                return Array.prototype.slice.call(arylike, s, n);
            } catch (e) {
                ary = new Array(arylike.length);
                for (i = s; i < n; i++) {
                    ary[i] = arylike[i];
                }
                return ary;
            }
        }
        return [];
    }

    function filter(ary, func) {
        var i, n;
        ary = jsArray(ary);
        n = ary.length;
        for (i = 0; i < n; i++) {
            if (func(ary[i], i)) {
                ary.push(ary[i]);
            }
        }
        ary.splice(0, n);
        return ary;
    }

    function bindEvent(ele, type, listener) {
        var bind;
        if (ele.attachEvent) {
            type = ('on' + type).toLowerCase();
            bind = 'attachEvent';
        } else if (ele.addEventListener) {
            bind = 'addEventListener';
        }
        if (bind) {
            ele[bind](type, listener);
            bindedEvents.push([ele, type, listener]);
        }
    }
    function unbindEvent(ele, type, listener) {
        var unbind;
        if (ele.detachEvent) {
            type = ('on' + type).toLowerCase();
            unbind = 'detachEvent';
        } else if (ele.removeEventListener) {
            unbind = 'removeEventListener';
        }
        if (unbind) {
            ele[unbind](type, listener);
        }
    }
    // 将指定函数包装后返回,指定函数在调用时会拥有返回函数执行的上下文,参数,以及会额外附加当前包装携带的参数
    function wrapFunc(func) {
        var params = jsArray(arguments, 1);
        return function () {
            func.apply(this, jsArray(arguments).concat(params));
        };
    }

    function nextColor(cols, c) {
        var i;
        for (i = 0; i < cols.length; i++) {
            if (cols[i].toLowerCase() === c.toLowerCase()) {
                return i + 1 < cols.length ? cols[i + 1] : cols[0];
            }
        }
    }
    function fireClickEvent(e) {
        var evt;
        if (e.click) {
            e.click();
        } else if (d.createEvent && e.dispatchEvent) {
            evt = d.createEvent('MouseEvents');
            evt.initMouseEvent('click', true, true, w, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
            e.dispatchEvent(evt);
        }
    }

    function getOrInitObjectData(ele, name, deffunc) {
        var d = objectData.get(ele);
        if (typeof d === 'undefined') {
            d = {};
        }
        if (typeof d[name] === 'undefined') {
            d[name] = deffunc();
        }
        objectData.set(ele, d);
        return d[name];
    }
    function initBgColorArray() {
        return new TagArray(function (a, b) {
            return typeof a.t !== 'undefined' && a.t === b.t &&
                (a.c === b.c || typeof a.c === 'undefined');
        });
    }
    // 返回指定元素的背景颜色的标签数组,其元素约定为{t:类型,c:'颜色'} 类型可以是任意类型,添加和删除时必须提供类型,(不指定颜色的删除即删除所有这个类型的元素),颜色在添加时应该提供,否则将有可能添加不进去
    function getBgColorArray(ele) {
        return getOrInitObjectData(ele, 'BgColorArray', initBgColorArray);
    }

    objectData = new ObjectDict();
    w.GridViewExtender = {
        // 对指定id的GridView 表格中数据行执行指定的操作
        ExtendDataRow: function (id, opt) {
            var gv = d.getElementById(id), rows, cell, i, r, type;
            if (gv && gv.tagName === 'TABLE') {
                opt.EventMap = opt.EventMap || {};
                opt.HighlightRowMap = opt.HighlightRowMap || {};
                objectData.set(gv, opt);

                rows = gv.tBodies[0].rows;
                for (i = 0; i < rows.length; i++) {
                    cell = rows[i].firstChild;
                    while (cell !== null && cell.nodeType !== 1) {
                        cell = cell.nextSibling;
                    }
                    if (cell === null) {
                        continue;
                    }

                    if (cell.tagName === 'TD' && cell.colSpan === 1) { // 行的第一个标签是td 并且这个td没有单元格合并
                        r = rows[i];
                        for (type in opt.EventMap) {
                            if (opt.EventMap.hasOwnProperty(type)) {
                                bindEvent(r, type, wrapFunc(opt.EventMap[type], r, i));
                            }
                        }
                    }
                }
            }
        },
        IsInExtendDataRow: function (e) {
            var r, d;
            try {
                do {
                    if (e.tagName === 'TD') {
                        e = e.parentNode;
                    }
                    if (e.tagName === 'TR') {
                        r = e;
                        e = e.parentNode;
                    }
                    if (e.tagName === 'TABLE') {
                        d = objectData.get(e);
                        if (d && d.HighlightRowMap && d.EventMap) {
                            return [e, r];
                        }
                    }
                    e = e.parentNode;
                } while (e !== null && e.tagName !== 'BODY');
            } catch (ex) { }
            return null;
        },
        Highlight: function (colors) {
            if (typeof colors === 'string') {
                colors = colors.split(/\s*,\s*/);
            }
            if (colors.length === 1) {
                colors.push('');
            }
            return function (e, row, i) {
                var s = row.style, d = getBgColorArray(row), c = d.has({ t: colors }), addfunc = 'push';
                if (c) {
                    c[1].c = nextColor(colors, c[1].c);
                } else {
                    if (d.length > 0) {
                        addfunc = 'unshift';
                    }
                    d[addfunc]({ t: colors, c: colors[0] });
                }
                c = d.last();
                if (c) {
                    s.backgroundColor = c.c;
                }
            };
        },
        HighlightRow: function (ele, name, toggle) {
            var color, map, row, d, c, gv = w.GridViewExtender.IsInExtendDataRow(ele);
            if (gv && gv[0] && gv[1]) {
                row = gv[1];
                gv = gv[0];
                map = objectData.get(gv).HighlightRowMap;

                if (!name) {
                    name = '';
                }
                if (map[name]) {
                    color = map[name];
                } else {
                    color = name;
                }

                d = getBgColorArray(row);
                c = d.has({ t: 'HighlightRow' }); // TODO 考虑是否有需要提供分组,而不是使用单一的HighlightRow的组

                if (typeof toggle === 'undefined') {
                    toggle = !c || (c[1].c && color && c[1].c.toLowerCase() !== color.toLowerCase());
                }

                if (c) {
                    d.remove({ t: 'HighlightRow' });
                }
                if (toggle && typeof color !== 'undefined' && color !== '') {
                    d.push({ t: 'HighlightRow', c: color });
                }

                setTimeout(function () {
                    c = d.last();
                    row.style.backgroundColor = c ? c.c : '';
                }, 15);

            }
        },
        ClickElement: function (tag, func) {
            return function (e, row, i) {
                var ele, eles = filter(row.getElementsByTagName(tag), func);
                ele = eles[0];
                if (ele) {
                    fireClickEvent(ele);
                }
            };
        }
    };

    bindEvent(w, 'unload', function () {
        var i, args;
        for (i = 0; i < bindedEvents.length; i++) {
            args = bindedEvents[i];
            unbindEvent.apply(this, args);
        }
    });
}());