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文档搞出来就最好不过了,现在姑且先放出让大家瞧瞧。最后还是那句老话,如果某某方法有什么好的实现,请不吝赐救!

文档下载地址

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

dom Framework核心模块发布!(更新)

你可能感兴趣的:(framework)