Javascript double click event issue - javascript

I have a click listener on a DOM element (no jQuery):
element.addEventListener('click', (e) => {
// some code
});
and obviously when I click, the code runs and everything is fine.
The problems is that when I double click, the code runs twice and I don't want this behavior (when I double click I want it to act like a single click and run the code once).

One possibility is to use Date to check to see if the last click that triggered the function proper was less than 1 second ago:
const element = document.querySelector('div');
let lastClick = 0;
element.addEventListener('click', (e) => {
const thisClick = Date.now();
if (thisClick - lastClick < 1000) {
console.log('quick click detected, returning early');
return;
}
lastClick = thisClick;
console.log('click');
});
<div>click me</div>
If you want the function proper to run only once the last click was more than 1 second ago (rather than the last function proper run being more than one second ago), change it so that lastClick is assigned to inside the if (thisClick - lastClick < 1000) { conditional:
const element = document.querySelector('div');
let lastClick = 0;
element.addEventListener('click', (e) => {
const thisClick = Date.now();
if (thisClick - lastClick < 1000) {
console.log('quick click detected, returning early');
lastClick = thisClick;
return;
}
lastClick = thisClick;
console.log('click');
});
<div>click me</div>

debounce the event to trigger in a certain period of time:
const element = document.querySelector('button');
let time;
element.addEventListener('click', (e) => {
if (time) {
clearTimeout(time);
}
time = setTimeout(() => console.log('runs after last click'), 500);
});
<button>Click!!!</button>

The most straightforward solution for this is to create a variable that acts as a gate that is reset after a certain time (one second in this example).
var el = document.querySelector('p');
var clickAllowed = true;
el.addEventListener('click', e => {
if (!clickAllowed) {
return;
}
clickAllowed = false;
setTimeout(() => clickAllowed = true, 1000);
// do stuff here
console.log('test');
});
<p>Test</p>
On the first click, your code will run and the "gate" will close to stop a second click. After one second, the "gate" opens to allow the code to run again.

you can set value to one of the input and see if the value is changed
function trigger(){
if(document.getElementById('isClicked').value ==0 ){
console.log('clicked for the first time');
document.getElementById('isClicked').value = 111;
setTimeout(function(){
document.getElementById('isClicked').value = 0;
}, 1000);
}
}
<button onclick='trigger()'>click me </button>
<input type='hidden' value=0 id='isClicked' />

this code working for you
var el=document.getElementById('demo');
window.clicks=0;
// handle two click
el.addEventListener('click',function(){
clicks++;
el.innerHTML='clicks: '+clicks;
setTimeout(function(){
if (clicks == 1) {
runYourCode();
clicks=0;
}
else{
clicks=0;
return;
}
},400);
})
// dblclick event
el.addEventListener('dblclick',function(){
runYourCode();
})
function runYourCode(){
document.getElementById('text').innerHTML += '<br>Run your Code...';
};
#demo{
background:red;
padding:5px 10px;
color:white;
max-width:100px;
}
<p id="demo">click me!</p>
<p id="text">
log:<br>
</p>

Related

how to stop function in js?

I have a form that counts when a button (button.clicked in the example below) is clicked. I want to make it operate in two modes: one keeps counting with every click, the other has a timer (started with the click of another button, button.start) that will disable the click-count button when the timer runs out. Each mode is chosen by clicking a button (button.menu-timer and button.menu-clicks). When the count mode is selected, one function (cc) is called. When switched to the timer mode, another function (tt) should be called and the first function should stop.
If I click one mode button, then everything works as it should, but if after that I click the other mode button, both functions continue to operate; each click of button.click adds two to the count. Moreover, if you click the mode buttons several times, clicking the count button will increase the counter many times, rather than only once.
I searched for solutions on the Internet and found one based on return; I tried to use return in various ways but couldn't get it to work.
I need that when choosing the right mode, only the desired function works. And so that when you click several times on one mode, the function will run once.
The following snippet is also available on CodePen.
let clicker = document.querySelector(".click");
let start = document.querySelector(".start");
let clickerValue = document.querySelector(".click").value;
const reset = document.querySelector(".reset");
const menuTimer = document.querySelector(".menu-timer");
const menuClicks = document.querySelector(".menu-clicks");
const times = document.querySelectorAll(".time");
let i = 0;
let y;
let tf;
let timer = 15;
function tt(tf) {
if (tf ===2) {
return;
}
start.addEventListener("click", () => {
start.style.zIndex = "-1";
y = setInterval(() => {
if (i === timer) {
clicker.setAttribute("disabled", "");
} else {
i++;
}
}, 1000);
});
clicker.addEventListener("click", () => {
clicker.textContent = clickerValue++;
});
reset.addEventListener("click", resetF);
}
function cc(tf) {
if (tf = 1) {
return;
}
start.addEventListener("click", () => {
console.log("111111");
start.style.zIndex = "-1";
});
clicker.addEventListener("click", () => {
clicker.textContent = `a ${clickerValue++}`;
});
reset.addEventListener("click", resetF);
}
function resetF() {
clearInterval(y);
i = 0;
start.style.zIndex = "2";
clickerValue = 0;
clicker.textContent = clickerValue;
clicker.removeAttribute("disabled", "");
}
menuTimer.addEventListener("click", function () {
menuTimer.classList.add("active");
menuClicks.classList.remove("active");
tt(1);
resetF();
});
menuClicks.addEventListener("click", function () {
menuClicks.classList.add("active");
menuTimer.classList.remove("active");
cc(2)
resetF();
});
<div class="menu">
<button type="button" onclick="tf = 1" class="menu-timer">TIMER</button>
<button type="button" onclick="tf = 2" class="menu-clicks">CLICKS</button>
</div>
<div class="click-btn">
<button class="click" type="button">0</button>
<button class="start" type="button">START</button>
</div>
<button class="reset" type="button">Reset</button>
You have a typo with assigning = instead of equality operator ===
function cc(tf) {
if (tf = 1) { // should be ===
return;
}
...
}
Also before you addEventListener('click', ...), a good practice is to remove previous click listeners with removeEventListener('click')

