トップ > Tech > JavaScript > テキストボックスに英数字しか入力できないようにする

テキストボックスに英数字しか入力できないようにする

全体

まずはじめに全体のコードを示しておく。 グローバル変数にするのははばかられるので、FormUtil というクラスの静的メソッドとして定義している。細部に関してはこれ以下で示しているので、参考にされたい。

// FormUtil クラス
var FormUtil = function()
{
}

// 制約をかけるクラス名と許可する文字の正規表現の対
FormUtil.RestrictionTable = {
  "numeric" : "\\d", 
  "alphanumeric" : "\\w"
  };

// RestrictionTable のキーに一致するクラス名をもった textbox に
// 制約用のインベントハンドラを関連づける
FormUtil.EnableTextBoxRestriction = function()
{
  //一致するクラス名を見つけるメソッド
  var findClass = function(obj)
  {
    for (var key in FormUtil.RestrictionTable) {
      var regexp = new RegExp("\\b" + key + "\\b", ""); // 単語一致
      if (obj.className.match(regexp))
      {
        return key;
      }
    }
    return null;
  }

  var inputs = document.getElementsByTagName("input");
  for (var i = 0; i < inputs.length; i++)
  {
    if (inputs[i].type == "text")
    {
      var key = findClass(inputs[i]); // クラス名検索
      if (key != null)
      {
        // 内部 で key(k) を保持するため、クロージャでかこう
        var closure = function(k)
        {
          // onkeypress イベントハンドラ
          //(e はイベント引数 Firefox のみ)
          inputs[i].onkeypress = function(e)
          {
            e = e || window.event;
            var c = FormUtil.GetPressedChar(e);
            var regexp = new RegExp(FormUtil.RestrictionTable[k], "");
            return (c == null || c.match(regexp) != null);
          };
        };
        // 呼び出し
        closure(key);
        // IME 無効(IE, Firefox3〜)
        inputs[i].style.imeMode = "disabled"; 
      }
    }
  }
}

// event を渡して、押されたキーの文字を取得する
FormUtil.GetPressedChar = function(event)
{
  var code = 0;
  if (event.charCode === 0)
  {
    // Firefox, Safari control code
    code = 0;
  }
  else if (!event.keyCode && event.charCode)
  {
    // Firefox
    code = event.charCode;
  }
  else if (event.keyCode && !event.charCode)
  {
    // IE
    code = event.keyCode;
  }
  else if (event.keyCode == event.charCode)
  {
    // Safari
    code = event.keyCode;
  }
  
  if (32 <= code && code <= 126)
  {
    // ASCII文字の範囲内
    return String.fromCharCode(code);
  }
  else
  {
    return null;
  }
}

詳解

どの言語でも大差はないのだが、テキストボックスへの入力を制限するとき、意識しなければならないのは、入力方法である。一般には 3 つの入力方法があり、それぞれの対応は下記のようになる。

  1. キー(文字)入力
    →onkeypress で許可文字以外はキャンセルする
  2. IME での日本語入力
    →IME を無効にする
  3. コピー&ペーストでの入力
    →フォーカスアウトしたとき(onchange)に内容を検証する

最低限フォーカスアウトするタイミングでチェックしてやればいいが、入力してから文句を言われるより元から入力できないほうがいいと思うので、1, 2 を実装することになる。3 は JavaScript では検出できないので onchange でのチェックになる。

onkeypress で押されたキーを判別して、入力をキャンセルする

テキストボックスで押されたキーを判別するには onkeypress イベントを利用する。これ下記のような html とイベントハンドラを書けばよい。

<input type="text" name="name" onkeypress="onNameKeyPress()"/>
onNameKeyPress()
{
  var code = window.event.keyCode;
  // code でキーを判断
}

という具合に keyCode を取得すればいい...はずだが、これは IE だけの話。Firefox ではこの window.event(直前のイベントの情報を取得できるオブジェクト)のスコープが IE と違うらしく、このままでは取得できない。これは html の側から event を渡してやるとうまくいく。

