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

发布于 2024-08-01 13:42:09 字数 588 浏览 8 评论 0原文

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

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

document.selectionmyField.selectionStart 都不适用于此,我觉得 TinyMCE 将支持这一点(通过我找不到的东西)在他们的论坛上)否则这将是一个非常丑陋的黑客行为。

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

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

If I'm inserting content into a textarea that TinyMCE has co-opted, what's the best way to set the position of the cursor/caret?

I'm using tinyMCE.execCommand("mceInsertRawHTML", false, content); to insert the content, and I'd like set the cursor position to the end of the content.

Both document.selection and myField.selectionStart won't work for this, and I feel as though this is going to be supported by TinyMCE (through something I can't find on their forum) or it's going to be a really ugly hack.

Later: It gets better; I just figured out that, when you load TinyMCE in WordPress, it loads the entire editor in an embedded iframe.

Later (2): I can use document.getElementById('content_ifr').contentDocument.getSelection(); to get the selection as a string, but not a Selection Object that I can use getRangeAt(0) on. Making progress little by little.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

匿名。 2024-08-08 13:42:09

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

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

ed.selection.collapse(false);

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

It is so simple to move the cursor to the end that I can't believe the awful kludges that have been posted elsewhere online to do this. Mr. Spocke's answer wasn't initially helpful but in the end the API docs provided me with the answer. "Select all content and then collapse the selection":

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

ed.selection.collapse(false);

I hope this helps someone else as this thread is one of the first to come up in Google.

半夏半凉 2024-08-08 13:42:09

我发现的最好方法是插入带有临时 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 按钮时对我有用,但在这种情况下不起作用。

The best way that I have found is to insert the content with a temp id and then give that focus using some trickery I found in the advlink plugin.

Hope this helps.

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

If you're doing this from a popup I think you also need to add

tinyMCEPopup.storeSelection();

before closing the popup.

For anyone trying to insert content from a Wordpress custom meta box into the TinyMCE editor, this is the solution that works. I tried a ton of other scripts, including another on this page, the answer above by Gary Tan, which worked for me when installing custom TinyMCE buttons but didnt work out in this scenario.

偏爱自由 2024-08-08 13:42:09

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

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时使用的策略。 阅读底层源代码对于解决此类问题非常有帮助。

First what you should do is add a span at the end of the content you want to create.

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

This is a strategy used by the TinyMCE developers themselves in writing Selection.js. Reading the underlying source can be massively helpful for this kind of problem.

蘑菇王子 2024-08-08 13:42:09

在这个问题上花费了超过 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 的错误)。

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

After spending over 15 hours on this issue (dedication, I know), I found a partial solution that works in FF and Safari, but not in IE. For the moment, this is good enough for me although I might continue working on it in the future.

The solution: When inserting HTML at the current caret position, the best function to use is:

tinyMCE.activeEditor.selection.setContent(htmlcontent);

In Firefox and Safari, this function will insert the content at the current caret position within the iframe that WordPress uses as a TinyMCE editor. The issue with IE 7 and 8 is that the function seems to add the content to the top of the page, not the iframe (i.e. it completely misses the text editor). To address this issue, I added a conditional statement based on this code that will use this function instead for IE:

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

The issue for this second function, however, is that the caret position is set to the beginning of the post area after it has been called (with no hope of recalling it based on the browser range, etc.). Somewhere near the end I discovered that this function works to restore the caret position at the end of the inserted content with the first function:

tinyMCE.activeEditor.focus();

In addition, it restores the caret position to the end of the inserted content without having to calculate the length of the inserted text. The downside is that it only works with the first insertion function which seems to cause problems in IE 7 and IE 8 (which might be more of a WordPress fault than TinyMCE).

A wordy answer, I know. Feel free to ask questions for clarification.

一曲爱恨情仇 2024-08-08 13:42:09

在小版本 5 中

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

In Tiny version 5

editor.selection.setCursorLocation(editor.getBody(), editor.getBody().childElementCount);
So尛奶瓶 2024-08-08 13:42:09

这是适合我的解决方案:

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

This is the solution that works for me:

// 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);
}
虫児飞 2024-08-08 13:42:09

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

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

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

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

So, here is solution from the our project. Our objective was to change (+)/(-)/(?) strings to the appropriate images "on the fly" while user is typing.

There was a problem: every time after changing string to image, cursor went the beginning of the image, not to the end as was expected.

We added bulk of the code which moves cursor to the end of the image, so user can type continuously w/o interrupting on "jumpy" cursor.

Key part: Instead of using editor.getBody, there is a more elegant way to create the temporary span and furthermore, delete it immediately after the necessary actions.

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();
    }
单身情人 2024-08-08 13:42:09

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

它有效,我自己使用它。

The correct solution is to use the tinyMCE api tinymce.dom.Selection

http://www.tinymce.com/wiki.php/API3:class.tinymce.dom.Selection

the syntaxe is something like :

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

it works I use this myself.

有木有妳兜一样 2024-08-08 13:42:09

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

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

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

I'm inserting html content at current caret position (without staying in that html parent element) like this:

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

That blank space at the end will ensure that the further typed text will be placed outside the inserted div element.

是伱的 2024-08-08 13:42:09

我抄袭了这个

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

I've plagiarized this from 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); 
    } 
} 
时光无声 2024-08-08 13:42:09

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

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

Insert a DOM node at the current selection/caret location.

tinyMCE.activeEditor.selection.setNode(tinyMCE.activeEditor.dom.create('img', {src : 'some.gif', title : 'some title'}));
迷荒 2024-08-08 13:42:09

只是在这里投入我自己的 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
        }
    });
}

Just throwing in my own 2 cents here. None of these answered my question. I was not putting in an HTML element, but a block of text ([code][/code] for example) and needed the cursor to go between the two.

Using part of @robyates answer, what I did was put a temporary HTML element in between the 2 [code] tags, focus on it, then removed the HTML element completely. Here is my code:

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
        }
    });
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文