skip to Main Content

Something I can’t understand :

I got a function opening the same page <div id="page"> but with different contents depending the clicked button in menu:

<nav>
    <button onclick="openPage(1)">PAGE 1</button> 
    <button onclick="openPage(2)">PAGE 2</button>
    <button onclick="openPage(3)">PAGE 3</button>
</nav>

Then the function:

function openPage(p){

    var move=0;  // define a var for USER action

    if(p==1){
         document.getElementById('page').innerHTML = text_1;  // content preloaded
    }
    else if(p==2){
         document.getElementById('page').innerHTML = text_2;
    }
    else if(p==3){
         document.getElementById('page').innerHTML = text_3;
    }

    // then on the top of the page (absolute + z-index) I add a HTML object:

    document.getElementById('page').innerHTML += '<aside id="pictures">content</aside>';

    // what I'm now trying to do is to remove this object once USER move its mouse on it 

    document.getElementById('pictures').addEventListener("mousemove",function(event) {
       setTimeout(function(){
          move+=1;  // increase the val each second
       },1e3)
       console.log('move'+p+' = '+move)  // control value
       if(move>100){
          document.getElementById('pictures').style.display = "none";  // OK, it works
          move=0;  // reinit the var
       }
   });  
}

Now the surprise:

console on page 1

   move1 = 0
   move1 = 1
   ...
   move1 = 99
   move1 = 100    //  'pictures' disappears

console on page 2

   move1 = 41
   move2 = 0
   ...
   move1 = 58
   move1 = 17
   ...
   move1 = 100    //  'pictures' disappears
   move2 = 59

console on page 3

   move1 = 15
   move2 = 88
   move3 = 0
   ...
   move1 = 37
   move2 = 100    //  'pictures' disappears
   move3 = 12
   ...

My var ‘move’ got 3 simultaneous values… how is it possible?

3

Answers


  1. Chosen as BEST ANSWER

    Found another (simpliest ?) way:

     var move=0;  // placed out of functions
    
     function openPage(p){
         getElementById('pictures').removeEventListener("mousemove",outPicts);
         move=0;  // reinit the var
    
         .... (same as previous)
    
         getElementById('pictures').addEventListener("mousemove",outPicts);
     }
    
     // put mousemove event in another function:
    
     function outPicts(p){
        setTimeout(function(){
            move+=1;
        },1e3)
        console.log('move = '+move)
        if(move>100){
            document.getElementById('pictures').style.display = "none";        
         }
      }
    

    works as expected


  2. The reason for your issue is that you’re adding an event listener every time you call the openPage function. This means that if you click on multiple buttons, each one will have its own event listener attached to the #pictures element. Now, when the mousemove event is triggered, all these listeners will execute simultaneously, causing the move variable to increment multiple times per second.

    The fix for this would be to remove the existing event listener before adding a new one.

    let handler; // to hold the event listener function
    const pictureEl = document.getElementById('pictures');
    let move = 0;
    
    function openPage(p){
    
       // Remove existing event listener
       if (handler) { // <-- Check here
           pictureEl.removeEventListener("mousemove", handler);
       }
       
       handler = function(event) {
           // ...Rest
           }
       };
       // Add new event listener
       pictureEl.addEventListener("mousemove", handler);
    // ...rest
    
    Login or Signup to reply.
  3. This is a slightly different take on this where I leverage the dataset and put values on the buttons and pass them around.
    I also used a class on the element to hide and to illustrate use when you click the button I remove it to show again. I had no idea on layout so I just put the picture in the "page" and added a span – NOTE: this avoids hitting the DOM to add/remove the element and the mousemove event listener.

    var move = 0;
    var textOptions = ["I am text one", "I am text two", "I am text three"];
    
    document.getElementById('my-page')
      .addEventListener("mousemove", function(event) {
        setTimeout(function() {
          move += 1;
        }, 1000);
        console.log('move' + event.currentTarget.dataset.targ + ' = ' + move);
        if (move > 100) {
          event.currentTarget.classList.add("hide-me");
          move = 0;
        }
      });
    document.querySelector('.my-nav')
      .addEventListener("click", function(event) {
        document.getElementById('my-page').classList.remove("hide-me");
        const buttonTarget = event.target.dataset.target;
        event.currentTarget.dataset.targ = buttonTarget;
        console.log(buttonTarget);
        openPage(buttonTarget);
      });
    
    function openPage(p) {
      const myPage = document.getElementById('my-page');
      myPage.querySelector('.first-part').textConent = textOptions[p];
      const myPic = myPage.querySelector('.my-pictures');
      myPic.textContent = `content Page: ${p}`;
      myPage.dataset.targ = p;
    }
    .hide-me {
      display: none
    }
    <nav class="my-nav">
      <button data-target="1">PAGE 1</button>
      <button data-target="2">PAGE 2</button>
      <button data-target="3">PAGE 3</button>
    </nav>
    
    <div id="my-page" data-targ="x"><span class="first-part">Hi! Click buttons!</span>
      <div class="my-pictures" id="pictures">content</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search