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

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

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

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

Q&A

解決済

3回答

582閲覧

AddEventListenerの動作について

rei78087487

総合スコア12

JavaScript

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

0グッド

0クリップ

投稿2021/04/14 00:33

背景:

下記ソースコードはテキストエリアを作成した後、要素どれか一つをクリックすると色が変わるというものです。
例えば要素が複数あった場合、どれか一つをクリックすると以前にクリックした要素の色は元の色に戻ります。
jqueryでのソースコードになりますが、参考のURLがこちらです。
https://liveweave.com/

これを参考にJavascriptで作成をしてみました。
成功はしたのですが、addEventListenerの要素を変えただけでなぜ挙動が変わるのか教えて頂きたく質問しました。

全体コード:
[https://codepen.io/mio-rei/pen/GRrdKzQ]

例1:

こちらは上記の内容をJavascriptにて記述したものです。
要素をダブルクリックで複数作成後、そのうちの要素一つをクリックすると要素の色が変わります。
その状態でまた別の要素をを選択すると選択した要素は変わり、以前に選択した要素は元の色に戻ります。

JavaScript

1const text = document.querySelectorAll('textarea'); 2 3 for (const tes of text) { 4 document.addEventListener('click', () => { 5 let t = event.target; 6 if(t.nodeName != 'TEXTAREA') return; 7 tes.classList.remove('active'); 8 t.classList.add('active'); 9    }); 10  }

例2:

JavaScript

1こちらはaddEventListenerの要素をdocumentからtesに変更したものです。 2挙動は例1:と違い、要素を作成後、要素をクリックすると色は変わりますが、 3他の要素を選択してもそのままの色の状態です。 4 5 const text = document.querySelectorAll('textarea'); 6 7 for (const tes of text) { 8 tes.addEventListener('click', () => { 9 let t = event.target; 10 tes.classList.remove('active'); 11 t.classList.add('active'); 12 }); 13 }

上記ソースコードは何故同じ動きにならないのか?

addEventListenerの対象要素が、documentかtes(textera)によって変わる動作の違いについて

例1はaddEventListenerの要素をdocumentにしていますが、クリックする対象がそれだと本来の目的であるテキストエリアの色を変更、戻すといった事ができません。なので、if(t.nodeName != 'TEXTAREA') return;を記述して、対象の要素をテキストエリアにしています。

例2はaddEventListenerの要素をtesとして、こちらは対象要素の目的であるテキストエリアにしています。対象要素をクリックしているにも関わらずなぜこちらは思うような動作にならないのか?
こちらの方がシンプルにクリック対象の要素であり、記述も簡易的でわかりやすいと思うのに。

ご教示お願い致します。

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

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

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

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

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

guest

回答3

0

例2が期待どおりに動かないのは、例2でイベントリスナでクリックされた要素以外を一切操作していないからです。例2で、tesevent.target は同じ要素です。tes.classList.remove('active')document.querySelector('textarea.active')?.classList.remove('active') とでも変えれば動くでしょう。

例1が期待どおり動くのは、イベントリスナが text の個数ぶん登録されていて、それぞれが別の tes を参照していて、どこをクリックされてもすべてのイベントリスナが呼ばれるからです。

例1も例2もイベントリスナを test の個数ぶん登録していますが、定石はdocumentに1つだけ登録することです。

js

1document.addEventListener('click', event => { 2 let t = event.target; 3 if (t.nodeName != 'TEXTAREA') 4 return; 5 document.querySelector('textarea.active')?.classList.remove('active'); 6 t.classList.add('active'); 7});

投稿2021/04/14 01:11

編集2021/04/14 01:29
int32_t

総合スコア21695

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

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

hatena19

2021/04/14 01:26

document.querySelector('textarea.active').classList.remove('active'); は繰り返し処理にしないとエラーになりませんか。
int32_t

2021/04/14 01:28

querySelectorAll()ではないので繰り返しは不要ですが、nullチェックは必要ですね。指摘ありがとうございます。修正します。
hatena19

2021/04/14 01:33

あっ、querySelectorAllと見間違ってました。 textarea.active は一つしかないはずですので、querySelectorでOKですね。
guest

0

ベストアンサー

例1はdocumenttextareaの数だけAddEventしているので1回のクリックでtextarea回数実行されます。
そのため、tes.classList.remove('active');で全textareaからactiveが削除されるので元にもどります

例2はtextareaAddEventしているので、textareaをクリックした時にだけ実行されますが
AddEventの中の処理は1回しか実行されません。

そのため、以下のように一旦すべてのtextAreaからactiveを削除する必要があります

javascript

1const text = document.querySelectorAll('textarea'); 2 3for (const tes of text) { 4 tes.addEventListener('click', () => { 5 const t = event.currentTarget; // ここはtargetではなくcurrentTargetにすべき 6 for(const x of text){ 7 x.classList.remove('active'); // 一旦全て削除 8 } 9 t.classList.add('active'); 10 }); 11}

投稿2021/04/14 01:05

編集2021/04/14 01:07
fijino

総合スコア136

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

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

rei78087487

2021/04/14 03:01

分かりやすい回答ありありがとうございます。 また、それにちなんだコードを教えて頂きありがとうございます。
guest

0

対象要素をクリックしているにも関わらずなぜこちらは思うような動作にならないのか?

こちらの方がシンプルにクリック対象の要素であり、記述も簡易的でわかりやすいと思うのに。

こちらのコードの場合、「元に戻す要素」を検出する必要があります。現状のコードでは、testもクリックされた<textarea>なので、別な<textarea>の色をもとに戻す処理がありません。

投稿2021/04/14 00:59

maisumakun

総合スコア146018

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

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

maisumakun

2021/04/14 01:01

前者の場合、1回のクリックで<textarea>の数だけイベントが起動しています。1回のイベントが1つの<textarea>の色を戻します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問