31

如果我将内容插入到 TinyMCE 选择的文本区域中,那么设置光标/插入符号位置的最佳方法是什么?

tinyMCE.execCommand("mceInsertRawHTML", false, content);用来插入内容,我想将光标位置设置到内容的末尾。

两者document.selectionmyField.selectionStart不起作用,我觉得这将得到 TinyMCE 的支持(通过我在他们的论坛上找不到的东西),或者这将是一个非常丑陋的黑客。

后来:它变得更好;我刚刚发现,当您在 WordPress 中加载 TinyMCE 时,它会将整个编辑器加载到嵌入式 iframe 中。

稍后(2):我可以使用document.getElementById('content_ifr').contentDocument.getSelection();将选择作为字符串获取,但不能用于我可以使用的选择对象getRangeAt(0)。一点一点的进步。

4

12 回答 12

29

首先,您应该在要创建的内容的末尾添加一个跨度。

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 时使用的策略。阅读底层源代码可以极大地帮助解决这类问题。

于 2010-04-25T18:48:39.483 回答
28

在这个问题上花费了超过 15 个小时(我知道是献身精神)之后,我找到了一个在 FF 和 Safari 中有效但在 IE 中无效的部分解决方案。目前,这对我来说已经足够了,尽管我将来可能会继续努力。

解决方案:在当前插入符号位置插入 HTML 时,最好使用的函数是:

tinyMCE.activeEditor.selection.setContent(htmlcontent);

在 Firefox 和 Safari 中,此功能将在 WordPress 用作 TinyMCE 编辑器的 iframe 中的当前插入符号位置插入内容。IE 7 和 8 的问题在于该功能似乎将内容添加到页面顶部,而不是 iframe(即它完全错过了文本编辑器)。为了解决这个问题,我添加了一个基于此代码的条件语句,它将使用此函数而不是 IE:

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

然而,第二个函数的问题是插入符号的位置在被调用后被设置为帖子区域的开头(不希望根据浏览器范围等来调用它)。在接近尾声的某个地方,我发现这个函数可以使用第一个函数恢复插入内容末尾的插入符号位置:

tinyMCE.activeEditor.focus();

此外,它将插入符号的位置恢复到插入内容的末尾,而无需计算插入文本的长度。缺点是它只适用于第一个插入函数,这似乎会导致 IE 7 和 IE 8 出现问题(这可能比 TinyMCE 更像是 WordPress 错误)。

一个冗长的答案,我知道。随时提出问题以进行澄清。

于 2009-08-18T01:27:04.837 回答
15

将光标移动到末尾是如此简单,以至于我无法相信已经在网上其他地方发布的可怕的kludges来做到这一点。Spocke 先生的回答最初并没有帮助,但最终 API 文档为我提供了答案。“选择所有内容,然后折叠选择”:

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

ed.selection.collapse(false);

我希望这对其他人有所帮助,因为该线程是最早出现在 Google 中的线程之一。

于 2011-11-30T01:32:19.757 回答
8

我发现最好的方法是插入带有临时 ID 的内容,然后使用我在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 编辑器的人来说,这是可行的解决方案。我尝试了很多其他脚本,包括此页面上的另一个脚本,Gary Tan 上面的答案,它在安装自定义 TinyMCE 按钮时对我有用,但在这种情况下不起作用。

于 2011-03-24T03:10:15.710 回答
6

正确的解决方案是使用 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);

它有效,我自己使用它。

于 2012-02-17T12:00:48.230 回答
3

所以,这是我们项目的解决方案。我们的目标是(+)/(-)/(?)在用户键入时“即时”将字符串更改为适当的图像。

有一个问题:每次将字符串更改为图像后,光标都会进入图像的开头,而不是预期的结尾。

我们添加了将光标移动到图像末尾的大量代码,因此用户可以连续键入而不会中断“跳跃”光标。

关键部分: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();
    }
于 2018-08-17T16:29:29.277 回答
2

我在当前插入符号位置插入 html 内容(不留在那个 html 父元素中),如下所示:

editor.insertContent( '<div>My html inserted code here...</div>' + '&nbsp;' , {format: 'html'} );

最后的空格将确保进一步键入的文本将放置在插入的 div 元素之外。

于 2019-06-19T15:28:08.463 回答
1

我从这里抄袭了这个。

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); 
    } 
} 
于 2009-08-12T02:21:49.733 回答
1

在当前选择/插入符号位置插入一个 DOM 节点。

tinyMCE.activeEditor.selection.setNode(tinyMCE.activeEditor.dom.create('img', {src : 'some.gif', title : 'some title'}));
于 2012-10-23T15:32:49.203 回答
1

只是在这里投入我自己的 2 美分。这些都没有回答我的问题。我没有放入一个 HTML 元素,而是一个文本块([code][/code]例如),并且需要光标在两者之间移动。

使用@robyates 回答的一部分,我所做的是在两个[code]标签之间放置一个临时 HTML 元素,关注它,然后完全删除 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
        }
    });
}
于 2015-11-17T19:02:06.813 回答
0

这是对我有用的解决方案:

// 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);
}
于 2014-02-12T10:05:21.397 回答
0

在小版本 5 中

editor.selection.setCursorLocation(editor.getBody(), editor.getBody().childElementCount);
于 2019-06-22T20:57:34.800 回答