らばーいもっきんぐ

プログラミング等々についての覚え書き

【JavaScript】inputフォームのmaxlengthで全角文字による入力超過を制御する方法

はじめに

HTMLのinputフォームでmaxlengthを指定した場合に、半角英数字の場合は上限値を超えて入力はできないが、全角文字の場合は上限値を超えて入力できるように見えるため、これをJavaScriptで制御する方法について検討しました。

事象

Edit fiddle - JSFiddle - Code Playground

<form>
    <label>MaxLengthSample</label>
    <input type="text" maxlength=3 />
</form>

上記のようなフォームがあった場合、maxlengthのとおり入力できる文字数は3文字になる。
半角英数字の場合は3文字まで入力でき、それ以上入力してもフォームの値は変更されない。
しかし、全角で入力した場合は3文字以上の入力が可能なように見える。
全角で3文字以上入力した場合も、入力値を確定した時点で上限値を超えた部分は切り捨てられる。
また、Chromeを使用した場合はブラウザ側の機能として、何文字超過しているかの表示がされる。

Chromeの機能により何文字超過しているのかが表示された画面キャプチャ
Chromeの機能により何文字超過しているのか表示される

全角入力時でも超過部分は切り捨てられるため機能的には問題無いが、半角入力時との動作の違いが気になったり、確定を押したタイミングで超過部分が切り捨てられるのは使用感がよろしくなさそう。
そこで、全角入力時も半角入力時と同じ挙動にできないか検証してみた。

結論

結果的には半角入力時とまったく同じようには実装できなかった。
全角の場合でも上限値を超えて入力できないようにすることはできるが、表示や挙動を完璧に一致させることができなかった。
おとなしくブラウザの標準機能かライブラリなどを使用するのが吉かも。

検討案

案1(sliceメソッドで超過分を削除)

https://jsfiddle.net/em8taw0q/1/

inputタグにaddEventListenerでinputイベントを付与し、入力された文字数を取得する。
maxLengthの値を超えて入力された場合はsliceメソッドで超過分を削除してvalueに入れ直す。

<form>
    <label>MaxLengthSample</label>
    <input id="hoge" type="text" maxlength=3 />
</form>
const inputForm = document.getElementById("hoge");
const maxLength = parseInt(inputForm.getAttribute("maxLength"), 10);

inputForm.addEventListener('input', function(e) {
    const inputValue = e.target.value;
    if (inputValue.length > maxLength) {
        e.target.value = inputValue.slice(0, maxLength);
    }
});

メリット

  • 実装がシンプル

デメリット

  • 最大まで入力した状態でも、途中に文字を挿入できてしまう
  • 最大値を超えてに入力はできないが、変換候補が一瞬表示されてしまう
  • 漢字を入力する場合に、変換前の文字数でカウントされるため、文字数によっては漢字での入力ができなくなる

案2(保存した入力値で上書き)

https://jsfiddle.net/em8taw0q/

入力された文字を一時的に保存しておき、上限値を超えて入力された場合は最後に保存された文字で上書きする方法。

<form>
    <label>MaxLengthSample</label>
    <input id="hoge" type="text" maxlength=3 />
</form>
const inputForm = document.getElementById("hoge");
const maxLength = parseInt(inputForm.getAttribute("maxLength"), 10);
let prevValue = '';

inputForm.addEventListener('input', function(e) {
    const inputValue = e.target.value;
    if (inputValue.length > maxLength) {
        e.target.value = prevValue;
    } else {
        prevValue = inputValue;
    }
});

メリット

  • 最大まで入力した状態でも、途中に文字を挿入できない(半角入力時と同じ挙動)

デメリット

  • フォームが複数ある場合は、一次保存用変数の状態管理が煩雑になる
  • 最大値を超えてに入力はできないが、変換候補が一瞬表示されてしまう
  • 漢字を入力する場合に、変換前の文字数でカウントされるため、文字数によっては漢字での入力ができなくなる

まとめ

変換候補の非表示や、漢字変換時の字数制限は対応できなかった。(何かしら手がありそうだけど。。。)
基本的にはブラウザの標準機能で対応が良さそう。
そもそも、文字数超過した場合に切り捨ててしまうのはユーザーに誤解を与える可能性が高い(入力できたと思ってしまう)ので、よくある超過した場合はフォームを赤反転してメッセージを表示するとかが最善な気がします。