skip to Main Content

Okay, I have a button element in my web application.

<button id="mybutton">My Button</button>

When clicked on an event listener triggers a function

document.getElementById('mybutton').addEventListener('click',myFunction, false);

myFunction() {
   console.log('myFunction called');
}

However, when my button is clicked, I don’t need it to call that same function again. However, it would simplyfy my code if I could have another event listener calling a different function, or perhaps the same event listener calling a different function.

document.getElementById('mybutton').addEventListener('click',myFunction2, false);

myFunction2() {
   console.log('myFunction2 called');
}

Now I believe, previously, it was possible to change the function of a button by changing the onclick event attribute using JavaScript. However, I believe that using onclick event attributes now go against Firefox and Chrom policies.

I have tried just having my event listener calling the function and then a new event listener in that function to see if it would override the first event listener, but it seems that the first event listener will continue listening.

2

Answers


  1. However, I believe that using onclick event attributes now go against Firefox and Chrom policies.

    They are widely considered to be bad practise, but I don’t believe either browser vendor has a stated policy about them.

    I have tried just having my event listener calling the function and then a new event listener in that function to see if it would override the first event listener, but it seems that the first event listener will continue listening.

    This is one of the advantages of addEventListener. I wrote some relatively complex code in the 90s to add new event listeners while preserving existing ones. I’m happy not to need to do that now.

    However, when my button is clicked, I don’t need it to call that same function again. However, it would simplyfy my code if I could have another event listener calling a different function, or perhaps the same event listener calling a different function.

    For that specific case, you can specify that an event listener should be called only once (there is an option for it that you can pass to addEventListener) and stopImmediatePropagation will prevent the second function being called on the first click.

    const button = document.querySelector('button');
    
    function myFunction(event) {
       console.log('myFunction called');
       event.stopImmediatePropagation();
    }
    
    function myFunction2() {
       console.log('myFunction2 called');
    }
    
    button.addEventListener('click', myFunction, { once: true });
    button.addEventListener('click', myFunction2);
    <button>Click</button>

    For other cases, you could make use of removeEventListener or define a boolean variable that you set to true when you want different behaviour from a function.

    const button = document.querySelector('button');
    
    
    let first = true;
    
    let myFunction = (event) => {
      if (first) {
        console.log('myFunction called');
        first = false;
      } else {
        console.log('myFunction2 called');
      }
    };
    
    button.addEventListener('click', myFunction);
    <button>Click</button>
    Login or Signup to reply.
  2. if I could have another event listener calling a different function, or perhaps the same event listener calling a different function.

    There’s no need in multiple event handlers in your case imho.

    Is it possible to select which function to execute with a finite state machine with just 1 event listener. You can chain any number of functions that way:

    const states = {
      // put your myFunction, myFunction2, ... here
      before: () => console.log('before'),
      prepare: () => console.log('install'),
      compile: () => console.log('compile'),
      execute: () => console.log('execute')
    };
    
    let state;
    
    const $button = document.querySelector('button');
    $button.addEventListener('click', nextState);
    
    function nextState() {
      
      const keys = Object.keys(states);
      const nextKey = state ? keys[keys.indexOf(state) + 1] : keys[0];
    
      if(!nextKey){
        console.log('finished');
        $button.removeEventListener('click', nextState);
        return;
      }
    
      states[state = nextKey]();
    
    }
    <button>Next state</button>

    A simplified version:

    function myFunction() {
       console.log('myFunction called');
    }
    function myFunction2() {
       console.log('myFunction2 called');
    }
    
    let step;
    
    const $button = document.querySelector('button');
    $button.addEventListener('click', () => (step = step ? myFunction2 : myFunction)());
    <button>Next state</button>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search