zoukankan      html  css  js  c++  java
  • dom Framework核心模块发布!(更新)

    想起几年 Dean Edwards 大神发布Base2时那句注释:

    You know, writing a javascript library is awfully time consuming.

    虽然javascript看似容易入门,但想深入是极其困难,因为它与java这些古典式的语言非常不同,最可恨的是那狗屎一般的DOM实现——API千差万别,bugs层出不同。因此光凭javascript是无能为力,DOM API的地位是相当重要。我们不需要hash,堆这样数据结构,加之IE6也承载不了这样复杂的东西,只需要能对DOM进行强大的处理就行了,随之很多东西都建立于其上。也基于这个原因,我的框架就直接叫dom了(终于被我想到一个与closure一样酷的名字了,泪目)。虽然有人不同意对原生对象进行扩展,但既然javascript提供了如此强大的入侵式语法,放弃它太可惜了,因此本框架还是走Prototypejs与mootools的走路。原型的充分利用能让我们真正实现那句所谓的:"Write Less, Do More!"

    由于我的东西是定位于"框架",非"类库",因此涉及的东西也非常多。由于战线过长,漫长的时间中发生各种事,导致有些模块被反复修改许多次,内部版本已达到3.0以上,有时模块则还没有完工。不过不管了,先放出来吧,长期的闭门造车也是个问题。

    为了开发这东西,我很久没有上来冒泡了,憋环了,唠叨了这么多。好了,先介绍一下我的核心模块。由于加载系统还没有选型好,现在但求轻松选用最简单的AJAX同步阻塞,也就是我原来的第一版实现。其次是浏览器的特性侦测,浏览器检测,对集合的操作等一些常用函数。最后还有domReady,本来想让它独立为一个模块的,不过如果颗粒过细就意味着请求很多,对服务器的压力太大了。当然,我最后放出来还是一个JS文件。我没有服务器,不能像jQuery,mootools那样提供合并模块的服务。不过,为了方便大家合并,它的设计也是非常良好,直接剪切到核心模块文件就行了。每一个模块都是一个自执行函数,不会让那些变量什么的跑出去。

    下面是源码,我会逐一讲解它们的用法,如果你们有什么好的实现也请不吝赐救!

     
    /*dom Framework version 1.0
    /*dom Framework version 1.0
    Copyright 2010
    Dual licensed under the MIT or GPL Version 2 licenses.
    author: <ruby> <rb>司徒正美<rp>(zhongqincheng)</rp></rb><rt>しとぅなさみ</rt></ruby>
    http://www.cnblogs.com/rubylouvre/
    */
    (function(){
        var window = this,
        dom = function (selector,context) {
            dom.require("node");
            return (this instanceof dom) ? this.init.apply(this,arguments) : new dom(selector,context)
        },
        //几个简写
        fn = "prototype",
        co = "constructor",
        has = "hasOwnProperty",
        tags = "getElementsByTagName",
        to_s = Object[fn].toString,
        //使用eval大法防止IE的条件编译在压缩时被删掉
        ie = eval("''+/*@cc_on"+" @_jscript_version@*/-0")*1,
        //把别人的库保存到一个临时变量中
        _dom = window.dom,
        //永久性命名空间,如果这个名字被其他库占用就没救了
        namespace = escape(document.URL.split("#")[0]),
        //判定原生对象与基本类型,第二个参数为字符串,大小写敏感
        is = function (obj,type) {
            return   (type === "Object" && obj === Object(obj)) ||
            (type === "Number" &&  obj === +obj ) ||
            (type === "Null" && obj === null) ||
            (type === "Undefined" && obj === void 0 ) ||
            to_s.call(obj).slice(8,-1) === type;
        },
        //=========================================
        // 判定是否为纯净的对象,
        // 指以{},{aa:1,bb:1}或new Object(不带参数,见ecma262v5 15.2.2.1)形式得到的对象实例,用于深拷贝
        //=========================================
        isPureObject = function(obj){
            return !!(obj && is(obj,"Object") && obj[co] === Object)
        },
        dontEnum = true;
        for (var i in {
            toString: 1
        }) dontEnum = null;//只处理这三个关键的不遍历属性
        if (dontEnum) dontEnum = ["constructor", "toString", "valueOf"];
        //=========================================
        // 特征侦探
        //==========================================
        dom.env = new function(){
            var div = dom.parser = document.createElement("div"),
            root = document.documentElement,sliceNodes = true;
            div.innerHTML = ' <link/><a href="/nasami" name="'+namespace+'" style="float:left;opacity:.25;"></a>'+
            '<input type="radio" name="n" checked="checked"/><object><param/></object><table></table>';
            var a = div[tags]("a")[0],s = a.style; a.expando = true;
            try{
                Array[fn].slice.call(div.childNodes)
            }catch(e){
                sliceNodes = false;
            }
            var box = div.cloneNode(true);
            box.style.width = box.style.paddingLeft = "1px";
            root.insertBefore(box, root.firstChild);
            var w3cBox = box.offsetWidth === 2,
            mixupsName = document.getElementById(namespace) === box[tags]("a")[0],
            method = a.matchesSelector  || a.webkitMatchesSelector || a.mozMatchesSelector
            root.removeChild(box);
            return {
                //某些浏览器的innerHTML会自动去掉标签外的空白
                removeBlank: div.innerHTML.charAt(0) === "<",
                //某些浏览器会自动为table添加tbody
                insertTbody: !!div[tags]("tbody").length,
                sliceNodes:sliceNodes,
                //IE67会混淆id与name
                mixupsName:mixupsName,
                //某些浏览器会自动补全路径
                convertUrl: a.getAttribute("href") !== "/nasami",
                //某些浏览器使用document.getElementByTagName("*")遍历Object元素下的param元素
                traverseAllElements: !!div[tags]("param").length,
                //http://www.cnblogs.com/rubylouvre/archive/2010/01/09/1642978.html
                traverseAllProperties: !dontEnum,
                //https://prototype.lighthouseapp.com/projects/8886/tickets/264-ie-can-t-create-link-elements-from-html-literals
                //某些浏览器不能通过innerHTML序列化link,style,script等元素
                serializeAll: !!div[tags]("link").length,
                //IE的cloneNode才是真正意义的复制,能复制动态添加的自定义属性与事件
                cloneAll: !!a.cloneNode(true).expando,
                //http://www.cnblogs.com/rubylouvre/archive/2010/05/16/1736711.html
                //在safari下,指定了name属性的radio是无法复制checked属性的
                cloneChecked: div[tags]("input")[0].cloneNode(true).checked,
                //IE67是没有style特性(特性的值的类型为文本),只有el.style(CSSStyleDeclaration)
                hasStyleAttribute:a.getAttribute("style") !== s,
                //http://www.cnblogs.com/rubylouvre/archive/2010/05/16/1736535.html
                //IE8返回".25" ,IE9pp2返回0.25,chrome等返回"0.25"
                w3cOpacity: s.opacity == "0.25",
                //某些浏览器不支持w3c的cssFloat属性来获取浮动样式,而是使用独家的styleFloat属性
                w3cFloat: !!s.cssFloat,
                //某些浏览器存在怪异模式,此时盒子模型的宽高所围成的矩形等于border围成的矩形
                //就像开发商计算建筑面积时用的是IE6模型 , 业主计算套内面积时用的是W3C模型
                w3cBox: w3cBox,
                //IE8等支持W3C的selector APIs
                querySelector:!!(document.querySelectorAll && div.querySelectorAll ),
                matchesSelector: method && method.name,//返回对应的方法名,没有为undefined
                //除safari与IE外默认新添加的option为选中状态
                optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected,
                //http://oreilly.com/catalog/jscript4/chapter/ch17.html
                w3cRange:!!(document.implementation && document.implementation.hasFeature("Range","2.0"))
            }
        };
        //=========================================
        // 数组化
        //==========================================
        dom.slice =  function(){
            var item = arguments[0]||[], method = Array[fn].slice;
            //IE中不能slice节点集合,它们是基于COM的,并非Object的实例,需要转换为原生数组
            if(!dom.env.sliceNodes && !(item instanceof Object)){
                var i = item.length,ret = [];
                while(i--){
                    ret[i] = item[i]
                }
                item = ret;
            }
            return  method.apply(item,  method.call(arguments, 1));
        }
        //==========================================
        // 混入方法
        //==========================================
        dom.mixin = function() {
            var queue = dom.slice(arguments),deep = false,tk,sk;
            if(typeof queue[0] === "boolean"){
                deep = queue.shift();
            }
            var target = queue[0], source = queue[1]
            if(queue.length===1){
                target = this; source = queue[0]
            }
            if (target && source ){
                for(var key in source){
                    if(source[has](key)){
                        tk = target[key]; sk = source[key];
                        if(target === tk) continue;//如window.window === window,会陷入死循环,
                        //如果是深拷贝,则检测source的当前属性是否为纯对象或数组,是则特殊处理它,
                        //对于其他类型的属性,它们的处理同浅拷贝
                        if ( deep && sk && ( dom.isPureObject(sk) || dom.isArray(sk) ) ) {
                            var clone = tk && ( dom.isPureObject(tk) || dom.isArray(tk) ) ? tk
                            : dom.isArray(tk) ? [] : {};
                            target[ key ] = dom.mixin(deep, clone, sk );
                        //属性值绝对不能为undefined
                        } else if ( sk !== undefined ) {
                            target[ key ] = sk;
                        }
                    }
                }
                if(!dom.env.traverseAllProperties && source[has]){
                    var d = 3;
                    while ((key = dontEnum[--d])) {
                        source[has](key) && (target[key] = source[key]);
                    }
                }
            }
            if(queue.length > 2 ){
                var others = queue.slice(2);//dom.slice(arguments,2);
                for(var i=0,n=others.length;i<n;i++){
                    target = arguments.callee(deep,target,others[i]);
                }
            }
            return target;
        };
        dom.include = function(obj){
            dom.require("node")
            dom.mixin(dom.prototype,obj)
        };
        dom.mixin({
            //=========================================
            // 浏览器嗅探
            //==========================================
            //除了另无它法,肯定不使用navigator.userAgent来判定浏览器。因为在第一次浏览器大战初期,
            //Netscape占绝对统计地位,大部分人们不愿意兼容其他浏览器,并通过检测其UA让他们的网站
            //只允许Netscape访问,这就逼使其他浏览器(包括IE)修改自己的UA伪装成Netscape来通过那
            //些自以为是的脚本,于是出现每个人都声称自己是别人的局面,即使最新的IE9的UA也是这样
            //Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)
            ie: !!ie,//内核为trident
            ie5: ie === 5.5,
            ie6: ie === 5.6,
            ie7: ie === 5.7,
            //指IE8以下的版本或IE8运行于兼容模式下
            ie67 :!-[1,] && dom.env.querySelector === false,
            ie8: ie === 5.8,
            ie9: ie === 5.9,
            firefox: !!top.crypto,//内核Gecko
            opera:  is(top.opera,"Opera"),//内核 Presto 9.5为Kestrel 10为Carakan
            chrome: !!(top.google && top.chrome) ,//内核V8
            safari: /apple/i.test(navigator.vendor),// 内核 WebCore
            quirk: !dom.env.w3cBox,
            //=========================================
            // 获取特殊节点
            //==========================================
            //参数都是可选,除了script方法要求可选参数为普通对象,其他为DOM对象
            document : function (obj) {
                if(obj){ //IE5.5中,HTML元素不存在ownerDocument属性
                    return obj.documentElement ? obj : (obj.ownerDocument || obj.document);
                }else{
                    return window.document;
                }
            },
            root:function(obj){
                return dom.document(obj).documentElement;
            },
            head:function(obj){
                return dom.document(obj)[tags]("HEAD")[0] ;
            },
            body: function(obj){
                return dom.document(obj).body
            },
            script:function(obj){
                //注意,charset属性当且仅当同时指定了src属性才有效
                //注意,IE下用innerHTML序列化script标签存在bug,script标签前面要有其他节点
                dom.parser.innerHTML = '<br><script type="text/javascript" charset="utf-8" ><\/script>'
                return dom.mixin(dom.parser.childNodes[1],obj);
            },
            //=========================================
            // 各种判定
            //==========================================
            is:is,
            isPureObject:isPureObject,
            //判断是否为XML文档
            //http://www.cnblogs.com/rubylouvre/archive/2010/03/14/1685360.html
            isXML: function(el){
                var doc = dom.document(el);
                return (!!doc.xmlVersion) || (!!doc.xml) || is(doc,"XMLDocument") || (!doc.body);
            },
            //是否这元素节点,如果传入两个参数,则判定元素的标签类型
            isElement : function (obj,tag) {
                if(arguments.length === 2){
                    tag = dom.isXML(obj) ? tag : tag.toUpperCase()
                    return  obj.nodeName === tag ;
                }
                return !! (obj && obj.nodeType === 1) ;
            },
            isFormElement : function(obj){
                return !!(obj.tagName && "name" in obj && "form" in obj);
            },
            isNative : function(obj){//判定是否为原生方法
                return !! obj && (/\{\s*\[native code\]\s*\}/.test(String(obj)) ||
                    /\{\s*\/\* source code not available \*\/\s*\}/.test(String(obj)));
            },
            //包括Array,Arguments,NodeList,HTMLCollection,IXMLDOMNodeList与自定义类数组对象
            //select.options集合(它们两个都有item与length属性)
            isArrayLike :  function (obj) {
                if(!obj || obj.document || obj.nodeType || is(obj,"Function")) return false;
                return isFinite(obj.length) ;
            },
            //检测是否为空对象,只检测本地属性
            isEmptyObject: function(obj ) {
                for ( var key in obj )
                    if(obj[has] && obj[has](key))
                        return false;
                return true;
            },
            isInDomTree : function(node,context){
                var root = (context || document).documentElement;
                return node === root || dom.contains(node,root);
            },
            contains :function(el, root) {//分别为子节点与父节点
                if (el.compareDocumentPosition)
                    return (el.compareDocumentPosition(root) & 8) === 8;
                if (root.contains && el.nodeType === 1){
                    return root.contains(el) && root !== el;
                }
                while ((el = el.parentNode))
                    if (el === root) return true;
                return false;
            },
            //=========================================
            // 各种处理集合的方法
            //==========================================
            keys : function(obj){
                var result = [],ri = 0;
                if(!dom.env.traverseAllProperties && obj[has]){
                    obj[has]("constructor") && (result[ri++] = "constructor");
                    obj[has]("toString") &&  (result[ri++] = "toString");
                    obj[has]("valueOf") &&  (result[ri++]= "valueOf");
                }
                for(var key in obj)
                    if(obj[has] && obj[has](key))
                        result[ri++] = key;
                return result;
            },
            each: function (obj, fn, bind ) {
                if (dom.isArrayLike(obj)) {
                    for (var i = 0, n = obj.length ; i < n; i++) {
                        if ( fn.call(bind || obj[i], obj[i], i, obj) === false ) {//绑定作用域
                            break;
                        }
                    }
                }else if(obj[has]){
                    for(var prop in obj){
                        if(obj[has](prop)){//value,key,obj,绑定对象默认为value
                            if ( fn.call(bind || obj[prop], obj[prop], prop, obj) === false ) {
                                break;
                            }
                        }
                    }
                    if(!dom.env.traverseAllProperties){
                        var d = 3;
                        while ((prop = dontEnum[--d])) {
                            if(obj[has](prop)){
                                if ( fn.call(bind || obj[prop], obj[prop], prop, obj) === false ) {
                                    break;
                                }
                            }
                        }
                    }
                }
                return obj
            },
    
            map:function(array, fn, bind){
                var result = [],ri = 0, value
                for (var i = 0,n = array.length; i < n; i++){
                    value = fn.call(bind || array[i],array[i],i,array)
                    if(value != null){
                        result[ri++] = value;
                    }
                }
                return result;
            },
    
            filter:function(array, fn, bind){
                var result = [],ri = 0;
                for (var i = 0,n = array.length; i < n; i++){
                    if(fn.call(bind || array[i],array[i],i,array)){
                        result[ ri++] = array[i];
                    }
                }
                return result;
            },
            //类似python中的range()函数
            range : function() {
                var a     = dom.slice(arguments);
                var solo  = a.length <= 1;
                var start = solo ? 0 : a[0],
                stop = solo ? a[0] : a[1],
                step = a[2] || 1;
                var len   = Math.ceil((stop - start) / step);
                if (len <= 0) return [];
                var range = [];
                for (var i = start, ri = 0; true; i += step) {
                    if ((step > 0 ? i - stop : stop - i) >= 0) return range;
                    range[ri++] = i;
                }
            },
            merge : function(array,args) {//合并集合
                array = dom.slice(array);
                var arrayLength = array.length, length = args.length;
                while (length--) array[arrayLength + length] = args[length];
                return array;
            },
            inArray : function(el,arr){
                if(arr.indexOf)
                    return arr.indexOf(el) !== -1;
                for (var i = 0, n = arr.length; i < n; i++)
                    if (arr[i] === el) return true;
                return false;
            },
            now: Date.now || function(){
                return new Date().valueOf();
            },
            random : function(min, max, exact){
                var range = min + (Math.random()*(max - min));
                return exact === void(0) ? Math.round(range) : range.toFixed(exact);
            },
            //var a = {length:4,0:1,1:2,2:3,3:4};
            //dom.console.log(dom.toArray(a)
            toArray : function (obj) {
                return  obj != null ? dom.isArrayLike(obj)  ? dom.slice(obj): [obj] :[]
            },
            alias : function(newName) {
                //如果不指定新名,则随机生成一个,换言之,则进入忍者模式,需要用一个变量来接受它
                newName = newName || "__dom__"+dom.now();
                window.dom = _dom;
                return window[namespace] = window[newName]  = dom;
            },
            //生成一个值都相同的对象,用于if语句进行过滤
            oneObject : function(array,val){
                var result = {},value = val !== undefined ? val :1;
                for(var i=0,n=array.length;i<n;i++)
                    result[array[i]] = value;
                return result;
            },
            globalEval: function( code ) {
                //IE中,window.eval()和eval()一样只在当前作用域生效。
                //Firefox,Safari,Opera中,直接调用eval()为当前作用域,window.eval()调用为全局作用域。
                if ( code && /\S/.test(code) ) {
                    var method = window.execScript ? "execScript" : "eval"
                    try{
                        window[method](code);
                    }catch(e){}
                }
            },
            uuid:1,
            expando : "dom" + (new Date-0),//设在元素上的自定义属性
            noop:function(){},
            cacher : function(fn, bind, post) {
                return function (){
                    var self = arguments.callee,
                    array = dom.slice(arguments),
                    args = array.join("\u25ba"),//►,一个黑色的三角形
                    cache = self.cache = self.cache || {},
                    count = self.count = self.count || [];
                    if (cache.hasOwnProperty(args)) {
                        return post ? post(cache[args]) : cache[args];
                    }
                    count.length >= 1e3 && delete cache[count.shift()];
                    count.push(args);
                    cache[args] = fn.apply(bind, array);
                    return post ? post(cache[args]) : cache[args];
                }
            },
    
            //此方法只对FF浏览器有效,调试用
            //https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/noSuchMethod
            __noSuchMethod__: function(name, args) {
                dom.require("console")
                dom.console.error("尝试用以下参数("+args+")执行当前对象的'" + name + "'方法遭遇失败!");
            },
            ready: function( fn ) {//domReady
                var self = arguments.callee;
                self.init();
                if ( self.status ) {
                    fn();
                } else if ( self.list) {
                    self.list.push( fn );
                }
            }      
        });
        dom.mixin(dom.ready,{
            list:[],
            status:false,
            init: function(){
                if (arguments.callee.used ) {
                    return;
                }
                arguments.callee.used = true;
                var fire = dom.ready.fire
                //用于window.onload的内部
                if ( document.readyState === "complete" ) {
                    return fire();
                }
                if (-[1,]) {//Safari3.1+,Chrome,Firefox2+ ,Opera9+,听说IE9也支持DOMContentLoaded
                    //https://developer.mozilla.org/en/Gecko-Specific_DOM_Events
                    document.addEventListener( "DOMContentLoaded", function() {
                        document.removeEventListener( "DOMContentLoaded",  arguments.callee , false );
                        fire();
                    }, false );
                } else {//IE5 IE6 IE7 IE8
                    //http://dev.jquery.com/ticket/2614
                    //当页面包含图片时,onreadystatechange事件会触发在window.onload之后,
                    //换言之,它只能正确地执行于页面不包含二进制资源或非常少或者被缓存时
                    document.attachEvent("onreadystatechange", function(e) {
                        if ( document.readyState == "complete" ) {
                            document.detachEvent("onreadystatechange", arguments.callee );
                            fire();
                        }
                    });
                    //doScroll方法通常只会正确执行一个全新的页面
                    (function(){
                        if ( dom.ready.status ) {
                            return;
                        }
                        //doScroll存在于所有标签而不管其是否支持滚动条
                        //当DOM树时我们就可以调用其doSroll方法
                        //若用document.documentElement.doScroll(),我们需要判定其是否位于顶层document
                        //http://msdn.microsoft.com/en-us/library/ms536414(VS.85).aspx
                        var node = new Image
                        try {
                            node.doScroll();
                            node = null//防止IE内存泄漏
                        } catch( e ) {
                            //javascrpt最短时钟间隔为16ms,这里取其倍数
                            //http://blog.csdn.net/aimingoo/archive/2006/12/21/1451556.aspx
                            setTimeout( arguments.callee, 64 );
                            return;
                        }
                        fire();
                    });
                }
            },
            fire: function() {
                if ( !dom.ready.status ) {
                    if ( !document.body ) {
                        return setTimeout(arguments.callee, 16 );
                    }
                    dom.ready.status = true;
                    if ( dom.ready.list ) {
                        for(var i=0, fn;fn = dom.ready.list[i++];)
                            fn();
                        delete dom.ready.list;
                    }
                }
            }
        });
        //添加更多见词明义的判定
        dom.each(["Array","Function","Number","String","Undefined","Null"],function(name){
            dom["is"+name] = function(obj){
                return is(obj,name);
            }
        });
    
        // ECMA-5 15.4.3.2
        if(dom.isNative(Array.isArray)){
            dom.isArray = Array.isArray;
        }
    
        // ECMA-5 15.2.3.14
        if(dom.isNative(Object.keys)){
            dom.keys = Object.keys;
        }
    
        (function(){
            //游览器环境不能使用Msxml2.XMLHTTP.5.0与Msxml2.XMLHTTP.4.0
            //http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
            var s = ["XMLHttpRequest",
            "ActiveXObject('Msxml2.XMLHTTP.6.0')",
            "ActiveXObject('Msxml2.XMLHTTP.3.0')",
            "ActiveXObject('Msxml2.XMLHTTP')",
            "ActiveXObject('Microsoft.XMLHTTP')"];
           
            if(dom.ie7 && location.protocol === "file:"){
                s.shift();
            }
            for(var i = 0 ,el;el=s[i++];){
                try{
                    if(eval("new "+el)){
                        dom.xhr = new Function( "return new "+el)
                        break;
                    }
                }catch(e){}
            }
        })();
    
        //=========================================
        // 核心模块 模块加载系统
        //==========================================
        //dom有三个重要的信息储存区,
        //一个是env用于储存与浏览器有关的东西
        //一个是lib用于储存与框架有关的东西
        //一个是cache用于储存运行收集的东西
        dom.lib = {
            loaded:{},
            //获取核心模块所在的JS文件所在的文件夹路径
            baseUrl :(function(){
                var result;
                try{
                    throw ""
                }catch(e){
                    result = e.fileName || e.sourceURL;
                }
                if(!result){
                    var scripts = document[tags]('script'),
                    script = scripts[scripts.length - 1];
                    result = script.src;
                }
                return result.substr( 0, result.lastIndexOf('/'));
            })()
        }
        //name为模块名,create不存在此属性是否创建一个空对象
        dom.mixin({
            //创建一个命名空间
            namespace:function(name,create,context){
                var parts=name.split("."),obj = context || window;
                for(var i=0, p; obj && (p=parts[i]); i++){
                    if(i == 0 && this[p]){
                        p = this[p];
                    }
                    obj = (p in obj ? obj[p] : (create ? obj[p]={} : undefined));
                }
                return obj;
            },
            //同步加载模块
            require : function(name,timeout){
                name = name.indexOf("dom.") === 0 ? name.slice(4):name
                timeout = timeout || 2000
                var module = "dom."+name,url;
                if(dom.lib.loaded[name]) return
                //处理dom.node(http://www.cnblogs.com/rubylouvre/dom/node.js)的情形
                var _url = module.match(/\(([^)]+)\)/);
                url = _url && _url[1] ? _url[1] : dom.lib.baseUrl+"/"+ module.replace(/\./g, "/") + ".js";
                var xhr = dom.xhr();
                xhr.open("GET",url,false);
                xhr.setRequestHeader("If-Modified-Since","0");
                xhr.send(null);
                dom.globalEval( xhr.responseText|| "")
                setTimeout(function(){
                    try{
                        xhr.abort()
                    }catch(e){}
                },timeout);
            },
            //提供命名空间,标识此模块已经加载过
            provide : function(name){
                name = name.indexOf("dom.") === 0 ? name.slice(4):name
                dom.lib.loaded[name] = true;
                dom.namespace("dom."+name,true)
            }
        });
        //====================添加其他模块======================
        window[namespace] = window.dom = dom;
    })();
    
    所有模块

    许多代码我以前都放过出来了,应该没有什么难度,我也将会在下一篇讲解它们的。如果到时能把chm文档搞出来就最好不过了,现在姑且先放出让大家瞧瞧。最后还是那句老话,如果某某方法有什么好的实现,请不吝赐救!

文档下载地址

下载回来后对着文件点右键-->属性-->解除锁定。

查看全文
  • 相关阅读:
    Hadoop Mapreduce分区、分组、二次排序过程详解
    hadoop的NullWritable
    CentOS7.0修改主机名(hostname)
    Linux下不重启永久修改hostname
    稀缺——我们是如何陷入贫穷与忙碌的
    slf4j log4j logback关系详解和相关用法
    使用logstash+elasticsearch+kibana快速搭建日志平台
    安装XAMPP时出现 unable to realloc 83886080 bytes
    ElasticSearch查询max_result_window问题处理
    后台CMS日志处理记录
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1761107.html
  • Copyright © 2011-2022 走看看