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
Antwort
Die folgende Version ist kürzer und effizienter als andere hier gepostet. Die Verbesserungen sind:
- Keine wiederholten Aufrufe
node.childNodes
undnode.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;
}
}
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
guter Pseudocode. Könnten Sie es auch in Javascript übersetzen? –
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;
}
}
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. –
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--;
}
}
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);
}
Ein Kommentar zu meiner Antwort wäre hilfreich gewesen, wenn sie nicht korrekt ist. Was haben Sie eigentlich korrigiert? –
+1 für '(leider)' – SLaks