[转帖]Mootools源码分析-14 -- Element-1

原帖地址:http://space.flash8.net/space/?18713/viewspace-402754.html

原作者:我佛山人

 

/*
对HTML Element的包装
*/
var Element = new Native({

    
//族名,为$type方法提供精准类型
    name: 'Element',

    
//包装扩展的原型
    legacy: window.Element,

    
//初始化,使用Document对象的newElement创建对象
    initialize: function(tag, props)    {

        
//先看有没有特殊的HTML Element
        var konstructor = Element.Constructors.get(tag);

        
//对特殊的HTML Element对象特别处理
        if (konstructor)    return konstructor(props);

        
//如果提供标签名,根据标签名创建HTML Element对象
        if (typeof tag == 'string')    return document.newElement(tag, props);

        
//设置属性
        return $(tag).set(props);
    },

    
//执行后续处理,每为Element增加一个扩展,Elements也会同时实现
    afterImplement: function(key, value)    {
        
if (!Array[key])    Elements.implement(key, Elements.multi(key));
        Element.Prototype[key] 
= value;
    }

});

Element.Prototype 
= {$family: {name: 'element'}};

Element.Constructors 
= new Hash;



//同时对Element和Document对象进行扩展
Native.implement([Element, Document], {

    
//根据选择符选择一个子Element
    getElement: function(selector, notrash)    {
        
return $(this.getElements(selector, true)[0|| null, notrash);
    },

    
//根据选择符选择子Element
    getElements: function(tags, nocash)    {
        tags 
= tags.split(',');
        
var elements = [];
        
var ddup = (tags.length > 1);
        tags.each(
function(tag)    {
            
var partial = this.getElementsByTagName(tag.trim());
            (ddup) 
? elements.extend(partial) : elements = partial;
        }, 
this);
        
return new Elements(elements, {ddup: ddup, cash: !nocash});
    }    

});

//用于获取保存在当前Element下的临时对象,参考Fx.Tween和Drag
Element.Storage = {

    get: 
function(uid)    {
        
return (this[uid] || (this[uid] = {}));
    }

};

//相当于当前Element的四个位置的DOM插入
Element.Inserters = new Hash({

    
//在context指代的Element之前插入eleemnt
    before: function(context, element)    {
        
if (element.parentNode)    element.parentNode.insertBefore(context, element);
    },

    
//在context指代的Element之后插入eleemnt
    after: function(context, element)    {
        
if (!element.parentNode)    return;
        
var next = element.nextSibling;
        (next) 
? element.parentNode.insertBefore(context, next) : element.parentNode.appendChild(context);
    },

    
//在context指代的Element内最后插入eleemnt
    bottom: function(context, element)    {
        element.appendChild(context);
    },

    
//在context指代的Element内首位插入eleemnt
    top: function(context, element)    {
        
var first = element.firstChild;
        (first) 
? element.insertBefore(context, first) : element.appendChild(context);
    }

});

//别名
Element.Inserters.inside = Element.Inserters.bottom;

//生成injectTop/grabTop之类的快捷方式
Element.Inserters.each(function(value, key)    {

    
var Key = key.capitalize();

    
//injectTop,injectBefore,injectAfter,injectBottom
    Element.implement('inject' + Key, function(el)    {
        value(
this, $(el, true));
        
return this;
    });

    
//grabTop,grabBefore,grabAfter,grabBottom
    Element.implement('grab' + Key, function(el)    {
        value($(el, 
true), this);
        
return this;
    });

});

Element.implement({

    
//当前Element所属的Document
    getDocument: function()    {
        
return this.ownerDocument;
    },

    
//当前Element所属的Window
    getWindow: function()    {
        
return this.ownerDocument.getWindow();
    },

    
//根据ID查找当前Element下的对象
    getElementById: function(id, nocash)    {
        
var el = this.ownerDocument.getElementById(id);
        
if (!el)    return null;
        
for (var parent = el.parentNode; parent != this; parent = parent.parentNode)    {
            
if (!parent)    return null;
        }
        
return $.element(el, nocash);
    },

    
//万能的setter
    set: function(prop, value)    {
        
switch ($type(prop))    {
        
case 'object':
            
for (var p in prop)    this.set(p, prop[p]);
            
break;
        
case 'string':
            
var property = Element.Properties.get(prop);
            (property 
&& property.set) ? property.set.apply(this, Array.slice(arguments, 1)) : this.setProperty(prop, value);
        }
        
return this;
    },

    
//万能的getter
    get: function(prop)    {
        
var property = Element.Properties.get(prop);
        
return (property && property.get) ? property.get.apply(this, Array.slice(arguments, 1)) : this.getProperty(prop);
    },

    
//万能的eraser
    erase: function(prop)    {
        
var property = Element.Properties.get(prop);
        (property 
&& property.erase) ? property.erase.apply(this, Array.slice(arguments, 1)) : this.removeProperty(prop);
        
return this;
    },

    
//判断当前Element是否匹配指定标签名
    match: function(tag)    {
        
return (!tag || Element.get(this'tag'== tag);
    },

    
//根据where指定的位置,将当前Element注入到el
    inject: function(el, where)    {
        Element.Inserters.get(where 
|| 'bottom')(this, $(el, true));
        
return this;
    },

    
//根据where指定的位置,使当前Element作为el的父Element
    wraps: function(el, where)    {
        el 
= $(el, true);
        
return this.replaces(el).grab(el, where);
    },

    
//和inject相反
    grab: function(el, where)    {
        Element.Inserters.get(where 
|| 'bottom')($(el, true), this);
        
return this;
    },

    
//追加文本
    appendText: function(text, where)    {
        
return this.grab(this.getDocument().newTextNode(text), where);
    },

    
//将多个对象追加到当前Element内
    adopt: function()    {
        Array.flatten(arguments).each(
function(element)    {
            element 
= $(element, true);
            
if (element)    this.appendChild(element);
        }, 
this);
        
return this;
    },

    
//从DOM节点中删除
    dispose: function()    {
        
return (this.parentNode) ? this.parentNode.removeChild(this) : this;
    },

    
//从当前Element克隆出新的Element,contents指定是否包含子节点,keepid指定是否忽略id属性
    clone: function(contents, keepid)    {
        
switch ($type(this))    {
        
case 'element':
            
var attributes = {};
            
for (var j = 0, l = this.attributes.length; j < l; j++)    {
                
var attribute = this.attributes[j], key = attribute.nodeName.toLowerCase();
                
var value = (key == 'style' && this.style) ? this.style.cssText : attribute.nodeValue;
                
if (!$chk(value) || key == 'uid' || (key == 'id' && !keepid))    continue;
                
if (value != 'inherit' && ['string''number'].contains($type(value)))    attributes[key] = value;
            }        
            
var element = new Element(this.nodeName.toLowerCase(), attributes);
            
if (contents !== false)    {
                
for (var i = 0, k = this.childNodes.length; i < k; i++)    {
                    
var child = Element.clone(this.childNodes[i], true, keepid);
                    
if (child)    element.grab(child);
                }
            }
            
return element;
        
//如果当前是文本节点
        case 'textnode'return    document.newTextNode(this.nodeValue);
        }
        
return null;
    },

    
//替换节点
    replaces: function(el)    {
        el 
= $(el, true);
        el.parentNode.replaceChild(
this, el);
        
return this;
    },

    
//是否使用指定css类名
    hasClass: function(className)    {
        
return this.className.contains(className, ' ');
    },

    
//添加指定css类名
    addClass: function(className)    {
        
if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
        
return this;
    },

    
//移除指定css类名
    removeClass: function(className)    {
        
this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean();
        
return this;
    },

    
//切换指定css类名
    toggleClass: function(className)    {
        
return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
    },

    
//获取运行时的样式属性
    getComputedStyle: function(property)    {
        
//IE
        if (this.currentStyle)    return this.currentStyle[property.camelCase()];
        
//非IE
        var computed = this.getWindow().getComputedStyle(thisnull);
        
return (computed) ? computed.getPropertyValue([property.hyphenate()]) : null;
    },

    
//清空当前Element,包括内部节点的删除和内存释放
    empty: function()    {
        $A(
this.childNodes).each(function(node)    {
            Element.empty(node);
            
this.removeChild(node);
            memfree(node);
        }, 
this);
        
return this;
    },

    
//销毁当前Element,删除所有有关的一切
    destroy: function()    {
        memfree(
this.empty().dispose());
        
return null;
    },

    
//获取选中的子项,仅当<select multi>有效
    getSelected: function()    {
        
return $A(this.options).filter(function(option){
            
return option.selected;
        });
    },

    
//将当前Element内的表单项数据转为查询串格式,以用于Ajax或get方式的提交
    toQueryString: function()    {
        
var queryString = [];
        
this.getElements('input, select, textarea').each(function(el)    {
            
if (!el.name || el.disabled)    return;
            
var value = (el.tagName.toLowerCase() == 'select'? Element.getSelected(el).map(function(opt)    {
                
return opt.value;
            }) : ((el.type 
== 'radio' || el.type == 'checkbox'&& !el.checked) ? null : el.value;
            $splat(value).each(
function(val)    {
                
if (val) queryString.push(el.name + '=' + encodeURIComponent(val));
            });
        });
        
return queryString.join('&');
    },

    
//读取属性值,包括自定义属性
    getProperty: function(attribute)    {
        
var EA = Element.Attributes, key = EA.Props[attribute];
        
var value = (key) ? this[key] : this.getAttribute(attribute, 2);
        
return (EA.Bools[attribute]) ? !!value : (key) ? value : value || null;
    },

    
//根据属性列表读取相应值,以objecct方式返回结果
    getProperties: function()    {
        
var args = $A(arguments);
        
return args.map(function(attr)    {
            
return this.getProperty(attr);
        }, 
this).associate(args);
    },

    
//属性设置
    setProperty: function(attribute, value)    {
        
var EA = Element.Attributes, key = EA.Props[attribute], hasValue = $defined(value);
        
if (key && EA.Bools[attribute]) value = (value || !hasValue) ? true : false;
        
else if (!hasValue)    return this.removeProperty(attribute);
        (key) 
? this[key] = value : this.setAttribute(attribute, value);
        
return this;
    },

    
//批量属性设置
    setProperties: function(attributes)    {
        
for (var attribute in attributes)    this.setProperty(attribute, attributes[attribute]);
        
return this;
    },

    
//移除属性
    removeProperty: function(attribute)    {
        
var EA = Element.Attributes, key = EA.Props[attribute], isBool = (key && EA.Bools[attribute]);
        (key) 
? this[key] = (isBool) ? false : '' : this.removeAttribute(attribute);
        
return this;
    },

    
//批量移除属性
    removeProperties: function()    {
        Array.each(arguments, 
this.removeProperty, this);
        
return this;
    }

});

 

posted @ 2009-10-29 09:28  webgis松鼠  阅读(461)  评论(0编辑  收藏  举报