<input type="text" name="name" onkeypress="onNameKeyPress(window.event)"/>
onNameKeyPress(event)
{
  var code = event.keyCode;
  // code でキーを判断
}

ただし、html 側にイベントハンドラを書きたくない場合(javascript でイベントをアタッチしたい場合)は、これがうまくいかない。この場合は、ちょっとしたハックが必要だ。

onBodyLoad() // body の onload のイベントハンドラ
{
  inputs[i].onkeypress = onNameKeyPress; // イベントハンドラのアタッチ
}
onNameKeyPress(e)
{
  var e = e || window.event;
  var code = e.keyCode;
  // code でキーを判断
}

あるいは無名関数を使って

onBodyLoad() // body の onload のイベントハンドラ
{
  inputs[i].onkeypress = function(e)
  {
    var e = e || window.event;
    var code = e.keyCode;
    // code でキーを判断
  };
}

Firefox ではイベントが呼ばれるときの第 1 引数にイベント引数が渡される。onkeypress ではこの引数には keyCode と charCode が格納されており、キーの判別に利用できる。IE では null になるため、e || window.event によって、Firefox の場合は引数が、IE の場合は event が e に設定され、keyCode の取得が可能になる。

keyCode あるいは charCode はクセがあって、ブラウザごとにとんでくる値が違う。そのあたりを吸収して、押されたキーの文字を返してくれるメソッドが こちら で紹介されているので、これを利用させていただく。これが下記の部分である。

// event を渡して、押されたキーの文字を取得する
FormUtil.GetPressedChar = function(event)
{
  var code = 0;
  if (event.charCode === 0)
  {
    // Firefox, Safari control code
    code = 0;
  }
  else if (!event.keyCode && event.charCode)
  {
    // Firefox
    code = event.charCode;
  }
  else if (event.keyCode && !event.charCode)
  {
    // IE
    code = event.keyCode;
  }
  else if (event.keyCode == event.charCode)
  {
    // Safari
    code = event.keyCode;
  }
  
  if (32 <= code && code <= 126)
  {
    // ASCII文字の範囲内
    return String.fromCharCode(code);
  }
  else
  {
    return null;
  }
}

ここまでで押されたキーの判別が可能だ。

onNameKeyPress(e)
{
  var e = e || window.event;
  var code = e.keyCode;
  var char = FormUtil.GetPressedChar(code);
  return (c == null || char.match(/\d/) != null) // 数字のみ
  // return (c == null || char.match(/\d/) != null) // 英数字のみ
}

onkeypress で false を返すと入力がキャンセル される。 GetPressedChar 関数は ASCII 文字でなければ null を返すので、もし null の場合は制御文字(DEL や BS など)だと思われるので true を返す。 ASCII 文字の場合は正規表現を使って、入力を許可したい文字なら true を返すように書けばよい。

IME を無効にする

CSS で ime-mode が定義されており、元々は IE の独自仕様だったが、Firefox も ver.3 からサポートするようになったので、ある程度の制御が可能だ。CSS で ime-mode を指定するには下記のように記述する。

ime-mode:disabled;

取り得る値は下表の通り。

auto動作を指定しない(デフォルト)
active日本語入力モード
inactive英数字入力モード
disabled無効

active, inactive はテキストボックスにフォーカスしたときの初期状態がそれになる。ただし、モードの切り替えは可能なので、完全に無効にしたい場合は disabled を使用する。

JavaScript から制御する場合は、style.imeMode を使用する。

element.style.imeMode = "disabled";

履歴

  • 2009.7.31 作成
(2010/06/28 11:01:58)
45806
プロフィール

Kenz Yamada(山田研二)。1984年生。大阪。ちょっとずつ好きなプログラム作ってます。 好きなものはカメラと旅行。ガジェットや身の回り、ちょっとこだわります。 詳しくは Web mixi で。

Bookmark and Share