26

更新:入力要素のカーソル位置またはテキスト位置をピクセル単位で取得するの複製。

TL; DR - 信じられないほど軽量で堅牢なtextarea-caret-position コンポーネントライブラリを使用します。これもサポート<input ype="text">されるようになりました。http://jsfiddle.net/dandv/aFPA7/のデモ


キャレットが HTML テキスト フィールド内のどこにあるかを知る方法はありますか?

<input type='text' /> 

キャレットの位置に応じて div をピクセル単位で配置 (および再配置) したいと思います。

: 文字または<textarea>. <input>要素内のピクセル単位の位置を知りたい。

4

7 に答える 7

18

目に見えないフェイク要素の使用

これは、入力テキスト ボックスと同じ CSS プロパティ (フォント、左ボーダー、左パディング)を持つ完全に配置された非表示 ( visibilitynotを使用) の偽要素を使用することで実現できます。display

この非常に短くて理解しやすい JSFiddleは、このスクリプトがどのように機能するかの出発点です。
Chrome と Firefox でそのまま動作します。また、 IE9 +でも動作するはずです。

Internet Explorer 8 (およびそれ以前) では、入力テキスト ボックス内のテキストの先頭からキャレット位置を取得するために、追加のコードが必要になります。上部にメーターを追加して、10 ピクセルごとに線を表示し、正しく測定されているかどうかを確認できるようにしました。線は 1、11、21、... ピクセルの位置にあることに注意してください。

この例では、実際にテキスト ボックス内のすべてのテキストをキャレット位置まで取得し、偽の要素内に配置してから、その幅をピクセル単位で測定します。これにより、テキスト ボックスの左からのオフセットが得られます。

テキストを偽の要素にコピーすると、通常のスペースも改行されていないスペースに置き換えられるため、スペースの直後にキャレットを配置すると、間違った位置になる場合に実際にレンダリングされます。

var faux = $("#faux");
$("#test").on("keyup click focus", function(evt) {
    // get caret offset from start
    var off = this.selectionStart;

    // replace spaces with non-breaking space
    faux.text(this.value.substring(0, off).replace(/\s/g, "\u00a0"));
});​

偽物の正しい寸法に注意してください

  • パディング
  • 国境
  • マージン

正しい値を取得するために削除されました。そうしないと、要素が広すぎます。要素のボックスは、含まれるテキストの直後で終了する必要があります。

入力ボックスの先頭からのピクセル単位のキャレットの位置は、次から簡単に取得できます。

faux.outerWidth();

問題

ただし、問題が 1 つあります。テキストボックス内のテキストがスクロールされ(長すぎる場合)、キャレットがテキストの最後ではなく、その間のどこかにある場合の状況を処理する方法がわかりません...最後にある場合、キャレットの位置は常に可能な最大位置 (入力幅から右側の寸法 - パディング、ボーダー、マージン) を差し引いたもの)。

テキスト ボックス内のテキスト スクロール位置を取得できるかどうかはわかりません。できれば、この問題も解決できます。しかし、私はこれに対する解決策を知りません...

お役に立てれば。

于 2012-11-15T16:33:33.753 に答える
4

上記の私のコメントを詳しく説明すると、次のように動作するはずです。

原則を示すために、書式設定を省略したため、要素 (id="spacer") の色を に設定する必要がある場合があります#FFFFFE。おそらく、先行スペースのピクセルをいくつか追加するなど...しかし、id のテストとスペーサーがあれば、キャレットは比例して移動します。同じフォントを使用します。

もちろん、求められた[px]単位の距離はわかりませんが、コンテンツ(この場合はキャレット)をプロポーショナル フォントの幅に完全に合わせて配置することができます。OP 行 3で)、次に .... voi lá!

<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <script type="text/javascript">
            function adjust()
            {
                document.getElementById('spacer').innerHTML=document.getElementById('test').value;
            }
        </script>
        <p>
            <input name="test" id="test" type="text" onkeyup="adjust()" /> Test <br />
            <span id="spacer"></span>^here
        </p>
    </body>
</html>

アップデート:

<span id="spacer" style="color: #FFFFFF"></span>

これにより、スペーサーは白い背景では見えなくなりますが、ユーザーがスパン要素を選択してスペーサー テキストを強調表示することはまだ妨げられません。スペーサーを選択不可にするタスクを残します -ここに良い解決策があります

