質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

JQuery クリックイベントの挙動について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,468

SUPER_SLiNKY

score 37

現在仕事で開発中のプログラムで、下記のようなチェックボックスをクリックした際(チェックボックスがONの時)にテキストボックスを入力不可にするといったものを実装しました。

<input name="" type="checkbox" value="" id="test_chk" />
<label for="test_chk">chk1</label>
<input name="" type="text" id="test_input" disabled="disabled" />

$('#test_chk').click(function(){
 var flg=$(this).prop('checked')
    $('#test_input').prop('disabled',flg);
});

クリックの間隔をあけて行う分には問題なく動くのですが、
クリックを連打した際に、チェックOFFの時に入力不可になったりチェックONのときに入力可になったり逆転してしまいます。

職場ではIEを使っていて、自宅でも同じようにやってみたのですが連続的なクリックを行っても問題なく動作しました。

なにが原因なのでしょうか?また、どうやって回避すればいいのでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • SurferOnWww

    2017/06/17 20:16

    ASP.NET のタグが付いてますが、質問を見る限り ASP.NET と直接の関係はなさそうに見えます。関係なければ ASP.NET のタグは外していただけると幸いです。

    キャンセル

回答 2

checkベストアンサー

+2

 checked 属性

まず、気になったのはHTMLの部分。

<input name="" type="checkbox" value="" id="test_chk" />
<label for="test_chk">chk1</label>
<input name="" type="text" id="test_input" disabled="disabled" />

チェックボックスにチェックすると #test_input が disabled 状態になりますが、既に disabled 状態になっているので初めの一回のクリックでは何も発生しません
チェックボックスには初期状態で checked 状態にしておくと良いと思います。

 考えられる原因

直接的な原因は分かりませんが、考えられる可能性は2通りあります。

  1. チェックボックスの状態遷移だけ発生し、clickイベントハンドラが実行されなかった
  2. clickイベントハンドラだけ実行され、チェックボックスの状態遷移が発生しなかった

clickイベントハンドラの方が後で発生する為、1. の可能性が高いと思われます。
ご掲示のコードは途中経過のclickイベントハンドラが発火しなかったとしても、最後のclickイベントハンドラが実行されれば期待撮りの動作するはずなので、少なくとも最後のclickイベントハンドラは発生していないと想像できます。

 対策コード

対策は2通りあります。

  1. 素のJavaScriptでコードを書き、clickイベントハンドラの処理時間を短くする(高速化による処理堕ち防止)
  2. clickイベントハンドラ処理中はclickされても何も実行しないようにclickイベントをロックする

両方の対策を施すと、次のように書けます。

<input name="" type="checkbox" value="" id="test_chk" />
<label for="test_chk">chk1</label>
<input name="" type="text" id="test_input" disabled="disabled" /><script>
'use strict';
document.getElementById('test_chk').addEventListener('click', {
  input: document.getElementById('test_input'),
  handleEvent: function (event) {
    var checkbox = event.target;
    checkbox.disabled = true;
    this.input.disabled = checkbox.checked;
    checkbox.disabled = false;
  }
}, false);
</script>

ただ、checkbox変数初期化が余計に発生しているので、checkbox.disabled = true; によるclickイベントロックが発生するまでの間にクリックされる可能性を考慮すると、ロックせずに1行でコードを実行した方がいい可能性もあるかもしれません。

document.getElementById('test_chk').addEventListener('click', {
  input: document.getElementById('test_input'),
  handleEvent: function (event) {
    this.input.disabled = event.target.checked;
  }
}, false);

これ以上、高速化しようとするなら event.targetthis.event のプロパティ参照コストをなくす為に変数やthis値にinput要素ノードを束縛する必要があります。

document.getElementById('test_chk').addEventListener('click', function (event) {
  this.disabled = true;
  document.getElementById('test_input').disabled = this.checked;
  this.disabled = false;
}.bind(document.getElementById('test_chk')), false);

#test_input はキャッシュしていないのでまだ高速化する余地がありますが、#test_chk が無効化(disabled)されるまでの処理時間としてはこれが最短のコードだと思います。
短時間で連続クリックすると、チェックボックスの遷移が行われない現象を確認できます。

Re: SUPER_SLiNKY さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/18 10:28

    ありがとうございます。
    一度試してみたいと思います

    キャンセル

  • 2017/06/20 17:31

    2日経過しましたが、試した結果はいかがでしたでしょうか。
    掲示板のログは共有資産ですので、解決法を追記する事で、他の皆さんの役に立つこともあると思います。
    https://teratail.com/help/question-tips#questionTips4-2

    キャンセル

+1

クリックイベントが発生してその処理が終わる前にクリックイベントが実行されたために意図しない動きになったのではないでしょうか?他にも方法はありますが、フラグを設置して、クリックされたらフラグをfalseに、クリックイベントが終わったらtrueに戻すというようにするとクリックイベントの発生が重複することを回避できると思います。また、チェックボックスにchecked属性を設定しておいたほうが良いと思います。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>タイトル</title>
</head>
<body>
<input name="" type="checkbox" value="" id="test_chk" checked>
<label for="test_chk">chk1
    <input name="" type="text" id="test_input" disabled="disabled">
</label>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
    var flag = true;
    $('#test_chk').click(function () {
        if (flag) {
            flag = false;
            var flg = $(this).prop("checked");
            $('#test_input').prop('disabled', flg);
            flag = true;
        } else {
            return false;
        }
    });
</script>
</body>
</html>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/18 10:28

    ありがとうございます。
    一度試してみたいと思います

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる