设置光标/插入位置的最佳方法是什么?

时间:2009-08-10 06:04:31

标签: javascript wordpress iframe tinymce getselection

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

我正在使用tinyMCE.execCommand("mceInsertRawHTML", false, content);插入内容,我想将光标位置设置为内容的结尾。

document.selectionmyField.selectionStart都不适用于此,我觉得TinyMCE会支持(通过我在论坛上找不到的东西),或者它会继续是一个非常难看的黑客。

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

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

12 个答案:

答案 0 :(得分:27)

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

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

答案 1 :(得分:23)

在这个问题上花了超过15个小时(奉献,我知道),我找到了一个部分解决方案,适用于FF和Safari,但不适用于IE。目前,这对我来说已经足够好了,尽管我将来可能继续努力。

解决方案:在当前插入位置插入HTML时,最好使用的功能是:

tinyMCE.activeEditor.selection.setContent(htmlcontent);

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

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

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

tinyMCE.activeEditor.focus();

此外,它将插入位置恢复到插入内容的末尾,而不必计算插入文本的长度。缺点是它只适用于第一个插入功能,它似乎在IE 7和IE 8中引起问题(可能比TinyMCE更像是一个WordPress故障)。

我知道,这是一个罗嗦的回答。请随意提出问题以便澄清。

答案 2 :(得分:15)

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

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

ed.selection.collapse(false);

我希望这可以帮助其他人,因为这个帖子是最早出现在谷歌中的人之一。

答案 3 :(得分:6)

我找到的最好方法是插入带有temp id的内容,然后使用我在advlink plugin中找到的一些技巧来提供焦点。

希望这有帮助。

            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按钮时对我有用,但在这种情况下没有用。

答案 4 :(得分: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);

它有效我自己用它。

答案 5 :(得分:2)

因此,这是我们项目的解决方案。我们的目标是在用户打字时将(+)/(-)/(?)字符串“动态”更改为适当的图像。

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

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

关键部分:除了使用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();
    }

答案 6 :(得分:1)

我从here抄袭了这个。

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

答案 7 :(得分:1)

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

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

答案 8 :(得分:1)

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

使用@robyates答案的一部分,我所做的是在2个[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
        }
    });
}

答案 9 :(得分: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);
}

答案 10 :(得分:0)

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

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

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

答案 11 :(得分:0)

在Tiny版本5中

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