HTMLテキストボックスにキーボードキャレットの位置を設定する


173

テキストボックスのキーボードキャレットを特定の位置に移動する方法を知っている人はいますか?

たとえば、テキストボックス(たとえば、text-areaではなくinput要素)に50文字が含まれていて、キャレットを文字20の前に配置したい場合、どうすればよいですか?

これは、この質問とは区別されます。jQueryを必要とするjQuery Set Cursor Position in Text Area

回答:


205

JavaScriptを使用したTextboxまたはTextAreaでの Josh Stodolaのキーボードキャレットの位置設定からの抜粋

必要なテキストボックスまたはテキストエリアの任意の位置にキャレットを挿入できるようにする汎用関数:

function setCaretPosition(elemId, caretPos) {
    var elem = document.getElementById(elemId);

    if(elem != null) {
        if(elem.createTextRange) {
            var range = elem.createTextRange();
            range.move('character', caretPos);
            range.select();
        }
        else {
            if(elem.selectionStart) {
                elem.focus();
                elem.setSelectionRange(caretPos, caretPos);
            }
            else
                elem.focus();
        }
    }
}

最初に予期されるパラメータは、キーボードキャレットを挿入する要素のIDです。要素が見つからない場合、何も起こりません(明らかに)。2番目のパラメーターは、キャレット位置インデックスです。ゼロは、キーボードキャレットを最初に置きます。要素の値の文字数より大きい数値を渡すと、キーボードキャレットが最後に置かれます。

IE6以降、Firefox 2、Opera 8、Netscape 9、SeaMonkey、Safariでテスト済み。残念ながらSafariでは、onfocusイベントとの組み合わせでは機能しません。

上記の関数を使用して、フォーカスを受け取ったときにキーボードキャレットがページ上のすべてのテキスト領域の最後にジャンプする例:

function addLoadEvent(func) {
    if(typeof window.onload != 'function') {
        window.onload = func;
    }
    else {
        if(func) {
            var oldLoad = window.onload;

            window.onload = function() {
                if(oldLoad)
                        oldLoad();

                func();
            }
        }
    }
}

// The setCaretPosition function belongs right here!

function setTextAreasOnFocus() {
/***
 * This function will force the keyboard caret to be positioned
 * at the end of all textareas when they receive focus.
 */
    var textAreas = document.getElementsByTagName('textarea');

    for(var i = 0; i < textAreas.length; i++) {
        textAreas[i].onfocus = function() {
            setCaretPosition(this.id, this.value.length);
        }
    }

    textAreas = null;
}

addLoadEvent(setTextAreasOnFocus);

4
if(elem.selectionStart)jhnnsの回答でも指摘されているように、selectionStartが0のときにブレークします。
mpartel 2012

1
これは私にはうまくいきません。実際のテキストボックスをクリックすると、キャレットの位置が最初になると思います。私のフィドルjsfiddle.net/khx2wを
elad.chen 2013

setCaretPosition関数は問題なく機能します。ただし、addActionHandler関数にはありません。しかし、それがなくても、カーソルをフォーカスに移動させることができませんでした。ほとんどの場合、それはブラウザがクリックの位置に基づいてカーソル位置自体を設定するためです。私が言えることからそれを回避する方法はないようですが、私は完全に間違っている可能性があります。
GJK 2013

IE9、FF25で機能しますが、Chrome 30では機能しません。
アンバーフェルール2013年

私が持っているelem.value = elem.value.replace(/^9/g,'+79')コードで。OperaMINIカーソル上で+。この機能は役に立ちません
eri

52

答えのリンクは壊れています、これはうまくいくはずです(すべてのクレジットはblog.vishalon.netに移動します):

http://snipplr.com/view/5144/getset-cursor-in-html-textarea/

コードが再び失われた場合のために、2つの主な機能を次に示します。

function doGetCaretPosition(ctrl)
{
 var CaretPos = 0;

 if (ctrl.selectionStart || ctrl.selectionStart == 0)
 {// Standard.
  CaretPos = ctrl.selectionStart;
 }
 else if (document.selection)
 {// Legacy IE
  ctrl.focus ();
  var Sel = document.selection.createRange ();
  Sel.moveStart ('character', -ctrl.value.length);
  CaretPos = Sel.text.length;
 }

 return (CaretPos);
}


function setCaretPosition(ctrl,pos)
{
 if (ctrl.setSelectionRange)
 {
  ctrl.focus();
  ctrl.setSelectionRange(pos,pos);
 }
 else if (ctrl.createTextRange)
 {
  var range = ctrl.createTextRange();
  range.collapse(true);
  range.moveEnd('character', pos);
  range.moveStart('character', pos);
  range.select();
 }
}

1
いくつかの調整を行う必要があります、基本機能の+1 。範囲メソッドを使用する場合は、「pos」からライン数を引く必要があります。
Rob W

36

