2010-01-07 6 views
5

Ich mache einige Manipulation von TextNodes in Javascript, und ich (leider) muss IE6 unterstützen. Node.normalize() stürzt ab und ich muss das umgehen. Meine erste Neigung ist es, es einfach mit anderen DOM-Methoden neu zu implementieren. Wie würde ich das umsetzen?Node.normalize() stürzt in IE6 ab

+1

+1 für '(leider)' – SLaks

Antwort

8

Die folgende Version ist kürzer und effizienter als andere hier gepostet. Die Verbesserungen sind:

  • Keine wiederholten Aufrufe node.childNodes und node.childNodes.length
  • Keine Schaffung von zusätzlichen Textknoten; Stattdessen für jede merge, hält die ersten vorhandenen Textknoten und benutzen ihre appendData() Methode
  • Shorter

den Code:

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; 
    } 
} 
1

Sie müssten rekursiv alle untergeordneten Knoten des aktuellen Knotens durchsehen. Bei der Betrachtung eines Knotens würden Sie alle leeren Textknoten löschen und alle benachbarten Textknoten kombinieren.

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 
+0

guter Pseudocode. Könnten Sie es auch in Javascript übersetzen? –

0

basierend auf tvanfosson der Pseudo-Code, hier ist, was ich mit in Javascript kam:

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; 
    } 
} 
+0

Ich hasse es wirklich, meine eigene Antwort zu akzeptieren, aber ich habe mich stark darauf verlassen, dass tvanfosson darauf gekommen ist, und ich habe ihn bereits gewählt. –

5

Die Lösung oben lief sehr langsam und für mich Firefox abstürzt. Also habe ich es ein bisschen optimiert und es funktioniert jetzt großartig (das Hauptproblem war, dass ich wiederholt auf das HTML-Sammlungsobjekt node.childNodes verweise).

Danke für den tollen Ausgangspunkt, aber ich dachte, das war es wert 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--; 
    } 
} 
0

Ich denke, daß die Lösung oben angegebenen nicht ganz korrekt ist. FWIW, hier ist eine Arbeits normalisieren Funktion sowie eine Klebefunktion, die das native normalisieren verwendet, wenn es verfügbar ist:

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); 

}

+0

Ein Kommentar zu meiner Antwort wäre hilfreich gewesen, wenn sie nicht korrekt ist. Was haben Sie eigentlich korrigiert? –