Si j'insère du contenu dans une zone de texte cooptée par TinyMCE, quel est le meilleur moyen de définir la position du curseur/curseur?
J'utilise tinyMCE.execCommand("mceInsertRawHTML", false, content);
pour insérer le contenu et j'aimerais définir la position du curseur à la fin du contenu.
document.selection
et myField.selectionStart
ne fonctionneront pas pour cela, et je sens que cela va être supporté par TinyMCE (via quelque chose que je ne trouve pas sur leur forum) ou que ce sera un bidouillage vraiment moche.
Plus tard: Ça va mieux; Je viens de comprendre que, lorsque vous chargez TinyMCE dans WordPress, l’éditeur entier est chargé dans un iframe intégré.
Plus tard (2): Je peux utiliser document.getElementById('content_ifr').contentDocument.getSelection();
pour obtenir la sélection sous forme de chaîne, mais pas d'objet Selection sur lequel je peux utiliser getRangeAt(0)
. Faire des progrès petit à petit.
Tout d’abord, vous devez ajouter une étendue à la fin du contenu que vous souhaitez créer.
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]);
Il s’agit d’une stratégie utilisée par les développeurs TinyMCE eux-mêmes pour écrire Selection.js. La lecture de la source sous-jacente peut s'avérer extrêmement utile pour résoudre ce type de problème.
C'est tellement simple de déplacer le curseur à la fin que je ne peux pas croire les horribles kludges qui ont été postés ailleurs en ligne pour le faire. La réponse de M. Spocke n'était pas utile au départ, mais les documents de l'API m'ont finalement fourni la réponse. "Sélectionner tout le contenu puis réduire la sélection":
ed.selection.select(ed.getBody(), true); // ed is the editor instance
ed.selection.collapse(false);
J'espère que cela aidera quelqu'un d'autre, car ce fil est l'un des premiers à apparaître dans Google.
Le meilleur moyen que j'ai trouvé est d'insérer le contenu avec un identifiant temporaire, puis de le focaliser à l'aide de trucs trouvés dans le plugin advlink .
J'espère que cela t'aides.
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 vous faites cela depuis un popup, je pense que vous devez aussi ajouter
tinyMCEPopup.storeSelection();
avant de fermer le popup.
Pour ceux qui essaient d'insérer du contenu d'une méta-boîte personnalisée Wordpress dans l'éditeur TinyMCE, c'est la solution qui fonctionne. J'ai essayé une tonne d'autres scripts, y compris un autre sur cette page, la réponse ci-dessus de Gary Tan, qui a fonctionné pour moi lors de l'installation des boutons personnalisés de TinyMCE mais n'a pas fonctionné dans ce scénario.
La solution correcte consiste à utiliser le tinyMCE api tinymce.dom.Selection
http://www.tinymce.com/wiki.php/API3:class.tinymce.dom.Selection
la syntaxe est quelque chose comme:
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);
cela fonctionne, je l'utilise moi-même.
J'ai plagié cela de ici .
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);
}
}
Insérez un nœud DOM à l'emplacement actuel de sélection/caret.
tinyMCE.activeEditor.selection.setNode(tinyMCE.activeEditor.dom.create('img', {src : 'some.gif', title : 'some title'}));
Juste en jetant mes propres 2 cents ici. Aucun de ceux-ci n'a répondu à ma question. Je ne mettais pas dans un élément HTML, mais un bloc de texte ([code][/code]
par exemple) et j'avais besoin que le curseur se place entre les deux.
En utilisant une partie de @robyates answer, ce que j’ai fait, c’est de placer un élément HTML temporaire entre les balises 2 [code]
, de me concentrer sur celui-ci, puis de supprimer complètement l’élément HTML. Voici mon code:
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
}
});
}
Donc, voici la solution de notre projet. Notre objectif était de remplacer les chaînes (+)/(-)/(?)
par les images appropriées "à la volée" lors de la frappe par l'utilisateur.
Il y avait un problème: chaque fois que la chaîne était passée à l'image, le curseur marquait le début de l'image, mais pas jusqu'à la fin, comme prévu.
Nous avons ajouté une grande partie du code qui déplace le curseur à la fin de l'image afin que l'utilisateur puisse taper en continu sans interrompre le curseur "saccadé".
Partie clé: au lieu d’utiliser editor.getBody
, il existe un moyen plus élégant de créer l’intervalle temporaire et de le supprimer immédiatement après les actions nécessaires.
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"> ');
value = value.replace('(-)', ' <img src="https://url_here/static/task_manager/img/forbidden.png"> ');
value = value.replace('(?)', ' <img src="https://url_here/static/task_manager/img/help_16.png"> ');
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();
}
C'est la solution qui fonctionne pour moi:
// 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);
}