2010-11-18 32 views
7

Al seleccionar textos en documentos HTML, se puede comenzar desde un elemento DOM a otro elemento, posiblemente pasando por otros elementos en el camino. Usando DOM API, es posible obtener el rango de la selección, los textos seleccionados, e incluso el elemento padre de todos los elementos DOM seleccionados (utilizando commonAncestorContainer o parentElement() basado en el navegador utilizado). Sin embargo, no hay manera de que yo sepa que puede enumerar todos aquellos que contienen elementos de los textos seleccionados, además de obtener el elemento monoparental que los contiene a todos. Usar el elemento primario y atravesar los nodos hijos no lo hará, ya que puede haber otros hermanos que no estén seleccionados dentro de este elemento primario.Obtener todos los elementos de bloque DOM para textos seleccionados

Entonces, ¿hay alguna manera de que pueda obtener todos estos elementos que contienen los textos seleccionados? Estoy interesado principalmente en obtener los elementos de bloque (p, h1, h2, h3, ... etc.) pero creo que si hay una manera de obtener todos los elementos, entonces puedo revisarlos y filtrarlos para obtener lo que querer. Doy la bienvenida a cualquier idea y sugerencia.

Gracias.

Respuesta

16

Key es window.getSelection().getRangeAt(0)https://developer.mozilla.org/en/DOM/range

He aquí algunos ejemplos de código que se puede jugar con hacer lo que quiere. Mencionar lo que realmente quieres para esto en cuestión ayudará a las personas a dar mejores respuestas.

var selection = window.getSelection(); 
var range = selection.getRangeAt(0); 
var allWithinRangeParent = range.commonAncestorContainer.getElementsByTagName("*"); 

var allSelected = []; 
for (var i=0, el; el = allWithinRangeParent[i]; i++) { 
    // The second parameter says to include the element 
    // even if it's not fully selected 
    if (selection.containsNode(el, true)) { 
    allSelected.push(el); 
    } 
} 


console.log('All selected =', allSelected); 

Ésta no es la forma más eficiente, se puede recorrer el DOM por sí mismo utilizando la gama de startContainer/endContainer, junto con nextSibling/previousSibling y childNodes.

+0

No fue la solución perfecta como dijiste, pero me dio una idea de cómo hacerlo. Por lo tanto, elegí esta como la respuesta más correcta a mi necesidad. Realmente lo aprecio – cria

+0

Esta es una respuesta decente, pero no funcionará en IE <9. Podría hacer una verificación de que la selección existe antes de llamar a 'selection.getRangeAt (0);' también (usando la propiedad 'rangeCount' de la selección es más fácil). –

+0

Hay muchos problemas que no he abordado, esto es solo para comenzar a encaminarse en la dirección correcta. Su biblioteca requiere 22k de javascript sin comprimir para manejarlo realmente y si lo necesitara, simplemente usaría eso. –

0

Parece que podría usar Traversing from the jQuery API.

.Contenido Posiblemente()

Hope que ayuda!

+0

Sí, los métodos son geniales. Pero no creo que pueda usar el rango de texto seleccionado por el navegador como entrada para esos métodos, ¿o sí? o tal vez me falta algo ... Gracias – cria

10

Puede usar mi Rangy library para hacerlo. Proporciona una implementación de objetos DOM Range y Selection para todos los navegadores, incluido IE, y tiene métodos de Rango adicionales. Uno de ellos es getNodes():

function isBlockElement(el) { 
    // You may want to add a more complete list of block level element 
    // names on the next line 
    return /h[1-6]|div|p/i.test(el.tagName); 
} 

var sel = rangy.getSelection(); 
if (sel.rangeCount) { 
    var range = sel.getRangeAt(0); 
    var blockElements = range.getNodes([1], isBlockElement); 
    console.log(blockElements); 
} 
+0

No tengo dudas de que este código es el más preciso. Pero usar tu lib es una exageración para mi caso debido al gran tamaño de la lib. Por lo tanto, elegí la otra respuesta a pesar de que tiene algunos problemas que debo manejar. Si hubiera una opción para elegir dos respuestas, seguramente marcaría la suya también. Sigan con la gran lib/work :) – cria

+0

@cria: Es suficiente. Lo que obtienes con el mío es soporte para IE. –

+3

@TimDown gracias por su trabajo en Rangy. Hace mucho más fácil una serie de problemas complicados. –

Cuestiones relacionadas