2012-03-02 12 views
9

Esto es lo que estoy tratando de lograr: cuando un usuario usa un mouse, teclado o toque para seleccionar texto dentro de "myDiv", quiero adquirir tres fragmentos discretos de HTML: el HTML antes de la selección (a la "izquierda" de ella), el HTML dentro de la selección y el HTML después de la selección (a la "derecha" de la misma). El html debería ser como aparecería con myDiv.innerHTML.¿Cómo obtener el HTML antes, dentro y después de una selección (no en textarea)?

La selección puede comenzar o finalizar dentro de un par de etiquetas (es decir, la selección aislada no es necesariamente válida HTML). No necesito lidiar con escenarios especiales como elementos de posición absoluta dentro de la selección; todas las selecciones que me interesan estarán restringidas a un div que contendrá etiquetas básicas como strong, em, ul, ol, h1, image y table.

Lo más parecido que he venido es usar rangy para enganchar la selección y llamar al selection.getRangeAt(0).cloneContents() para obtener la selección HTML. Esto funciona bastante bien hasta que realice una selección que no es válida de forma aislada, y el navegador altera el código HTML del fragmento de documento para que sea válido.

Información adicional: He aquí por qué necesito esto:

Estoy creando un sistema de retroalimentación de documentos, por lo que necesito para salvar la información de selección a una base de datos para su posterior recuperación y reconstitución. Normalmente, guardaría la selección usando la ruta DOM y el texto seleccionado, pero el texto puede cambiar entre guardar y reconstituir. Por ejemplo, el autor podría mover párrafos enteros, eliminar secciones, etc. La ruta DOM se vuelve bastante inútil.

Así que mi plan (imperfecto) es almacenar la selección como [desplazamiento, longitud, html_snippet]. Esa es la "posición". También almacenaré los fragmentos de html que vinieron directamente antes y después del texto seleccionado. Este es el "contexto".

Utilizando una combinación de estos datos, podría reubicar el texto seleccionado la mayor parte del tiempo, incluso si se ha movido o ha cambiado parcialmente. Cuando eso falla, la interfaz de usuario tendrá una forma de abordarlo, pero me gustaría que ocurra con la menor frecuencia posible.

Superthanks!

+3

Ese es un texto de lotta. –

+0

Sí, estaba tratando de proporcionar la mayor cantidad de información posible, y en lugar de eso era desagradablemente prolijo. Justo ahora lo reduje un poco. :) –

+0

Para que quede claro: ¿los fragmentos de HTML que necesita son exactamente como aparecen en la fuente HTML enviada al navegador? –

Respuesta

1

tengo varias preguntas:

1.- Cuando se dice 'el html después de la selección' - cómo habría que html ser diferente que el HTML anterior a la selección o viceversa? ¿El proceso de 'selección' está alterando el html debido a su 'script' o lo que sea?

2.- Dijo que las selecciones de texto no están teniendo lugar en áreas de texto ... ¿con qué elementos está trabajando entonces? ¿párrafos? divs ...? Reducirlo ayudaría.

3.- ¿Has pensado en usar jquery?

http://api.jquery.com/select/

hacer algo como

$('#element_with_text_goes_here').select(function() { 

//apply grabbing functions here, for example 

//copy html 'before' selection: 
    $pre_html = $('html').clone(); 

    // copy selection...see below: 

    // copy html 'after' selection'...same as before 


}); 

Copiar selección:

Como se ha señalado aquí:

Selecting text in an element (akin to highlighting with your mouse)

Jason escribió la siguiente función:

function selectText(element) { 
    var doc = document; 
    var text = doc.getElementById(element);  

    if (doc.body.createTextRange) { // ms 
     var range = doc.body.createTextRange(); 
     range.moveToElementText(text); 
     range.select(); 
    } else if (window.getSelection) { // moz, opera, webkit 
     var selection = window.getSelection();    
     var range = doc.createRange(); 
     range.selectNodeContents(text); 
     selection.removeAllRanges(); 
     selection.addRange(range); 
    } 
} 

Con una demostración en vivo de trabajo que se pueden encontrar aquí: http://jsfiddle.net/edelman/KcX6A/339/

y una versión plugin de jQuery aquí: http://jsfiddle.net/edelman/KcX6A/340/

que se puede utilizar para la obtención del texto seleccionado. Tendrás que modificarlo en consecuencia ya que se acercaba desde un ángulo invertido. Cuantos más detalles nos puede dar ... mejor podemos ayudar.

Esperanza esto ayuda
G

+0

En respuesta a su primera pregunta: por "anterior" a la selección no me refiero a "en el pasado", me refiero a "a la izquierda de". Imagine que hacer una selección divide los contenidos de mi div en tres secciones: html a la izquierda de la selección, html dentro de la selección y html a la derecha de la selección. Necesito obtener el html no modificado para cada una de esas secciones. –

+0

En respuesta a su segunda pregunta: Todo esto está contenido en un div que contiene algunas etiquetas como strong, em, image, etc. –

+0

... y jQuery es definitivamente mi preferencia, pero no es obligatorio. –

0

Este código obtiene html/texto de la selección del usuario, pero funciona sólo en IE. El código también funciona con la selección de etiquetas cruzadas. (Globals utilizan para mantener el código de acceso.)

<script> 
function selected(){ 
    thediv=document.getElementById('div'); 
    res=document.getElementById('htm'); 
    userSelection=document.selection; 
    userRange=userSelection.createRange(); 
    /* For wider scale of elements */ 
    // rangeParent=userRange.parentElement(); 
    // if(rangeParent!=thediv) userRange.moveToElementText(rangeParent); 
    rangeText=userRange.htmlText; // OR: rangeText=userRange.text; 
    res.innerText=rangeText;  
    return; 
}  
</script> 
</head>  
<body onload="document.onselectionchange=selected;"> 
<div id="div"> 
<h1>The great testpage</h1> 
<p>A paragraph with some text</p> 
<p>This paragraph <b>contains</b> a child element.</p> 
<p>And this is the last paragraph.</p> 
<table> 
<tr><td>Cell1-1</td><td>cell1-2</td></tr> 
<tr><td>Cell2-1</td><td>cell2-2</td></tr> 
</table> 
<ol> 
<li>item1</li> 
<li>item2</li> 
<li>item3</li> 
</ol> 
</div> 
<br> 
<span id="htm"></span> 
</body> 

contenido antes & después de la selección en el thediv obtendrá así: prepost=thediv.innerHTML/innerText.split(rangeText);

Si la página contiene otros elementos, pero thediv, tienen que hacerse inasegible.

+0

IE-only no funciona para mí, pero gracias por el esfuerzo de todos modos. :) –

+0

@AlanBellows Antes de "talar" su publicación original, IE fue mencionado. De todos modos, el código contiene ciertas ideas, que también podrían ser "traducidas" para otros navegadores. Esta respuesta ni siquiera se propuso como una solución perfecta para su pregunta.Tienes una tarea muy interesante y desafiante, buena suerte con ella ... – Teemu

+0

En mi publicación original decía que está bien si no funciona en IE. :) Lo que busco puede que ni siquiera sea posible, pero por goma lo intentaré. ¡Gracias! –

Cuestiones relacionadas