Skip to main content
 首页 » 编程设计

jQuery jsADS库

2022年07月16日26java哥
/** 
 * project:javascript DOM Advanced 
 */ 
(function () { 
    'use strict'; 
    //ADS命名空间 
    //判断ADS对象是否存在,否则创建 
    if (!window.ADS) { 
        window.ADS = {}; 
    } 
 
    //确定当前浏览器是否与整个库兼容 
    function isCompatible(other) { 
        //使用能力检测来检查必要条件 
        if (other === false || !Array.prototype.push || !Object.hasOwnProperty || !document.createElement || !document.getElementsByTagName) { 
            return false; 
        } 
        return true; 
    } 
 
    window.ADS.isCompatible = isCompatible; 
 
    function $() { 
        var elements = []; 
        //查找作为参数提供的所有元素 
        for (var i = 0; i < arguments.length; i++) { 
            var element = arguments[i]; 
            //如果这参数是一个字符串那假设它是一个id 
            if (typeof element === "string") { 
                element = document.getElementById(element); 
            } 
            //如果只提供一个参数 
            //则立即返回这个元素 
            if (arguments.length === 1) { 
                return element; 
            } 
            //否则,将它添加到数组中 
            elements.push(element); 
        } 
        //返回包含多个被请求元素的数组 
        return elements; 
    } 
 
    window.ADS.$ = $; 
 
    /** 
     * addEvent(node, type, listener)   添加事件程序处理 
     * @param node DOM节点元素 
     * @param type 事件类型 
     * @param listener 事件函数 
     * @return {Boolean} 
     */ 
    function addEvent(node, type, listener) { 
        //使用方法检查兼容性以保证平稳退化 
        if (!isCompatible()) { 
            return false; 
        } 
        //检查是不是DOM对象的引用 
        if (!(node = $(node))) { 
            return false; 
        } 
        if (node.addEventListener) { 
            //W3C的方法 
            node.addEventListener(type, listener, false);       //第三个参数为true时则启用捕获阶段 
            return true; 
        } else { 
            //MSIE的方法 
            //修正ie事件中this指向window的问题 
            //把执行函数赋给自定义对象属性 
            node["e" + type + listener] = listener; 
            //把事件函数赋给自定义对象属性 
            node[type + listener] = function () { 
                node["e" + type + listener](window.event); 
            }; 
            node.attachEvent("on" + type, node[type + listener]); 
            return true; 
        } 
        //若两种方法都不具备则返回false 
        return false; 
    } 
 
    window.ADS.addEvent = addEvent; 
 
    /** 
     * load事件在嵌入图像载入完成之前运行 
     * @param {Function} loadEvent 
     * @param {Boolean} waitForImages 当为true时,调用原始的addEvent()方法,等待加载完毕后才执行 
     * demo: 
     *      ADS.addLoadEvent(function(w3cEvent){ 
     *          //... 
     *      }); 
     */ 
    function addLoadEvent(loadEvent, waitForImages) { 
        if (!isCompatible()) { 
            return false; 
        } 
 
        //如果等待标记是true则使用常规的添加事件的方法 
        if (waitForImages) { 
            return addEvent(window, 'load', loadEvent); 
        } 
 
        //否则使用一些不同的方式包装loadEvent()方法 
        //以便为this关键字制定正确的内容,同时确定 
        //事件不会被执行两次 
        var init = function () { 
            //如果这个函数已经被调用过了则返回 
            if (init.done) { 
                return; 
            } 
 
            //标记这个函数以便检测它是否运行过 
            init.done = true; 
 
            //在document的环境中运行载入事件 
            loadEvent.apply(document, arguments); 
        }; 
 
        //为DOMContentLoaded事件注册事件侦听器 
        if (document.addEventListener) { 
            document.addEventListener('DOMContentLoaded', init, false); 
        } 
 
        //对于safari,使用setInterval()函数检测 
        //document是否载入完成 
        if (/WebKit/i.test(navigator.userAgent)) { 
            var _timer = setInterval(function () { 
                if (/loaded|complete/.test(document.readyState)) { 
                    clearInterval(_timer); 
                    init(); 
                } 
            }, 10); 
        } 
 
        //对于IE(使用条件注释) 
        //附加一个在载入过程最后执行的脚本 
        //并检测该脚本是否载入完成 
        /*@cc_on @*/ 
        /*@if (@_win32) 
         document.write("<script id=_ie_onload defer src=javascript:void(0)><\/script>"); 
         var script = document.getElementById('_ie_onload'); 
         script.onreadystatechange = function(){ 
         if((this.readyState === 'complete') || this.readyState === 'loaded'){ 
         init(); 
         } 
         }; 
         /*@end @*/ 
        return true; 
    } 
 
    window.ADS.addLoadEvent = addLoadEvent; 
 
    function removeEvent(node, type, listener) { 
        if (!(node = $(node))) { 
            return false; 
        } 
        if (node.removeEventListener) { 
            //W3C 方法 
            node.removeEventListener(type, listener, false); 
            return true; 
        } else if (node.detachEvent) { 
            //MSIE方法 
            node.detachEvent("on" + type, node[type + listener]); 
            node[type + listener] = null; 
            return true; 
        } 
        //若两种方法都不具备则返回false 
        return false; 
    } 
 
    window.ADS.removeEvent = removeEvent; 
 
    /** 
     * 获取event事件对象 
     * @param w3cEvent 
     * @return {*|Event} 
     */ 
    function getEventObject(w3cEvent) { 
        return w3cEvent || window.event; 
    } 
 
    window.ADS.getEventObject = getEventObject; 
 
    function getTarget(event) { 
        event = event || getEventObject(event); 
 
        //如果是w3c或MSIE的模型 
        var target = event.target || event.srcElement; 
 
        //如果像Safari中一样是一个文本节点 
        //重新将目标对象指定为父元素 
        if (target.nodeType === 3) { 
            target = target.parentNode; 
        } 
 
        return target; 
    } 
 
    window.ADS.getTarget = getTarget; 
 
    function getMouseButton(event) { 
        event = event || getEventObject(event); 
 
        //使用适当的属性初始化一个对象变量 
        var buttons = { 
            left: false, 
            middle: false, 
            right: false 
        }; 
 
        //检查event对象的toString()方法的值 
        //w3c有toString方法并且此时该方法的 
        // 返回应该是MouseEvent 
        if (event.toString() && event.toString().indexOf('MouseEvent') !== -1) { 
            //w3c 
            switch (event.button) { 
                case 0: 
                    buttons.left = true; 
                    break; 
                case 1: 
                    buttons.middle = true; 
                    break; 
                case 2: 
                    buttons.right = true; 
                    break; 
                default: 
                    break; 
            } 
        } else if (event.button) { 
            //MSIE 
            switch (event.button) { 
                case 1: 
                    buttons.left = true; 
                    break; 
                case 2: 
                    buttons.right = true; 
                    break; 
                case 3: 
                    buttons.left = true; 
                    buttons.right = true; 
                    break; 
                case 4: 
                    buttons.middle = true; 
                    break; 
                case 5: 
                    buttons.left = true; 
                    buttons.middle = true; 
                    break; 
                case 6: 
                    buttons.middle = true; 
                    buttons.right = true; 
                    break; 
                case 7: 
                    buttons.left = true; 
                    buttons.middle = true; 
                    buttons.right = true; 
                    break; 
                default: 
                    break; 
 
            } 
        } else { 
            return false; 
        } 
        return buttons; 
    } 
 
    window.ADS.getMouseButton = getMouseButton; 
 
    /** 
     * 光标相对于文档原点的位置 
     * @param {event} event 
     * @return {Object} 
     */ 
    function getPointerPositionInDocument(event) { 
        event = event || getEventObject(event); 
        var x = event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)); 
        var y = event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)); 
        //现在x和y中包含着鼠标 
        //相对于文档原点的坐标 
        return { 
            x: x, 
            y: y 
        }; 
    } 
 
    window.ADS.getPointerPositionInDocument = getPointerPositionInDocument; 
 
    /** 
     * 获取键盘按键的Unicode值 
     * @param event 
     * @return {Object} 
     */ 
    function getKeyPressed(event) { 
        event = event || getEventObject(event); 
 
        //charCode for FF 
        var code = (typeof event.charCode === 'number') ? event.charCode : event.keyCode; 
        var value = String.fromCharCode(code); 
        return { 
            code: code, 
            value: value 
        }; 
    } 
 
    window.ADS.getKeyPressed = getKeyPressed; 
 
    /** 
     * getElementsByClassName(className, tag, parent)    获取class为className的DOM元素 
     * @param searchClass 类名 (第二个函数可实现多类名查询) 
     * @param node DOM元素 
     * @param tag 标签名 
     * @return {*} 
     */ 
    /*原书 
     function getElementsByClassName(className, tag, parent) { 
     parent = parent || document; 
     if (!(parent = $(parent))) { 
     return false; 
     } 
     //查找所有匹配的标签 
     //由于IE5不支持document.getElementsByTagName("*"),要使用分支document.all以防错误 
     var allTags = (tag == "*" && parent.all) ? parent.all : parent.getElementsByTagName(tag); 
     var matchingElements = []; 
     //创建一个正则表达式,来判断className是否正确 
     className = className.replace(/\-/g, "\\-"); 
     var regex = new RegExp("(^|\\s)" + className + "(\\s|$)"); 
     var element; 
     if (document.getElementsByClassName) { 
     return document.getElementsByClassName(className); 
     } else { 
     //检查每个元素 
     for (var i = 0; i < allTags.length; i++) { 
     element = allTags[i]; 
     if (regex.test(element.className)) { 
     matchingElements.push(element); 
     } 
     } 
     //返回任何匹配的元素 
     return matchingElements; 
     } 
     }*/ 
    function getElementsByClassName(searchClass, tag, node) { 
        node = node || document; 
        tag = tag || "*"; 
        if (!(node = $(node))) { 
            return false; 
        } 
        //如果支持原生getElementsByClassName 
        if (document.getElementsByClassName) { 
            //获取所有匹配的className的DOM元素 
            var nodes = node.getElementsByClassName(searchClass), 
                result = nodes; 
            //如果tag被定义了 
            if (tag !== '*') { 
                result = []; 
                for (var i = 0; node = nodes[i]; i++) { 
                    //匹配标签名为非“*”的标签 
                    if (node.tagName.toLowerCase() === tag.toLowerCase()) { 
                        result.push(node); 
                    } 
                } 
            } 
            return result; 
        } else { 
            //不支持原生getElementsByClassName的 
            var classes = searchClass.split(" "), //要查询的所有className 
                elements = (tag === "*" && node.all) ? node.all : node.getElementsByTagName(tag), //获取所有匹配的标签DOM元素 
                patterns = [], 
                returnElements = [], 
                current, 
                match; 
            var i = classes.length; 
            while (--i >= 0) { 
                patterns.push(new RegExp("(^|\\s)" + classes[i] + "(\\s|$)")); 
            } 
            var j = elements.length; 
            while (--j >= 0) { 
                current = elements[j]; 
                match = false; 
                //每个元素的className分别和要查询的className对比 
                for (var k = 0, kl = patterns.length; k < kl; k++) { 
                    match = patterns[k].test(current.className); 
                    if (!match) { 
                        break; 
                    } 
                } 
                if (match) { 
                    returnElements.push(current); 
                } 
            } 
            return returnElements; 
        } 
    } 
 
    window.ADS.getElementsByClassName = getElementsByClassName; 
    //运用:var a = ADS.getElementsByClassName("li", "li", document); 
 
    function toggleDisplay(node, value) { 
        if (!(node = $(node))) { 
            return false; 
        } 
        if (node.style.display !== "none") { 
            node.style.display = "none"; 
        } else { 
            node.style.display = value || ""; 
        } 
        return true; 
    } 
 
    window.ADS.toggleDisplay = toggleDisplay; 
 
    /** 
     * DOM操作:将节点插入到目标节点之后 
     * @param node 新节点 
     * @param referenceNode 目标节点 
     * @return {*} 
     * etc: ADS.insertAfter("l1","l2"); 
     */ 
    function insertAfter(node, referenceNode) { 
        if (!(node = $(node))) { 
            return false; 
        } 
        if (!(referenceNode = $(referenceNode))) { 
            return false; 
        } 
        return referenceNode.parentNode.insertBefore(node, referenceNode.nextSibling); 
    } 
 
    window.ADS.insertAfter = insertAfter; 
 
    /** 
     * 删除所有子节点 
     * @param parent 父节点 
     * @return {*} 
     */ 
    function removeChildren(parent) { 
        if (!(parent = $(parent))) { 
            return false; 
        } 
        //当存在子节点时删除该子节点 
        while (parent.firstChild) { 
            parent.firstChild.parentNode.removeChild(parent.firstChild); 
        } 
        //再返回父元素,以便实现方法连缀 
        return parent; 
    } 
 
    window.ADS.removeChildren = removeChildren; 
 
    /** 
     * 添加为节点第一个子节点 
     * @param parent 父节点 
     * @param newChild 新节点 
     * @return {*} 
     */ 
    function prependChild(parent, newChild) { 
        if (!(parent = $(parent))) { 
            return false; 
        } 
        if (!(newChild = $(newChild))) { 
            return false; 
        } 
        if (parent.firstChild) { 
            //如果存在一个子节点,则在这个字节点之前插入 
            parent.insertBefore(newChild, parent.firstChild); 
        } else { 
            //如果没有子节点则直接添加 
            parent.appendChild(newChild); 
        } 
        //再返回父元素,以便实现方法连缀 
        return parent; 
    } 
 
    window.ADS.prependChild = prependChild; 
 
    /** 
     * 绑定函数到指定作用域 
     * @param obj 对象 
     * @param func 函数 
     * @return {Function} 
     */ 
    function bindFunction(obj, func) { 
        return function () { 
            //调用func函数,指定环境为obj,添加arguments参数 
            func.apply(obj, arguments); 
        }; 
    } 
 
    window.ADS.bindFunction = bindFunction; 
 
    /** 
     * 获取浏览器窗口大小 
     * @return {Object} 
     */ 
    function getWinSize() { 
        var de = document.documentElement; 
        return { 
            'width': (window.innerWidth || (de && de.clientWidth) || document.body.clientWidth), 
            'height': (window.innerHeight || (de && de.clientHeight) || document.body.clientHeight) 
 
        }; 
    } 
 
    window.ADS.getWinSize = getWinSize; 
 
    /** 
     * 定义DOM常量 
     * @type {Object} 
     */ 
    window.ADS.node = { 
        ELEMENT_NODE: 1, 
        ATTRIBUTE_NODE: 2, 
        TEXT_NODE: 3, 
        CDATA_SECTION_NODE: 4, 
        ENTITY_REFERENCE_NODE: 5, 
        ENTITY_NODE: 6, 
        PROCESSING_INSTRUCTION_NODE: 7, 
        COMMENT_NODE: 8, 
        DOCUMENT_NODE: 9, 
        DOCUMENT_TYPE_NODE: 10, 
        DOCUMENT_FRAGMENT_NODE: 11, 
        NOTATION_NODE: 12 
    }; 
 
    /** 
     * 遍历DOM,并调用函数(效率最慢) 
     * @param {Function} func 
     * @param {Node} node 
     */ 
    function walkElementsLinear(func, node) { 
        var root = node || window.document; 
        var nodes = root.getElementsByTagName('*'); 
        for (var i = 0, len = nodes.length; i < len; i++) { 
            func.call(nodes[i]); 
        } 
    } 
 
    window.ADS.walkElementsLinear = walkElementsLinear; 
 
    /** 
     * 迭代DOM 
     * @param {Function} func 
     * @param {Node} node 
     * @param {Number} depth 
     * @param returnedFromParent 
     */ 
    function walkTheDOMRecursive(func, node, depth, returnedFromParent) { 
        var root = node || window.document; 
        //父节点调用函数的返回值,作为子节点调用函数时候的参数 
        returnedFromParent = func.call(root, depth++, returnedFromParent); 
        node = root.firstChild; 
        while (node) { 
            //迭代该节点后代元素 
            walkTheDOMRecursive(func, node, depth, returnedFromParent); 
            //移向下一个子节点 
            node = node.nextSibling; 
        } 
    } 
 
    window.ADS.walkTheDOMRecursive = walkTheDOMRecursive; 
 
    /** 
     * 迭代DOM节点的属性 
     * @param {Node} node 
     * @param {Function} func 
     * @param {Number} depth 
     * @param returnedFromParent 
     */ 
    function walkTheDOMWithAttributes(node, func, depth, returnedFromParent) { 
        var root = node || window.document; 
        returnedFromParent = func(root, depth++, returnedFromParent); 
        if (root.attributes) { 
            for (var i = 0; i < root.attributes.length; i++) { 
                walkTheDOMWithAttributes(root.attributes[i], func, depth - 1, returnedFromParent); 
            } 
        } 
        if (root.nodeType !== window.ADS.node.ATTRIBUTE_NODE) { 
            node = root.firstChild; 
            while (node) { 
                walkTheDOMWithAttributes(node, func, depth, returnedFromParent); 
                node = node.nextSibling; 
            } 
        } 
    } 
 
    window.ADS.walkTheDOMWithAttributes = walkTheDOMWithAttributes; 
 
    function walkTheDOM(node, func) { 
        func(node); 
        node = node.firstChild; 
        while (node) { 
            walkTheDOM(node, func); 
            node = node.nextSibling; 
        } 
    } 
 
    window.ADS.walkTheDOM = walkTheDOM; 
 
    /** 
     * 把word-word转换为wordWord 
     * @param {String} s 
     * @return {String|XML|void} 
     */ 
    function camelize(s) { 
        return s.replace(/-(\w)/g, function (strMatch, p1) {    //strMatch为正则匹配的字符 
            //p1为\w匹配的一个字符 
            return p1.toUpperCase(); 
        }); 
    } 
 
    window.ADS.camelize = camelize; 
 
    /** 
     * 阻止事件冒泡 
     * @param {event} eventObject 
     */ 
    function stopPropagation(eventObject) { 
        eventObject = eventObject || getEventObject(eventObject); 
        if (eventObject.stopPropagation) { 
            eventObject.stopPropagation(); 
        } else { 
            eventObject.cancelBubble = true; 
        } 
    } 
 
    window.ADS.stopPropagation = stopPropagation; 
 
    /** 
     * 取消默认事件 
     * @param {event} eventObject 
     * 可被取消的DOM事件: 
     * click, mousedown, mouseup, mouseover, mouseout, submit, DOMActive及键盘事件 
     */ 
    function preventDefault(eventObject) { 
        eventObject = eventObject || getEventObject(eventObject); 
        if (eventObject.preventDefault) { 
            eventObject.preventDefault(); 
        } else { 
            eventObject.returnValue = false; 
        } 
    } 
 
    window.ADS.preventDefault = preventDefault; 
 
    function uncamelize(property, splitChar) { 
        return property.replace(/([a-z])([A-Z])/, '$1' + splitChar + '$2').toLowerCase(); 
    } 
 
    window.ADS.uncamelize = uncamelize; 
 
    /** 
     * 用过ID修改单个元素的样式 
     * @param {Node} element 元素节点 
     * @param {Object} styles 样式对象 
     */ 
    function setStyleById(element, styles) { 
        //取得对象的引用 
        if (!(element = $(element))) { 
            return false; 
        } 
        //循环遍历styles对象并应用每个属性 
        for (var property in styles) { 
            //检测是否是样式属性 
            if (!styles.hasOwnProperty(property)) { 
                continue; 
            } 
 
            try { 
                //DOM2样式规范方法 
                element.style.setProperty(uncamelize(property, '-'), styles[property], null); 
            } catch (ex) { 
                //备用方法 
                element.style[camelize(property)] = styles[property]; 
            } 
        } 
        return true; 
    } 
 
    window.ADS.setStyle = setStyleById; 
    window.ADS.setStyleById = setStyleById; 
 
 
    /** 
     * 通过类名修改多个元素的样式 
     * @param {Node} parent 
     * @param {String} tag 
     * @param {String} className 
     * @param {Object} styles 
     */ 
    function setStylesByClassName(parent, tag, className, styles) { 
        if (!(parent = $(parent))) { 
            return false; 
        } 
        var elements = getElementsByClassName(className, parent, tag); 
        for (var i = 0; i < elements.length; i++) { 
            setStyleById(elements[i], styles); 
        } 
        return true; 
    } 
 
    window.ADS.setStylesByClassName = setStylesByClassName; 
 
    /** 
     * 涌过标签名修改多个元素的样式 
     * @param {String} tagname 
     * @param {Object} styles 
     * @param {Node} parent 
     */ 
    function setStylesByTagName(tagname, styles, parent) { 
        parent = $(parent) || document; 
        var elements = parent.getElementsByTagName(tagname); 
        for (var i = 0, len = elements.length; i < len; i++) { 
            setStyleById(elements[i], styles); 
        } 
    } 
 
    window.ADS.setStylesByTagName = setStylesByTagName; 
 
    /** 
     * 取得包含元素className的数组 
     * @param {Node} element 
     */ 
    function getClassName(element) { 
        if (!(element = $(element))) { 
            return false; 
        } 
        return element.className.replace(/\s+/g, ' ').split(' '); 
    } 
 
    window.ADS.getClassName = getClassName; 
 
    /** 
     * 检察院苏中是否存在某个className 
     * @param {Node} element 
     * @param {String} className 
     * @return {Boolean} 
     */ 
    function hasClassName(element, className) { 
        if (!(element = $(element))) { 
            return false; 
        } 
        var classes = getClassName(element); 
        for (var i = 0; i < classes.length; i++) { 
            //检测className是否匹配,如果是则返回true 
            if (classes[i] === className) { 
                return true; 
            } 
        } 
        return false; 
    } 
 
    window.ADS.hasClassName = hasClassName; 
 
    /** 
     * 为元素添加className 
     * @param element 
     * @param className 
     * @return {Boolean} 
     */ 
    function addClassName(element, className) { 
        if (!(element = $(element))) { 
            return false; 
        } 
        //将className添加到当前className的末尾 
        //如果没有className,则不包含空格 
        element.className += (element.className ? ' ' : '') + className; 
        return true; 
    } 
 
    window.ADS.addClassName = addClassName; 
 
    /** 
     * 删除一个或多个类名 
     * @param element 
     * @param className 
     * @return {Boolean} 
     */ 
    function removeClassName(element, className) { 
        if (!(element = $(element))) { 
            return false; 
        } 
        className = (className || '').trim().replace(/\s+/g, ' '); 
        if (className === '') { 
            //未定义或者空的情况为删除所有类名 
            element.className = ''; 
        } else if (className.indexOf(' ') !== -1) { 
            //对多个以空格为分隔的类名进行处理,然后迭代 
            var classarr = className.split(' '); 
            for (var i = 0; i < classarr.length; i++) { 
                removeClassName(element, classarr[i]); 
            } 
        } else { 
            //对单个类名的处理 
            className = (' ' + className + ' '); 
            var elemClass = ' ' + element.className + ' '; 
            if (elemClass.indexOf(className) !== -1) { 
                element.className = elemClass.replace(className, ' ').replace(/\s+/g, ' ').trim(); 
            } else { 
                return false; 
            } 
        } 
        return true; 
    } 
 
    window.ADS.removeClassName = removeClassName; 
 
    /** 
     * 切换类名 
     * @param element 
     * @param className 
     */ 
    function toggleClassName(element, className) { 
        if (!hasClassName(element, className)) { 
            addClassName(element, className); 
        } else { 
            removeClassName(element, className); 
        } 
    } 
 
    window.ADS.toggleClassName = toggleClassName; 
 
    /** 
     * 添加样式表 
     * @param {String} url url地址 
     * @param {String} media 媒介类型 
     */ 
    function addStyleSheet(url, media) { 
        media = media || 'screen'; 
        var link = document.createElement('link'); 
        link.setAttribute('rel', 'stylesheet'); 
        link.setAttribute('type', 'stylesheet'); 
        link.setAttribute('href', url); 
        link.setAttribute('media', media); 
        link.disabled = false; 
        document.getElementsByTagName('head')[0].appendChild(link); 
    } 
 
    window.ADS.addStyleSheet = addStyleSheet; 
 
    /** 
     * 禁用样式表 
     * @param url 
     * @param media 
     */ 
    function removeStyleSheet(url, media) { 
        var styles = getStyleSheets(url, media); 
        for (var i = 0; i < styles.length; i++) { 
            // for standard and IE 
            var node = styles[i].ownerNode || styles[i].owningElement; 
            //禁用样式表 
            styles[i].disabled = true; 
            //移除节点 
            node.parentNode.removeChild(node); 
        } 
    } 
 
    window.ADS.removeStyleSheet = removeStyleSheet; 
 
    /** 
     * 通过URL取得包含所有样式表的数组 
     * @param url 
     * @param media 
     * @return {Array} 
     */ 
    function getStyleSheets(url, media) { 
        var sheets = []; 
        for (var i = 0; i < document.styleSheets.length; i++) { 
            if (url && document.styleSheets[i].href.indexOf(url) === -1) { 
                continue; 
            } 
            if (media) { 
                //规范化media字符串 
                media = media.replace(/,\s*/, ','); 
                var sheetMedia; 
 
                if (document.styleSheets[i].media.mediaText) { 
                    //DOM方法 
                    sheetMedia = document.styleSheets[i].media.mediaText.replace(/,\s*/, ','); 
                    //Safari会添加额外的都好和空格 
                    sheetMedia = sheetMedia.replace(/,\s*$/, ''); 
                } else { 
                    // MSIE 
                    sheetMedia = document.styleSheets[i].media.replace(/,\s*/, ','); 
                } 
 
                //如果media不匹配则跳过 
                if (media !== sheetMedia) { 
                    continue; 
                } 
            } 
            sheets.push(document.styleSheets[i]); 
        } 
        return sheets; 
    } 
 
    window.ADS.getStyleSheets = getStyleSheets; 
 
    /** 
     * 编辑一条样式规则 
     * @param {String} selector 选择器 
     * @param {Object} styles 样式对象 
     * @param {String || Array} url url地址或者styleSheets数组 
     * @param {String} media 媒介查询 
     */ 
    function editCSSRule(selector, styles, url, media) { 
 
        var styleSheets = (typeof url === 'array') ? url : getStyleSheets(url, media); 
 
        for (var i = 0; i < styleSheets.length; i++) { 
            // 取得规则列表 
            // DOM2样式规范方法是styleSheets[i].cssRules 
            // MSIE方法是styleSheets[i].rules 
            var rules = styleSheets[i].cssRules || styleSheets[i].rules; 
            if (!rules) { 
                continue; 
            } 
 
            // 由于MSIE默认使用大写故转换为大写形式 
            // 如果拟使用的是区分大小写的id,则可能会 
            // 导致冲突 
            selector = selector.toUpperCase(); 
 
            for (var j = 0; j < rules.length; j++) { 
                // 检查是否匹配 
                if (rules[i].selectorText.toUpperCase() === selector) { 
                    for (var property in styles) { 
                        if (!styles.hasOwnProperty(property)) { 
                            continue; 
                        } 
                        // 设置新的样式属性 
                        rules[i].style[camelize(property)] = styles[property]; 
                    } 
                } 
            } 
        } 
    } 
 
    window.ADS.editCSSRule = editCSSRule; 
 
    /** 
     * 添加一条css规则 
     * @param selector 
     * @param styles 
     * @param {Number} index 列表规则的序号 
     * @param url 
     * @param media 
     */ 
    function addCSSRule(selector, styles, index, url, media) { 
        var declaration = ''; 
 
        // 根据styles参数(样式对象)构建声明字符串 
        for (var property in styles) { 
            if (!styles.hasOwnProperty(property)) { 
                continue; 
            } 
            declaration += property + ':' + styles[property] + ';'; 
        } 
 
        var styleSheets = (typeof url === 'array') ? url : getStyleSheets(url, media); 
        var newIndex; 
        for (var i = 0; i < styleSheets.length; i++) { 
            // 添加规则 
            if (styleSheets[i].insertRule) { 
                // DOM2样式规范方法 
                // index = length 是列表末尾 
                newIndex = (index >= 0 ? index : styleSheets[i].cssRules.length); 
                styleSheets[i].insertRule( 
                    selector + ' { ' + declaration + ' } ', 
                    newIndex 
                ); 
            } else if (styleSheets[i].addRule) { 
                // MSIE的方法 
                // index = -1 是列表末尾 
                newIndex = (index >= 0 ? index : -1); 
                styleSheets[i].addRule(selector, declaration, newIndex); 
            } 
        } 
    } 
 
    window.ADS.addCSSRule = addCSSRule; 
 
    /** 
     * 取得一个元素的计算样式 
     * @param {Node} element 元素节点 
     * @param {String} property css属性 
     *      格式:font-size 
     * @return {*} 
     */ 
    function getStyle(element, property) { 
        if (!(element = $(element)) || !property) { 
            return false; 
        } 
        // 检测元素style属性中的值 
        // 只能获取嵌入方式定义的样式 
        var value = element.style[camelize(property)]; 
        if (!value) { 
            // 取得计算的样式值 
            if (document.defaultView && document.defaultView.getComputedStyle) { 
                // DOM方法 
                var css = document.defaultView.getComputedStyle(element, null); 
                // 也可以使用css[camelize(property)] 
                value = css ? css.getPropertyValue(property) : null; 
            } else if (element.currentStyle) { 
                // MSIE方法 
                value = element.currentStyle[camelize(property)]; 
            } 
        } 
        // 返回字符串不包括auto的值 
        return value === 'auto' ? '' : value; 
    } 
 
    window.ADS.getStyle = getStyle; 
    window.ADS.getStyleById = getStyle; 
 
    /** 
     * 检查JSON文本,确保安全 
     * @param {String} s JSON字符串 
     * @param {Function} filter 过滤方法 
     * @return {*} 
     */ 
    function parseJSON(s, filter) { 
        var j; 
 
        /** 
         * 递归地遍历了新生成的结构 
         而且将每个名/值对传递给一个过滤函数,以便进行 
         可能的转换 
         * @param k 
         * @param v 
         * @return {*} 
         */ 
        function walk(k, v) { 
            if (v && typeof v === 'object') { 
                for (var i in v) { 
                    if (v.hasOwnProperty(i)) { 
                        v[i] = walk(i, v[i]); 
                    } 
                } 
            } 
            return filter(k, v); 
        } 
 
        /* 
         解析通过3个阶段进行。第一阶段,通过正则表达式 
         检测JSON文本,查找非JSON字符串。其中,特别关注 
         “()”和"new",因为它们会引起语句的调用,还有“=”, 
         因为它会导致变量的值发生改变。不过,为安全起见 
         这里会拒绝所有不希望出现的字符串 
         */ 
        /* 
         首先这个串分成两部分,看中间的或符号(|) 
         "(\\.|[^\\\n\r])*?"和[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t] 
         先分解"(\\.|[^\\\n\r])*?" 
         它匹配一个双引号的字符串,两边引号不说了括号内一个“|”又分成两段 “\\.“匹配一个转义字符 
         比如js字符串里的\n,\r,\',\"等。[^\\\n\r]匹配一个非\,回车换行的字符 其实它就是js里字符串的规则---不包含回车换行,回车换行用 \n\r表示,\后面跟一个字符表示转义 
         其次看[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t] 
         它匹配一个单个字符,这个字符可以是 ,,:,{,},[,],数字,除 "\n" 之外的任何单个字符,-,+,E,a,e,f,l,n,r-u之间的字符,回车,换行,制表符, 
         */ 
        if (/^("(\\.|[^"\\\n\r])*?"|[,:\{\}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(s)) { 
            /* 
             第二阶段,使用eval()函数将JSON文本编译为js 
             结构。其中的“{”操作符具有语法上的二义性,即它可 
             以定义一个语句块,也可以表示对象字面量。这里将 
             JSON文本用括号括起来是为了消除这种二义性 
             */ 
            try { 
                j = eval('(' + s + ')'); 
            } catch (e) { 
                throw new SyntaxError('parseJSON'); 
            } 
        } else { 
            throw new SyntaxError('parseJSON'); 
        } 
 
        /* 
         在可选的第三阶段,代码递归地遍历了新生成的结构 
         而且将每个名/值对传递给一个过滤函数,以便进行 
         可能的转换 
         */ 
        if (typeof filter === 'function') { 
            j = walk('', j); 
        } 
        return j; 
    } 
 
    /** 
     * 设置XMLHttpRequest对象的各个不同的部分 
     * @param url 
     * @param options 
     *      参数options的成员属性 
     *      method, 适用于请求的方法,默认为GET。 
     *      send, 是一个包含在XMLHttpRequest.send()中的可选字符串,默认为null。 
     *      loadListener, 是当readyState为1时调用的onreadystatechange侦听器 
     *      loadedListener, 是当readyState为2时调用的onreadystatechange侦听器。 
     *      interactiveListener, 是当readyState为3时调用的onreadystatechange侦听器。 
     *      jsResponseListener, 是当请求成功并且响应的Content-Type为application/javascript或text/javascript时调用的侦听器,这个侦听器将从响应中取得js字符串作为其第一个参数。如果要执行该js字符串,必须使用eval()方法。 
     *      jsonResponseListener, 是当请求成功并且响应的Content-Type为application/json时调用的侦听器。这个侦听器将从响应中取得JSON对象作为其第一个参数。 
     *      xmlResponseListener, 是当请求成功并且响应的Content-Type为application/xml或application/xhtml+xml时调用的侦听器。这个侦听器将从响应中取得的XML DOM文档作为其第一个参数。 
     *      htmlResponseListener, 是当请求成功并且响应的content-Type为text/html时调用的侦听器。这个侦听器将从响应中取得的HTML字符串作为其第一个参数。 
     *      completeListener, 是当上面所列的针对Content-Type的响应侦听器调用之后被调用的侦听器。这个方法总是在成功的响应最后被调用,也就是说如果相应中没有适当的Content-Type头部信息,那么你可以制定这个方法作为兜底儿的侦听器。 
     *      errorListener, 是当响应状态值不是200也不是0时被调用的侦听器。如果是在不会提供适当响应代码的系统上运行(如硬盘驱动器中的本地文件系统)XMLHttpRequest,那么状态值将始终为0.在这种情况下,只有completeListener会被调用。 
     */ 
    /* 
     demo: 
     ADS.ajaxRequest('/path/to/script/',{ 
     method:'GET', 
     completeListener:function(){ 
     alert(this.responseText); 
     } 
     }); 
     */ 
    // 因为使用了call和apply方法,此时的this引用的是 
    // 请求对象而不是onreadystatechange方法。 
    function getRequestObject(url, options) { 
        // 初始化请求对象 
        var req = false; 
        if (window.XMLHttpRequest) { 
            req = getRequestObject.req = new window.XMLHttpRequest(); 
        } else if (window.ActiveXObject) { 
            req = getRequestObject.req = new ActiveXObject('Microsoft.XMLHTTP'); 
        } 
 
        if (!req) { 
            return false; 
        } 
 
        // 定义默认的选项 
        options = options || {}; 
        options.method = options.method || 'GET'; 
        options.send = options.send || null; 
 
        // 为请求的每个阶段定义不同的侦听器 
        req.onreadystatechange = function () { 
            switch (req.readyState) { 
                case 1: 
                    // 载入中 
                    if (options.loadListener) { 
                        options.loadListener.apply(req, arguments); 
                    } 
                    break; 
                case 2: 
                    // 载入完成 
                    if (options.loadedListener) { 
                        options.loadedListener.apply(req, arguments); 
                    } 
                    break; 
                case 3: 
                    // 交互 
                    if (options.interactiveListener) { 
                        options.interactiveListener.apply(req, arguments); 
                    } 
                    break; 
                case 4: 
                    // 完成 
                    // 如果失败则抛出错误 
                    try { 
                        if (req.status && (req.status >= 200 && req.status < 300) || req.status === 304) { 
                            // 针对Content-type的特殊侦听器 
                            // 由于Content-Type头部中可能包含字符集,如: 
                            // Content-Type: text/html; charset=ISO-8859-4 
                            // 因此通过正则表达式提取出所需的部分 
                            var contentType = req.getResponseHeader('Content-Type'); 
                            var mimeType = contentType.match(/\s*([^;]+)\s*(;|$)/i)[1]; 
                            switch (mimeType) { 
                                case 'text/javascript': 
                                case 'application/javascript': 
                                    // 响应时javascript,因此以 
                                    // req.responseText作为回调函数 
                                    if (options.jsResponseListener) { 
                                        options.jsResponseListener.call(req, req.responseText); 
                                    } 
                                    break; 
                                case 'application/json': 
                                    // 响应是JSON,因此需要用匿名函数对 
                                    // req.responseText进行解析 
                                    // 已返回作为回调参数的JSON对象 
                                    if (options.jsonResponseListener) { 
                                        var json; 
                                        try { 
                                            json = parseJSON(req.responseText); 
                                        } catch (e) { 
                                            json = false; 
                                        } 
                                        options.jsonResponseListener.call(req, json); 
                                    } 
                                    break; 
                                case 'text/xml': 
                                case 'application/xml': 
                                case 'application/xhtml+xml': 
                                    // 响应是XML,因此以 
                                    // req.responseXML作为 
                                    // 回调的参数 
                                    // 此时是Document对象 
                                    if (options.xmlResponseListener) { 
                                        options.xmlResponseListener.call(req, req.responseText); 
                                    } 
                                    break; 
                                case 'text/html': 
                                    // 响应是HTML,因此以 
                                    // req.responseText作为 
                                    // 回调的参数 
                                    if (options.htmlResponseListener) { 
                                        options.htmlResponseListener.call(req, req.responseText); 
                                    } 
                                    break; 
                                default: 
                                    break; 
                            } 
 
                            // 针对响应成功完成的侦听器 
                            if (options.completeListener) { 
                                options.completeListener.apply(req, arguments); 
                            } 
                        } else { 
                            // 相应完成但却存在错误 
                            if (options.errorListener) { 
                                options.errorListener.apply(req, arguments); 
                            } 
                        } 
                    } catch (e) { 
                        // 忽略错误 
                    } 
                    break; 
            } 
        }; 
 
        // 开启请求 
        req.open(options.method, url, true); 
        // 添加特殊的头部信息以标识请求 
        req.setRequestHeader('X-ADS-Ajax-Request', 'AjaxRequest'); 
        return req; 
    } 
 
    window.ADS.getRequestObject = getRequestObject; 
 
    // 通过简单的包装getRequestObject()和send() 
    // 方法发送XMLHttpRequest对象的请求 
    function ajaxRequest(url, options) { 
        var req = getRequestObject(url, options); 
        req.send(options.send); 
        return req; 
    } 
 
    window.ADS.ajaxRequest = ajaxRequest; 
 
 
    /** 
     * 此处的XssHttpRequest对象在模拟了某些XMLHttpRequest对象属性的基础上,还添加了以下一些属性 
     * responseJSON。 包含相应的结果,这个属性已经是一个js对象了,因此不需要再使用eval(); 
     * status. 在这里可能的值有如下两个 
     *      1: 表示成功 
     *      2: 表示存在错误 
     * statusText。 包含错误的原因。 
     * 可以通过在下列侦听器内使用this关键字来访问以上属性 
     * loadedListener。 当对象处于载入完成状态时调用。 
     * waitListener。 当对象等待响应时调用。 
     * completeListener。 当对象取得成功的响应后调用。 
     * errorListener。 当脚本载入外部脚本失败或载入的脚本格式不正确时调用。 
     * 
     * 为了保证对象正确运行,相应必须要调用GET变量中所引用的js函数,一般而言,最好的方式就是想这个函数中传递一个JSON对象,但如果你想传递XML文件或其他信息,也可以简单的将这些信息包含在JSON对象中,然后用过响应侦听器来按照需要解析这些信息。 
     */ 
    // XssHttpRequest对象的计数器 
    var XssHttpRequestCount = 0; 
    // XssHttpRequest对象的一个 
    // 跨站点<script>标签的实现 
    var XssHttpRequest = function () { 
        this.requestID = 'XSS_HTTP_REQUEST_' + (++XssHttpRequestCount); 
    }; 
    XssHttpRequest.prototype = { 
        url: null, 
        scriptObject: null, 
        responseJSON: null, 
        status: 0, 
        readyState: 0, 
        timeout: 30000, 
        onreadystatechange: function () { 
        }, 
        setReadyState: function (newReadyState) { 
            // 如果比当前状态更新 
            // 则只更新就绪状态 
            if (this.readyState < newReadyState || newReadyState === 0) { 
                this.readyState = newReadyState; 
                this.onreadystatechange(); 
            } 
        }, 
        open: function (url, timeout) { 
            this.timeout = timeout || this.timeout; 
            // 将以革名为XSS_HTTP_REQUEST_CALLBACK 
            // 的特殊变量附加给URL,其中包含本次请求的 
            // 回调函数的名称 
            this.url = url + 
                ((url.indexOf('?') !== -1) ? '&' : '?') + 
                'XSS_HTTP_REQUEST_CALLBACK=' + 
                this.requestID + 
                '_CALLBACK'; 
            this.setReadyState(0); 
        }, 
        send: function () { 
            var requestObject = this; 
            // 创建一个载入外部数据的新script对象 
            this.scriptObject = document.createElement('script'); 
            this.scriptObject.setAttribute('id', this.requestID); 
            this.scriptObject.setAttribute('type', 'text/javascript'); 
            // 汕尾设置src属性,也先不降其添加到文档 
 
            // 创建一个在给定的毫秒数之后触发的 
            // setTimeout()方法。如果在给定的时间 
            // 内脚本没有载入完成,则取消载入 
            var timeoutWatcher = setTimeout(function () { 
                // 在脚本晚于我们假定的停止时间之后载入的情况下 
                // 通过一个空方法来重新为window方法赋值 
                window[requestObject.requestID + '_CALLBACK'] = function () { 
                }; 
 
                // 移除脚本以防止进一步载入 
                requestObject.scriptObject.parentNode.removeChild(requestObject.scriptObject); 
 
                // 将状态设置为错误 
                requestObject.status = 2; 
                requestObject.statusText = 'Timeout after: ' + 
                    requestObject.timeout + 
                    ' milliseconds.'; 
 
                // 更新就绪状态 
                requestObject.setReadyState(2); 
                requestObject.setReadyState(3); 
                requestObject.setReadyState(4); 
            }, this.timeout); 
 
            // 在window对象中创建一个与 
            // 请求中的回调方法匹配的方法 
            // 在调用时负责处理请求的其他部分 
            window[this.requestID + '_CALLBACK'] = function (JSON) { 
                // 当脚本载入时将执行这个方法 
                // 同时传入预期的JSON对象 
 
                // 在请求载入成功时 
                // 清除timeoutWatcher方法 
                clearTimeout(timeoutWatcher); 
 
                // 更新就绪状态 
                requestObject.setReadyState(2); 
                requestObject.setReadyState(3); 
 
                // 将状态设置为成功 
                requestObject.responseJSON = JSON; 
                requestObject.status = 1; 
                requestObject.statusText = 'Loaded.'; 
 
                // 更新就绪状态 
                requestObject.setReadyState(4); 
            }; 
 
            // 设置初始就绪状态 
            this.setReadyState(1); 
 
            // 现在再设置src属性并将其添加 
            // 到文档头部。这样会载入脚本 
            this.scriptObject.setAttribute('src', this.url); 
            var head = document.getElementsByTagName('head')[0]; 
            head.appendChild(this.scriptObject); 
        } 
    }; 
 
    window.ADS.XssHttpRequest = XssHttpRequest; 
 
    // 设置XssHttpRequest对象的不同部分 
    function getXssRequestObject(url, options) { 
        var req = new XssHttpRequest(); 
 
        options = options || {}; 
        // 默认中断时间为30秒 
        options.timeout = options.timeout || 30000; 
        req.onreadystatechange = function () { 
            switch (req.readyState) { 
                // 载入中 
                case 1: 
                    if (options.loadListener) { 
                        options.loadListener.apply(req, arguments); 
                    } 
                    break; 
                case 2: 
                    // 载入完成 
                    if (options.loadedListener) { 
                        options.loadedListener.apply(req, arguments); 
                    } 
                    break; 
                case 3: 
                    // 交互 
                    if (options.interactiveListener) { 
                        options.interactiveListener.apply(req, arguments); 
                    } 
                    break; 
                case 4: 
                    // 完成 
                    if (req.status === 1) { 
                        if (options.completeListener) { 
                            options.completeListener.apply(req, arguments); 
                        } 
                    } else { 
                        if (options.errorListener) { 
                            options.errorListener.apply(req, arguments); 
                        } 
                    } 
                    break; 
                default: 
                    break; 
            } 
        }; 
        req.open(url, options.timeout); 
 
        return req; 
 
    } 
 
    window.ADS.getXssRequestObject = getXssRequestObject; 
 
    // 发送XssHttpRequest请求 
    function xssRequest(url, options) { 
        var req = getXssRequestObject(url, options); 
        req.send(null); 
        return req; 
    } 
 
    window.ADS.xssRequest = xssRequest; 
 
    //跟踪hash地址变化 
 
    /* 声称回调函数的一个辅助方法 */ 
    function makeCallback(method, target) { 
        return function () { 
            method.apply(target, arguments); 
        }; 
    } 
 
    /* 一个用来基于hash触发注册的方法的URL hash侦听器 */ 
    var actionPager = { 
        // 前一个hash 
        lastHash: '', 
        // 为hash模式注册的方法列表 
        callbacks: [], 
        // Safari历史记录列表 
        safariHistory: false, 
        // 对为IE准备的iframe的引用 
        msieHistory: false, 
        // 应该被转换的链接的类名 
        ajaxifyClassName: '', 
        // 应用程序的根目录。当创建hash时 
        // 它将是被清理后的URL 
        ajaxifyRoot: '', 
 
        /** 
         * 初始化页面(pager)功能 
         * @param {String} ajaxifyClass 预定义的类名,只有符合该类名的链接才具备功能,默认为 ADSActionLink 
         * @param {String} ajaxifyRoot 预定义的根路径 
         * @param {String} startingHash 预定义的hash值,默认为start 
         * @example actionPager.init(); 
         */ 
        init: function (ajaxifyClass, ajaxifyRoot, startingHash) { 
 
            this.ajaxifyClassName = ajaxifyClass || 'ADSActionLink'; 
            this.ajaxifyRoot = ajaxifyRoot || ''; 
 
            var ua = navigator.userAgent; 
            if (/Safari/i.test(ua) && /Version\/3/.test(ua)) { 
                this.safariHistory = []; 
            } else if (/MSIE/i.test(ua) && (parseInt(ua.split('MSIE')[1],10) < 8)) { 
                // 如果是MSIE 6/7,添加一个iframe以便 
                // 跟踪重写(override)后退按钮 
                this.msieHistory = document.createElement('iframe'); 
                this.msieHistory.setAttribute('id', 'msieHistory'); 
                this.msieHistory.setAttribute('name', 'msieHistory'); 
                this.msieHistory.setAttribute('src', 'fakepage'); 
                setStyleById(this.msieHistory, { 
                    'width': '100px', 
                    'height': '100px', 
                    'border': '1px solid black', 
                    'display': 'none', 
                    'z-index': -1 
                }); 
                document.body.appendChild(this.msieHistory); 
                this.msieHistory = frames.msieHistory; 
            } 
 
            // 将链接转换为Ajax链接 
            this.ajaxifyLinks(); 
 
            // 取得当前的地址 
            var locat = this.getLocation(); 
 
            // 检测地址中是否包含hash(来自书签) 
            // 或者是否已经提供了hash 
            if (!locat.hash && !startingHash) { 
                startingHash = 'start'; 
            } 
 
            // 按照需要保存hash 
            var ajaxHash = this.getHashFromURL(window.location.href) || startingHash; 
            this.addBackButtonHash(ajaxHash); 
 
            // 添加监视事件以观察地址栏中的变化 
            var watcherCallback = makeCallback(this.watchLocationForChange, this); 
 
            if (/MSIE/i.test(ua) && (parseInt(ua.split('MSIE')[1],10) < 8)) { 
                window.setInterval(watcherCallback, 200); 
            } else { 
                addEvent(window, 'hashchange', watcherCallback); 
            } 
 
        }, 
 
        /** 
         * 会自动将任何带标识的锚标签转换为页面(pager)可以识别的链接 
         */ 
        ajaxifyLinks: function () { 
            // 将链接转换为锚以便Ajax进行处理 
            var links = getElementsByClassName(this.ajaxifyClassName, 'a'); 
            for (var i = 0, len = links.length; i < len; i++) { 
                var curLink = links[i]; 
                if (hasClassName(curLink, 'ADSActionPagerModified')) { 
                    continue; 
                } 
 
                // 将href属性转换为#value形式 
                curLink.setAttribute('href', this.convertURLToHash(curLink.getAttribute('href'))); 
                addClassName(curLink, 'ADSActionPagerModified'); 
 
                // 注册单击事件以便在必要时添加历史纪录 
                addEvent(curLink, 'click', function () { 
                    if (this.href && this.href.indexOf('#') > -1) { 
                        actionPager.addBackButtonHash(actionPager.getHashFromURL(this.href)); 
                    } 
                }); 
            } 
        }, 
 
        /** 
         * 记录后退行为 
         * @param {String} ajaxHash hash值 
         * @return {Boolean} 
         */ 
        addBackButtonHash: function (ajaxHash) { 
            // 保存hash 
            if (!ajaxHash) { 
                return false; 
            } 
            if (this.safariHistory) { 
                // 为Safari使用特殊数组 
                if (this.safariHistory.length === 0) { 
                    this.safariHistory[window.history.length] = ajaxHash; 
                } else { 
                    this.safariHistory[window.history.length + 1] = ajaxHash; 
                } 
                return true; 
            } else if (this.msieHistory) { 
                // 在MSIE中通过导航iframe 
                this.msieHistory.document.execCommand('Stop'); 
                this.msieHistory.location.href = '/fakepage?hash=' + 
                    ajaxHash + 
                    '&title=' + 
                    document.title; 
                return true; 
            } else { 
                // 通过改变地址的值 
                // 使用makeCallback包装函数 
                // 以便在超时方法内部使this 
                // 引用actionPager 
                var timeoutCallback = makeCallback(function () { 
                    if (this.getHashFromURL(window.location.href) !== ajaxHash) { 
                        location.replace(location.href + '#' + ajaxHash); 
                    } 
                }, this); 
                setTimeout(timeoutCallback, 200); 
                return true; 
            } 
            return false; 
        }, 
 
        /** 
         * 间隔地检测hash的变化,还可执行注册的侦听器 
         */ 
        watchLocationForChange: function () { 
            var newHash; 
            // 取得新的hash值 
            if (this.safariHistory) { 
                // 在Safari中从历史记录数组中取得 
                if (this.safariHistory[history.length]) { 
                    newHash = this.safariHistory[history.length]; 
                } 
            } else if (this.msieHistory) { 
                // 在MSIE中从iframe的地址中取得 
                newHash = this.msieHistory.location.href.split('&')[0].split('=')[1]; 
            } else if (location.hash !== '') { 
                // 对其他浏览器从window.location中取得 
                newHash = this.getHashFromURL(window.location.href); 
            } 
 
            // 如果新hash与最后一次的hash不相同,则更新页面 
            if (newHash && this.lastHash !== newHash) { 
                if (this.msieHistory && this.getHashFromURL(window.location.href) !== newHash) { 
                    // 修复MSIE中的地址栏 
                    // 以便能适当地加上标签(或加入收藏夹) 
                    location.hash = newHash; 
                } 
 
                // 在发生异常的情况下使用try/catch 
                // 结构尝试执行任何注册的侦听器 
                try { 
                    if (this.callbacks.length) { 
                        this.executeListeners(newHash); 
                    } 
                    // 在通过处理程序添加任何 
                    // 新链接的情况下进行更新 
                    this.ajaxifyLinks(); 
                } catch (ex) { 
                    // 这里将捕获到回调函数中的任何异常JS 
                    alert(ex); 
                } 
 
                // 将其保存为最后一个hash 
                this.lastHash = newHash; 
            } 
        }, 
 
        /** 
         * 用于根据特殊的hash来注册侦听器 
         * @param {RegExp || String} regex 正则表达式 
         * @param {Function} method 执行的方法 
         * @param {Object || Element} context 执行环境,上下文 
         */ 
        register: function (regex, method, context) { 
            var obj = {'regex': regex}; 
            context = context || window; 
            // 一个已经指定的环境 
            obj.callback = function (matches) { 
                method.apply(context, matches); 
            }; 
 
            // 将侦听器添加到回调函数数则中 
            this.callbacks.push(obj); 
        }, 
 
        /** 
         * 把链接的URL地址转换为hash值 
         * @param {String} url 
         * @return {*} 
         */ 
        convertURLToHash: function (url) { 
            if (!url) { 
                // 没有url,因而返回一个'#' 
                return '#'; 
            } else if (url.indexOf('#') > -1) { 
                // 存在hash,因而返回它 
                return '#' + url.split('#')[1]; 
            } else { 
                // ie67会自动添加域名 
                // 如果URL中包含域名(MSIE)则去掉它 
                if (url.indexOf('://') > -1) { 
                    url = url.match(/:\/\/[^\/]+(.*)/)[1]; 
                } 
                // 按照init()约定去掉根目录 
                return '#' + url.substring(this.ajaxifyRoot.length); 
            } 
        }, 
 
        /** 
         * 从指定的URL中提取出hash值 
         * @param url 
         * @return {*} 
         */ 
        getHashFromURL: function (url) { 
            if (!url || url.indexOf('#') === -1) { 
                return ''; 
            } 
            return url.split('#')[1]; 
        }, 
 
        /** 
         * 获取当前URL地址 
         * @return {*} 
         */ 
        getLocation: function () { 
            // 检查hash 
            if (!window.location.hash) { 
                // 没有则生成一个 
                var url = { 
                    domain: null, 
                    hash: null 
                }; 
                if (window.location.href.indexOf('#') > -1) { 
                    var parts = window.location.href.split('#')[1]; 
                    url.domain = parts[0]; 
                    url.hash = parts[1]; 
                } else { 
                    url.domain = window.location; 
                } 
                return url; 
            } 
            return window.location; 
        }, 
 
        /** 
         * 执行侦听器 
         * @param hash 
         */ 
        executeListeners: function (hash) { 
            var matches; 
            // 执行与hash匹配的任何侦听器 
            for (var i = 0, len = this.callbacks.length; i < len; i++) { 
                if ((matches = hash.match(this.callbacks[i].regex))) { 
                    this.callbacks[i].callback(matches); 
                } 
            } 
 
        } 
    }; 
 
    window.ADS.actionPager = actionPager; 
 
    /* 一个复制对象的辅助方法 */ 
    function clone(myObj) { 
        if (typeof myObj !== 'object') { 
            return myObj; 
        } 
        if (myObj === null) { 
            return myObj; 
        } 
        var myNewObj = {}; 
        for (var i in myObj) { 
            myNewObj[i] = clone(myObj[i]); 
        } 
        return myNewObj; 
    } 
 
    /* 用于保存队列的数组 */ 
    var requestQueue = []; 
 
    /** 
     * 为ADS.ajaxRequest方法启用排队功能的包装对象 
     * @param url 
     * @param options 
     * @param queue 
     * @example 
     *      ADS.ajaxRequestQueue('/your/script/', { 
     *          completeListener: function(){ 
     *              alert(this.responseText); 
     *          } 
     *      }, 'Queue1'); 
     */ 
    function ajaxRequestQueue(url, options, queue) { 
        queue = queue || 'default'; 
 
        // 这个对象将把可选的侦听器包装在另一个函数中 
        // 因此,可选的对象必须唯一。否则,如果该方法 
        // 被调用时使用的是共享的可选对象,那么会导致 
        // 陷入递归中 
        options = clone(options) || {}; 
        if (!requestQueue[queue]) { 
            requestQueue[queue] = []; 
        } 
 
        // 当前一次请求完成时,需要使用completeListener 
        // 调用队列中的下一次请求。如果完成侦听器已经 
        // 有定义,那么需要首先调用它 
 
        // 取得旧侦听器 
        var userCompleteListener = options.completeListener; 
 
        // 添加新侦听器 
        options.completeListener = function () { 
            // 如果存在旧的侦听器则首先调用它 
            if (userCompleteListener) { 
                // this引用的是情求对象 
                userCompleteListener.apply(this, arguments); 
            } 
 
            // 从队列中移除这个请求 
            requestQueue[queue].shift(); 
 
            // 调用队列中的下一项 
            if (requestQueue[queue][0]) { 
                // 请求保存在req属性中,但为防止它是 
                // 一个POST请求,故也需包含send选项 
                var q = requestQueue[queue][0].req.send( 
                    requestQueue[queue][0].send 
                ); 
            } 
        }; 
 
        // 如果发生了错误,应该通过调用相应的 
        // 错误处理方法取消队列中的其他请求 
 
        // 取得旧侦听器 
        var userErrorListener = options.errorListener; 
 
        // 添加新侦听器 
        options.errorListener = function () { 
            if (userErrorListener) { 
                userErrorListener.apply(this, arguments); 
            } 
 
            // 由于已经调用了错误侦听器 
            // 股从队列中移除这个请求 
            requestQueue[queue].shift(); 
 
            // 由于出错需要取消队列中的其余请求,但首先要调用 
            // 每个请求的errorListener。通过调用队列中 
            // 下一项的错误侦听器就会才清楚所有排队的请求,因为在 
            // 链中的调研那个是一次发生的 
 
            // 检测队列中是否还存在请求 
            if (requestQueue[queue].length) { 
                // 取得下一项 
                var q = requestQueue[queue].shift(); 
 
                // 中断请求 
                q.req.abort(); 
 
                // 伪造请求对象,以便errorListener 
                // 认为请求已经完成并相应地运行 
 
                var fakeRequest = {}; 
 
                // 将status设置为0,将readyState设置为4 
                // 就好像请求虽然完成但却失败了一样 
                fakeRequest.status = 0; 
                fakeRequest.readyState = 4; 
 
                fakeRequest.responseText = null; 
                fakeRequest.responseXML = null; 
 
                // 设置错误信息,以便需要时显示 
                fakeRequest.statusText = 'A request in the queue received an error'; 
 
                // 调用状态改变,如果readyState是4,而 
                // status不是200,则会调用errorListener 
                q.error.apply(fakeRequest); 
            } 
        }; 
 
        // 将这个请求添加到队列中 
        requestQueue[queue].push({ 
            req: getRequestObject(url, options), 
            send: options.send, 
            error: options.errorListener 
        }); 
 
        // 如果队列的长度表明只有一个 
        // 项(即第一个)则调用请求 
        if (requestQueue[queue].length === 1) { 
            ajaxRequest(url, options); 
        } 
    } 
 
    window.ADS.ajaxRequestQueue = ajaxRequestQueue; 
 
    //客户端检测 
    var client = (function(){ 
        //呈现引擎 
        var engine = { 
            ie: 0, 
            gecko: 0, 
            webkit: 0, 
            khtml: 0, 
            opera: 0, 
            ver: null           //具体版本号 
        }; 
 
        //浏览器 
        var browser = { 
            //主要浏览器 
            ie: 0, 
            firefox: 0, 
            kong: 0, 
            opera: 0, 
            chrome: 0, 
            safari: 0, 
            ver: null      //具体的版本 
        }; 
 
        //平台,设备和操作系统 
        var system = { 
            win: false, 
            mac: false, 
            x11: false, 
 
            //移动设备 
            iphone: false, 
            ipod: false, 
            nokiaN: false, 
            winMobile: false, 
            macMobile: false, 
 
            //游戏系统 
            wii: false, 
            ps: false 
        }; 
 
        //在此检测呈现引擎,平台和设备 
        var ua = navigator.userAgent; 
 
        if (window.opera) { 
 
            //第一步检测opera,因为它的用户代理字符串有可能完全模仿其他浏览器 
            //要识别Opera,必须的检测window.opera对象 
            engine.ver = browser.ver = window.opera.version(); 
            engine.opera = browser.opera = parseFloat(engine.ver); 
        } else if (/AppleWebkit\/(\S+)/.test(ua)) { 
 
            //第二个要检测的是Webkit,因为Webkit的永华代理字符串中包含“Gecko”和“KHTML” 
            //Webkit的用户代理字符串中的“AppleWebkit”是独一无二的 
            engine.ver = RegExp.$1; 
            engine.webkit = parseFloat(engine.ver); 
 
            //确定是Chrome还是Safari 
            if (/Chrome\/(\S+)/.test(ua)) { 
                browser.ver = RegExp.$1; 
                browser.chrome = parseFloat(browser.ver); 
            } else if (/Version\/(\S+)/.test(ua)) { 
                browser.ver = RegExp.$1; 
                browser.safari = parseFloat(browser.ver); 
            } else { 
                //近似地确定版本号 
                var safariVersion = 1; 
                if (engine.webkit < 100) { 
                    safariVersion = 1; 
                } else if (engine.webkit < 312) { 
                    safariVersion = 1.2; 
                } else if (engine.webkit < 412) { 
                    safariVersion = 1.3; 
                } else { 
                    safariVersion = 2; 
                } 
                browser.safari = browser.ver = safariVersion; 
            } 
 
        } else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)) { 
 
            //接下来测试KHTML,KHTML的用户代理字符串也包含“Gecko” 
            //使用Konqueror检测Konqueror3.1及更早版本 
            engine.ver = browser.ver = RegExp.$1; 
            engine.khtml = browser.kong = parseFloat(engine.ver); 
 
        } else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) { 
 
            //检测Gecko,Gecko版本号会出现在字符串"rv:"的后面 
            engine.ver = RegExp.$1; 
            engine.gecko = parseFloat(engine.ver); 
 
            //确定是不是Firefox 
            if (/Firefox\/(\S+)/.test(ua)) { 
                browser.ver = RegExp.$1; 
                browser.firefox = parseFloat(browser.ver); 
            } 
 
        } else if (/MSIE ([^;]+)/.test(ua)) { 
 
            //检测IE,IE版本号位于字符串“MSIE”之后,一个分号的前面 
            engine.ver = browser.ver = RegExp.$1; 
            engine.ie = browser.ie = parseFloat(engine.ver); 
 
        } 
 
        //检测浏览器 
        browser.ie = engine.ie; 
        browser.opera = engine.opera; 
 
        //识别平台 
        var p = navigator.platform; 
        system.win = p.indexOf("Win") > -1; 
        system.mac = p.indexOf("Mac") > -1; 
        system.x11 = (p.indexOf("x11") > -1) || (p.indexOf("Linux") > -1); 
 
        //识别windows操作系统 
        if (system.win) { 
            if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)) { 
                if (RegExp.$1 === "NT") { 
                    switch (RegExp.$2) { 
                        case "5.0": 
                            system.win = "2000"; 
                            break; 
                        case "5.1": 
                            system.win = "XP"; 
                            break; 
                        case "6.0": 
                            system.win = "Vista"; 
                            break; 
                        case "6.1": 
                            system.win = "WIN7"; 
                            break; 
                        default: 
                            system.win = "NT"; 
                            break; 
                    } 
                } else if (RegExp.$1 === "9x") { 
                    system.win = "ME"; 
                } else { 
                    system.win = RegExp.$1; 
                } 
            } 
        } 
 
 
        system.iphone = ua.indexOf('iPhone') > -1; 
        system.ipod = ua.indexOf('iPod') > -1; 
        system.ipad = ua.indexOf('iPad') > -1; 
        system.nokiaN = ua.indexOf('NokiaN') > -1; 
 
        // windows mobile 
        if (system.win === 'CE') { 
            system.winMobile = system.win; 
        } else if (system.win === 'Ph') { 
            if (/Windows Phone OS (\d+\.\d+)/.test(ua)) { 
                system.win = 'Phone'; 
                system.winMobile = parseFloat(RegExp.$1); 
            } 
        } 
 
        // 检测IOS版本 
        if (system.mac && ua.indexOf('Mobile') > -1) { 
            if (/CPU (?:iPhone )?OS (\d+_\d+)/.test(ua)) { 
                system.ios = parseFloat(RegExp.$1.replace('_', '.')); 
            } else { 
                // 不能真正检测出来,所以只能猜测 
                system.ios = 2; 
            } 
        } 
 
        // 检测android版本 
        if (/Android (\d+\.\d+)/.test(ua)) { 
            system.android = parseFloat(RegExp.$1); 
        } 
 
        // 游戏系统 
        system.wil = ua.indexOf('Wii') > -1; 
        system.ps = /playstation/i.test(ua); 
 
        // 返回这些对象 
        return { 
            engine: engine, 
            browser: browser, 
            system: system 
        }; 
    })(); 
 
    window.ADS.client = client; 
 
    //对非DOM元素实现自定义事件 
    function EventTarget() { 
        //存储事件处理程序的属性对象 
        this.handlers = {}; 
    } 
 
    EventTarget.prototype = { 
        //重新将constructor指向EventTarget构造函数 
        constructor: EventTarget, 
        /** 
         * 注册给定类型的事件处理程序 
         * @param type 自定义的事件类型 
         * @param handler 处理该事件类型的函数 
         */ 
        addHandler: function (type, handler) { 
            //如果handlers属性中没有存在一个针对该事件类型的数组 
            //则创建一个新的。(一个事件类型可以对应多个事件处理函数,因此要用数组保存) 
            //然后使用push()将该处理程序添加到数组的末尾 
            if (typeof this.handlers[type] === "undefined") { 
                this.handlers[type] = []; 
            } 
            this.handlers[type].push(handler); 
        }, 
        /** 
         * 触发事件 
         * @param event 一个至少包含type属性的对象 
         */ 
        fire: function (event) { 
            //给event对象设置一个target属性 
            if (!event.target) { 
                event.target = this; 
            } 
            //如果该事件类型的执行函数存在, 
            //调用各个函数,并给出event对象 
            if (this.handlers[event.type] instanceof Array) { 
                var handlers = this.handlers[event.type]; 
                for (var i = 0, len = handlers.length; i < len; i++) { 
                    handlers[i](event); 
                } 
            } 
        }, 
        /** 
         * 注销事件类型的事件处理程序 
         * @param type 事件类型 
         * @param handler 执行的函数 
         */ 
        removeHandler: function (type, handler) { 
            if (this.handlers[type] instanceof Array) { 
                var handlers = this.handlers[type]; 
                //搜索事件处理程序的数组找到要删除的处理程序的位置 
                //找到了就退出循环,然后将该项目丛数组中删除 
                for (var i = 0, len = handlers.length; i < len; i++) { 
                    if (handlers[i] === handler) { 
                        break; 
                    } 
                } 
                handlers.splice(i, 1); 
            } 
        } 
    }; 
 
    window.ADS.EventTarget = EventTarget; 
 
    /** 
     * 封装cookie的操作 
     * @type {Object} 
     */ 
    var CookieUtil = { 
        /** 
         * 根据cookie的名字获取相应的值 
         * @param name cookie名字 
         * @return {*} 
         */ 
        get: function (name) { 
            //对name进行URL编码 
            var cookieName = encodeURIComponent(name) + '=', 
                cookieStart = document.cookie.indexOf(cookieName), 
                cookieValue = null; 
            //找到cookieName 
            if (cookieStart > -1) { 
                //以cookieStart为起点找到最近的";" 
                var cookieEnd = document.cookie.indexOf(';', cookieStart); 
                //没找到";",则是document.cookie的最后一个值 
                if (cookieEnd === -1) { 
                    cookieEnd = document.cookie.length; 
                } 
                //提取相应value字段 
                cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd)); 
            } 
            //返回 
            return cookieValue; 
        }, 
        /** 
         * 设置一个cookie 
         * @param name cookie名字 
         * @param value 相应的值 
         * @param expire 生存周期 Date 
         * @param path 路径 
         * @param domain 域名 
         * @param secure Boolean 
         */ 
        set: function (name, value, expire, path, domain, secure) { 
            //必须先进行URL编码 
            var cookieText = encodeURIComponent(name) + '=' + encodeURIComponent(value); 
            if (expire instanceof Date) { 
                //toGMTString()方法正确格式化Date对象 
                cookieText += '; expire=' + expire.toGMTString(); 
            } 
            if (path) { 
                cookieText += '; path=' + path; 
            } 
            if (domain) { 
                cookieText += '; domain=' + domain; 
            } 
            if (secure) { 
                cookieText += '; secure'; 
            } 
            document.cookie = cookieText; 
        }, 
        /** 
         * 删除cookie 
         * @param name 
         * @param path 
         * @param domain 
         * @param secure 
         */ 
        unset: function (name, path, domain, secure) { 
            this.set(name, '', new Date(0), path, domain, secure); 
        } 
    }; 
 
    window.ADS.CookieUtil = CookieUtil; 
 
