Spiga

自制原生js工具库——DOM篇

2008-05-06 23:33:23

源码

/* ******************************************************************* */
/*   DOM FUNCTIONS                                                     */
/* ******************************************************************* */
var DOM = (function() {
    var dom = {};
​
    //查找相关元素的前兄弟元素
    dom.prev = function(elem) {
        do {
            elem = elem.previousSibling;
        } while (elem && elem.nodeType != 1);
        return elem;
    };
​
    //查找相关元素的后兄弟元素
    dom.next = function(elem) {
        do {
            elem = elem.nextSibling;
        } while (elem && elem.nodeType != 1);
        return elem;
    };
​
    //查找第一个子元素
    dom.first = function(elem) {
        elem = elem.firstChild;
        return elem && elem.nodeType != 1 ? nextSibling(elem) : elem;
    };
​
    //查找最后一个子元素
    dom.last = function(elem) {
        elem = elem.lastChild;
        return elem && elem.nodeType != 1 ? prevSibling(elem) : elem;
    };
​
    //查找父元素
    dom.parent = function(elem, num) {
        num = num || 1;
        for (var i = 0; i < num; i++)
            if (elem != null) elem = elem.parentNode;
        return elem;
    };
​
    //找出所有指定类值的元素
    dom.hasclass = function(name, type) {
        var r = [];
        // 定位到类值上
        var re = new RegExp("(^|\\s)" + name + "(\\s|$)");
​
        //限制类型的查找,或者遍历所有元素
        var e = tag(type || "*", "");
        for (var j = 0; j < e.length; j++)
        //如果元素拥有指定类,把它添加到函数的返回值中
            if (re.test(dom.attr(e[j], "class"))) r.push(e[j]);
​
        // 返回符合的元素列表
        return r;
    };
​
    //获取元素文档内容
    dom.text = function(e) {
        var t = "";
​
        // 如果传入的是元素,则继续遍历其子元素
        // 否则假定它是一个数组
        e = e.childNodes || e;
​
        // 遍历所有字节点
        for (var j = 0; j < e.length; j++) {
            //如果不是元素,追加其文本值
            // 否则遍历所有元素的子节点
            t += e[j].nodeType != 1 ? e[j].nodeValue : dom.text(e[j].childNodes);
        }
​
        // 返回匹配的文本
        return t;
    };
​
    //检查元素是否有可用的一个指定特性
    dom.hasAttribute = function(elem, name) {
        return elem.getAttribute(name) != null;
    };
​
    //获取和设置元素特性的值
    dom.attr = function(elem, name, value) {
        //确保提供的name是正确的
        if (!name || name.constructor != String) return '';
​
        // 检查name是否处在怪异命名的情形中
        name = { 'for': 'htmlFor', 'class': 'className'}[name] || name;
​
        //如果用户传入了value参数的话,那么
        if (value != null) {
            //首先使用快捷方式
            elem[name] = value;
​
            // 可以的话使用setAttribute
            if (elem.setAttribute)
                elem.setAttribute(name, value);
        }
​
        // 返回特性的值
        return elem[name] || elem.getAttribute(name) || '';
    };
​
    //创造新DOM元素
    dom.creatr = function(elem) {
        return document.createElementNS ?
            document.createElementNS('http://www.w3.org/1999/xhtml', elem) :
            document.createElement(elem);
    };
​
    //转化一个DOM节点/HTML字符串混合型参数数组为纯粹的DOM节点数组的辅助函数
    dom.checkElem = function(a) {
        var r = [];
        // 如果参数不是数组,则强行转换
        if (a.constructor != Array) a = [a];
​
        for (var i = 0; i < a.length; i++) {
            // 如果是字符串
            if (a[i].constructor == String) {
                // 则用一个临时元素存放HTML
                var div = document.createElement("div");
​
                // 注入HTML转换成DOM结果
                div.innerHTML = a[i];
​
                // 提取DOM结构到临时div中
                for (var j = 0; j < div.childNodes.length; j++)
                    r[r.length] = div.childNodes[j];
            } else if (a[i].length) {
                // 假设是DOM节点数组
                for (var j = 0; j < a[i].length; j++)
                    r[r.length] = a[i][j];
            } else { // 否则假设是DOM节点
                r[r.length] = a[i];
            }
        }
        return r;
    };
​
    //插入和内容到DOM
    dom.before = function(parent, before, elem) {
        // 检验是否提供parent节点参数
        if (elem == null) {
            elem = before;
            before = parent;
            parent = before.parentNode;
        }
​
        // 获取元素的新数组
        var elems = dom.checkElem(elem);
​
        // 向后遍历数组,因为我们向前插入元素
        for (var i = elems.length - 1; i >= 0; i--) {
            parent.insertBefore(elems[i], before);
        }
    };
​
    //追加内容到DOM
    dom.append = function(parent, elem) {
        // 获取元素数组
        var elems = dom.checkElem(elem);
​
        // 把它们所有都追加到元素中
        for (var i = 0; i < elems.length; i++) {
            parent.appendChild(elems[i]);
        }
    };
​
    // 删除一个独立的DOM节点
    dom.remove = function(elem) {
        if (elem) elem.parentNode.removeChild(elem);
    };
​
    // 在DOM中删除一个元素的所有子节点
    dom.empty = function(elem) {
        while (elem.firstChild)
            dom.remove(elem.firstChild);
    };
​
    return dom;
})();

范例

function test_dom_node()
{
    var parentB = id("parentB");
    alert(DOM.prev(parentB).innerHTML);
    alert(DOM.next(parentB).innerHTML);
    alert(DOM.first(parentB).innerHTML);
    alert(DOM.last(parentB).innerHTML);
    alert(DOM.parent(parentB).innerHTML);
    alert(DOM.hasclass("classB","div").length);
    alert(DOM.text(parentB));
    DOM.attr(parentB,"class", "classA");
    alert(DOM.attr(parentB,"class"));
}
​
function test_dom()
{
    DOM.before(id("childB3"), "<div id=\"childB4\">childB4</div>");
    DOM.append(id("childB3"), "<div id=\"childB5\">childB5</div>");
    DOM.remove(id("childB2"));
    DOM.empty(id("childB1"));
}

HTML结构如下

<body onload="test_dom()">
 <div>
  <div id="parentA" class="classA">
   <div id="childA1">childA1</div>
   parentA
   <div id="childA2">childA2</div>
  </div>
  <div id="parentB" class="classB">
   <div id="childB1">childB1</div>
   parentB
   <div id="childB2">childB2</div>
   <div id="childB3">childB3</div>
  </div>
  <div id="parentC" class="classC">parentC
      <input id="btnClick" type="button" value="点击" />
  </div>
 </div>
</body>