views:

121

answers:

3

I am doing some manipulation of TextNodes in javascript, and I (unfortunately) need to support IE6. Node.normalize() is crashing, and I need to work around this. My first inclination is to just re-implement it using other DOM methods. How would I implement this?

+1  A: 

You'd need to recursively look through all of the child nodes of the current node. When considering a node, you'd delete any empty text nodes and combine any adjacent text nodes.

 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
tvanfosson
good pseudocode. could you also translate it to javascript?
Christian Oudard
A: 

based on tvanfosson's pseudocode, here's what I came up with in 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;
    }
}
Christian Oudard
I really hate to accept my own answer, but I did rely heavily on tvanfosson to come up with this, and I've already voted him up.
Christian Oudard
A: 

The solution above was running very slow and crashing Firefox for me. So I optimized it a bit and it's working great now (the main issue was with repeatedly referencing the HTML collection object node.childNodes).

Thanks for the great starting point, but I figured this was worth posting:


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--;
    }
}
Jon Raasch