//子cookie的操作 
//为了绕开浏览器的单域名下的cookie数限制 
//子cookie是存放在单个cookie中的更小段的数据 
    var SubCookieUtil = { 
        /** 
         * 获取单个子cookie的值 
         * @param name cookie名称 
         * @param subName 子cookie名称 
         * @return {*} 
         */ 
        get: function (name, subName) { 
            var subCookies = this.getAll(name); 
            if (subCookies) { 
                return subCookies(subName); 
            } else { 
                return null; 
            } 
        }, 
        /** 
         * 获取所有子cookie并将它们放入一个对象中返回 
         * @param name cookie名称 
         * @return {*} 返回对象或null 
         */ 
        getAll: function (name) { 
            var cookieName = encodeURIComponent(name) + "=", 
                cookieStart = document.cookie.indexOf(cookieName), 
                cookieValue = null, 
                result = {}; 
            if (cookieStart > -1) { 
                var cookieEnd = document.cookie.indexOf(";", cookieName); 
                if (cookieEnd === -1) { 
                    cookieEnd = document.cookie.length; 
                } 
                //没有进行解码,因为要对子cookie分离操作 
                cookieValue = document.cookie.substring(cookieStart + cookieName.length, cookieEnd); 
                // 
                if (cookieValue.length > 0) { 
                    //分离出子cookie的对象 
                    var subCookies = cookieValue.split("&"); 
                    //遍历分隔出子cookie的名称和值,解码后返回对象 
                    for (var i = 0, len = subCookies.length; i < len; i++) { 
                        var parts = subCookies[i].split("="); 
                        result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]); 
                    } 
                    return result; 
                } 
            } 
            //没找到,返回空 
            return null; 
        }, 
        /** 
         * 存储单个子cookie 
         * @param name cookie名称 
         * @param subName 子cookie名称 
         * @param value 子cookie值 
         * @param expires 失效日期 
         * @param path 路径 
         * @param domain 域名 
         * @param secure Boolean安全作用域 
         */ 
        set: function (name, subName, value, expires, path, domain, secure) { 
            //获取name名称的所有子cookie,没有则创建空对象 
            var subcookies = this.getAll(name) || {}; 
            //给对象添加属性和值 
            subcookies[subName] = value; 
            //调用setAll()方法 
            this.setAll(name, subcookies, expires, path, domain, secure); 
        }, 
        /** 
         * 存储所有子cookie 
         * @param name cookie名称 
         * @param subcookies 子cookie名称 
         * @param expires 失效日期 
         * @param path 路径 
         * @param domain 域名 
         * @param secure Boolean安全作用域 
         */ 
        setAll: function (name, subcookies, expires, path, domain, secure) { 
            var cookieText = encodeURIComponent(name) + "="; 
            //创建数组,用于保存子cookie 
            var subcookieParts = []; 
            //遍历对象属性 
            for (var subName in subcookies) { 
                //如果存在,则把编码后的名称和值保存到数组 
                if (subName.length > 0 && subcookies.hasOwnProperty(subName)) { 
                    subcookieParts.push(encodeURIComponent(subName) + "=" + encodeURIComponent(subcookies[subName])); 
                } 
            } 
            //存在子cookie 
            if (subcookieParts.length > 0) { 
                //连接子cookie 
                cookieText += subcookieParts.join("& "); 
                if (expires instanceof Date) { 
                    cookieText += ";expires=" + expires.toGMTString(); 
                } 
                if (path) { 
                    cookieText += ";path=" + path; 
                } 
                if (domain) { 
                    cookieText += ";domain=" + domain; 
                } 
                if (secure) { 
                    cookieText += ";secure"; 
                } 
            } else { 
                //相当于删除cookie操作 
                cookieText += ";expires=" + (new Date(0)).toGMTString(); 
            } 
            document.cookie = cookieText; 
        }, 
        /** 
         * 删除单个子cookie的名称和值 
         * @param name 
         * @param subName 
         * @param path 
         * @param domain 
         * @param secure 
         */ 
        unset: function (name, subName, path, domain, secure) { 
            var subcookies = this.getAll(name); 
            if (subcookies) { 
                //删除对应的属性和值 
                delete subcookies[subName]; 
                //重新设置cookie 
                this.setAll(name, subcookies, null, path, domain, secure); 
            } 
        }, 
        /** 
         * 删除所有子cookie 
         * @param name 
         * @param path 
         * @param domain 
         * @param secure 
         */ 
        unsetAll: function (name, path, domain, secure) { 
            this.setAll(name, null, new Date(0), path, domain, secure); 
        } 
    }; 
 
    window.ADS.SubCookieUtil = SubCookieUtil; 
})(); 
 
