How to make onclick function execute only once?
Event Handlers & Listeners
There are three ways* to register an event to an element. The following examples show how to register the click event to a link with the class .once
** which calls the function test()
when triggered.
- Event Listener (recommended)
document.querySelector('.once')
.addEventListener('click', test);`
- On-event Attribute (not recommended)
<a href='#/' class='once'
onclick='test()'>Click</a>
- On-event Property
document.querySelector('.once')
.onclick = test;`
*See DOM on-event handlers for details
** .once
class is not relevant for #2
Issues
The OP (Original Post) has an event listener (see #1 above) registering a click event to the <body>
tag and an on-event attribute (see #2 above) registering the click event to a <div>
. Each one calls a function (aka callback function) named klikaj()
which is redundant. Clicking the body (which is normally everywhere) isn't useful when you intend to have the user click a div. Should the user click anywhere but the div, klikaj()
will be called. Should the user click the div, klikaj()
will be called twice. I suggest that you remove both event handlers and replace them with this:
A.
document.getElementById('thumb0').addEventListener("click", klikaj);
Note that klikaj
has no parenthesis ()
because the browser interprets ()
as to run the function now instead of when the user triggers the registered event (see #1 and #3 above). Should an event handler have additional statements and/or callback functions then an anonymous function should be wrapped around it and normal syntax applies:
B.
document.getElementById('thumb0').addEventListener("click", function(event) {
klikaj();
console.log('clicked');
});
A cleaner alternative is to add extra lines in the definition of the callback function instead and registering events like #A.
Solution
Simply add the following statement as the last line of klikaj()
:
this.style.pointerEvents = "none";
That will render the clicked tag unclickable. Applied to OP code it should be like this:
<div id="thumb0" class="thumbs">Thumb 0</div>
<script>
function klikaj(event) {
gtag('event', 'first-4', {
'event_category' : 'cat-4',
'event_label' : 'site'
});
this.style.pointerEvents = "none";
}
document.getElementById('thumb0').addEventListener("click", klikaj);
</script>
Demo
The following demo has two links:
.default
- a normal link registered to the click event which when triggered callstest()
.once
- a link registered to the click event which when triggered callstest()
and renders the link unclickable.
function test() {
console.log('test');
}
document.querySelector('.default').onclick = function(e) {
test();
}
document.querySelector('.once').onclick = function(e) {
test();
this.style.pointerEvents = 'none';
}
<a href='#/' class='default'>Default</a><br>
<a href='#/' class='once'>Once</a>
Remove onclick
attribute on your button and register listener via JavaScript, as you tried to do:
<div id="thumb0" class="thumbs"
style="border: 1px solid; cursor: pointer; float: left">
My button
</div>
<script>
function klikaj(i) {
console.log(i);
}
document.getElementById('thumb0')
.addEventListener("click", function(event) {
klikaj('rad1');
}, {once: true});
</script>
If your browser doesn't support { once: true }
option, you can remove event listener manually:
<div id="thumb0" class="thumbs"
style="border: 1px solid;cursor: pointer;float:left">
My button
</div>
<script>
function klikaj(i) {
console.log(i);
}
function onClick(event) {
klikaj('rad1');
document
.getElementById('thumb0')
.removeEventListener("click", onClick);
}
document
.getElementById('thumb0')
.addEventListener("click", onClick);
</script>
I would recommend setting a variable and checking its value.
<script>
var clicked = false;
function klikaj(i) {
if (clicked === false) {
gtag('event', 'first-4', {
'event_category' : 'cat-4',
'event_label' : 'site'
});
}
clicked = true;
}
...
</script>
Or removing the onclick event as suggested by others,
<script>
function klikaj(i) {
gtag('event', 'first-4', {
'event_category' : 'cat-4',
'event_label' : 'site'
});
document.getElementById('thumb0).onclick = undefined;
}
...
</script>
Note that once: true
is unfortunately not supported in IE and Edge. See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
you could use removeAttribute()
like this: document.getElementById('thumb0').removeAttribute("onclick");
or you could let the function return false like this: document.getElementById('thumb0').onclick = ()=> false