読者です 読者をやめる 読者になる 読者になる

俺でもできるもんな

独立系SI企業から完全異業種のベンチャー企業に転職、社内のITインフラを整えるべく颯爽と登場した自称天才プログラマー俺のハートフルブログ

jQuery 「↓」、「↑」キーでinputのフォーカスを移動させる

何がやりたいか

縦にテキストボックスが並んでいるフォームがあるとします

<table>
    <tr>
      <td>
        <input type="text" class="sample-input" id="sample64">
      </td>
    <tr>
    <tr>
      <td>
        <input type="text" class="sample-input" id="sample256">
      </td>
    <tr>
    <tr>
      <td>
        <input type="text" class="sample-input" id="sample512">
      </td>
    <tr>
    <tr>
      <td>
        <input type="text" class="sample-input" id="sample128">
      </td>
    <tr>
</table>

イメージはこんな感じ
スクリーンショット 2017-05-12 10.41.55.png

この各input間を「↓」、「↑」キーで移動できるようにしたいのです。
(実際には左右にもinputがあり、tabでは移動できない画面です)

各機能

「↓」、「↑」のイベント取得

keydownイベントそ取得してなんのキーが押されたかをkeyCodeを使って調べるだけです。
keyCodeは以下の通り。

keyCode キー
37
38
39
40

ソースはこんな感じ。

// 対象フォーム群のキーダウンイベントを取得
$(".sample-input").on("keydown", function(e) {
    if(e.keyCode === 40) {
        // 「↓」キーが押されました
    }else if(e.keyCode === 38) {
        // 「↑」キーが押されました
    }
});

フォーカスの移動

.focus()で指定した要素にフォーカスを移動できる。

$("#id").focus();

問題発生

ちょっと待て

今回のフロントの実装では、連番ではなくDBのID(以後「d_id」と呼ぶ)をinputのidに付与していたので

<input type="text" class="sample-input" id="sample64←ココ!">

id+1とかで次を指定できない

強引に問題解決

一番良かったのは、idの前方一致で$(this)の次の要素が取得すること(感じ取ってくださいw)。
でもちょっと実装が思い浮かばなかったので強引に解決! そうだ、d_idリストを用意してしまおう

// d_idリストを用意
// d_id_list = [64, 256, 512, 128]
// (今回はPHPで実装しています)
var d_id_list = [];

<?php 
    $set = '';
    foreach ($array as $value) {
        if($set){
            $set .= ',';
        }
        $set .= $value;
    }
    echo "d_id_list = [{$set}];";
?>

完成

全てを合体させて完成したのが以下のソース

// d_idリストを用意
// d_id_list = [64, 256, 512, 128]
// (今回はPHPで実装しています)
var d_id_list = [];

<?php 
    $set = '';
    foreach ($array as $value) {
        if($set){
            $set .= ',';
        }
        $set .= $value;
    }
    echo "d_id_list = [{$set}];";
?>



// 対象フォーム群のキーダウンイベントを取得
$(".sample-input").on("keydown", function(e) {

    // キーダウンイベントを検知した要素のidからd_idを取得
    // その値とd_idリストを使用してd_idリストのindexを取得する
    d_id_list_index = d_id_list.indexOf(Number($(this).attr("id").replace("sample","")));

        // 「↓」キーが押された && 最終要素ではない
    if(e.keyCode === 40 && d_id_list_index < d_id_list.length-1) {

        // d_idリストと先ほど取得したd_idリストでの自分のindexを使用して1つ下のinputへfocusを移す
        $("#sample"+d_id_list[d_id_list_index+1]).focus();

    // 「↑」キーが押された && 最初の要素ではない
    }else if(e.keyCode === 38 && d_id_list_index > 0) {

        // d_idリストと先ほど取得したd_idリストでの自分のindexを使用して1つ上のinputへfocusを移す
        $("#sample"+d_id_list[d_id_list_index-1]).focus();

    }

});

これが一番スマートではないと思います