over onmouseup ejemplo javascript ckeditor range

onmouseup - JavaScript convierte la posición del ratón al rango de selección



onmouseover html ejemplo (3)

Estaba trabajando en una tarea similar para permitir que TinyMCE (modo en línea) se inicialice con un cursor colocado en la posición de clic del mouse. El siguiente código funciona en las últimas versiones de Firefox y Chrome, al menos:

let contentElem = $(''#editorContentRootElem''); let editorConfig = { inline: true, forced_root_block: false }; let onFirstFocus = () => { contentElem.off(''click focus'', onFirstFocus); setTimeout(() => { let uniqueId = ''uniqueCaretId''; let range = document.getSelection().getRangeAt(0); let caret = document.createElement("span"); range.surroundContents(caret); caret.outerHTML = `<span id="${uniqueId}" contenteditable="false"></span>`; editorConfig.setup = (editor) => { this.editor = editor; editor.on(''init'', () => { var caret = $(''#'' + uniqueId)[0]; if (!caret) return; editor.selection.select(caret); editor.selection.collapse(false); caret.parentNode.removeChild(caret); }); }; tinymce.init(editorConfig); }, 0); // after redraw }; // onFirstFocus contentElem.on(''click focus'', onFirstFocus);

Explicación

Parece que después de hacer clic con el mouse / evento de enfoque y volver a dibujar (setTimeout ms 0) document.getSelection().getRangeAt(0) devuelve un rango de cursor válido. Podemos usarlo para cualquier propósito. TinyMCE mueve caret para comenzar la inicialización, por lo que creo un elemento especial ''caret'' de intervalo en el inicio del rango actual y luego obligo al editor a seleccionarlo, luego lo elimino.

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

El CKEditor proporciona una API para configurar el cursor según un rango:

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

Dado que CKEditor proporciona esta API, el problema puede simplificarse eliminando este requisito y simplemente encuentra una manera de producir el rango desde las coordenadas del mouse 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 de texto tienen anchos de columna y alturas de fila fijos donde el CKEditor presenta HTML a través de un iframe.

Sobre this base, parece que el rango puede aplicarse a los elementos.

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

Edición: un ejemplo de cómo se podría 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. $. Target) solo se activa para los nodos como HTML, BODY 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.


Hay dos formas de hacer esto, al igual que lo hace cada WYSIWYG.

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

Segundo: - intenta analizar el texto y colocarlo en el lugar exacto en un área de texto semitransparente o div sobre el original, pero aquí tenemos dos problemas:

1) ¿Cómo analizaría los fragmentos dinámicos de datos para obtener solo el texto y asegurarse de que se asigna a la posición exacta del contenido real?

2) ¿Cómo resolvería la actualización para analizar cada maldito carácter que escriba o cada acción que realice en el editor?

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


Lo que estás tratando de hacer es realmente difícil en un navegador. No estoy familiarizado con ckeditor en particular, pero el javascript regular le 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, a continuación, buscar el carácter dentro del elemento en el que se hizo clic.

Detectar el elemento del navegador es muy sencillo: debe registrar su controlador en cada elemento o usar el campo de destino del evento. Hay mucha información sobre esto por ahí, haga una pregunta más específica sobre si eso es con lo que está teniendo problemas.

Una vez que tenga el elemento, debe averiguar en qué personaje del elemento se hizo clic y luego crear un rango apropiado para colocar el cursor allí. Como se indica en la publicación que vinculaste, las variaciones del navegador hacen que esto sea realmente difícil. Esta página es un poco anticuada, pero tiene una buena discusión de rangos: http://www.quirksmode.org/dom/range_intro.html

Los rangos no pueden decirle sus posiciones en la página, por lo que tendrá que usar otra técnica para averiguar en qué parte del 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 realmente difíciles). El enfoque que utilicé fue un truco horrible: inserte espacios en el texto y utilícelos para realizar búsquedas binarias hasta que encuentre el espacio más pequeño posible que contenga el clic del mouse. Los spans no cambian el diseño, por lo que puede usar las propiedades position_x / y de span para descubrir que contienen el clic.

Por ejemplo, supongamos que tiene el siguiente texto en un nodo:

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

Sabemos que el clic estaba en algún lugar de este párrafo. Divide el párrafo por la mitad con un lapso:

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

Si el intervalo contiene las coordenadas de clic, continúe la búsqueda binaria en esa mitad, de lo contrario busque 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 si los intervalos pueden superponerse. También tiene que averiguar qué hacer cuando el clic no estaba en ningún texto, pero estaba en el elemento, más allá del final de la última línea en un párrafo, por ejemplo.

Desde que trabajé en este navegador he conseguido mucho más rápido. 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. Puede 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 dedicarle tiempo.