4

カレットを特定のインデックスに設定するための次のコードフラグメントがありますindex

var el = $("#subjectMessage"), index = 9 ;
var range = rangy.createRange();
range.setStart(el[0].childNodes[0], index);
range.collapse(true);
var sel = rangy.getSelection();
sel.setSingleRange(range);

contentEditableに入力要素を追加すると、問題が発生します。これ以上、ケアレットdivを目的の位置に一貫して設定できなくなります。

これらの入力をdiv内の1つの位置として扱いたい(まるで1つの文字であるかのように)。

これとは別に、このcontentEditable内の選択範囲divを自分のテキストに置き換えるには、同様のコードが必要になります。これを機能させる方法を理解するために、私は(まったく)怒りに精通していません...

すべての助けは大歓迎です!

これがあなたがおもちゃにできるフィドルです:

http://jsfiddle.net/ee93P/

4

1 に答える 1

7

RangyのSelectionおよびRangeAPIは、標準のDOMSelectionおよびRangeAPIのスーパーセットであるため、MDN(RangeSelection)などの場所からのドキュメントが適用されます。

あなたが抱えている問題は、範囲の境界が、含まれているDOMノード内のオフセットとして表されることです。たとえば、以下のHTMLでは、カレットはパイプ文字として示されています。

<p>Foo<br>b|ar</p>

...カレット範囲の開始境界と終了境界は同一であり、テキストノード「バー」でオフセット1に設定されます。

要素のテキストコンテンツ内のオフセットとして位置を設定する場合は、<p>DOMトラバーサルを実行する必要があります。私の別の答えに基づいて、これの実装を書きました。これは単純な実装です。CSSによって、または要素内にあるなどの理由で非表示にされる可能性のあるテキストを考慮せず、改行を含むブラウザーの不一致(IEと他のすべて)がある可能性があります。折りたたまれた空白の説明はありません(2つ以上の連続したスペース文字がページ上の1つの表示可能なスペースに折りたたまれているなど)。これは正しく理解するのが難しいので、私は一般的にそれをお勧めしません。これらすべてを処理するRangy用のテキストベースのモジュールを作成することを計画していますが、まだ開始していません。

http://jsfiddle.net/ee93P/2/

コード:

function setCaretCharIndex(containerEl, index) {
    var charIndex = 0, stop = {};

    function traverseNodes(node) {
        if (node.nodeType == 3) {
            var nextCharIndex = charIndex + node.length;
            if (index >= charIndex && index <= nextCharIndex) {
                rangy.getSelection().collapse(node, index - charIndex);
                throw stop;
            }
            charIndex = nextCharIndex;
        }
        // Count an empty element as a single character. The list below may not be exhaustive.
        else if (node.nodeType == 1
                 && /^(input|br|img|col|area|link|meta|link|param|base)$/i.test(node.nodeName)) {
            charIndex += 1;
        } else {
            var child = node.firstChild;
            while (child) {
                traverseNodes(child);
                child = child.nextSibling;
            }
        }
    }

    try {
        traverseNodes(containerEl);
    } catch (ex) {
        if (ex != stop) {
            throw ex;
        }
    }
}
于 2011-12-13T15:22:51.337 に答える