Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 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">&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

Я плагиатом это из здесь.

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>' + '&nbsp;' , {format: 'html'} );

Это пустое пространство в конце будет гарантировать, что дополнительный напечатанный текст будет помещен вне вставленного элемента div.

Ответ 12

В крошечной версии 5

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