web-dev-qa-db-ja.com

カーソル/キャレットの位置を設定する最良の方法は何ですか?

TinyMCEが選択したテキストエリアにコンテンツを挿入する場合、カーソル/キャレットの位置を設定するための最良の方法は何ですか?

tinyMCE.execCommand("mceInsertRawHTML", false, content);を使用してコンテンツを挿入しています。カーソル位置をコンテンツの末尾に設定したいと思います。

_document.selection_と_myField.selectionStart_の両方はこれでは機能せず、これはTinyMCEによってサポートされるか(私が彼らのフォーラムで見つけられないものを通じて)、またはそれは本当に醜いハック。

後で:良くなります。 WordPressにTinyMCEを読み込むと、埋め込みiframeにエディター全体が読み込まれることを理解しました。

後で(2):document.getElementById('content_ifr').contentDocument.getSelection();を使用して選択を文字列として取得できますが、getRangeAt(0)を使用できるSelectionオブジェクトは使用できません。少しずつ進歩していきます。

31

この問題に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);

ただし、この2番目の関数の問題は、キャレットの位置が呼び出された後(ブラウザーの範囲などに基づいて呼び出されることを望んでいない)、ポスト領域の先頭に設定されることです。終わり近くのどこかで、最初の関数を使用して、この関数が挿入されたコンテンツの最後のキャレット位置を復元するように機能することを発見しました。

tinyMCE.activeEditor.focus();

さらに、挿入されたテキストの長さを計算する必要なく、挿入されたコンテンツの最後にキャレット位置を復元します。欠点は、IE 7とIE 8で問題が発生する可能性がある最初の挿入関数でのみ機能することです(WordPressフォールトの可能性があります) TinyMCEよりも)。

端的に言うと、私は知っています。説明のために気軽に質問してください。

25

まず、作成するコンテンツの最後にスパンを追加する必要があります。

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を記述する際に使用する戦略です。根本的なソースを読むことは、この種の問題に非常に役立ちます。

27
Garry Tan

カーソルを最後に移動するのはとても簡単なので、これを行うためにオンラインで他の場所に投稿されたひどいクラッジは信じられません。 Spocke氏の回答は当初は役に立ちませんでしたが、最終的にはAPIドキュメントが答えを提供してくれました。 "すべてのコンテンツを選択してから選択を折りたたみます":

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

ed.selection.collapse(false);

このスレッドがGoogleで最初に登場したスレッドの1つであるため、これが他の人の役に立つことを願っています。

15
Peter Wooster

私が見つけた最良の方法は、一時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ボタンをインストールするときにうまくいきましたが、このシナリオではうまくいきませんでした。

7
robyates

正しい解決策は、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
Benibur

だから、ここに私たちのプロジェクトからの解決策があります。私たちの目的は、ユーザーが入力しているときに(+)/(-)/(?)文字列を「オンザフライ」で適切な画像に変更することでした。

問題が発生しました。文字列を画像に変更するたびに、カーソルが画像の先頭に移動しました。

カーソルを画像の最後に移動するコードの大部分を追加したため、ユーザーは「ジャンプ」カーソルで中断せずに連続して入力できます。

重要な部分: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();
    }
2
Pavel Druzhinin

次のように、現在のキャレット位置にhtmlコンテンツを挿入しています(そのhtml親要素にとどまることはありません)。

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

末尾の空白スペースにより、入力したテキストが挿入されたdiv要素の外側に配置されます。

1
Richard Bdžoch

これを 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); 
    } 
} 
1
camomileCase

現在の選択/キャレットの場所にDOMノードを挿入します。

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

ここに自分の2セントを投入するだけです。これらのどれも私の質問に答えませんでした。 HTML要素ではなく、テキストのブロック([code][/code]など)、2つの間を移動するカーソルが必要でした。

@robyatesの回答の一部を使用して、私が行ったのは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
        }
    });
}
1
James

Tinyバージョン5

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

これは私のために働く解決策です:

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