代码改变世界

QWrap骨骼

2011-01-06 00:31  BlueDream  阅读(1172)  评论(1编辑  收藏  举报

记录一下,有时间更新说明。这里只是提取了QW的实现骨架。剔除了selector的query,简单演示了QW的Node包装器以及setterAll/getterOne的实现思路。原理还是比较简单比较好理解。

<!doctype html> 
<html> 
<head> 
<meta charset="utf-8" /
<title> QW子集函数 </title>
<style>
.greencolor { color: green; }
</style>
</head>
<body>
<div id="odiv1" style="width:100px;height:100px;background-color:red"></div>
<div id="odiv2" style="width:100px;height:100px;background-color:red"></div>
<input type="button" value="运行QW" onclick="RunQW();" />
<script>
var QW = {};

// ObjectH method
(function () {
var getConstructorName= function (o) {
    
return o && Object.prototype.toString.call(o).slice(8-1);
};
//ObjectH
var ObjectH = {
    isString: 
function (obj) {
        
return typeof obj === 'string';
    },
    isArray: 
function (obj) {
        
return getConstructorName(obj) === 'Array';
    },
    isWrap: 
function (obj, coreName) {
        
return !!obj && (coreName || 'core'in obj;
    },
    mix: 
function (des, src, override) {
        
if (ObjectH.isArray(src)) {
            
for (var i = 0,  len = src.length; i < len; i++) {
                ObjectH.mix(des, src[i], override);
            }
            
return des;
        } 
        
for (var i in src) {
            
if (override || !(des[i]) && !(i in des)) {
                des[i] 
= src[i];
            } 
        }
        
return des;
    }
};
QW.ObjectH 
= ObjectH;
})();



(
function(){
var FunctionH = {
    
/**
     * 函数包装器 methodize,对函数进行methodize化,使其的第一个参数为this,或this[attr]。
     * @method methodize
     * @static
     * @param {function} func要方法化的函数
     * @optional {string} attr 属性
     * @optional {boolean} chain 串化,如果串化,返回this,否则返回原来的函数返回值 
     * @return {function} 已方法化的函数
     
*/
     
    methodize: 
function(func,attr,chain){
        
if(attr) return function(){
            
var ret = func.apply(null,[this[attr]].concat([].slice.call(arguments)));
            
return chain?this:ret;
        };
        
return function(){
            
var ret = func.apply(null,[this].concat([].slice.call(arguments)));
            
return chain?this:ret;
        };
    },

   
/**
    * 对函数进行集化,使其在第一个参数为array时,结果也返回一个数组
    * @method mul
    * @static
    * @param {function} func
    * @param {boolean} recursive 是否递归
    * @param {boolean} getFirst 是否只是getFirst
    * @return {Object} 已集化的函数
    
*/
    mul: 
function(func, recursive, getFirst){
        
function flat_arr(array, findFirst){
            
var ret = [];
            
for(var i = 0, len = array.length; i < len; i++){
                
var o = array[i];
                
if(o instanceof Array){
                    ret 
= ret.concat(flat_arr(o,findFirst));
                }
else{
                    ret 
= ret.concat([o]);
                }
                
if(findFirst && ret.length) return ret;
            }
            
return ret;
        }
        
        
return function(){
            
var list = arguments[0];
            
if(!(list instanceof Array)){
                
return func.apply(this, arguments); //不是数组,直接调用后返回
            }
            
if(recursive){//如果是一个递归的数组,先解递归,然后继续
                list = flat_arr(list, getFirst);
            }
            
var ret = [];
            
var eachArgs = [].slice.call(arguments,0);
            
for(var i = 0, len = list.length; i < len; i++){
                eachArgs[
0]=list[i];
                
var r = func.apply(this, eachArgs);
                
if(getFirst) return r;
                ret.push(r);     
            }
            
return ret;        
        }
    },
    
/**
     * 函数包装变换
     * @method rwrap
     * @static
     * @param {func} 
     * @return {Function}
     
*/
    rwrap: 
function(func,wrapper,idx){
        idx
=idx|0;
        
return function(){
            
var ret = func.apply(this, arguments);
            
if(idx>=0) ret=arguments[idx];
            
return wrapper ? new wrapper(ret) : ret;
        }
    }
};


QW.FunctionH
=FunctionH;

})();
// HelperH
(function(){

var FunctionH = QW.FunctionH,
    mix 
= QW.ObjectH.mix;

var HelperH = {
    
/**
    * 对于需要返回wrap对象的helper方法,进行结果包装
    * @method rwrap
    * @static
    * @param {Helper} helper Helper对象
    * @param {Class} wrapper 将返回值进行包装时的包装器(WrapClass)
    * @param {Object} wrapConfig 需要返回Wrap对象的方法的配置
    * @return {Object} 方法已rwrap化的<strong>新的</strong>Helper
    
*/
    rwrap: 
function(helper, wrapper, wrapConfig){
        
var ret = {};
        
if(null == wrapConfig) wrapConfig = {};

        
for(var i in helper){
            
var wrapType=wrapConfig;
            
if (typeof wrapType != 'string') {
                wrapType
=wrapConfig[i] || '';
            }
            
if(/queryer/.test(wrapType)){
                ret[i] 
= FunctionH.rwrap(helper[i], wrapper, -1);//对返回值进行包装
            }
            
else if('operator'==wrapType){
                ret[i] 
= FunctionH.rwrap(helper[i], wrapper, 0);//对第一个参数进行包装
            }
            
else ret[i] = helper[i]; //不作变幻
        }
        
return ret;
    },

    
/**
    * 根据配置,产生gsetter新方法,它根椐参数的长短来决定调用getter还是setter
    * @method gsetter
    * @static
    * @param {Helper} helper Helper对象
    * @param {Object} gsetterConfig 需要返回Wrap对象的方法的配置
    * @return {Object} 方法已gsetter化的<strong>新的</strong>helper
    
*/
    gsetter: 
function(helper,gsetterConfig){
        
var ret = mix({}, helper);
        gsetterConfig
=gsetterConfig||{};
        
for(var i in gsetterConfig){
            ret[i]
=function(config){
                
return function(){return ret[config[Math.min(arguments.length,config.length)-1]].apply(null,arguments);}
            }(gsetterConfig[i]);
        }
        
return ret;
    },
    
    
/**
    * 对helper的方法,进行mul化,使其在第一个参数为array时,结果也返回一个数组
    * @method mul
    * @static
    * @param {Helper} helper Helper对象
    * @param {boolean} recursive (Optional)是否递归
    * @param {json|string} mulConfig mulConfig,
    * @return {Object} 方法已mul化的<strong>新的</strong>Helper
    
*/

    mul: 
function (helper, recursive,wrapConfig){ 
        wrapConfig 
=wrapConfig ||{};
        
var ret = {};
        
for(var i in helper){
            
if(typeof helper[i] == "function"){
                
var wrapType=wrapConfig;
                
if (typeof wrapType != 'string') {
                    wrapType
=wrapConfig[i] || '';
                }
                ret[i] 
= FunctionH.mul(helper[i], recursive, wrapType=='getter_first');
            }
            
else
                ret[i] 
= helper[i];
        }
        
return ret;
    },
    
/**
    * 将一个Helper应用到某个Object上,Helper上的方法作为静态函数,即:extend(obj,helper)
    * @method applyTo
    * @static
    * @param {Helper} helper Helper对象,如DateH
    * @param {Object} obj 目标对象.
    * @return {Object} 应用Helper后的对象 
    
*/
    applyTo: 
function(helper,obj){
        
return mix(obj, helper);  //复制属性
    },
    
/**
    * 对helper的方法,进行methodize化,使其的第一个参数为this,或this[attr]。
    * <strong>methodize方法会抛弃掉helper上的非function类成员以及命名以下划线开头的成员(私有成员)</strong>
    * @method methodize
    * @static
    * @param {Helper} helper Helper对象,如DateH
    * @param {optional} attr (Optional)属性
    * @param {optional} wrapConfig (Optional) 方法类型配置
    * @return {Object} 方法已methodize化的对象
    
*/
     
//HelperH.methodize(helper, 'core', wrapConfig)
    methodize: function(helper, attr, wrapConfig){
        wrapConfig
=wrapConfig||{};
        
var ret = {};
        
for(var i in helper){
            
var wrapType=wrapConfig;
            
if (typeof wrapType != 'string') {
                wrapType
=wrapConfig[i] || '';
            }
            
if(typeof helper[i] == "function" && !/^_/.test(i)){
                ret[i] 
= FunctionH.methodize(helper[i], attr, wrapType=='operator'); 
            }
        }
        
return ret;
    },
    
/**
    * <p>将一个Helper应用到某个Object上,Helper上的方法作为对象方法</p>
    * @method methodizeTo
    * @static
    * @param {Helper} helper Helper对象,如DateH
    * @param {Object} obj  目标对象.
    * @param {string} attr (Optional)包装对象的core属性名称。如果为空,则用this,否则用this[attr],当作Helper方法的第一个参数
    * @param {json|string} wrapConfig (Optional) 方法类型配置
    * @return {Object} 应用Helper后的对象
    
*/
    methodizeTo: 
function(helper, obj, attr, wrapConfig){
        helper 
= HelperH.methodize(helper,attr, wrapConfig);    //方法化
        return mix(obj, helper);  //复制属性         
    }
};

QW.HelperH 
= HelperH;
})();


// NodeH method
QW.NodeH = function () {
    
var ObjectH = QW.ObjectH;
    
var $ = function (el, doc) {
        
if ('string' == typeof el) {
            doc 
= doc || document;
            
return doc.getElementById(el);
        } 
else {
            
return (ObjectH.isWrap(el)) ? arguments.callee(el.core) : el;
        }
    };

    
var NodeH = {
        hasClass: 
function (el, className) {
            el 
= $(el);
            
return new RegExp('(?:^|\\s)' + className + '(?:\\s|$)').test(el.className);
        },
        addClass: 
function (el, className) {
            el 
= $(el);
            
if (!NodeH.hasClass(el, className)) {
                el.className 
= el.className ? el.className + ' ' + className : className;
            } 
        },
        getHtml : 
function (el) {
            el 
= $(el);
            
return el.innerHTML;
        },
        setHtml : 
function (el, value) {
            $(el).innerHTML 
= value;
        }
    }
    
    NodeH.$ 
= $;
    
return NodeH;
}();
// NodeC定义了NodeW的getter/setter
(function () {
var queryer = 'queryer',
    getter 
= 'getter',
    getter_first 
= 'getter_first',
    operator 
= 'operator',
    operator__query 
= 'operator,query';

QW.NodeC 
= {
    getterType: getter_first,
    arrayMethods: 
'map,forEach,filter,toArray'.split(','),
    wrapMethods : {
        
//NodeH
        $ : queryer,
        hasClass : getter_first,
        addClass : operator,
        getHtml : getter_first,
        setHtml : operator
    },
    gsetterMethods : {
        html : [
'getHtml''setHtml']
    }

};

})();

// NodeW HTMLElement对象包装器
(function () {
    
var ObjectH = QW.ObjectH,
        mix 
= ObjectH.mix,
        isString 
= ObjectH.isString,
        isArray 
= ObjectH.isArray,
        push 
= Array.prototype.push,
        NodeH 
= QW.NodeH,
        $ 
= NodeH.$;

    
var NodeW = function (core) {
        
if (!core) return null//用法: var w = NodeW(null); 返回null
        var args1 = arguments[1];
        
//if (isString(core)) {
            //return new NodeW(query(arg1, core));
        //} else {
            core = $(core, args1);
            
if (this instanceof NodeW) {
                
this.core = core;
                
if (isArray(core)) {
                    
this.length = 0;
                    push.apply(
this, core);
                } 
                
else {
                    
this.length = 1;
                    
this[0= core;
                }
            }
            
else return new NodeW(core); //用法: var w = NodeW(element); var w2 = NodeW(elemsArray);
        //}
    };

    NodeW.one 
= function (core) {
        
if (!core) return null// 用法: var w = NodeW.one(null); 返回null
        var args1 = arguments[1];
        
//if (isString(core)) {
            //return new NodeW(query(arg1, core)[0]);
        //
        //else {
            core = $(core, arg1);
            
if (isArray(core)) {
                
return new NodeW(core[0]);
            } 
            
else {
                
return new NodeW(core); // 用法:var w = NodeH.one(element);
            }
        
//}
    };

    
//getterType: getter_first,
    //arrayMethods: 'map,forEach,filter,toArray'.split(','),
    //wrapMethods : {
        ////NodeH
        //$ : queryer,
        //hasClass : getter_first,
        //addClass : operator,
        //getHtml : getter_first,
        //setHtml : operator
    //},
    //gsetterMethods : {
        //html : ['getHtml', 'setHtml']
    //}

//};
/*
NodeH, wrapMethods, gsetterMethods*/
    NodeW.pluginHelper 
= function (helper, wrapConfig, gsetterConfig) {
        
var HelperH = QW.HelperH;
        helper 
= HelperH.mul(helper, true, wrapConfig); // 支持第一个参数为Array
        
        helper 
= HelperH.rwrap(helper, NodeW,  wrapConfig);// 对返回值进行包装处理
        
        
var helper2 = gsetterConfig ? HelperH.gsetter(helper, gsetterConfig) : helper; // 如果有gsetter需要处理
        HelperH.applyTo(helper2, NodeW); // 应用于NodeW的静态方法

        
var pro = HelperH.methodize(helper, 'core', wrapConfig); // ?????
        if (gsetterConfig) {
            
for (var i in gsetterConfig) {
                pro[i] 
= function (config) {
                    
return function () {
                        
return pro[config[Math.min(arguments.length, config.length)]].apply(this, arguments);
                    }
                }(gsetterConfig[i]);
            }
        } 
        mix(NodeW.prototype, pro);
    };

    mix(NodeW.prototype, {
        first: 
function () {
            
return NodeW(this[0]);
        },
        last: 
function () {
            
return NodeW(this[this.length - 1]);
        },
        item: 
function (i) {
            
return NodeW(this[i]);
        }
    });
    QW.NodeW 
= NodeW;

})();
// Dom-retouch
void function () {
    
var mix = QW.ObjectH.mix,
    HH 
= QW.HelperH,
    NodeC 
= QW.NodeC,
    NodeH 
= QW.NodeH,
    NodeW 
= QW.NodeW;
    
    NodeW.pluginHelper(NodeH, NodeC.wrapMethods, NodeC.gsetterMethods);
    window.$ 
= NodeH.$;
    window.W 
= NodeW;
}();



// TEST setterAll getOne
function RunQW() {
    W([
'odiv1''odiv2']).addClass('greencolor').html('这是一段测试文本');
    alert(W([
'odiv1''odiv2']).html());
}
</script>
</body>
</html>