Si estoy insertar contenido en un textarea que TinyMCE ha cooptado, ¿cuál es la mejor manera de establecer la posición del cursor/símbolo de intercalación?

Estoy usando tinyMCE.execCommand("mceInsertRawHTML", false, content); para insertar el contenido, y me gustaría establecer la posición del cursor al final del contenido.

Tanto document.selection y myField.selectionStart no trabajo de esto, y me siento como si esto va a ser apoyado por TinyMCE (a través de algo que no puede encontrar en su foro) o va a ser una muy feo hack.

Más tarde: Se pone mejor; me di cuenta de que, cuando se carga TinyMCE en WordPress, se carga el editor incorporado un iframe.

Más tarde (2): puedo usar document.getElementById('content_ifr').contentDocument.getSelection(); para obtener la selección como una cadena, pero no un Objeto de Selección que puedo usar getRangeAt(0) en. Progresando poco a poco.

12 Comentarios

  1. 27

    Primero que debe hacer es agregar un intervalo al final del contenido que desea crear.

    var ed = tinyMCE.activeEditor;
    
    //add an empty span with a unique id
    var endId = tinymce.DOM.uniqueId();
    ed.dom.add(ed.getBody(), 'span', {'id': endId}, '');
    
    //select that span
    var newNode = ed.dom.select('span#' + endId);
    ed.selection.select(newNode[0]);

    Esta es una estrategia utilizada por el TinyMCE los propios desarrolladores en la escritura Selection.js. La lectura de la fuente subyacente puede ser enormemente útil para este tipo de problema.

    • Excelente, gracias!
    • Esta solución se hizo n’trabajado en el interior de defecto de WordPress editor, por lo que añadió &nbsp; en el interior de span: ‘<span id=»caret_pos_holder»>&nbsp;</span>’ y ayudó. Gracias!
    • Tan, he editado el fragmento de código, funciona como lo es para mí. Gracias!
    • su mejor añadir <br data-mce-bogus=’1′ /> en el último lugar de &nbsp; porque en el tiempo de ahorro de tinymce no contar br–falso y usted también no conseguirá espacio seleccionado en tinymce
    • El uso de data-mce-bogus=’1′ mi span obtiene con un cero a la anchura de espacio y cuando se selecciona, no muestra un color negro sólido cursor/cursor pero un azul (mac) del espacio seleccionado. Yo no uso un BR, porque es peor. Cuando se selecciona la secuencia de comandos, un conjunto azul de la fila se muestra, por lo que la primera reacción por el usuario a hacer clic de nuevo, para ver el símbolo de intercalación/cursor, antes de escribir. Es que con el tiempo se quita cuando se escriba sobre él, si no clic de distancia. Tengo que encontrar una manera de eliminar el relleno o el usuario puede escribir DENTRO de mi palmo, en lugar de escribir sobre él y obtener su contenido despojado?
    • Este trabajó como un encanto para mí. Terminé usando tinyMCEPopup.editor en lugar de tinyMCE.activeEditor como yo estaba trabajando en el cuadro de diálogo de js, pero tengo la leve sospecha que son intercambiables.

  2. 25

    Después de pasar más de 15 horas sobre este tema (dedicación, lo sé), he encontrado una solución parcial que funciona en FF y Safari, pero no en IE. Por el momento, esto es lo suficientemente bueno para mí, aunque yo podría continuar en el futuro.

    La solución: Al insertar HTML en la actual posición del cursor, el mejor de la función a utilizar es:

    tinyMCE.activeEditor.selection.setContent(htmlcontent);

    En Firefox y Safari, esta función va a insertar el contenido en la actual posición del cursor dentro del iframe que WordPress utiliza como un editor TinyMCE. El problema con IE 7 y 8 es que la función parece añadir el contenido a la parte superior de la página, no el iframe (es decir, completamente pierde el editor de texto). Para solucionar este problema, he añadido una instrucción condicional basado en este código que se use esta función en lugar de IE:

    tinyMCE.activeEditor.execCommand("mceInsertRawHTML", false, htmlcontent);

    El problema para esta segunda función, sin embargo, es que la posición del cursor se establece al principio del post área después de que ha sido llamado (sin la esperanza de la recuperación basada en el navegador, etc.). En algún lugar cerca del final, he descubierto que esta función trabaja para restaurar la posición del cursor al final del contenido insertado con la primera función:

    tinyMCE.activeEditor.focus();

    Además, restaura la posición del cursor hasta el final de la inserción de contenido sin tener que calcular la longitud del texto insertado. La desventaja es que sólo funciona con la primera función de inserción de la que parece ser la causa de problemas en IE 7 e IE 8 (que podrían ser más de un WordPress culpa de TinyMCE).

    Un prolijo respuesta, lo sé. Siéntase libre de hacer preguntas de aclaración.

  3. 15

    Es tan simple para mover el cursor hasta el final que no me puedo creer que la terrible kludges que se han publicado en otros lugares en línea para hacer esto. El señor Spocke la respuesta no estaba inicialmente útil, pero en el final de la API docs me proporcionó la respuesta. «Seleccionar todo el contenido y, a continuación, el colapso de la selección»:

    ed.selection.select(ed.getBody(), true); //ed is the editor instance
    
    ed.selection.collapse(false);

    Espero que esto ayude a alguien más como este hilo es uno de los primeros en llegar en Google.

    • Esto no coloque el cursor después de que el último elemento, si la última es un elemento ul o ol .
    • funciona perfecto, Gracias!
  4. 7

    La mejor manera que he encontrado es insertar el contenido con una temp de id y, a continuación, dar ese enfoque usando algunos trucos que he encontrado en la advlink plugin.

    Espero que esto ayude.

                var ed = tinyMCE.activeEditor;
    
                ed.execCommand('mceInsertContent', false, '<a id="_mce_temp_rob" href="http://robubu.com">robubu.com</a>');
    
                //horrible hack to put the cursor in the right spot
                ed.focus(); //give the editor focus
                ed.selection.select(ed.dom.select('#_mce_temp_rob')[0]); //select the inserted element
                ed.selection.collapse(0); //collapses the selection to the end of the range, so the cursor is after the inserted element
                ed.dom.setAttrib('_mce_temp_rob', 'id', ''); //remove the temp id

    Si usted está haciendo esto desde un popup creo que también es necesario agregar

            tinyMCEPopup.storeSelection();

    antes de cerrar la ventana emergente.

    Para cualquier persona tratando de insertar el contenido de un WordPress personalizado meta cuadro en el editor TinyMCE, esta es la solución que funciona. He intentado un montón de otras secuencias de comandos, incluyendo otra en esta página, la respuesta anterior por Gary Bronceado, que trabajó para mí cuando la instalación personalizada de TinyMCE botones, pero no funciona en este escenario.

    • Esto funciona bien cuando se trabaja dentro de los límites de WordPress.
  5. 6

    La solución correcta es utilizar el tinyMCE api de tinymce.dom.Selección

    http://www.tinymce.com/wiki.php/API3:class.tinymce.dom.Selection

    la syntaxe es algo así como :

    var rng = tinymce.DOM.createRng();  //the range obj
    var newNode = editor.dom.select(...    //find the correct selector so that newNode is the element of your editor text
    rng.setStart(newNode.firstChild, 0); //0 is the offset : here it will be at the beginning of the line.
    rng.setEnd(newNode.firstChild, 0);
    editor.selection.setRng(rng);

    funciona yo uso esto a mí mismo.

    • Podría usted por favor aclarar qué significa…? Tal vez dar un ejemplo?
  6. 2

    Así que, aquí está la solución de nuestro proyecto. Nuestro objetivo era cambiar (+)/(-)/(?) cadenas a las imágenes adecuadas «sobre la marcha», mientras que el usuario está escribiendo.

    Había un problema: cada vez que después de cambiar de cadena para la imagen, el cursor se fue el comienzo de la imagen, no al final como era de esperar.

    Hemos añadido la mayor parte del código que se mueve el cursor hasta el final de la imagen, de manera que el usuario puede escribir continuamente w/o interrumpir en «saltos» cursor.

    Parte fundamental: en Lugar de usar editor.getBody, hay una forma más elegante para crear el lapso temporal y, además, eliminar inmediatamente después de las acciones necesarias.

    if (value.match(/\([+?-]\)/)) {
            //set current cursor via span
            editor.selection.setContent('<span id="temp-span"/>');
    
            //refresh Content with new span
            value = editor.getContent();
    
            //changing (+)/(-)/(?) to the appropriate image "on the fly"
            value = value.replace('(+)', ' <img src="https://url_here/static/task_manager/img/add.png">&nbsp;');
            value = value.replace('(-)', ' <img src="https://url_here/static/task_manager/img/forbidden.png">&nbsp;');
            value = value.replace('(?)', ' <img src="https://url_here/static/task_manager/img/help_16.png">&nbsp;');
            if (this.state.editor) {
                editor.setContent(value);
    
                //move cursor to the latter span
                var newNode = editor.dom.select('span#temp-span');
                editor.selection.select(newNode[0]);
                editor.selection.setContent('');
            }
            //and refreshing content again w/o span
            value = editor.getContent();
        }
  7. 1

    Insertar un nodo DOM en la selección actual/símbolo de intercalación ubicación.

    tinyMCE.activeEditor.selection.setNode(tinyMCE.activeEditor.dom.create('img', {src : 'some.gif', title : 'some title'}));
  8. 1

    Acaba de tirar mi propia 2 centavos de dólar por aquí. Ninguno de estos contestado a mi pregunta. Yo no estaba poniendo en un elemento HTML, pero un bloque de texto ([code][/code] por ejemplo) y necesitaba el cursor para ir entre los dos.

    El uso de parte de @robyates respuesta, lo que yo hice fue poner un temporal de elemento HTML en entre el 2 [code] etiquetas, se centran en ella, luego se retira el elemento HTML completo. Aquí está mi código:

    setup : function(ed) {
        //Add a custom button
        ed.addButton('codeblock', {
            title : 'Code Block',
            text : '[code/]',
            icon: false,
            onclick : function() {
                //Add you own code to execute something on click
                ed.focus();
                //ed.selection.setContent('[code][/code]');
                ed.execCommand('mceInsertContent', false, '[code]<span id="_cursor" />[/code]');
    
                ed.selection.select(ed.dom.select('#_cursor')[0]); //select the inserted element
                ed.selection.collapse(0); //collapses the selection to the end of the range, so the cursor is after the inserted element
                ed.dom.remove('_cursor'); //remove the element
            }
        });
    }
  9. 1

    He plagiado a este de aquí.

    function setCaretTo(obj, pos) { 
        if(obj.createTextRange) { 
            /* Create a TextRange, set the internal pointer to
               a specified position and show the cursor at this
               position
            */ 
            var range = obj.createTextRange(); 
            range.move("character", pos); 
            range.select(); 
        } else if(obj.selectionStart) { 
            /* Gecko is a little bit shorter on that. Simply
               focus the element and set the selection to a
               specified position
            */ 
            obj.focus(); 
            obj.setSelectionRange(pos, pos); 
        } 
    } 
    • Creo que el gran problema es que TinyMCE carga el contenido dentro de un iframe en WordPress. Normalmente algo como esto iba a funcionar, pero getSelection() sólo devuelve una cadena y no de una selección. Estoy usando .selectionStart a la hora de manipular el textarea que el editor de HTML usa, pero no funciona para el TinyMCE iframe.
  10. 1

    Estoy insertar contenido html en la posición del símbolo actual (sin permanecer en el html del elemento padre) como este:

    editor.insertContent( '<div>My html inserted code here...</div>' + '&nbsp;' , {format: 'html'} );

    Que en el espacio en blanco al final se asegurará de que el texto escrito se colocarán fuera de la insertado elemento div.

    • Esta solucionado mi problema en el que se inserta un elemento html se repite después de cada salto de línea.
  11. 0

    Esta es la solución que me funciona:

    //params: 
    //  $node: jquery node with tinymce loaded 
    //  text: text to set at then before caret
    function setTextAndCaretToEnd($node, text) {
         var ed = window.tinyMCE.get($node.attr("id"));
         ed.focus();
         ed.selection.setContent(text);
    }
  12. 0

    En Pequeñas versión 5

    editor.selection.setCursorLocation(editor.getBody(), editor.getBody().childElementCount);

Dejar respuesta

Please enter your comment!
Please enter your name here