2009-08-10 12 views
27

Si inserto contenido en un área de texto que TinyMCE ha elegido, ¿cuál es la mejor manera de establecer la posición del cursor/cursor?¿Cuál es la mejor manera de establecer la posición del cursor/cursor?

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

Tanto document.selection y myField.selectionStart no funcionará para esto, y me siento como si esto va a ser apoyado por TinyMCE (a través de algo que no puedo encontrar en su foro) o que va a ser un corte muy feo.

Más tarde: Se pone mejor; Acabo de descubrir que, cuando carga TinyMCE en WordPress, carga todo el editor en un iframe incrustado.

tarde (2): puedo usar document.getElementById('content_ifr').contentDocument.getSelection(); para obtener la selección como una cadena, pero no un objeto Selection que puedo usar en getRangeAt(0). Avanzando poco a poco.

+0

aquí es una respuesta mejor: http://stackoverflow.com/a/7977681/3197383 –

Respuesta

20

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 podría seguir trabajando en él en el futuro.

La solución: Al insertar HTML en la posición del símbolo actual, la mejor función a utilizar es:

tinyMCE.activeEditor.selection.setContent(htmlcontent);

En Firefox y Safari, esta función se inserte el contenido en la posición de cursor actual dentro de la iframe que WordPress usa como editor de TinyMCE. El problema con IE 7 y 8 es que la función parece agregar el contenido a la parte superior de la página, no el iframe (es decir, falla por completo el editor de texto). Para abordar esta cuestión, he añadido una sentencia condicional based on this code que va a utilizar esta función en lugar de IE:

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

El tema para esta segunda función, sin embargo, es que la posición de intercalación se establece en el inicio de la área de publicación después de haber sido llamada (sin esperanza de recuperarla en función del rango del navegador, etc.). En algún lugar cerca del final descubrí que esta función se puede utilizar para restaurar la posición de intercalación al final del contenido insertado con la primera función:

tinyMCE.activeEditor.focus();

Además, se restaura la posición de intercalación al final del insertada contenido sin tener que calcular la longitud del texto insertado. La desventaja es que solo funciona con la primera función de inserción que parece causar problemas en IE 7 e IE 8 (que podría ser más un error de WordPress que TinyMCE).

Una respuesta vergonzosa, lo sé. Siéntase libre de hacer preguntas para aclaraciones.

1

He plagiado esto de here.

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); 
    } 
} 
+2

Creo que el gran problema es que TinyMCE carga el contenido en un marco flotante en WordPress. Normalmente algo como esto funcionaría, pero 'getSelection()' solo devuelve una cadena y no una selección. Estoy usando .selectionStart al manipular el área de texto que utiliza el editor HTML, pero no funciona para el iframe TinyMCE. –

26

Lo primero que debe hacer es agregar un lapso 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 los propios desarrolladores de TinyMCE al escribir Selection.js. Leer la fuente subyacente puede ser de gran ayuda para este tipo de problema.

+0

Excelente, gracias! – Alex

+0

Esta solución no funcionó dentro del editor de Wordpress predeterminado, así que agregué   dentro del span: '  ' y me ayudó. ¡Gracias! – Andrius

+0

@Garry Tan, he editado el fragmento, funciona como es para mí. ¡Gracias! – Evgeny

4

La mejor manera que he encontrado es insertar el contenido con una identificación temporal y luego darle ese enfoque usando algún truco que encontré en el 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 estás haciendo esto desde una ventana emergente creo que también hay que añadir

 tinyMCEPopup.storeSelection(); 

antes de cerrar la ventana emergente.

Para cualquiera que intente insertar contenido de un cuadro meta personalizado de Wordpress en el editor TinyMCE, esta es la solución que funciona. Probé muchas otras secuencias de comandos, incluida otra en esta página, la respuesta anterior de Gary Tan, que funcionó para mí al instalar botones TinyMCE personalizados, pero no funcionó en este escenario.

+0

Este funciona bien cuando se trabaja dentro de los límites de Wordpress. – Cleanshooter

14

Es tan simple mover el cursor hasta el final que no puedo creer los horribles kludges que se han publicado en otro lugar en línea para hacer esto. La respuesta del Sr. Spocke no fue útil al principio, pero al final los documentos de API me proporcionaron la respuesta. "Seleccionar todo el contenido y luego colapsar 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 ya que este hilo es uno de los primeros en llegar en Google.

+1

Esto no coloca el cursor después del último elemento si el último elemento es un ul o ol. – rpilkey

+0

funciona perfecto ¡Gracias! – SamSerious

6

La solución correcta es utilizar la API tinymce.dom.Selection TinyMCE

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 utilizo yo mismo.

+2

¿Podría aclarar qué significa ...? Quizás dar un ejemplo? – Evgeny

1

Inserte un nodo DOM en la ubicación actual de selección/intercalación.

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

Esta es la solución que funciona para mí:

// 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); 
} 
1

simplemente tirar en mis propias 2 centavos aquí. Ninguno de estos respondió mi pregunta. No estaba poniendo un elemento HTML, sino un bloque de texto ([code][/code] por ejemplo) y necesitaba el cursor para ir entre los dos.

Utilizando parte de @robyates respuesta, lo que hice fue poner un elemento HTML temporal entre las 2 [code] etiquetas, centrarme en él, y luego eliminar el elemento HTML por 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 
     } 
    }); 
} 
Cuestiones relacionadas