Weird JS scope issue in Firefox

I’m doing my portfolio page and there I made a div (here defined as ‘work’), added a click event listener, so when the user clicks it creates three bubbles that float up. It works as expected in Chrome and Edge, but Firefox says that ‘event’ is not defined and throws a ReferenceError. As far as I know from YDKJS book, inner functions have access to all variables from outer functions - so I’m puzzled.
I tried moving the createBubble() function to global scope, and calling it inside of callback function directly, it won’t budge…
Why?
Short version:

work.addEventListener('click', function(event){
   bubblesOnClick();
});

function bubblesOnClick() {
   createBubble();
   createBubble();
   createBubble();
   
   function createBubble() {
      var div = document.createElement('div');
      
      // get the coordinates of click where new bubble element will be created 
      var x = event.clientX; // these event objects aren't recognized in firefox
      var y = event.clientY;
      // ... create some nice bubbles on these coords ....
      }

Long version:

work.addEventListener('click', function(event){
   console.log('work-clicked');
   work.classList.toggle('bubble--paused');
   bubblesOnClick();
});

function bubblesOnClick() {
   createBubble();
   createBubble();
   createBubble();
   
   function createBubble() {
      var div = document.createElement('div');
      
      // get the coordinates of click where new bubble element will be created 
      var x = event.clientX; // these event objects aren't recognized in firefox
      var y = event.clientY;
      
      // give dimensions to the element
      var height = randomSize(); // bubble's size should be different
      div.style.height = height + 'px'; console.log('Height: ' + div.style.height);
      div.style.width = height + 'px'; // so the bubble is perfect circle
      
      // centering the bubble's position around pointer
      div.style.position = 'absolute';
      div.style.left = x - height + randomNum() + 'px';
      div.style.top = y - height + randomNum() + 'px';
      
      document.body.appendChild(div);
      
      if (div.clientHeight < 16) {
         div.setAttribute('class', 'bubble-small bubble-small--fast');
         // deletes the buuble only when the animation is about to end
         setTimeout(function(){
            div.parentNode.removeChild(div);
         }, 1950);
      }
      else if (div.clientHeight < 31) {
         div.setAttribute('class', 'bubble-small bubble-small--intermediate');
         setTimeout(function(){
            div.parentNode.removeChild(div);
         }, 2450);
      } 
      else {
         div.setAttribute('class', 'bubble-small bubble-small--slow')
         setTimeout(function(){
            div.parentNode.removeChild(div);
         }, 2950);
      }
   }

   function randomSize() {
      // this function is used to give variability to bubble's sizes
      var randomNumber = (Math.floor(Math.random() * 10) + 1) * 5;
      console.log('Random number:' + randomNumber);
      return randomNumber;
   }

   function randomNum() {
      // this function is used to give randomness to bubble's position
      return Math.floor(Math.random() * 100);
   }
}

That is because you don’t pass event to the function. In Chrome event is added to the window object. You can therefore use event to access window.event, but in FireFox this fails, because there is no variable event nor does window.event exist.

According to MDN:

Non-standard

This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

1 Like

Oh, so it is accessing the global event object… that’s why if I change event to say e or something else, Chrome will throw an error too…
I was expecting that because the anonymous callback function has the event object in the parameters that it will be available to other functions, that are called inside of it, automatically… I was wrong it needs to be passed (silly me) :smiley:

Anyhow the solution would be just to pass the event object from the anonymous function and make the bubblesOnClick function accept one parameter which would end up being the event object, like this:

work.addEventListener('click', function(event){
   bubblesOnClick(event);
});

function bubblesOnClick(event) {
   createBubble();
   createBubble();
   createBubble();
   
   function createBubble() {
      var div = document.createElement('div');
      
      // get the coordinates of click where new bubble element will be created 
      var x = event.clientX; // the event object is now properly recognized
      var y = event.clientY;
      // ... create some nice bubbles on these coords ....
      }

And the ReferenceError is no more :smiley: