JS: Obtenga una matriz de todos los nodos seleccionados en contentEditable div

Hola, he estado trabajando con contentEditable desde hace un tiempo y creo que tengo un buen manejo de eso. Una cosa que me está evadiendo es cómo obtener una serie de referencias a todos los nodos que están total o parcialmente dentro de la selección del usuario. Alguien tiene una idea?

Aquí hay algo para empezar:

     function getSelectedNodes(){ var sel = window.getSelection(); try{var frag=sel.getRangeAt(0).cloneContents()}catch(e){return(false);} var tempspan = document.createElement("span"); tempspan.appendChild(frag); var selnodes = Array() //<<- how do I fill this array?? var output = '' for(i in selnodes){ output += "A "+selnodes[i].tagName+" was found\n" //do something cool with each element here... } return(output) }    
This div is content editable and has a couple of child nodes within it


hover here

Aquí hay una versión que le brinda los nodos seleccionados y parcialmente seleccionados en lugar de los clones. Alternativamente, podría usar mi biblioteca Rangy , que tiene un método getNodes() de sus objetos Range y funciona en IE <9.

 function nextNode(node) { if (node.hasChildNodes()) { return node.firstChild; } else { while (node && !node.nextSibling) { node = node.parentNode; } if (!node) { return null; } return node.nextSibling; } } function getRangeSelectedNodes(range) { var node = range.startContainer; var endNode = range.endContainer; // Special case for a range that is contained within a single node if (node == endNode) { return [node]; } // Iterate nodes until we hit the end container var rangeNodes = []; while (node && node != endNode) { rangeNodes.push( node = nextNode(node) ); } // Add partially selected nodes at the start of the range node = range.startContainer; while (node && node != range.commonAncestorContainer) { rangeNodes.unshift(node); node = node.parentNode; } return rangeNodes; } function getSelectedNodes() { if (window.getSelection) { var sel = window.getSelection(); if (!sel.isCollapsed) { return getRangeSelectedNodes(sel.getRangeAt(0)); } } return []; } 

¡Estás tan cerca! Cuando agrega el Document Fragment al elemento de span temporal, los ha convertido en un grupo manejable, al que se puede acceder a través de la matriz de childNodes confianza.

  var selnodes = tempspan.childNodes; 

Además, te estás creando algunos problemas con ese bucle for(i in selnodes) , que devolvería los elementos en el conjunto, MÁS la propiedad length , y la propiedad __proto__ , y cualquier otra propiedad que el objeto pueda tener.

En realidad, solo debería usar esos tipos de bucles for alternar sobre las propiedades de un objeto, y siempre con if (obj.hasOwnProperty[i]) para filtrar las propiedades heredadas del prototipo.

Al pasar por las matrices, use:

  for(var i=0,u=selnodes.length;i 

Finalmente, una vez que cargue esa matriz, necesitará verificar cada elemento para ver si es un nodo DOM o un nodo de texto antes de poder manejarlo. Podemos hacer eso comprobando para ver si es compatible con la propiedad tagName .

  if (typeof selnodes[i].tagName !== 'undefined') 

Aquí está todo:

        
This div is content editable and has a couple of child nodes within it


hover here

Debajo del código se muestra una muestra para resolver su problema, debajo del código devuelve todos los nodos seleccionados que estén dentro del scope

     payam jabbari     

Even a week ago, the idea of a Russian military intervention in Ukraine seemed far-fetched if not totally alarmist. But the arrival of Russian troops in Crimea over the weekend has shown that he is not averse to reckless adventures, even ones that offer little gain. In the coming days and weeks

  1. China says military will respond to provocations.
  2. This Man Has Served 20 Years—and May Die—in Prison for Marijuana.
  3. At White House, Israel's Netanyahu pushes back against Obama diplomacy.