2016年12月5日月曜日

jQuery:EnterキーでSubmitしない(意図しない送信の防止、Enterキーをすべて禁止しない)

なんかわけわからんタイトルになりましたが、要はEnterキーを押したとき、意図しないタイミングで送信されるのを防ぎたかったのです。
この<意図しないタイミング>というのがミソで、思い通りにしようと思ったら案外考えることがあったので記録しておきます。

【目的】
・テキストボックスや、カーソルが画面外にあるときEnterキーを押したときなど  操作者が意図していないところでSubmitされるのを防ぐ

【条件】
・Enterキーをすべて無効にはしない
 - テキストエリアでEnterキーが無効になってしまう
 - 本当にEnterキーで送信したいとき(ボタンにフォーカスを明示的に当ててsubmitしたい場合)困る
・typeをsubmitからbuttonに変更しての対応はしない
 - 随所にある「input type="submit"」を「input type="button" onclick="submit();"」に書き換えたくない

【前提と方針】
・入力フォームがフォーカスされていないときでもEnterキーが押されると画面はsubmitする
・この場合、画面で一番最初に出現するsubmitボタンが発動
・しかしながら、フォーカスされているフォームを取得してみると、typeもtagも「undefined」となる

そこで、
・エンターキーは特定の種類のフォームにフォーカスされたときに押された場合を除いてすべて無効にする
・特定の種類とは、button, submit, テキストエリアとする
という方向で実装することにしました。

→エンターキーを押されたときフォーカスされているフォームのtypeとフォームのtag(タグ種別)を取得して
 ・typeがbuttonまたはsubmitであればなにもしないでその動作に任せる
 ・tagがtextareaであればなにもしないで動作に任せる
 ・type・tagがそれ以外であれば、return falseしてそれ以上動作しないようにする

javascriptでもjqueryでもいいですがここはjqueryで...
【実装】

// キー押下のイベント
$("body").keydown( function ( e ){
    // Enterキーを押下されたとき
    if((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)){
        // フォーカスされてるフォームのIDとtypeを取得
        var id = $(':focus').attr("id");
        var type = $(':focus').attr("type");

        // textareaを除外するためにフォーカスされているtagの種類を取得
        var tag = $("#"+id).prop("tagName");
        var tag = (tag !== undefined) ? tag.toLowerCase() : "";

        // typeがbutton・submit、またはtagがtextarea以外はEnterを無効
        if((type !== 'button' && type !== 'submit' && tag !== "textarea")) {
            alert("Enterキーが押されました。\nこの項目でEnterは無効となっています"); //debugのためにアラート出してただけ
            return false;
        }
    }
});