2017-01-20

tobijibu

w2uiのグリッドでテンキー入力を可能にする

w2uiのグリッド(w2grid)ではセルにeditable属性が指定されていれば、セルのダブルクリックで入力モードに変化します。また、セル選択状態であれば、キーを入力するだけで自動的に入力モードになり、データを入力することができます。

しかし、テンキーからデータを入力する場合、入力モードになりません。テンキー入力もQWERTYからと同様に入力すると入力モードに変化させるにはどうすればよいでしょうか。今回はその対処方法を説明します。

なお、w2ui-1.4.3.jsではテンキーでの入力はできませんでしたが、w2ui-1.5.rc1.jsではテンキーでの入力が可能でした。w2ui-1.5.rc1.jsを利用している場合は対応不要です。

処理を確認

キーの入力を判定し、編集モードに以降している処理を探したところ、w2ui-1.4.3.jsでは、ll.4185-4195で判定しているようです。その部分を抜き出したのが下記のソースです。

var tmp = [187, 189, 32]; // =-spacebar
for (var i=48; i<=90; i++) tmp.push(i); // 0-9,a-z,A-Z
if (tmp.indexOf(key) != -1 && !event.ctrlKey && !event.metaKey && !cancel) {
    if (columns.length == 0) columns.push(0);
    var tmp = String.fromCharCode(key);
    if (key == 187) tmp = '=';
    if (key == 189) tmp = '-';
    if (!shiftKey)  tmp = tmp.toLowerCase();
    obj.editField(recid, columns[0], tmp, event);
    cancel = true;
}

keyには押されたキーのコードが入っています。ですので、3行目のif (tmp.indexOf(key)~) {で押されたキーがtmpに定義されているかを判定しているということになります。

では、tmpには何が入っているでしょうか。1行目で[187, 189, 32]を格納しており、その後に"48~90"までの値を追加(push)しています。

テンキーのキーコードは0~996~105*106+107-109.110/111がそれぞれ割り当てられています。つまり、tmpにテンキーのキーコードが含まれていないので、反応しなかったということになります。

tmpにテンキーのキーコードを追加してしまいましょう。
w2ui-1.4.3.jsではll.4186-4187間に挿入

var tmp = [187, 189, 32]; // =-spacebar
for (var i=48; i<=90; i++) tmp.push(i); // 0-9,a-z,A-Z
for (var i=96; i<=111; i++) tmp.push(i); // numeric keypad 0-9
if (tmp.indexOf(key) != -1 && !event.ctrlKey && !event.metaKey && !cancel) {
    if (columns.length == 0) columns.push(0);

正しいキーコードを設定

これで完了と思いきや、実際に試してみると正常に動きません。テンキーで"1"を入力すると確かに入力モードに変化して、文字が入力されますが、表示される文字はaです。続けて数字を入力すると正しい数字が入力されますが、セルを移動して入力すると、1文字目は必ずその数字に対応したa~oの文字が表示されてしまいます。何故でしょうか。

実は5行目のvar tmp = String.fromCharCode(key);が原因です。テンキーのキーコードは96~111の範囲です。その数値にString.fromCharCodeを使うと、文字コードに対応した文字が返ってきます。例えば"1"を打つとキーコード97が渡り、String.fromCharCode(97)となりますので、結果は"a"になります。
String.fromCharCode(97)が"a"になる理由はこちらの一覧ご覧ください。

そこで、数字についてはString.fromCharCodeの前で処理します。
w2ui-1.4.3.jsではll.4188-4189間に挿入

if (tmp.indexOf(key) != -1 && !event.ctrlKey && !event.metaKey && !cancel) {
    if (columns.length == 0) columns.push(0);
    if (key >= 96 && key <= 105) key -= 48; // numeric keypad 0-9
    var tmp = String.fromCharCode(key);

続いて数字以外の文字に対しては個別に対応します。
w2ui-1.4.3.jsではll.4191-4192間に挿入

if (key == 187) tmp = '=';
if (key == 189) tmp = '-';
if (key == 106) tmp = '*'; // numeric keypad *
if (key == 107) tmp = '+'; // numeric keypad +
if (key == 109) tmp = '-'; // numeric keypad -
if (key == 110) tmp = '.'; // numeric keypad .
if (key == 111) tmp = '/'; // numeric keypad /
if (!shiftKey)  tmp = tmp.toLowerCase();

完了

最終的に下記のようになります。この状態で試すとテンキーのどのキーを押しても正しく入力出来るようになっています。

var tmp = [187, 189, 32]; // =-spacebar
for (var i=48; i<=90; i++) tmp.push(i); // 0-9,a-z,A-Z
for (var i=96; i<=111; i++) tmp.push(i); // numeric keypad 0-9
if (tmp.indexOf(key) != -1 && !event.ctrlKey && !event.metaKey && !cancel) {
    if (columns.length == 0) columns.push(0);
    if (key >= 96 && key <= 105) key -= 48; // numeric keypad 0-9
    var tmp = String.fromCharCode(key);
    if (key == 187) tmp = '=';
    if (key == 189) tmp = '-';
    if (key == 106) tmp = '*'; // numeric keypad *
    if (key == 107) tmp = '+'; // numeric keypad +
    if (key == 109) tmp = '-'; // numeric keypad -
    if (key == 110) tmp = '.'; // numeric keypad .
    if (key == 111) tmp = '/'; // numeric keypad /
    if (!shiftKey)  tmp = tmp.toLowerCase();
    obj.editField(recid, columns[0], tmp, event);
    cancel = true;
}

冒頭でも書いたとおり、w2ui-1.5.rc1.jsではこの問題は解消されています。w2ui-1.4.3.jsを利用している場合はお試してみてください。

今回説明で利用したソースはこちらにあります。

参考サイト

文字コードの一覧は下記サイトにまとめられています。
http://www.w3ii.com/ja/charsets/ref_utf_basic_latin.html

キーコード一覧
http://www.programming-magic.com/file/20080205232140/keycode_table.html