LoginSignup
9
10

More than 5 years have passed since last update.

[JS] Tabキーによる移動を禁止してTabを入力する。

Last updated at Posted at 2018-01-10

Update

  • 2018/01/10 14:59
    @hoo-chan さんにご提示頂いたコードを元に再構成。
    コードは解説が要らないくらいシンプル&スマートに。
    元記事は「出来の悪い元記事」として残します。

やりたいこと

  • テキストエリアやテキストボックスで、タブを入力したい。

スニペット

javascript

// element: Tabを入力できるようにしたい要素
element.addEventListener("keydown", input_tab);

function input_tab(event) {
    if (event.key === "Tab") {
        // デフォルト動作停止
        event.preventDefault();
        //  Tabを挿入。範囲指定時は置換。
        var TAB = "\t";
        var value = this.value;
        var sPos = this.selectionStart;
        var ePos = this.selectionEnd;
        var result = value.slice(0, sPos) + TAB + value.slice(ePos);
        var cPos = sPos + TAB.length;
        this.value = result;
        this.setSelectionRange(cPos, cPos);
    }
}

tabの挿入には setRangeText() を使うと更に簡単に書けますが、現状IE/Edgeが未対応であるため、今回は使用しない方法で記載します。

サンプル

sample.html
<html>
    <head>
    </head>
    <body>
        ▼タブで移動<br>
        <textarea rows=3 cols=40></textarea><br>
        <input type=text>
        <input type=password>
        <br>
        <br>
        ▼タブ入力可(タブでの移動禁止)<br>
        <textarea rows=3 cols=40 class="tab_input"></textarea><br>
        <input type=text     class="tab_input">
        <input type=password class="tab_input">

        <script>
            // Tabを入力できるようにしたい要素
            var elements = document.getElementsByClassName("tab_input");
            for ( var i = 0; i < elements.length; i++ ){
                elements[i].addEventListener("keydown", input_tab);
            }

            function input_tab(event) {
                if (event.key === "Tab") {
                    // デフォルト動作停止
                    event.preventDefault();
                    //  タブを挿入。範囲指定時は置換。
                    var TAB = "\t";
                    var value = this.value;
                    var sPos = this.selectionStart;
                    var ePos = this.selectionEnd;
                    var result = value.slice(0, sPos) + TAB + value.slice(ePos);
                    var cPos = sPos + TAB.length;
                    this.value = result;
                    this.setSelectionRange(cPos, cPos);
                }
            }
        </script>
    </body>
</html>

出来の悪い元記事

スニペット

javascript
function tab_input(element){
    //  フォーカスイン
    element.addEventListener("focus", function(event) {
        //  Tabキーの挙動をフォーカス移動ではなくタブ入力にする。
        window.document.onkeydown = function(event){
            // 9 = Tab
            if(event.keyCode === 9) {
                // デフォルト動作停止
                event.preventDefault();

                //  Tabを挿入。範囲指定時は置換。
                var obj  = event.target;        // オブジェクト取得
                var sPos = obj.selectionStart;  // 入力(選択)開始位置
                var ePos = obj.selectionEnd;    // 入力(選択)終了位置
                var result  = obj.value.substr(0, sPos) + "\t" + obj.value.substr(ePos);
                obj.value   =   result;

                // 入力したタブの後ろを選択。
                var cPos    =   sPos + "\t".length;
                obj.setSelectionRange(cPos, cPos);
            }
        };
    },false);

    //  フォーカスアウト
    element.addEventListener("blur", function(event) {
        // デフォルト動作を行うように再設定
        window.document.onkeydown = function(event){
            return true;
        };
    },false);
}

簡単に解説

  • まず、Tabキーによるコントロールの移動を禁止する。
    window.document.onkeydown イベントの処理でタブキーが押された時に event.preventDefault(); を実行して、デフォルト動作をしないよう設定する。
  • だがそれだけでは影響範囲が「ページ上の全てのコントロール」になってしまう。
    対象となるコントロールを限定するため以下のようにする。
    • 対象コントロールにフォーカスインしたら window.document.onkeydown のイベント処理を登録。
    • 対象コントロールからフォーカスアウトしたらイベント処理を解放。
  • Tabを入力する処理については特記事項なし。

サンプル

sample.html
<html>
    <head>
    </head>
    <body>
        ▼タブで移動<br>
        <textarea rows=3 cols=40></textarea><br>
        <input type=text>
        <input type=password>
        <br>
        <br>
        ▼タブ入力可(タブでの移動禁止)<br>
        <textarea rows=3 cols=40 class="tab_input"></textarea><br>
        <input type=text     class="tab_input">
        <input type=password class="tab_input">

        <script>
            //  "tab_input"クラスが設定されているコントロールを対象として設定
            let elements = document.getElementsByClassName("tab_input");
            for( let element of elements ){
                tab_input(element);
            }

            function tab_input(element){
                //  フォーカスイン
                element.addEventListener("focus", function(event) {
                    //  タブキーの挙動をフォーカス移動ではなくタブ入力にする。
                    window.document.onkeydown = function(event){
                        // 9 = Tab
                        if(event.keyCode === 9) {
                            // デフォルト動作停止
                            event.preventDefault();

                            //  タブを挿入。範囲指定時は置換。
                            var obj  = event.target;        // オブジェクト取得
                            var sPos = obj.selectionStart;  // 入力(選択)開始位置
                            var ePos = obj.selectionEnd;    // 入力(選択)終了位置
                            var result  = obj.value.substr(0, sPos) + "\t" + obj.value.substr(ePos);
                            obj.value   =   result;

                            // 入力したタブの後ろを選択。
                            var cPos    =   sPos + "\t".length;
                            obj.setSelectionRange(cPos, cPos);
                        }
                    };
                },false);

                //  フォーカスアウト
                element.addEventListener("blur", function(event) {
                    // デフォルト動作を行うように再設定
                    window.document.onkeydown = function(event){
                        return true;
                    };
                },false);
            }
        </script>
    </body>
</html>
9
10
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10