Добавление прослушивателя события второго клика в слушателе события клика - PullRequest
1 голос
/ 01 октября 2019

Я безуспешно пытаюсь добавить слушатель события второго щелчка в существующем слушателе события щелчка, используя D3.

По сути, у меня есть карта событий (круги). Я бы хотел, чтобы пользователь мог щелкнуть по кругу и открыть всплывающее окно. Я хочу, чтобы это всплывающее окно исчезало только тогда, когда пользователь щелкает в любом месте во второй раз. Таким образом, нажатие на круг создаст экземпляр всплывающего окна и свяжет его, а если щелкнуть ЛЮБОЕ ГДЕ во второй раз, всплывающее окно исчезнет и обратные круги будут восприимчивы только к зависанию, если только один из них не будет нажат снова.

Я подошел к этому, добавив еще один прослушиватель событий щелчка "body" в прослушивателе событий круга:

  // event listener: if events (circles) are clicked, instantiate pop-up
  d3.selectAll(".events").on("click", function(d) { 
        console.log("event clicked!")
         //disable hover event listeners
         d3.selectAll(".events").on("mouseout", null);
         d3.selectAll(".events").on("mouseover", null);              
              popup.transition()        
                 .duration(200)      
                .style("opacity", .9);
              popup.html(d.ArtistBio)

        // if user clicks a SECOND time, anywhere, make popup disappear
        d3.select("body").on("click", function(d) { 
            console.log("body clicked")
            //hide popup
            popup.transition()        
                  .duration(200)      
                  .style("opacity", 0);  
            //revert back to hover, unless user clicks again!
            d3.selectAll(".events").on("mouseout", true);
            d3.selectAll(".events").on("mouseover", true);
            d3.selectAll(".events").on("mouseout", function(d) { 
            console.log("mousing out!")      
                popup.transition()        
                  .duration(200)      
                  .style("opacity", 0);              
              })

            // mouseover event listers added back in
            d3.selectAll(".events").on("mouseover", function(d) { 
              popup.transition()        
                 .duration(200)      
                .style("opacity", .9);
              popup.html(d.ArtistBio)

          })            
        })

Моя проблема в том, что оба события запускаются одновременно, а не последовательно: один разЯ нажимаю на событие круга, также создается экземпляр прослушивателя события щелчка тела, и поэтому всплывающее окно удаляется, как только оно отображается. Есть ли способ сделать то, что я пытаюсь сделать, способом, подобным тому, что я описываю выше? Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 01 октября 2019

Клик будет пузыриться, это правильно ожидается. Чтобы избежать этого, используйте event.stopPropagation. Вы также можете использовать d3.events (пока они существуют ...):

d3.event.stopPropagation();

Вот демонстрация, нажмите на прямоугольник и за его пределами:

d3.select("rect").on("click", function() {
  console.log("rectangle clicked");
  d3.event.stopPropagation();
  d3.select("body").on("click", function() {
    console.log("body clicked")
  })
})
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg>
  <rect width="50" height="50" x="100" y="50"></rect>
</svg>
0 голосов
/ 01 октября 2019

Вы можете сделать что-то вроде этого:

  // event listener: if events (circles) are clicked, instantiate pop-up
  d3.selectAll(".events").on("click", function(d) { 
        console.log("event clicked!")
        const currentCircle = this; 
        //disable hover event listeners
         d3.selectAll(".events").on("mouseout", null);
         d3.selectAll(".events").on("mouseover", null);              
              popup.transition()        
                 .duration(200)      
                .style("opacity", .9);
              popup.html(d.ArtistBio)
        // if user clicks a SECOND time, anywhere, make popup disappear
        d3.select("body").on("click", function(d) { 
    if(this !== currentCircle){
            console.log("body clicked")
            //hide popup
            popup.transition()        
                  .duration(200)      
                  .style("opacity", 0);  
            //revert back to hover, unless user clicks again!
            d3.selectAll(".events").on("mouseout", true);
            d3.selectAll(".events").on("mouseover", true);
            d3.selectAll(".events").on("mouseout", function(d) { 
            console.log("mousing out!")      
                popup.transition()        
                  .duration(200)      
                  .style("opacity", 0);              
              })

            // mouseover event listers added back in
            d3.selectAll(".events").on("mouseover", function(d) { 
              popup.transition()        
                 .duration(200)      
                .style("opacity", .9);
              popup.html(d.ArtistBio)

          })
       }            
        })

Внутри слушателя событий тела убедитесь, что нажатый элемент не совпадает с текущим нажатием на кружок / всплывающее окно.

...