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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

3回答

8494閲覧

addEventListenerでセットした子要素でイベントが発火するのを防ぐには

Fushihara

総合スコア52

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2016/09/14 02:40

編集2016/09/14 02:51

以下のコードでid=koreにクリックイベントをセットします。
しかし、ボタンに表示されている画像の部分をクリックするとコールバックのe.targetがbuttonでなくimgになってしまいます。
e.currentTargetを使えばbutton要素が取得出来るのは知っているのですが、button要素を取得する方法ではなくimg要素でイベントが発生しないようにする方法を知りたいです。

ボタンの中の画像をクリックしてe.targetがimgの時と、ボタンの中の画像が無い所をクリックしてe.targetがbuttonの時で、画面の表示が微妙に異なり、e.targetがbuttonの時の表示に固定したいのです。

createEvent→initMouseEvent でイベントを作成しても挙動が違いました。

js

1document.querySelector("#kore").addEventListener("click",function(e){ 2 //e.target or e.currentTarget 3});

html

1<button id="kore"> 2 <img src="xxx"> 3</button> 4```、

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

バブリングフェーズ、キャプチャリングフェーズを強制終了

イベントの発火を防止するのは原理的に不可能だと思います。
バブリングを停止することで上位要素のバブリングフェーズにおいてイベントが発火していないかのように見せかける事は可能です。

JavaScript

1'use strict'; 2document.querySelector('#kore *').addEventListener('click', function (event) { 3 event.preventDefault(); // デフォルトアクションを抑止 4 event.stopImmediatePropagation(); // バブリングを停止 5}, true); 6 7document.getElementById('kore').addEventListener('click', function (event) { // // #kore のみ発火する 8 console.log(event.type, 'bubbling-phase', '/ target = #' + event.target.id + ' / currentTarget = #' + event.currentTarget.id); 9}, false); 10 11document.getElementById('kore').addEventListener('click', function (event) { // // #kore 以外も発火する 12 console.log(event.type, 'capturing-phase', '/ target = #' + event.target.id + ' / currentTarget = #' + event.currentTarget.id); 13}, true); 14 15addEventListener('click', function (event) { // #kore 以外も発火する 16 console.log(event.type, 'capturing-phase', '/ target = #' + event.target.id + ' / currentTarget = window'); 17}, true);

キャプチャリングフェーズまで対応するなら最上位ノードである window.addEventListener を監視するしかありません。

JavaScript

1'use strict'; 2addEventListener('click', function (event) { // #kore 以外も発火する 3 console.log(event.type, 'capturing-phase', '/ target = #' + event.target.id + ' / currentTarget = window'); 4}, true); 5 6addEventListener('click', function (event) { 7 for (var target = event.target, i = 0, elements = event.currentTarget.document.querySelectorAll('#kore *'), l = elements.length; i < l; ++i) { 8 if (target === elements[i]) { 9 event.preventDefault(); // デフォルトアクションを抑止 10 event.stopImmediatePropagation(); // キャプチャリングフェーズを強制終了 11 return; 12 } 13 } 14}, true); 15 16document.getElementById('kore').addEventListener('click', function (event) { // #kore のみ発火する 17 console.log(event.type, 'bubbling-phase', '/ target = #' + event.target.id + ' / currentTarget = #' + event.currentTarget.id); 18}, false); 19 20document.getElementById('kore').addEventListener('click', function (event) { // #kore のみ発火する 21 console.log(event.type, 'capturing-phase', '/ target = #' + event.target.id + ' / currentTarget = #' + event.currentTarget.id); 22}, true); 23 24addEventListener('click', function (event) { // #kore のみ発火する 25 console.log(event.type, 'capturing-phase', '/ target = #' + event.target.id + ' / currentTarget = window'); 26}, true);

当然ながら event.stopImmediatePropagation() 実行前のリスナーは無効化できませんので、event.stopImmediatePropagation() は一番初めに実行する必要があります。

event.target で分岐処理

Fushihara さんが期待する動作ではないかもしれませんが、個人的には次のように書きます。

JavaScript

1document.getElementById('kore').addEventListener('click', function (event) { 2 if (event.target !== event.currentTarget) { // event.target が #kore でないなら強制終了 3 return; 4 } 5 6 console.log(event.type, '#' + event.target.id); 7}, false);

Re: Fushihara さん

投稿2016/09/14 03:27

編集2016/09/14 04:34
think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

イベント自体を止めることは無理ですが、無視することは出来ます。

HTML

1<div id="kore"> 2 <img src="https://placehold.jp/8/cc9999/993333/50x30.png"> 3 てきすと 4</div> 5```として 6```JavaScript 7document.querySelector( '#kore' ).addEventListener( 'click', function( e ) { 8// if ( e.target.tagName === 'img' ) { // 修正前(コメント欄参照) 9 if ( e.target.tagName === 'IMG' ) { // 修正後 10 e.stopPropagation(); 11 return; 12 } 13 /* do something. */ 14}, false ); 15```か 16```JavaScript 17document.querySelector( '#kore img' ).addEventListener( 'click', function( e ) { 18 e.stopPropagation(); 19}, false ); 20document.querySelector( '#kore' ).addEventListener( 'click', function( e ) { 21 /* do something. */ 22} );

ではどうでしょう。
※ buttonタグの場合上記記述では使え無いと思います。

動くサンプル:https://jsfiddle.net/pj75tsbg/

投稿2016/09/14 03:57

編集2016/09/14 04:28
kei344

総合スコア69407

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

think49

2016/09/14 04:24

> if ( e.target.tagName === 'img' ) { XHTMLを想定されているのでしょうか。 HTML では tagName は常に大文字ですので e.target.tagName === 'IMG' もしくは String#toLowerCase を併用する必要があります。
kei344

2016/09/14 04:27

指摘ありがとうございます! 手元の環境で試したときには toLowerCase していたのに失敗しました・・・。 本文を修正しておきます。
guest

0

querySelector()はあまり使ったことがないですが、ブラウザによって挙動が違うようですね
いずれ仕様が統一されるような気もしますが、今回の件に関していえば場当たり的ですが
子要素を掴んでいるのであれば親に遡ればよいのではないでしょうか?

javascript

1function(e){ 2 var t=e.target; 3 while(t){ 4 if(t.nodeName=="BUTTON") break; 5 t=t.parentNode; 6 } 7 console.log(t.nodeName); 8}); 9

投稿2016/09/14 03:24

yambejp

総合スコア114806

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2016/09/14 04:47

失礼しました e.currentTargetで取れるって書いてありましたね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問