クリックイベントの中身はifで囲め

佐野

佐野 2016年1月13日

開けすぎまして、おめでとう。
お正月はとっくに過ぎてしまいましたが、今年もがんばります。

さて、今回の話題はjQueryでクリックイベントを作成する際の注意点を言います。

クリックイベントの中身はifで囲め

jQueryのクリックイベントと言えば、「.click()」ですが、
以下に「.click()」を使用した、簡単なトグルボックスを作って見ました。

サンプル1

※ボタンのCSSは略しています。

<script>
$(document).ready(function(){
    $(".toggle_button1").click(function(){
        $(this).next(".toggle_zone").slideToggle(500);
    });
});
</script>

<div class="toggle_button1">押してね!</div>
<div class="toggle_zone" style="display:none;">
あいうえお
かきくけこ
さしすせそ
たちつてと
なにぬねの
はひふへほ
</div>

押してね!

以上の「押してね!」ボタンをクリックすると、
ボタンの次(.next())にある「.toggle_zone」というクラスの要素を
「.slideToggle(500)」で開閉しているという単純なものです。

ですが、このボタンを連打してみてください。
ボタンを押すのをやめても、テキストがパカパカと開閉する動作を繰り返すはずです。

これは、「.toggle_zone」という要素のキュー(実行待ちの命令)が、
消化される前にボタンが押され、蓄積されているからなのです。

じつは、上記サンプルコードでは省略していますが、

console.log($(this).next(".toggle_zone").queue().length);

このコードも、クリックイベントの部分に埋め込んでいます。

つまり、ボタンをクリックする度に、ブラウザの検証モードに、
その時点での「.toggle_zone」のキューの数が出力されます。
その際に「.queue()」を使用していますが、これは対象要素に蓄積されたキューを、
配列に格納した状態で返し、配列の中にはオブジェクトが格納されています。
これ自体が返す値は数値ではないため、「.length」で数を計っています。

これを使った、具体的な開閉現象を解消する方法は、以下のとおりです。

<script>
$(document).ready(function(){
    $(".toggle_button1").click(function(){
        if($(this).next(".toggle_zone").queue().length <= 0){
            $(this).next(".toggle_zone").slideToggle(500);
        }
    });
});
</script>

「.click()」の中身をif文で囲み、キューの数が0以下である場合に実行するようにするだけです。

サンプル2

※キューの数を読み取り、クリックイベントを制御しています。

押してね!

これで連打しても勝手に開閉しなくなりました。

今回は、トグルボックスの開閉で試しましたが、
これはクリックイベント全体に対して、該当する事でもあります。
今回は単純に同じメソッドで開閉を繰り返す「.slideToggle()」を使用しましたが、
もしこれが、要素を追加・削除するものであった場合、
あらぬ不具合を起こす可能性も考えられます。
たとえば、目的ではない要素を削除したり、変なところに要素が残ったり、
無数に要素を増やし続けたり、JavaScript上でエラーを発生させる可能性も考えられます。
そうなるとカッコ悪いだけでなく、ブラウザクラッシュにもつながります。

それに、訪問者の人も、必ずしもアニメーションが完了するまで
クリックを待ってくれるとは限りませんし、
製作者の意図せぬ動作を起こさないためにも、
自分自身でも乱暴な操作を行ってみて、変な動作を起こさないかどうかを検証し、
今回のように、クリックイベントでの制御は必ず行ったほうがよいでしょう。