input type =“ number”のselectionStart / selectionEndは、Chromeでは許可されなくなりました


83

このアプリケーションは、入力フィールドでselectionStartを使用して、ユーザーが矢印キーを押したときに(つまり、選択がテキストの最後にあり、ユーザーが移動先の右矢印を押したときに、ユーザーを次/前のフィールドに自動的に移動するかどうかを決定します。次のフィールド、それ以外の場合)

Chromeでは、type = "number"の場所でselectionStartが使用されないようになりました。例外がスローされるようになりました。

Failed to read the 'selectionStart' property from 'HTMLInputElement': The input element's type ('number') does not support selection.

以下を参照してください。

https://codereview.chromium.org/100433008/#ps60001

http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#do-not-apply

type = "number"の入力フィールドでキャレットの場所を特定する方法はありますか?


3
うーん、これに対する更新はありません。この機能が削除される理由について知りたい。
リンゴ2014

1
別の使用法:入力タイプ番号でjquery-maskmoneyプラグインを使用すると、同じ問題が発生します
Alexandre

入力タイプを一時的にに変更しtext、キャレットの位置を確認してから、タイプを元に戻すことはできnumberますか?
スタン

1
@Stanまだ試していませんが、タイプの交換はあまり効果的ではないと思います。
スティーブン

2
:それは仕事、したselectionStart /終了は、常に0として返されない@Steven jsfiddle.net/Mottie/wMYKU
Mottie

回答:


43

選択は、テキスト/検索、URL、tel、およびパスワードでのみ許可されます。タイプ番号の入力に対して選択が無効になっている理由として考えられるのは、一部のデバイス、または特定の状況(入力がショートとして表示されている場合などlist)では、キャレットがない可能性があるためです。私が見つけた唯一の解決策は、入力タイプをテキストに変更することでした(入力を制限するための適切なパターンを使用)。入力タイプを変更せずに処理する方法をまだ探しています。何かが見つかったら更新を投稿します。


6
一部のデバイスではキャレットが表示されない場合があることは理解していますが、複雑になっているようです。すべてにtype = "text"を使用することになった場合、型を持つという目的さえも無効になります。また、電話が数値入力などのために異なるキーボードを表示する機能も失います。入力から選択を削除するという選択には同意しませんが、解決策がわかりません...
Steven

49
これは本当にひどいです。これは大きな間違いだと思うので、これについてWHAT-WGに連絡しました。ユーザーエージェントの99.9%は、<input type="number"/>フィールドをテキストフィールドとしてレンダリングし、デフォルトのオンスクリーンキーボード(使用可能な場合)を数字キーボードに設定しますが、それでもフィールドを「テキスト入力」フィールドとしてレンダリングします。フィールドに計算機または同様の値操作機能を追加しようとする既存/将来の試みは、フィールドを強制的にテキストに戻してユーザーエクスペリエンスを台無しにしない限り、役に立たなくなります。
scunliffe 2014

3
私はあなたの両方に同意します。この投稿で指摘しているように、値IDL属性には、入力に含まれるものすべてのテキストレンダリングが常に含まれている必要があると思います。また、ユーザーエージェントが選択を許可している場合は、selectionStart / Endが使用可能である必要があります。
Patrice Chalin 2014

6
Whaaaaat o_0Chromeはちょうどインターネットを壊しました..そして私のテスト。もっと深刻なことに、私は論理を理解していません。ユーザーが自分のメールアドレスや番号を選択できないのはなぜですか?stackoverflow.com/questions/22171694/…–
Peter

22

の簡単な回避策(Chromeでテスト済み)を見つけましたsetSelectionRange()。あなたは、単に変更することができますtypetextは、使用する前にsetSelectionRange()、その後にそれをバックに変更しますnumber

これは、入力をクリックするたびに入力された数値の4番目の位置にキャレットを配置するjqueryの簡単な例です(動作を確認するには、入力に5つ以上の数値を追加してください)。

プランカー


このアプローチはemail入力に対しても機能します(これがsetSelectionRange()、ChromeではなくIE11(!)で機能した理由をこのページで疑問に思った理由です)。
jdunning 2018

純粋なJavaScriptobj.type = "text";として、これはjQueryなしで機能します。次に、obj.type = "number"に戻ります。
jacouh

ただし、plunkrでは、ユーザーがマウスで選択することはできなくなりました。
リスター氏

1
私の場合(Chromeバージョン80)、を使用して入力タイプを「テキスト」に設定するとinput.type = 'text'、Chromeは入力からフォーカスを削除し、カーソルが消えてinput.selectionStartetcがnullを返すため、これは機能しなくなりました。
アナンダマスリ

16

現在、テキストを安全に選択できる要素は次のとおりです。

<input type="text|search|password|tel|url">説明されているように:
whatwg:selectionStart属性

HTMLInputElementインターフェースのドキュメントを読んで、入力要素を詳しく調べることもできます。

この「問題」を安全に克服するために、今のところ最善の方法は、<input type="text">数字のみを受け入れるマスク/制約を処理して適用することです。要件を満たすプラグインがいくつかあります。

以前のプラグインの1つのライブデモをここで見ることができます:

安全に使用したい場合はselectionStart、それをサポートする要素を確認できます(入力タイプの属性を参照)。

実装

// Fix: failed to read the 'selectionStart' property from 'HTMLInputElement'
// The @fn parameter provides a callback to execute additional code
var _fixSelection = (function() {
    var _SELECTABLE_TYPES = /text|password|search|tel|url/;
    return function fixSelection (dom, fn) {
        var validType = _SELECTABLE_TYPES.test(dom.type),
            selection = {
                start: validType ? dom.selectionStart : 0,
                end: validType ? dom.selectionEnd : 0
            };
        if (validType && fn instanceof Function) fn(dom);
        return selection;
    };
}());

