2010-01-07 15 views
5

Estoy haciendo algo de manipulación de TextNodes en JavaScript, y yo (lamentablemente) necesito soportar IE6. Node.normalize() se cuelga, y necesito solucionar esto. Mi primera inclinación es simplemente volver a implementarlo usando otros métodos DOM. ¿Cómo implementaría esto?Node.normalize() se bloquea en IE6

+1

1 para '(por desgracia)' – SLaks

Respuesta

8

La siguiente versión es más corta y más eficientes que otros publicados aquí. Las mejoras son:

  • No repetidas llamadas a node.childNodes y node.childNodes.length
  • hay creación de nodos de texto adicionales; en cambio, para cada combinación, guardar el primer nodo de texto existente y utilizar su método appendData()
  • Shorter

El código:

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

Tendría que buscar recursivamente a través de todos los nodos secundarios del nodo actual. Al considerar un nodo, debe eliminar los nodos de texto vacíos y combinar los nodos de texto adyacentes.

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

buen pseudocódigo. ¿podrías traducirlo también a javascript? –

0

basado en pseudocódigo de tvanfosson, esto es lo que se me ocurrió en 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; 
    } 
} 
+0

Realmente odio aceptar mi propia respuesta, pero confié fuertemente en tvanfosson para llegar a esto, y ya lo he votado. –

5

La solución anterior estaba funcionando muy lento y estrellarse Firefox para mí. Así que lo optimicé un poco y está funcionando bien ahora (el problema principal fue hacer referencias repetidas al objeto de colección HTML node.childNodes).

Gracias por el gran punto de partida, pero pensé que merecía la pena publicación:


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

creo que la solución descrita anteriormente no es del todo correcto. Fwiw, aquí es una función normalizar trabajo y una función de pegamento que utiliza el normalizar nativa si está disponible:

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

Un comentario sobre mi respuesta habría sido útil si no es correcto. Además, ¿qué has corregido en realidad? –