Каков наилучший способ установить положение курсора / курсора?

если я вставляю контент в текстовую область, которую TinyMCE кооптировал, каков наилучший способ установить положение курсора/каретки?

я использую tinyMCE.execCommand("mceInsertRawHTML", false, content); вставить содержимое, и я хотел бы установить курсор в конец контента.

и document.selection и myField.selectionStart не будет работать для этого, и я чувствую, что это будет поддерживаться TinyMCE (через то, что я не могу найти на своем форуме), или это будет действительно уродливо мотыга.

позже: становится лучше; я только что понял, что, когда вы загружаете TinyMCE в WordPress, он загружает весь редактор во встроенный iframe.

позже (2): Я могу использовать document.getElementById('content_ifr').contentDocument.getSelection(); чтобы получить выбор в виде строки, но не объект выбора, который я могу использовать getRangeAt(0) on. Постепенно продвигаюсь вперед.

10 ответов


сначала вы должны добавить промежуток в конце содержимого, которое вы хотите создать.

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 при написании выбора.js. Чтение базового источника может быть массово полезно для такого рода проблем.


потратив более 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).

многословный ответ, я знаю. Не стесняйтесь задавать уточняющие вопросы.


так просто переместить курсор в конец, что я не могу поверить, что ужасные kludges, которые были размещены в другом месте в интернете, чтобы сделать это. Ответ г-на Spocke не было изначально полезны, но в конце концов описании API дал мне ответа. "Выберите все содержимое, а затем сверните выделение":

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

ed.selection.collapse(false);

Я надеюсь, что это поможет кому-то еще, так как этот поток является одним из первых в Google.


правильное решение-использовать для TinyMCE API-интерфейс для TinyMCE.дом.Выбор

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);

это работает, я использую это сам.


лучший способ, который я нашел, - вставить содержимое с идентификатором temp, а затем дать этот фокус, используя некоторые хитрости, которые я нашел в плагин 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, но не работал в этом сценарии.


вставьте узел DOM в текущее местоположение выбора / каретки.

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

просто бросаю свои собственные 2 цента здесь. Никто из них не ответил на мой вопрос. Я не вставлял HTML-элемент, а блок текста ([code][/code] например) и нужен курсор между двумя.

используя часть ответа @robyates, я поставил временный HTML-элемент между 2 [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
        }
    });
}

я списал это из здесь.

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

Итак, вот решение из нашего проекта. Нашей целью было изменить (+)/(-)/(?) строки для соответствующих изображений "на лету" во время ввода пользователем.

возникла проблема: каждый раз после смены строки на изображение курсор шел в начало изображения, а не в конец, как ожидалось.

мы добавили большую часть кода, который перемещает курсор в конец изображения, поэтому пользователь может вводить непрерывно без прерывания на "нервном" курсоре.

ключевые части: Вместо использования 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">&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();
    }

Это решение, которое работает для меня:

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