Disable Button with a bind function?

Hello how can i disable a button with the bind function for 10 sec?
jQuery('#wsf-1-field-155').bind('click', function() {
ScanRegistration();
setTimeout(function() {
jQuery('#wsf-1-field-155').bind();
}, 10000);
})
I solved this Problem with this, I change .removeProp with .removeAttr
jQuery('#wsf-1-field-155').on('click', function() {
jQuery(this).prop('disabled', true);
ScanRegistration();
setTimeout(() =>
jQuery(this).removeAttr('disabled'), 20000);
})
Here's a plain JavaScript solution. scanRegistration() just counts up to 10sec.
Details are commented in example
// count and interval variables should be declared outside of function
let i = 0;
let int;
// Reference the <button>
const btn = document.querySelector('#GO');
// Function enables the <button>
const enableBtn = () => btn.disabled = false;
/*
Bind the "click" event to the <button>
Disable <button>
call scanRegistration()
call enableBtn() #10 seconds
*/
btn.onclick = function(event) {
this.disabled = true;
scanRegistration();
setTimeout(() => {
enableBtn();
}, 10000);
};
// Function logs every second
const logScan = i => console.log("SCAN: " + i);
/*
Set an interval at the rate of 1 second
Increment the count variable i
call logScan()
If i is equal to or more than 10 end interval
*/
function scanRegistration() {
console.log("START SCAN");
int = setInterval(() => {
i++;
logScan(i);
if (i >= 10) {
console.log("END SCAN");
clearInterval(int);
}
}, 1000);
}
<button id="GO">GO!</button>
.bind() is deprecated. You should use .on() instead.
You don't use event binding to disable a button, you set its disabled attribute. Then use removeAttr() to re-enable it after 10 seconds.
jQuery('#wsf-1-field-155').on('click', function() {
$(this).attr('disabled', true);
ScanRegistration();
setTimeout(() =>
$(this).removeAttr('disabled'), 10000);
})

Javascript: Disable double click everywhere

I want disable double click everywhere in my application to avoid multiple tipe of issue (eg. double calls to apis).
I have tried to listen all 'dblclick' event on document and stop propagation, but doesn't works, the click are excecuted.
I want prevent two prevent two clicks in rapid succession.
document.addEventListener('dblclick', (event) => {
console.log('click disabled!');
event.preventDefault();
event.stopPropagation();
return false;
}, true);
function testClick(){
console.log('click reached!');
}
function testDblClick() {
console.log('dblclick reached!');
}
<button onclick="testClick()" ondblclick="testDblClick()">Try double click</button>
Your code does prevent dblclick, but wasn't checking whether it does. It does not prevent two clicks in rapid succession.
Two answers for you:
Handle it by disallowing overlapping requests
Rather than prevent standard browser behavior, which will be surprising to users trying to use double-click to select words in the page and such, ensure that your code doesn't allow overlapping requests when it shouldn't. For example:
// Stand-in for something that takes time
function doSomethingThatTakesTime() {
return new Promise(resolve => setTimeout(resolve, 2000));
}
// Code triggered by the button
let running = 0;
function doOperation() {
if (running > 0) {
console.log("Call ignored, already running");
return;
}
++running;
updateUI();
console.log("Started running");
doSomethingThatTakesTime()
.finally(() => {
console.log("Done running");
--running;
updateUI();
});
}
// Update the UI to match our current state
function updateUI() {
document.getElementById("btn-start").disabled = running > 0;
}
// Handle clicks on the button
document.getElementById("btn-start").addEventListener("click", doOperation);
<button id="btn-start">Click to start</button>
Prevent two clicks on same element within X milliseconds
I don't recommend this, but it will prevent the processing of two clicks within X milliseconds on the same element:
document.getElementById("btn-start").addEventListener("click", function() {
console.log("Do the operation");
});
let lastClickElement = null;
let lastClickTime = Date.now();
document.addEventListener("click", function(e) {
const {target} = e;
const now = Date.now();
if (target === lastClickElement && (now - lastClickTime) < 2000) {
// Same element and less than two seconds
console.log("Second click denied");
e.preventDefault();
e.stopPropagation();
}
lastClickElement = target;
lastClickTime = now;
}, true);
<button id="btn-start">Start Operation</button>
Because it ran the function testClick() before listen to event dblclick, you can set timeout for function testClick like:
onclick="setTimeout(testClick, 100)"