// Gets the current position of the cursor in the @dom element
function getCaretPosition (dom) {
    var selection, sel;
    if ('selectionStart' in dom) {
        return _fixSelection(dom).start;
    } else { // IE below version 9
        selection = document.selection;
        if (selection) {
            sel = selection.createRange();
            sel.moveStart('character', -dom.value.length);
            return sel.text.length;
        }
    }
    return -1;
}

使用法

// If the DOM element does not support `selectionStart`,
// the returned object sets its properties to -1.
var box = document.getElementById("price"),
    pos = getCaretPosition(box);
console.log("position: ", pos);

上記の例はここにあります:jsu.fnGetCaretPosition()


こんにちは、投稿ありがとうございます。「数字だけを受け入れる制約」とはどういう意味ですか?
petarMI 2015

1
こんにちは@PetarMI、制約により、<input>要素は数字のみを受け入れることができます。これはJavaScriptを介して行われます。これは、すべてのブラウザーが新しいHTML5 <input>タグで正しく機能するわけではないためです。
jherax 2015


5

回避策として、type="tel"入力タイプはtype="number"Chromeと非常によく似た機能を提供し、この制限はありません(Patriceが指摘しているように)。


fwiwこれは、Androidで電話固有のテンキーを提供しますが、番号は別のテンキーを提供します
patrick

5

Chromeでこれを実現する方法が1つあります(他のブラウザもありますが、ここではChromeが大きな問題です)。を使用window.getSelection()して、現在の入力から選択オブジェクトを取得し、選択を後方(または前方)にテスト拡張して、選択のtoString()値が変化するかどうかを確認します。そうでない場合、カーソルは入力の最後にあり、次の入力に移動できます。含まれている場合は、操作を逆にして選択を元に戻す必要があります。

s = window.getSelection();
len = s.toString().length;
s.modify('extend', 'backward', 'character');
if (len < s.toString().length) {
    // It's not at the beginning of the input, restore previous selection
    s.modify('extend', 'forward', 'character');
} else {
    // It's at the end, you can move to the previous input
}

私はこのSOの答えからこのアイデアを得ました:https//stackoverflow.com/a/24247942


3

次のように、要素チェックを逆にして、サポートされている要素だけを含めることはできません。

if (deviceIsIOS &&
    targetElement.setSelectionRange &&
    (
        targetElement.type === 'text' ||
        targetElement.type === 'search' ||
        targetElement.type === 'password' ||
        targetElement.type === 'url' ||
        targetElement.type === 'tel'
    )
) {

これの代わりに:

if (deviceIsIOS && 
    targetElement.setSelectionRange && 
    targetElement.type.indexOf('date') !== 0 && 
    targetElement.type !== 'time' && 
    targetElement.type !== 'month'
) {

1

このタイプのフォームフィールドの非推奨イベントの問題は依然として関連している可能性がありますが、私が見る限り、この種のフィールドは通常どおり「変更」イベントでリッスンできます。

このタイプのフィールドのイベントの問題に対する回答を探しているときにこの記事にたどり着きましたが、テストしていると、前述の「変更」イベントに頼ることができることがわかりました。


1

このエラーはangularjsのWebサイトで受け取りました。

入力にカスタムデータ属性を作成し、ng-blur($ eventを使用)も使用していました。

コールバックが呼び出されたとき、次のように「data-id」値にアクセスしようとしていました。

var id = $event.target.attributes["data-id"]

そしてそれはこのようになっているはずです:

var id = $event.target.attributes["data-id"].value

このエラーについてはどこにもあまりないようですので、ここに残しておきます。



0

Failed to read the 'selectionStart' property from 'HTMLInputElement': The input element's type ('number') does not support selection.次のように解きます。

var checkFocus = false;
var originalValue = "";
$(document).ready(function() {
  $("input").focus(function() {
    var that = this;
    if ($('#' + $(this).context.id).attr("type") == "text") {
      setTimeout(function() {
        if (that.selectionStart != null || that.selectionEnd != null) {
          that.selectionStart = that.selectionEnd = 10000;
        }
      }, 0);
    } else if ($('#' + $(this).context.id).attr("type") == "number") {
      if (checkFocus) {
        moveCursorToEnd($('#' + $(this).context.id), $(this).context.id);
        checkValue($('#' + $(this).context.id))
        checkFocus = false;
      } else {
        $('#' + $(this).context.id).blur();
      }
    }
  });
});

function FocusTextBox(id) {
  checkFocus = true;
  document.getElementById(id).focus();
}

function checkValue(input) {
  if ($(input).val() == originalValue || $(input).val() == "") {
    $(input).val(originalValue)
  }
}

function moveCursorToEnd(input, id) {
  originalValue = input.val();
  input.val('');
  document.getElementById(id).focus();
  return originalValue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<button onclick="FocusTextBox('textid')">
   <input id="textid" type="number" value="1234" > 
</button>


0

Chromeのデバイステストモードを使用している場合は、Angularでこれに関する誤検知に注意してください。

したがって、これは明らかにChromeであり、実際のiPhoneではありません-それでも、_platform.IOStrueを返し、その後エラーが発生するため、エラーが発生しますsetSelectionRangeその後失敗するます。

これはAngularですが、他のフレームワーク/環境にも同様の問題が存在する可能性があります。

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.