私は実際にこのソリューションを本当に必要としており、一般的なベースラインソリューション(入力に焦点を合わせ、それ自体に等しい値を設定するはブラウザー間で機能しないため、すべてを微調整して編集し、機能させるようにしました。@ kd7のコードに基づいて、ここに私が思いついたものがあります。

楽しい!IE6 +、Firefox、Chrome、Safari、Operaで動作します

クロスブラウザーキャレットの配置手法(例:カーソルをENDに移動)

// ** USEAGE ** (returns a boolean true/false if it worked or not)
// Parameters ( Id_of_element, caretPosition_you_want)

setCaretPosition('IDHERE', 10); // example

肉とジャガイモは基本的に@ kd7のsetCaretPositionであり、最大の調整はif (el.selectionStart || el.selectionStart === 0)、FirefoxではselectionStartが0から始まり、ブール値ではもちろんFalseになっているため、そこで壊れていました。

クロムの最大の問題は、それを与えるだけで.focus()は不十分だったことです(テキスト全体を選択し続けました!)したがって、el.value = el.value;関数を呼び出す前に、それ自体に値を設定しました。これで、selectionStartを使用するための入力。

function setCaretPosition(elemId, caretPos) {
    var el = document.getElementById(elemId);

    el.value = el.value;
    // ^ this is used to not only get "focus", but
    // to make sure we don't have it everything -selected-
    // (it causes an issue in chrome, and having it doesn't hurt any other browser)

    if (el !== null) {

        if (el.createTextRange) {
            var range = el.createTextRange();
            range.move('character', caretPos);
            range.select();
            return true;
        }

        else {
            // (el.selectionStart === 0 added for Firefox bug)
            if (el.selectionStart || el.selectionStart === 0) {
                el.focus();
                el.setSelectionRange(caretPos, caretPos);
                return true;
            }

            else  { // fail city, fortunately this never happens (as far as I've tested) :)
                el.focus();
                return false;
            }
        }
    }
}

@mcpDESIGNSテキスト入力にフォーカスが当たっているときにこの関数を使用しようとしていますが、どこにも行けません。純粋なJavaScriptを使用してこの関数を適用するのを手伝っていただけませんか?
elad.chen 2013

@ elad.chenテキストボックスに集中したらすぐにテキストボックスの最後に配置しようとしていますか?
Mark Pieszak-Trilon.io 2013年

@mcpDESIGNS要素がフォーカスされたらすぐにカーソルをフィールドの先頭に置きたいです。フィドルを参照してください:jsfiddle.net/KuLTU/3
elad.chen 2013

@ elad.chenクレイジーな返事でごめんなさい!そのイベントをsearch_field_focus関数内では.onclickなくに変更するだけ.onfocus
Mark Pieszak-Trilon.io

2
el.value = el.value; [...] if(el !== null)-私はこれらの2行を入れ替えます。elがnullの場合はel.value = el.value失敗するため、その行は内にある必要がありifます。
BackSlash 2018年

21

selectionStartが偶発的に0になるとelem.selectionStartがfalseと評価されるため、kd7の回答を少し調整しました。

function setCaretPosition(elem, caretPos) {
    var range;

    if (elem.createTextRange) {
        range = elem.createTextRange();
        range.move('character', caretPos);
        range.select();
    } else {
        elem.focus();
        if (elem.selectionStart !== undefined) {
            elem.setSelectionRange(caretPos, caretPos);
        }
    }
}

5

IEとChromeでテストして、この問題を解決する簡単な方法を見つけました。

function setCaret(elemId, caret)
 {
   var elem = document.getElementById(elemId);
   elem.setSelectionRange(caret, caret);
 }

テキストボックスIDとキャレット位置をこの関数に渡します。


3

テキストボックスをフォーカスする必要があり、キャレットを最後に配置したいのにテキスト全体がハイライト表示されるという唯一の問題がある場合、その特定のケースでは、フォーカス後にテキストボックスの値をそれ自体に設定するこのトリックを使用できます。

$("#myinputfield").focus().val($("#myinputfield").val());

2
<!DOCTYPE html>
<html>
<head>
<title>set caret position</title>
<script type="application/javascript">
//<![CDATA[
window.onload = function ()
{
 setCaret(document.getElementById('input1'), 13, 13)
}

function setCaret(el, st, end)
{
 if (el.setSelectionRange)
 {
  el.focus();
  el.setSelectionRange(st, end);
 }
 else
 {
  if (el.createTextRange)
  {
   range = el.createTextRange();
   range.collapse(true);
   range.moveEnd('character', end);
   range.moveStart('character', st);
   range.select();
  }
 }
}
//]]>
</script>
</head>
<body>

<textarea id="input1" name="input1" rows="10" cols="30">Happy kittens dancing</textarea>

<p>&nbsp;</p>

</body>
</html>

2
function SetCaretEnd(tID) {
    tID += "";
    if (!tID.startsWith("#")) { tID = "#" + tID; }
    $(tID).focus();
    var t = $(tID).val();
    if (t.length == 0) { return; }
    $(tID).val("");
    $(tID).val(t);
    $(tID).scrollTop($(tID)[0].scrollHeight); }

Uncaught TypeError:Object [object HTMLInputElement] has no method 'startsWith'
bobpaul

1
@bobpaul:tID要素オブジェクト自体ではなく、要素のIDである必要があります。要素オブジェクトを渡す場合は、このメソッドの最初の2行を削除するだけで機能します。
畏敬の念

2

私は以下のような条件を修正します:

function setCaretPosition(elemId, caretPos)
{
 var elem = document.getElementById(elemId);
 if (elem)
 {
  if (typeof elem.createTextRange != 'undefined')
  {
   var range = elem.createTextRange();
   range.move('character', caretPos);
   range.select();
  }
  else
  {
   if (typeof elem.selectionStart != 'undefined')
    elem.selectionStart = caretPos;
   elem.focus();
  }
 }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.