代码之家  ›  专栏  ›  技术社区  ›  Christian Oudard

node.normalize()在IE6中崩溃

  •  5
  • Christian Oudard  · 技术社区  · 15 年前

    我在javascript中对textnode进行一些操作,我(不幸的是)需要支持IE6。node.normalize()即将崩溃,我需要解决这个问题。我的第一个倾向是使用其他DOM方法重新实现它。我将如何实现这一点?

    5 回复  |  直到 10 年前
        1
  •  7
  •   Tim Down    10 年前

    下面的版本比这里发布的其他版本短,效率更高。改进包括:

    • 没有重复呼叫 node.childNodes node.childNodes.length
    • 不创建额外的文本节点;相反,对于每次合并,保留第一个现有的文本节点并使用其 appendData() 方法
    • 更短的

    代码:

    function normalize(node) {
        var child = node.firstChild, nextChild;
        while (child) {
            if (child.nodeType == 3) {
                while ((nextChild = child.nextSibling) && nextChild.nodeType == 3) {
                    child.appendData(nextChild.data);
                    node.removeChild(nextChild);
                }
            } else {
                normalize(child);
            }
            child = child.nextSibling;
        }
    }
    
        2
  •  5
  •   Jon Raasch    14 年前

    上面的解决方案运行非常慢,让我的火狐崩溃。所以我对它进行了一些优化,现在它工作得很好(主要问题是重复引用HTML集合对象node.childnodes)。

    谢谢你给我一个很好的起点,但我觉得这是值得一贴的:

    
    function myNormalize(node) {
        for (var i=0, children = node.childNodes, nodeCount = children.length; i<nodeCount; i++) {
            var child = children[i];
            if (child.nodeType == 1) {
                myNormalize(child);
                continue;
            }
            if (child.nodeType != 3) { continue; }
            var next = child.nextSibling;
            if (next == null || next.nodeType != 3) { continue; }
            var combined_text = child.nodeValue + next.nodeValue;
            new_node = node.ownerDocument.createTextNode(combined_text);
            node.insertBefore(new_node, child);
            node.removeChild(child);
            node.removeChild(next);
            i--;
            nodeCount--;
        }
    }
    
        3
  •  1
  •   tvanfosson    15 年前

    您需要递归地查看当前节点的所有子节点。当考虑一个节点时,您将删除任何空文本节点并合并任何相邻的文本节点。

     function myNormalize( node )
         for each child node of node do
             if child is not text
                normalize(child)
             else
                if child node is empty
                   delete
                   continue
                else 
                    sibling = next node
                    while sibling exists and sibling is a text node
                        if sibling is empty
                           delete sibling
                        else
                           combine sibling with child
                        get next sibling
                    end
                end
            end
        end
    end
    
        4
  •  0
  •   Christian Oudard    15 年前

    基于Tvanfosson的伪代码,我在javascript中得出了以下结论:

    var ELEMENT_NODE = 1;
    var TEXT_NODE = 3;
    function normalize(node) {
        for (i=0; i<node.childNodes.length; i++) {
            var child = node.childNodes[i];
            if (child.nodeType == ELEMENT_NODE) {
                normalize(child);
                continue;
            }
            if (child.nodeType != TEXT_NODE) { continue; }
            var next = child.nextSibling;
            if (next == null || next.nodeType != TEXT_NODE) { continue; }
            var combined_text = child.nodeValue + next.nodeValue;
            new_node = node.ownerDocument.createTextNode(combined_text);
            node.insertBefore(new_node, child);
            node.removeChild(child);
            node.removeChild(next);
            i -= 1;
        }
    }
    
        5
  •  0
  •   imdfl    11 年前

    我认为上述解决方案并不完全正确。 fwiw,这里是一个正常工作的函数加上一个粘合函数,如果它可用,则使用本机正常化:

    function _myNormalizeNode(node) {
    if (! node) {
        return;
    }
    
    var ELEMENT_NODE = 1;
    var TEXT_NODE = 3;
    var child = node.firstChild;
    while (child) {
        if (child.nodeType == ELEMENT_NODE) {
            this._myNormalizeNode(child);
        }
        else if (child.nodeType == TEXT_NODE) { 
            var next;
            while ((next = child.nextSibling) && next.nodeType == TEXT_NODE) { 
                var value = next.nodeValue;
                if (value != null && value.length) {
                    child.nodeValue = child.nodeValue + value;
                }
                node.removeChild(next);
            }
        }
        child = child.nextSibling;
    }
    

    }

    function  _normalizeNode(node) {
    if (! node) {
        return;
    }
    if (typeof node.normalize == "function") {
        return node.normalize();
    }
    return _myNormalizeNode(node);
    

    }