Какой лучший способ установить положение курсора/каретки?
Если я вставляю содержимое в текстовое поле, которое котируется TinyMCE, лучший способ установить положение курсора/каретки?
Я использую tinyMCE.execCommand("mceInsertRawHTML", false, content);
для вставки содержимого, и я бы хотел установить позицию курсора в конец содержимого.
Оба document.selection
и myField.selectionStart
не будут работать для этого, и я чувствую, что это будет поддерживаться TinyMCE (через то, что я не могу найти на их форуме), или это будет действительно уродливый взлом.
Позже: Это становится лучше; Я просто понял, что при загрузке TinyMCE в WordPress он загружает весь редактор во встроенный iframe.
Позже (2): Я могу использовать document.getElementById('content_ifr').contentDocument.getSelection();
для выбора в качестве строки, но не для объекта выделения, который я могу использовать getRangeAt(0)
. Прогресс постепенно.
Ответы
Ответ 1
Проведя более 15 часов по этой проблеме (посвящение, я знаю), я нашел частичное решение, которое работает в FF и Safari, но не в IE. На данный момент это достаточно хорошо для меня, хотя я могу продолжить работу над этим в будущем.
Решение: при вставке HTML в текущую позицию каретки наилучшей функцией является:
tinyMCE.activeEditor.selection.setContent(htmlcontent);
В Firefox и Safari эта функция будет вставлять содержимое в текущую позицию каретки в iframe, которую WordPress использует в качестве редактора TinyMCE. Проблема с IE 7 и 8 заключается в том, что функция, похоже, добавляет контент в начало страницы, а не iframe (то есть полностью пропускает текстовый редактор). Чтобы решить эту проблему, я добавил условный оператор на основе этого кода, который будет использовать эту функцию вместо IE:
tinyMCE.activeEditor.execCommand("mceInsertRawHTML", false, htmlcontent);
Однако проблема для этой второй функции заключается в том, что позиция каретки устанавливается в начало области сообщения после ее вызова (без надежды напомнить ее на основе диапазона браузера и т.д.). Где-то ближе к концу я обнаружил, что эта функция работает, чтобы восстановить положение каретки в конце вставленного содержимого с помощью первой функции:
tinyMCE.activeEditor.focus();
Кроме того, он восстанавливает положение каретки до конца вставленного содержимого, не вычисляя длину вставленного текста. Недостатком является то, что он работает только с первой функцией вставки, которая, похоже, вызывает проблемы в IE 7 и IE 8 (что может быть скорее ошибкой WordPress, чем TinyMCE).
А словесный ответ, я знаю. Не стесняйтесь задавать вопросы для уточнения.
Ответ 2
Сначала вам нужно добавить промежуток в конце содержимого, которое вы хотите создать.
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]);
Это стратегия, используемая самими разработчиками TinyMCE при написании Selection.js. Чтение базового источника может быть очень полезным для этой проблемы.
Ответ 3
Так просто перемещать курсор до конца, что я не могу поверить в ужасные kludges, которые были размещены в другом месте в Интернете, чтобы сделать это. Ответ г-на Спок не был изначально полезен, но в конце API-документы предоставили мне ответ. Msgstr "Выбрать все содержимое, а затем свернуть выбор":
ed.selection.select(ed.getBody(), true); // ed is the editor instance
ed.selection.collapse(false);
Я надеюсь, что это поможет кому-то другому, поскольку этот поток является одним из первых, кто появился в Google.
Ответ 4
Лучший способ, который я нашел, - это вставить контент с временным идентификатором, а затем выделить его, используя хитрость, которую я нашел в плагине advlink.
Надеюсь это поможет.
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
Если вы делаете это из всплывающего окна, я думаю, вам также нужно добавить
tinyMCEPopup.storeSelection();
перед закрытием всплывающего окна.
Для тех, кто пытается вставить содержимое из пользовательского метаблока Wordpress в редактор TinyMCE, это решение работает. Я перепробовал множество других сценариев, в том числе другой на этой странице, ответ Гэри Тана, который мне помог при установке пользовательских кнопок TinyMCE, но не сработал в этом сценарии.
Ответ 5
Правильное решение - использовать tinyMCE api tinymce.dom.Selection
http://www.tinymce.com/wiki.php/API3:class.tinymce.dom.Selection
Синтаксис выглядит примерно так:
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);
он работает, я сам это использую.
Ответ 6
Итак, вот решение нашего проекта. Нашей целью было изменить строки (+)/(-)/(?)
На соответствующие изображения "на лету", пока пользователь печатает.
Возникла проблема: каждый раз после смены строки на изображение курсор переходил в начало изображения, а не в конец, как ожидалось.
Мы добавили большую часть кода, который перемещает курсор в конец изображения, чтобы пользователь мог непрерывно печатать без прерывания на "скачкообразном" курсоре.
Ключевая часть: вместо использования editor.getBody
, есть более элегантный способ создания временного промежутка и, более того, удаляйте его сразу после необходимых действий.
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();
}
Ответ 7
Я плагиатом это из здесь.
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);
}
}
Ответ 8
Вставьте DOM node в текущую позицию выбора/каретки.
tinyMCE.activeEditor.selection.setNode(tinyMCE.activeEditor.dom.create('img', {src : 'some.gif', title : 'some title'}));
Ответ 9
Просто бросьте свои 2 цента здесь. Никто из них не ответил на мой вопрос. Я не помещал элемент HTML, но блок текста (например, [code][/code]
) и нуждался в курсоре для перехода между ними.
Используя часть ответа @robyates, я поставил временный элемент HTML между тегами [code]
, сосредоточился на нем, а затем полностью удалил элемент HTML. Вот мой код:
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
}
});
}
Ответ 10
Это решение, которое работает для меня:
// 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);
}
Ответ 11
Я вставляю html-контент в текущую позицию каретки (не оставаясь в этом родительском html-элементе) следующим образом:
editor.insertContent( '<div>My html inserted code here...</div>' + ' ' , {format: 'html'} );
Это пустое пространство в конце будет гарантировать, что дополнительный напечатанный текст будет помещен вне вставленного элемента div.
Ответ 12
В крошечной версии 5
editor.selection.setCursorLocation(editor.getBody(), editor.getBody().childElementCount);