

# 実現したいこと

下記ソースコードは、それぞれJavascript,css,HTMLとなっています。  
このHTML内のid属性のcontextmenu1とcontextmenu2を右クリック表示させたいです。

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

[code]

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charser="UTF-8">
        <meta name="viewport" content="Width=device-width">
        <title>ここに記入した文字が上のタグに入る</title>
    
    </head>
    <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 id="tokyo">東京</li>
            <li id="osaka">大阪</li>
            <li id="nagoya">名古屋</li>
        </ul>
    
        <ul id="contextmenu2">
            <li>アメリカ</li>
            <li>イギリス</li>
            <li>フランス</li>
        </ul>
    
        <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) {
                    
                                conme1.style.left = e.pageX + "px";//メニューをマウスの位置へ移動
                                conme1.style.top = e.pageY + "px";
                                conme1.style.display = "block";//メニューを表示
                                conme2.style.display = "none";
                                
                        if (e.srcElement.className === "food") {//class=foodの場合
      　　　　　　　　　　　　　　　　　　　      　　　　　 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 + "です");
                                }
                            });
                            }
                        } 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";
                        });
    
                    });
            }
        </script>
    </body>
    
    </html>
[/code]


CC BY-SA 4.0
2022-06-26T03:33:50.547
89597
2022-06-29T12:43:40.170
2022-06-27T16:02:20.420
30760
30760
question
javascript html css
addEventListenerにより発生したcontextmenuが一度目の右クリックで表示されない


最初のイベントでclass=foodのとき、追加のaddEventListenerを実行することしかやっていないですよね。

[code]

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charser="UTF-8">
        <meta name="viewport" content="Width=device-width">
        <title>ここに記入した文字が上のタグに入る</title>
    
    </head>
    <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 id="tokyo">東京</li>
            <li id="osaka">大阪</li>
            <li id="nagoya">名古屋</li>
        </ul>
    
        <ul id="contextmenu2">
            <li>アメリカ</li>
            <li>イギリス</li>
            <li>フランス</li>
        </ul>
    
        <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 () {
                for (let i = 0; i < japan.length; i++) {
    
                    menu.addEventListener('contextmenu', function (e) {
    
                        if (e.srcElement.className === "food") {//class=foodの場合
    
    +                       conme1.style.left = e.pageX + "px";//メニューをマウスの位置へ移動
    +                       conme1.style.top = e.pageY + "px";
    +                       conme1.style.display = "block";//メニューを表示
    +                       conme2.style.display = "none";
    
                            food[i].addEventListener('contextmenu', function (e) {//右クリックイベントを追加
    -                           conme1.style.left = e.pageX + "px";//メニューをマウスの位置へ移動
    -                           conme1.style.top = e.pageY + "px";
    -                           conme1.style.display = "block";//メニューを表示
    -                           conme2.style.display = "none";
    
                                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 + "です");
                                }
    
                            });
                        } 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";
                        });
    
                    });
                }
            }
        </script>
    </body>
    
    </html>
[/code]

追記

[code]

    let japan = document.getElementsByClassName('japan');
    let food = document.getElementsByClassName('food');
    
[/code]

で、

[code]

    for (let i = 0; i < japan.length; i++) {
    
[/code]

でループしていて、このループの中で `food[i]` を参照しているのは、おかしいと思います。

イベントリスナーの中で別のイベントリスナーを追加していますが、これは複雑すぎます。特別な理由が無いなら、最初にすべての要素にイベントリスナーを設定すれば良いかと。


CC BY-SA 4.0
2022-06-26T09:39:03.490
89606
2022-06-26T13:58:40.127
2022-06-26T13:58:40.127
45045
45045
89597
answer


この度は以下のように書き換えることによって、問題点は解決いたしました。

[code]

      <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>
[/code]


CC BY-SA 4.0
2022-06-29T12:43:40.170
89671
2022-06-29T12:43:40.170
30760
89597
answer