How can I add an event for a one time click to a function?
Asked Answered
L

9

40

I would like to add a click event listener to a function but would only like it to happen once. How could i do this?

I would like to stay clear of JQuery as well if it is possible please.

EDITED

As the answers that I am getting for this aren't fully satisfying my need i thought i may make it a bit more clear with context.

I am writing a function to draw a rectangle, first with one click on a button to initiate the rectangle function. Then there are two click event listeners in the drawRectangle function. These are the events i would like to happen only once in the function. Allowing the user to then create another rectangle if they click on the rectangle initiation button again.

Landau answered 19/2, 2015 at 15:35 Comment(2)
@antyrat OP specifically asked for no jQuery.Sublingual
Wouldn't setting a boolean to false on start and then do an if if it's the first time, and if it is indeed the first time change it to true?Canopy
B
136

Use modern JavaScript!

EventTarget.addEventListener("click", function() {

    // Do something cool

}, {once : true});

A Boolean indicating that the listener should be invoked at most once after being added. If true, the listener would be automatically removed when invoked.

- MDN web docs

All modern browsers support this feature

Other reference

Branham answered 19/9, 2017 at 3:55 Comment(1)
Still cannot be used for most production sites because it has no IE11 support. But very nice indeed!Forklift
I
20

You have to use removeEventListener once the event is fired once. However, removeEventListener takes a function as argument, which means you need to declare a named function, add it with addEventListener, and have it removing itself. Example:

function foo() {
    // do things, then
    removeEventListener('click', foo);
}

addEventListener('click', foo);
Interdict answered 19/2, 2015 at 15:38 Comment(4)
I forgot about this initially too, but removeEventListener needs the event type too: removeEventListener("click", foo);Libertinage
wait wait, removeEventListener and addEventListener are both methods not functions!Alyce
This is a deprecated solution. See https://mcmap.net/q/389483/-how-can-i-add-an-event-for-a-one-time-click-to-a-functionKelsi
@Kelsi this is NOT deprecated. it's a valid answer with no deprecated code and sometimes the best you can do e.g. for a conditional one time listenerUtile
U
3
function one(el, type, fn) {
    function handler(event) {
        el.removeEventListener(type, handler);
        fn(event);
    }
    el.addEventListener(type, handler);
}

// use it like
one(window, 'resize', function () {
    alert("This triggers just once");
});

Example: http://jsfiddle.net/6njpem7x/

Unchain answered 19/2, 2015 at 15:45 Comment(0)
A
1

The other answers are correct in that this can be achieved with a named function, but you don't need to declare the function separately. You can use a named function expression:

element.addEventListener("click", function handler(event) {
  this.removeEventListener("click", handler);
  // ...
});

An alternative, though less optimal, approach is to keep around a variable that keeps track whether the handler was executed:

var wasExecuted = false;
element.addEventListener("click", function(event) {
  if (wasExecuted) {
    return;
  }
  wasExecuted = true;
  // ...
});

The variable needs to be declared outside the handler but within scope, so that its value persists across event triggers.

Amman answered 2/3, 2020 at 23:58 Comment(0)
L
0

Combination of addEventListener and removeEventListener:

element.addEventListener("click", clickFunction);
function clickFunction(e) {
    console.log("clicked");
    element.removeEventListener("click", clickFunction);
}

jsFiddle

Libertinage answered 19/2, 2015 at 15:38 Comment(1)
Maybe i didn't explain what i wish to achieve fully. I would like to call a function using a click event. and then within this i would like to have two click functions that work only once. for that function call. To put it into context, I am writing a function to draw an SVG rectangle. The two one time clicks are for getting the points on the canvas of the corners of the rectangle and the overall function is the one to draw the rectangle.Landau
U
0

something like this

var el = document.getElementById('something');
el.addEventListener('click', doSomething);

function doSomething() {
  el.removeEventListener('click', doSomething);

  //code
}
Untrue answered 19/2, 2015 at 15:39 Comment(0)
A
-1

Inside event handler you can use universal: e.target.removeEventListener(e.type, arguments.callee)
Or you can make special function for creating "one time" event listeners:

function oneTimeListener(node, type, callback) {
    // create event
    node.addEventListener(type, function(e) {
        // remove event listener
        e.target.removeEventListener(e.type, arguments.callee);
        // call handler with original context 
        // as it happens with native addEventListener
        return callback.call(this, e); 
    });
}

oneTimeListener(document.getElementById("myElement"), "click", myHandler);
Allineallis answered 4/6, 2020 at 7:4 Comment(0)
D
-2

You can set a cookie after first click:

document.cookie="click=1; expires=.......";

and add condition to listener - if cookie is set, you omit that.

Decrepit answered 19/2, 2015 at 15:41 Comment(5)
I don't believe that's actually what the OP wanted. He said he was using the click event listener, not cookies.Canopy
Taking the one click thing very literally there, I like it!Libertinage
@RGraham that's why I added "expires" - besides the cookie can be deleted anywhere else in the code if that click is required to function again.Decrepit
@Decrepit Absolutely! I'm saying you might be right in saying that the OP doesn't want the user to be able to click that element on subsequent visits.Libertinage
But it's actually a totally valid answer, a bit over-engineered but works, huh?Canopy
D
-2

Another simple solution which I'm using is to add a dummy class to the element to which we are listening so that it will not fire again.

const myButton = document.querySelector('#my-button:not(.init)');
myButton.addEventListener('click', (e) => {
     e.preventDefault();
     myButton.classList.add('init');
  });
Dismal answered 3/6, 2021 at 9:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.