【jQuery】イベントオブジェクト ー親要素で発火するイベントを特定の子孫では解除したいー
こんにちは、マリンです。
今回はJSでのイベントを発火させる要素の特定です。
親要素で指定するが、特定の子孫要素では実行してほしくない。
そんな時どのように指定すればよいでしょうか?
:not
とか調べてみたのですが、
子孫要素でのやり方がイマイチよくわからず。。。
そこで今回はイベントオブジェクトを使ってこれを実装しました。
もっと簡単に実装できる、
セレクタとか、便利なメソッドとか、
皆様ぜひ教えてください。
概要
table
の概要を記述したtr
をクリックした時、詳細の列が表示されるようにする。tr
の中には承認ボタンがある。親の
tr
にイベントを付けているので、子要素のボタンのクリックでもshow
hide
が実行されてしまう。
以上のことから、子要素のボタンだけクリックイベントを外したいわけです。
最初は:not
などを使って特定しようとしたのですが、
うまくボタンだけを取ることが出きませんでした。
そこで、イベントオブジェクトを使ってみました。
詳細
サンプルコード
まずは解説に使うサンプルコードを記載しておきます。
<form action="sample/create" method="post"> <table class="table"> <tr id="sample-tr"> <td>Name: Yamada Hanako</td> <td>Age: 20</td> <td><button name="approve" type="submit" value="approve">承認</button></td> </tr> <tr id="sample-hidden-tr style="display: none"> <td>Address: Tokyo Minato-Ku</td> <td>Email: sample@example.com</td> <td>Password: password</td> </tr> </table> </form>
上段のtr
が表示されている行。
下段のtr
が非表示部分で、上段をクリックすると表示されます。
しかし、上段3つ目のカラムにあるボタンだけはクリックの対象外にします。
以下が今回のCoffeeです。
$('#sample-tr').on 'click', (e)-> target = $(e.target) if target[0].nodeName == "BUTTON" return if $(@).hasClass('show') $(@).removeClass('show') $('#sample-hidden-tr').hide() else $(@).addClass('show') $('#sample-hidden-tr').show() retrun
詳細解説
HTMLは省略します。
$('#sample-tr').on 'click', (e)-> target = $(e.target)
まずは最初の2行です。
1行目は上段tr
へのクリックイベントで、引数e
がイベントオブジェクトです。
2行目はイベントが発生したjQueryオブジェクトを変数に入れています。
target
の中身は以下のようになっています。
target: jQuery.fn.init(1) 0: button accessKey: "" assignedSlot: null attributeStyleMap: StylePropertyMap {size: 0} attributes: NamedNodeMap {0: type, 1: name, type: type, name: name, length: 2} autocapitalize: "" . . . nextElementSibling: null nextSibling: null nodeName: "BUTTON" nodeType: 1 . . .
次の2行です。
if target[0].nodeName == "BUTTON" return
if文でイベントが発生した要素がボタンだったら何もしないで終了させています。
if文の内容と、先ほどのtarget
の中身を見比べてみてください。
target: jQuery.fn.init(1) 0: button accessKey: "" . . . nodeName: "BUTTON" . . .
target[0].nodeName == "BUTTON"
イベントオブジェクトのtarget
。
その中に入っているキー[0]でDOM要素を取得し、
さらにその中からnodeName
プロパティで対象となった要素名を取得します。
そして、要素名が"BUTTON"だったら何もせずreturn
というわけです。
ちなみに、最初にe.target
を変数targetに入れましたが、
今回のような単純なコードでしたら入れる必要もないと思います。
if $(e.target)[0].nodeName == "BUTTON"
でいけます。
個人的に見やすかっただけです、、、
まとめ
今まで苦手意識のあったイベントオブジェクトやjQueryオブジェクトでしたが、
一度じっくり眺めてみるとなんとなく解ってきました。
やはりぱっと見よくわからない!と思っても、
テンパることなく冷静に眺めていることって必要ですね。
余談ですが、今回のことで
なぜ$()
を使ってjQueryオブジェクトにするのか?
ということが今更ながら理解できました。
根本が解っていないと理解が遅くなる一方ですね。。。
まだまだ奥が深いと思うので、これを機にちゃんと勉強してみます。