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

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

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

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

Q&A

解決済

1回答

448閲覧

addEventListenerにより発生したcontextmenuが一度目の右クリックで表示されない

kikumaru0703

総合スコア6

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

0グッド

1クリップ

投稿2022/06/25 14:12

編集2022/06/29 12:33

実現したいこと

<style> #contextmenu1 { display: none; position: fixed; left: 0px; top: 0px; width: 200px; height: 180px; border: 1px solid #000; background-color: #fff; border-radius: 5px; } #contextmenu li { cursor: pointer; } #contextmenu2 { display: none; position: fixed; left: 0px; top: 0px; width: 200px; height: 180px; border: 1px solid #000; background-color: #fff; border-radius: 5px; } #contextmenu2 li { cursor: pointer; } </style>
<body onContextmenu="return false;"> <div id="menu" style="width:100px; background-color:bisque; height: 300px;"> <a class="japan" href="#"> <p class="food">焼肉</p> </a> <a class="japan" href="#"> <p class="food">寿司</p> </a> <a class="japan" href="#"> <p class="food">ラーメン</p> </a> </div> <ul id="contextmenu1"> <li>東京</li> <li>大阪</li> <li>名古屋</li> </ul> <ul id="contextmenu2"> <li>アメリカ</li> <li>イギリス</li> <li>フランス</li> </ul> </body>

この中のid属性のcontextmenu1とcontextmenu2を右クリック表示させたいです。
contextmenu1は class="japan" 上で右クリックした際に、contextmenu2 はそれ以外の場所(id="menu"内)で右クリックした際に表示させたいのですが、下記ソースコードではclass="japan"リンク上で右クリックすると、contextmenu1が一度目は表示されず、二度目の右クリックから表示されてしまいます。
一度目の右クリックからcontextmenu1を表示させたいのですが、どのようなソースコードを書けばよいかご教授お願いいたします。

該当ソースコード

<script type="text/javascript"> let menu = document.getElementById('menu'); let japan = document.getElementsByClassName('japan'); let food = document.getElementsByClassName('food'); let conme1 = document.getElementById('contextmenu1'); let conme2 = document.getElementById('contextmenu2'); window.onload = function () { menu.addEventListener('contextmenu', function (e) { if (e.srcElement.className === "food") { conme1.style.left = e.pageX + "px";//メニューをマウスの位置へ移動 conme1.style.top = e.pageY + "px"; conme1.style.display = "block";//メニューを表示 conme2.style.display = "none"; } else { conme1.style.display = "none"; conme2.style.left = e.pageX + "px";//メニューをマウスの位置へ移動 conme2.style.top = e.pageY + "px"; conme2.style.display = "block";//メニューを表示 } document.body.addEventListener('click', function (e) {//body要素をクリックしたときにイベントを発生 conme1.style.display = "none";//右クリックメニューを非表示 conme2.style.display = "none"; }); }); for (let i = 0; i < food.length; i++) { food[i].addEventListener('contextmenu', function (e) {//右クリックイベントを追加 document.getElementById("tokyo").onclick = function () { alert("東京の" + food[i].innerHTML + "です"); } document.getElementById("osaka").onclick = function () { alert("大阪の" + food[i].innerHTML + "です"); } document.getElementById("nagoya").onclick = function () { alert("名古屋の" + food[i].innerHTML + "です"); } }); } } </script>

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

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

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

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

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

guest

回答1

0

ベストアンサー

addEventListenerにより発生したcontextmenuが

addEventListener() について勘違いがあるような気がします。addEventListener() は指定イベントが発生したときに呼ばれる関数を登録するだけです。addEventListener() によってイベントが発生するわけではありません。

現状のコードは、右クリックで menu.addEventListener() で登録した関数が呼ばれ、その中で food[i].addEventListener() で別の関数を登録しているだけでなので1回目の右クリックでは後者の関数は呼ばれないわけです。

また、menu.addEventListener() がループ中にあるため同じ関数が何個も登録されているのも問題です。

全体的な構成は以下のようにしましょう。

js

1window.onload = function () { 2 let menu = document.getElementById('menu'); 3 let conme1 = document.getElementById('contextmenu1'); 4 let conme2 = document.getElementById('contextmenu2'); 5 6 menu.addEventListener('contextmenu', function (e) { //menu上で右クリック 7 if (e.target.closest(".food")) { //class=foodの場合に実行 8 // conme1 を表示 9 } else { //food以外 10 // conme2 を表示 11 } 12 }); 13 document.body.addEventListener('click', function (e) { //body要素をクリックしたときに非表示にする 14 if (!conme1.contains(e.target) && !conme2.contains(e.target)) { 15 // conme1 conem2 を非表示に。 16 });

投稿2022/06/26 22:16

編集2022/06/26 22:17
int32_t

総合スコア20925

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

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

kikumaru0703

2022/06/27 16:19 編集

ご回答ありがとうございます!! addEventListener()の仕組みをご教示くださいましてありがとうございます。 そしてjavascriptのソースコードを改変いたしました。 私のやりたい事といたしましては、contextmenu1内に、それぞれのfood(焼肉・寿司・ラーメン)に対応した関数を持たせたいです。そうしてしまうと、どうしてもこのようなソースの形になってしまいます。 これではまた、addEventListenerが2重になってしまい、次はcontextmenu1内の関数が1発目で発生いたしません。こちら他に方法はありませんでしょうか、ご教授お願いしたいです。
int32_t

2022/06/27 20:42

addEventListener() に渡す関数の中で addEventListener() onclick 代入などは混乱のもとなのでやめましょう。 tokyo/osaka/nagoya の onclick 登録は addEventListener() の外側でやってください。
kikumaru0703

2022/06/29 12:39

上記のソースコードで今回の問題点は解決する事が出来ました。 ただ、スコープの問題で food の addEventListener は外から見えてないのでは?や、for文はどのような契機 で実行されているのか?など疑問点があり、これからまた勉強してまいります。 この度はありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問