显示标签为“dom”的博文。显示所有博文
显示标签为“dom”的博文。显示所有博文

2011年12月22日星期四

ie6 getElementById/getElementsByName bug

ref
in ie6:
document.getElementsByName(nameValue) will return the element which id attribute equals to nameValue
document.getElementById(idValue) will return the element which name attribute equals to idValue
so prevent to use the same id and name attribute value in dom!

getElementsByAttribute

//属性选择符
//author:司徒正美 ref:http://www.cnblogs.com/rubylouvre/archive/2009/10/26/1590102.html
//正则支持 tag[attrName ^\$\*\~\!=attrValue]
var getElementsByAttribute = function(search) {
    var tag = /([\*a-zA-Z1-6]*)?(\[(\w+)\s*(\^|\$|\*|\||~|!)?=?\s*([\w\u00C0-\uFFFF\s\-_\.]+)?\])?/,
            node = arguments[1] || document,
            agent = search.match(tag),
            tag = agent[1] || "*",  //html标签
            attribute = agent[3],  //属性名
            type = agent[4] + "=", //比较符号 ^ $ * | ~ !
            value = agent[5],//属性值
            ieAttrFix = {"class": "className","for": "htmlFor"},  //特殊属性名
            returnElements = [],
        //IE5.5不支持“*”
            elements = (tag === "*" && node.all) ? node.all : node.getElementsByTagName(tag),
            length = elements.length;
    if ((!!document.querySelectorAll) && type != "!=") {//ie8+ 标准browser
        elements = document.querySelectorAll(search);
        for (var i = 0,length = elements.length; i < length; i++) {
            returnElements.push(elements[i]);
        }
        return returnElements
    }
    if (!+"\v1")  //ie检测
        attribute = ieAttrFix[attribute] ? ieAttrFix[attribute] : attribute;
    while (length--) {
        var current = elements[length],
                _value = !+"\v1" ? current[attribute] : current.getAttribute(attribute);
        if (typeof _value === "string" && _value.length > 0) {
            if (!!value) {
                var condition =
                        type === "=" ? //完全等于
                                _value === value :
                                type === "!=" ? //不等于
                                        _value != value :
                                        type === "*=" ? //包含
                                                _value.indexOf(value) >= 0 :
                                                type === "~=" ? //匹配当中的某个单词,如警告
                                                        (" " + _value + " ").indexOf(value) >= 0 :
                                                        type === "^=" ? //以XX开头
                                                                _value.indexOf(value) === 0 :
                                                                type === "$=" ? //以XX结尾
                                                                        _value.slice(-value.length) === value :
                                                                        type === "|=" ? //匹配属性值为XX或以XX-打头的元素
                                                                                _value === value || _value.substring(0, value.length + 1) === value + "-" :
                                                                                false;
                condition && returnElements.push(current);
            } else {
                returnElements.push(current)
            }
        }
    }
    return returnElements;
}

Node.contains

/*
 code ref  http://www.cnblogs.com/rubylouvre/archive/2009/10/14/1583523.html
 IE有contains方法。如果A元素包含B元素,则返回true,否则false。唯一不支持这个方法的是firefox。
 不过火狐支持compareDocumentPosition() 方法,这是W3C制定的方法,标准浏览器都支持。
 它的使用形式与contains差不多,但返回的不是一个布尔值,而是一个很奇怪的数值,它是通过如下方式累加计算出来的:
 二进制   数值 含义
 000000 0    元素一致
 000001 1    节点在不同的文档(或者一个在文档之外)
 000010 2    节点 B 在节点 A 之前
 000100 4    节点 A 在节点 B 之前
 001000 8    节点 B 包含节点 A
 010000 16   节点 A 包含节点 B
 100000 32    浏览器的私有使用
 A.compareDocumentPosition(B);//B与A不相连,B在A的后面,B被A包含 4+16 = 20
 B.compareDocumentPosition(A);//A与B不相连,A在B的前面,A包含B 2+8 = 10
 */
//PPK给出如下解决方法。
if (window.Node && Node.prototype && !Node.prototype.contains) {
    Node.prototype.contains = function (arg) {
        return !!(this.compareDocumentPosition(arg) & 16);//位运算 小于16结果为0
    }
} 
//2011.9.24 by 司徒正美
var contains = function(root, el) {
    if (root.compareDocumentPosition)
        return root === el || !!(root.compareDocumentPosition(el) & 16);
    if (root.contains && el.nodeType === 1) {
        return root.contains(el) && root !== el;
    }
    //两种原生方法都不支持的话 -_-||| 递归吧
    while ((el = el.parentNode))
        if (el === root) return true;
    return false;
}