于 2012-11-20T08:39:48.287 に答える
2
于 2012-11-20T14:01:08.967 に答える
2

を使用できます<span contenteditable="true"></span><input type="hidden" />。そうすれば、 と を使用しwindow.getSelection()て位置を取得できます。これは、IE9+ を含むほとんどの最新のブラウザーで動作するはずです。getRangeAtgetClientRects

function getCaret() {
    var caret = caret = {top: 0, height: 0},
        sel = window.getSelection();
    caret.top = 0;
    caret.height = 0;
    if(sel.rangeCount) {
        var range = sel.getRangeAt(0);          
        var rects = range.getClientRects();
        if (rects.length > 0) {
            caret.top = rects[0].top;
            caret.height = rects[0].height;
        } else {
            caret.top = range.startContainer.offsetTop - document.body.scrollTop;
            caret.height = range.startContainer.clientHeight;
        }
    }
    return caret;
}

(私がこれを引っ張ってきたプロジェクトは Mobile Safari をターゲットにしており、1 つの大きな contenteditable ビューを使用していることに注意してください。ニーズに合わせて微調整する必要があるかもしれません。これは、X 座標と Y 座標を取得する方法を示すためのものです。)

IE8 以下の場合、IE には同じ情報を取得するための独自の API があります。

注意が必要な部分は、要素がプレーン テキストのみを許可するようにすることです。具体的には、貼り付けイベントを使用します。スパンがフォーカスを失ったとき (onblur)、内容を隠しフィールドにコピーして投稿できるようにします。

于 2012-11-19T19:58:45.140 に答える
1

キャンバス 2D はどうですか? 測定テキストを描画するための API を持っています。あなたはそれを使うことができます。同じフォント、font-size を設定すると、テキスト ボックスから文字列の幅を測定できるはずです。

      $('body').append('<canvas id="textCanvas" width="100px" height="100px">I\'m sorry your browser does not support the HTML5 canvas element.</canvas>');
      var canvas = document.getElementById('textCanvas');
      var ctx = canvas.getContext('2d');
      ctx.measureText(text);
      var width = mes.width;

この種のソリューションを使用して、テキストの幅を取得し、WebGL で描画しました。私は問題なく動作しましたが、テキストを測定するための API であるため、テキストがキャンバス コンテキストに対して大きすぎる場合に何が起こるかをテストしたことはありません。しかし、あなたはそれを完全にチェックする必要があることを知っています! :)

于 2012-11-19T18:35:38.023 に答える
0

HERESの実例http://jsfiddle.net/gPL3f/2/

キャレットの位置を見つけるために、入力内の文字を数え、その値に1文字のサイズを掛けました。

その後、divをその場所に移動しました。

<html>
<head>
<style type="text/css">
body { font-size: 12px; line-height: 12px; font-family: arial;}
#box { width: 100px; height: 15px; position: absolute; top: 35px; left: 0px; background: pink;}
</style>
<script type="text/javascript" src="jquery-1.7.1.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var letter_size = 6;
$("input[type='text']").keyup(function(e) {
    move_size = $(this).val().length * letter_size;
    $('#box').css({'left': move_size+'px'}); 
});
});
</script>

</head>
<body>
<input type="text" />
<div id="box">
/ move 
</div>
</body>
<html>

アップデート

$(document).ready(function(){
    var letter_size = 6;
    $("input[type='text']").keyup(function(e) {
        $('.hidden_for_width').text($(this).val());
        move_size = $('.hidden_for_width').width();
        $('#box').css({'left': move_size});
    });
});

入力から値を挿入する隠しコンテナを追加しました。その後、そのコンテナの幅を取得し、それに応じて DIV を移動します

于 2012-11-18T23:54:56.100 に答える
-1
function getCursorPosition (elem) {
  var pos = 0;  
  if (document.selection) {
    elem.focus ();
    var sele = document.selection.createRange();
    sele.moveStart('character', -elem.value.length);
    pos = sele.text.length;
  }
  else if (elem.selectionStart || elem.selectionStart == '0')
    pos = elem.selectionStart;
  return pos;
}​

getCursorPosition(document.getElementById('textbox1'))
于 2012-11-12T16:32:40.287 に答える