Kill, abort, stop, cancel a previous call/queue to a javascript function

I have a function which will take some time to run on click event.
Following is merely an example and setTimeout is there only to simulate time it may take to run it. How can I ensure when a user click on an item any previous running function(s) is(are) cancelled and only the latest onclick function is fired?
i.e. if a user clicked on it 10 times. I want to only execute the only the 10th click not the 9 clicks before.
I am hoping for a pure/vanilla js solution... NOT jQuery
(function () {
var nav = document.querySelector('.nav__toggle');
var toggleState = function (elem, one, two) {
var elem = document.querySelector(elem);
elem.setAttribute('data-state', elem.getAttribute('data-state') === one ? two : one);
};
nav.onclick = function (e) {
setTimeout(function(){
toggleState('.nav ul', 'closed', 'open');
}, 5000);
e.preventDefault();
};
})();
fiddle: http://jsfiddle.net/6p94p48m/
You need to debounce your click handler.
var button = document.getElementById("debounced");
var clickHandler = function() {
alert('click handler');
}
var debounce = function(f, debounceTimeout) {
var to;
return function() {
clearTimeout(to);
to = setTimeout(f, debounceTimeout);
}
}
button.addEventListener('click', debounce(clickHandler, 5000));
<button id="debounced" href="#">debounced</button>
Or use underscore/lodash https://lodash.com/docs#debounce

Changing HTML on click in D3.js disables doubleclick [duplicate]

I've toggled click event to a node and I want to toggle a dbclick event to it as well. However it only triggers the click event when I dbclick on it.
So How do I set both events at the same time?
You have to do your "own" doubleclick detection
Something like that could work:
var clickedOnce = false;
var timer;
$("#test").bind("click", function(){
if (clickedOnce) {
run_on_double_click();
} else {
timer = setTimeout(function() {
run_on_simple_click(parameter);
}, 150);
clickedOnce = true;
}
});
function run_on_simple_click(parameter) {
alert(parameter);
alert("simpleclick");
clickedOnce = false;
}
function run_on_double_click() {
clickedOnce = false;
clearTimeout(timer);
alert("doubleclick");
}
Here is a working JSFiddle
For more information about what delay you should use for your timer, have a look here : How to use both onclick and ondblclick on an element?
$("#test-id").bind("click dblclick", function(){alert("hello")});
Works for both click and dblclick
EDIT --
I think its not possible. I was trying something like this.
$("#test").bind({
dblclick: function(){alert("Hii")},
mousedown: function(){alert("hello")}
});
But its not possible to reach double click without going through single click. I tried mouse down but it does not give any solution.
I pretty much used the same logic as Jeremy D.
However, in my case, it was more neat to solve this thing with anonymous functions, and a little slower double click timeout:
dblclick_timer = false
.on("click", function(d) {
// if double click timer is active, this click is the double click
if ( dblclick_timer )
{
clearTimeout(dblclick_timer)
dblclick_timer = false
// double click code code comes here
console.log("double click fired")
}
// otherwise, what to do after single click (double click has timed out)
else dblclick_timer = setTimeout( function(){
dblclick_timer = false
// single click code code comes here
console.log("single click fired")
}, 250)
})
you need to track double click and if its not a double click perform click action.
Try this
<p id="demo"></p>
<button id='btn'>Click and DoubleClick</button>
<script>
var doubleclick =false;
var clicktimeoutid = 0;
var dblclicktimeoutid = 0;
var clickcheck = function(e){
if(!clicktimeoutid)
clicktimeoutid = setTimeout(function(){
if(!doubleclick)
performclick(e);
clicktimeoutid =0;
},300);
}
var performclick =function(e){
document.getElementById("demo").innerHTML += 'click';
}
var performdblclick = function(e)
{
doubleclick = true;
document.getElementById("demo").innerHTML += 'dblclick';
dblclicktimeoutid = setTimeout(function(){doubleclick = false},800);
};
document.getElementById("btn").ondblclick = performdblclick;
document.getElementById("btn").onclick=clickcheck;
</script>
a slightly different approach - The actual click comparison happens later in the timeOut function, after a preset interval... till then we simply keep tab on the flags.
& with some simple modifications (click-counter instead of flags) it can also be extended to any number of rapid successive clicks (triple click, et al), limited by practicality.
var clicked = false,
dblClicked = false,
clickTimer;
function onClick(param){
console.log('Node clicked. param - ',param);
};
function onDoubleClick(param){
console.log('Node Double clicked. param - ',param);
};
function clickCheck(param){
if (!clicked){
clicked = true;
clickTimer = setTimeout(function(){
if(dblClicked){
onDoubleClick(param);
}
else if(clicked){
onClick(param);
}
clicked = false;
dblClicked = false;
clearTimeout(clickTimer);
},150);
} else {
dblClicked = true;
}
};

Categories

Resources