2011-11-14 15 views
18

Me gustaría poder convertir la posición actual del mouse en un rango, en particular en CKEditor.JavaScript convierte la posición del mouse al rango de selección

El CKEditor proporciona una API para establecer el cursor de acuerdo con un rango:

var ranges = new CKEDITOR.dom.range(editor.document); 
editor.getSelection().selectRanges([ ranges ]); 

Desde CKEditor ofrece esta API, el problema puede ser simplificado mediante la eliminación de este requisito y acaba de encontrar una manera de producir el rango de el mouse coordina sobre un div que contiene varios elementos HTML.

Sin embargo, esto no es lo mismo que convertir una coordenada del mouse en la posición del cursor en un área de texto ya que las áreas textareas han fijado anchos de columna y alturas de fila donde el CKEditor representa HTML a través de un iframe.

Según this, parece que el rango se puede aplicar a los elementos.

¿Cómo calificaría el rango de inicio/final más cercano a la posición actual del mouse?

Edit: Un ejemplo de cómo uno puede usar la API de ckeditor para seleccionar un rango en el evento mouseup.

editor.document.on('mouseup', function(e) { 
    this.focus(); 
    var node = e.data.$.target; 

    var range = new CKEDITOR.dom.range(this.document); 
    range.setStart(new CKEDITOR.dom.node(node), 0); 
    range.collapse(); 

    var ranges = []; 
    ranges.push(range); 
    this.getSelection().selectRanges(ranges); 
}); 

El problema con el ejemplo anterior es que el nodo de destino del evento (e.data. $. Objetivo) solamente está disparando para los nodos tales como HTML, el cuerpo o IMG pero no para los nodos de texto. Incluso si lo hiciera, estos nodos representan trozos de texto que no admitirían colocar el cursor en la posición del mouse dentro de ese trozo de texto.

Respuesta

1

Hay dos formas de hacerlo, como lo hace cada WYSIWYG.

Primero: - te rindes porque es demasiado difícil y terminará siendo un asesino del navegador;

Segundo: - que tratar de analizar el texto y ponerlo en el lugar exacto en una área de texto semitransparente o div por encima de la original, pero aquí tenemos dos problemas:

1) ¿Cómo analizar la dinámica trozos de datos para obtener solo el texto y para asegurarse de asignarlo a la posición exacta del contenido real

2) cómo resolvería la actualización para analizar por cada maldito personaje que escriba o cada acción que haga en el editor.

Al final, esta es solo una "Odisea brutal en el lado oscuro del árbol DOM", pero si elige la segunda forma, el código de su publicación funcionará como un amuleto.

2

Lo que intenta hacer es realmente difícil en un navegador. No estoy familiarizado con ckeditor en particular, pero javascript regular te permite seleccionar texto usando un rango, así que no creo que esté agregando nada especial. Debe encontrar el elemento del navegador que contiene el clic y luego buscar el carácter dentro del elemento en el que se hizo clic.

La detección del elemento del navegador es la parte fácil: debe registrar su controlador en cada elemento o utilizar el campo de destino del evento. Hay mucha información sobre esto, haz una pregunta más específica sobre stackoverflow si es con lo que estás teniendo problemas.

Una vez que tenga el elemento que necesita para averiguar qué carácter del elemento se hizo clic, cree un rango apropiado para colocar el cursor allí. Como dice la publicación a la que vinculó, las variaciones del navegador lo hacen realmente difícil. Esta página está un poco pasada de moda, pero tiene una buena discusión sobre los rangos: http://www.quirksmode.org/dom/range_intro.html

Los rangos no pueden indicarle sus posiciones en la página, por lo que tendrá que usar otra técnica para averiguar en qué fragmento de texto se hizo clic. .

Nunca he visto una solución completa a esto en javascript. Hace unos años trabajé en uno, pero no encontré una respuesta con la que estuviera contento (algunos casos muy difíciles). El enfoque que utilicé fue un hack horrible: inserte los tramos en el texto y luego utilícelos para realizar una búsqueda binaria hasta que encuentre el tramo más pequeño posible que contenga el clic del mouse. Los tramos no cambian el diseño, por lo que puede usar las propiedades position_x/y del tramo para descubrir que contienen el clic.

E.g. supongamos que tiene el siguiente texto en un nodo:

<p>Here is some paragraph text.</p> 

Sabemos el clic fue en alguna parte de este párrafo. Dividir el párrafo en el medio con un palmo:

<p><span>Here is some p</span>aragraph text.</p> 

Si el lapso contiene las coordenadas clic, continuar con la búsqueda binaria en la que la mitad, de lo contrario buscar la segunda mitad.

Esto funciona muy bien para líneas individuales, pero si el texto abarca varias líneas primero tiene que encontrar saltos de línea, o los tramos se pueden superponer. También debe determinar qué hacer cuando el clic no estaba en ningún texto, sino que estaba en el elemento, por ejemplo, más allá del final de la última línea de un párrafo.

Desde que trabajé en este, los navegadores se han vuelto mucho más rápidos. Probablemente sean lo suficientemente rápidos ahora para agregar s alrededor de cada carácter, luego alrededor de cada dos caracteres, etc. para crear un árbol binario que sea fácil de buscar. Podría probar este enfoque, sería mucho más fácil determinar en qué línea está trabajando.

TL; DR este es un problema realmente difícil y si hay una respuesta, puede que no valga la pena el tiempo para llegar a ella.

Cuestiones relacionadas