//重复一个字符串 
if (!String.repeat) { 
    String.prototype.repeat = function (times) { 
        return new Array(times + 1).join(this); 
    }; 
} 
 
//清除结尾和开头处的空白符 
if (!String.trim) { 
    String.prototype.trim = function () { 
        return this.replace(/^\s+|\s+$/g, ''); 
    }; 
} 
 
// 扩展链式调用方法 
Function.prototype.method = function (name, fn) { 
    this.prototype[name] = fn; 
    return this; 
}; 
 
// 扩展数组方法 
if (!Array.prototype.forEach) { 
    Array.method('forEach', function (fn, thisObj) { 
        var scope = thisObj || window; 
        for (var i = 0, len = this.length; i < len; i++) { 
            fn.call(scope, this[i], i, this); 
        } 
    }); 
} 
 
if (!Array.prototype.filter) { 
    Array.method('filter', function (fn, thisObj) { 
        var scope = thisObj || window; 
        var a = []; 
        for (var i = 0, len = this.length; i < len; i++) { 
            if (!fn.call(scope, this[i], i, this)) { 
                continue; 
            } 
            a.push(this[i]); 
        } 
        return a; 
    }); 
} 
 
/* Object-oriented Helper functions. */ 
function clone(object) { 
    function F() { 
    } 
 
    F.prototype = object; 
    return new F(); 
} 
 
function extend(subClass, superClass) { 
    var F = function () { 
    }; 
    F.prototype = superClass.prototype; 
    subClass.prototype = new F(); 
    subClass.prototype.constructor = subClass; 
 
    subClass.superclass = superClass.prototype; 
    if (superClass.prototype.constructor === Object.prototype.constructor) { 
        superClass.prototype.constructor = superClass; 
    } 
} 
 
function augment(receivingClass, givingClass) { 
    if (arguments[2]) { // Only give certain methods. 
        for (var i = 2, len = arguments.length; i < len; i++) { 
            receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]]; 
        } 
    } 
    else { // Give all methods. 
        for (var methodName in givingClass.prototype) { 
            if (!receivingClass.prototype[methodName]) { 
                receivingClass.prototype[methodName] = givingClass.prototype[methodName]; 
            } 
        } 
    } 
}

本文参考链接:https://www.cnblogs.com/webFrontDev/archive/2012/12/16/2820399.html