15

カレットの配置に関するいくつかの投稿を読みましたが、私の特定の問題に答えるものはないようです。

  1. 私は2つのdiv(div1div2)を持っています
  2. div1 =編集不可のdiv
  3. div2 = contenteditable div
  4. 両方のdivにまったく同じ内容が含まれています
  5. ユーザーがdiv1をクリックすると、非表示になり、div2が正確な場所に表示され、ユーザーは編集できます

問題:キャレットをdiv2の正確な位置にdiv1として表示したい

したがって、ユーザーがdiv1をクリックした場所を読み取る方法が必要です。次に、div2が表示されたら、カーソル/キャレットを同じ場所に置きます。つまり、getCaretLocation(in_div_id)およびsetCaretLocation(in_div_id)関数のセットです。

それを行う方法はありますか?

ありがとう -

4

6 に答える 6

8

短い答え: できません

長い答え:あなたが直面する問題は、div1のクリックイベントの(x、y)座標を取得できることですが、キャレット位置の実装では、コンテンツ内のキャレットの位置を知る必要があります(キャレットの前の文字数)。

(x,y) 座標を文字位置に変換するには、実際に前の文字数を知る必要があります (つまり、テキストがltrの場合、現在の行とその上に残っています)。

固定幅フォントを使用すると、問題を単純化できます。つまり、(x,y) 座標を文字グリッド上の (行、列) 座標にマッピングします。

ただし、テキストがどのように折り返されているのかわからないという問題は依然としてあります。例えば ​​:

------------------
|Lorem ipsum     |
|dolor sit amet  |
|consectetur     |
|adipiscing elit |
------------------

ユーザーがd in dolorをクリックすると、その文字が 2 行目の 1 番目の文字であることがわかりますが、ラッピング アルゴリズムを知らなければ、「Lorem ipsum dolor sit…」の 13 番目の文字であることがわかりません。 "。また、このようなラッピング アルゴリズムがブラウザーやプラットフォーム間で同一であるという保証はありません。

さて、私が疑問に思っているのは、divそもそもなぜ2つの異なる同期を使用するのですか? 1 つの div のみを使用し、ユーザーがクリック (またはホバー) したときにそのコンテンツを編集可能に設定する方が簡単ではないでしょうか?

于 2010-05-16T18:25:14.423 に答える
1

カレットに小さなスパン要素を挿入し、その位置を取得して、削除することができます。クロスブラウザの範囲と選択ライブラリについては、rangyを参照してください。

于 2011-02-01T09:11:52.103 に答える
1

できます。基本的に、最初のdivで編集可能な一時コンテンツを設定して、キャレット位置をキャッチする必要があります

$('div1').hover(function()
{ $(this).attr('contenteditable','true');
},function()
{ $(this).removeAttr('contenteditable');
}).mouseup(function()
{   var t = $(this);
    // get caret position and remove content editable
    var caret = t.getCaret();
    t.removeAttr('contenteditable');
    // do your div switch stuff
    ...
    // and apply saved caret position
    $('div2').setCaret(caret);
});

get/set キャレットメソッドが必要です:)

編集>ここに私自身のものがあります(ライブデモ

        getSelection:function($e)
        {   if(undefined === window.getSelection) return false;
            var range = window.getSelection().getRangeAt(0);

            function getTreeOffset($root,$node)
            {   if($node.parents($root).length === 0) return false; // is node child of root ?
                var tree = [], treesize = 0;
                while(1)
                {   if($node.is($root)) break;
                    var index, $parent = $node.parent();
                    index = $parent.contents().index($node);
                    if(index !== -1) { tree[treesize++] = index; } $node = $parent;
                };  return tree.reverse();
            }

            var start = getTreeOffset($e,$(range.startContainer));
            var end   = getTreeOffset($e,$(range.endContainer));

            if(start & end === false) return false;

            return {start:start,end:end,startOffset:range.startOffset,endOffset:range.endOffset};
        }, setSelection:function($e,s,win)
        {   $e.focus(); if(s === false) return; var sel = win.getSelection(); sel.removeAllRanges();

            function getNode($e,s)
            {   var node = $e;
                for( var n=0;n<s.length;n++ )
                {   var index = s[n]; if(index < 0) break;
                    node = node.contents(':eq('+index+')');
                }   return node.get(0);
            }

            var start = getNode($e,s.start), end = getNode($e,s.end), range = win.document.createRange();
            range.setStart(start,s.startOffset); range.setEnd(end,s.endOffset); sel.addRange(range);
        }
于 2012-12-17T13:20:18.323 に答える
0

要素をクリックすると、長さゼロの Selection オブジェクトが作成されます ( element.getSelection() から取得します。要素は問題の div です)。そのオブジェクトの focusOffset は、たとえば、その div の 74 番目の文字をクリックしたことを知らせます (これは Adrien が別の回答で不可能だと言ったことです)。

于 2012-06-15T13:43:28.223 に答える
0

インライン編集をしようとしているようですね... jeditableプラグインを見ましたか?

于 2010-05-17T00:49:43.830 に答える