Detect key released without using keyup event - Javascript - javascript

IE appears not to always respond to a keyup event in one of my scripts.
I looked for an alternative way to detect if a key had been released.
Given that a held down key repeats the keydown event at intervals (except modifier keys on Mac), I thought it would be possible to increment a variable and listen for the point at which it stopped incrementing. When it stops incrementing, the key has been released?
Unfortunately, on occasions (not always), my script is detecting an end to the incrementing whilst the key is still held down. It tends to fail more if the key is held down for repeated short intervals. I have tested with IE and FF.
I have allowed for 2 seconds between checking each increment. Setting my Windows Control Panel to the slowest keyboard settings, 1 second would probably be sufficient.
<!DOCTYPE html>
<html>
<head>
<title>Detect keyup not using keyup event using Javascript</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
// opening variables
var keyDownCount = 0;
var nextLastTimeout1 = false;
var nextLastTimeout2 = false;
var lastCount = false;
var nextCount = false;
// function to compare the last two outcomes for keyDownCount by assigning them to variables lastCount and nextCount
function nextLastCount() {
if (lastCount) {
nextCount = keyDownCount;
if (lastCount === nextCount) {
// clear any outstanding timeouts
clearTimeout(nextLastTimeout1);
clearTimeout(nextLastTimeout2);
// they match, display the count in the html
document.getElementById('matched-next-last').innerHTML = keyDownCount;
} else {
// clear any outstanding timeouts
clearTimeout(nextLastTimeout1);
clearTimeout(nextLastTimeout2);
// reset variable
lastCount = false;
// they don't match, call the function again after allowing sufficient time for the key repetition rate to increment the keyDownCount
nextLastTimeout1 = self.setTimeout("nextLastCount()", 2000);
}
} else {
lastCount = keyDownCount;
if (lastCount === nextCount) {
// clear any outstanding timeouts
clearTimeout(nextLastTimeout1);
clearTimeout(nextLastTimeout2);
// they match, display the count in the html
document.getElementById('matched-next-last').innerHTML = keyDownCount;
} else {
// clear any outstanding timeouts
clearTimeout(nextLastTimeout1);
clearTimeout(nextLastTimeout2);
// reset variable
nextCount = false;
// they don't match, call the function again after allowing sufficient time for the key repetition rate to increment the keyDownCount
nextLastTimeout2 = self.setTimeout("nextLastCount", 2000);
}
}
}
// keydown listener
document.addEventListener('keydown', function(e) {
if (!e) e = window.event;
// listen for alt key down
if (e.altKey) {
if (keyDownCount === 0) {
// call nextLastCount() to start comparing the last two outcomes for keyDownCount
// allow sufficient time for the key repetition rate to increment keyDownCount
setTimeout("nextLastCount()", 2000);
}
// increment the counter on each keydown repeat
keyDownCount++;
// display the current count in the html
document.getElementById('display-count').innerHTML = keyDownCount;
}
});
// keyup listener
document.addEventListener('keyup', function(e) {
if (!e) e = window.event;
// listen for alt key released
if (!e.altKey) {
// clear any outstanding timeouts
clearTimeout(nextLastTimeout1);
clearTimeout(nextLastTimeout2);
// reset the counter and the html fields when the keys are released
keyDownCount = 0;
document.getElementById('display-count').innerHTML = keyDownCount;
document.getElementById('matched-next-last').innerHTML = "";
}
});
</script>
</head>
<body>
<p>Hold down the alt key to start the counter, relese to reset.</p>
<p>keyDownCount is: <span id="display-count"></span>
</p>
<p>Matching next and last detected on key count of: <span style="color:blue;" id="matched-next-last"></span>
</p>
</body>
</html>

In the unlikely event that someone else might need this, I resolved it as follows. Simplified code and only one timeout.
In Firefox, pressing the spacebar whilst the alt key is down will serve to simulate a non keyup event.
<!DOCTYPE html>
<html>
<head>
<title>Detect keyup without using keyup event</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
// opening variables
var keyDownCount = 0;
var nextLastTimeout = false;
var nextCount = false;
var lastCount = false;
var nextCountTime = false;
var lastCountTime = false;
// function to compare the last two outcomes for keyDownCount by assigning them to variables lastCount and nextCount
function nextLastCount() {
if (lastCount) {
nextCount = keyDownCount;
// record the time for use in calculating the keyboard delay
nextCountTime = +new Date(); // milliseconds since 01 January, 1970
if (lastCount === nextCount) {
// they match, display the count in the html
document.getElementById('matched-next-last').innerHTML = keyDownCount;
}else{
// reset variable
lastCount = false;
}
}else{
lastCount = keyDownCount;
// record the time for use in calculating the keyboard delay
lastCountTime = +new Date(); // milliseconds since 01 January, 1970
if (lastCount === nextCount) {
// they match, display the count in the html
document.getElementById('matched-next-last').innerHTML = keyDownCount;
}else{
// reset variable
nextCount = false;
}
}
}
// keydown listener
document.addEventListener('keydown',function(e) {
if(!e) e = window.event;
// listen for alt key down
if (e.altKey) {
// increment the counter on each keydown repeat
keyDownCount++;
// display the current count in the html
document.getElementById('display-count').innerHTML = keyDownCount;
// see below
clearTimeout(nextLastTimeout);
// call function
nextLastCount();
// calculate the keyboard delay i.e. time between repeated keystrokes
if (nextCountTime && lastCountTime) {
// returns an always positive value in milliseconds
var keyboardDelay = Math.abs(nextCountTime - lastCountTime);
}else{
// in the first few increments both count times are not available, use an estimate
var keyboardDelay = 3000; // also 500ms added below
}
// call nextLastCount() again, but on a delay that exceeds the keyboard delay
// .. for safety, add 500ms to the calculated / estimated keyboard delay
// this timeout will only complete when the increments stop
// .. see clearTimeout(nextLastStickyTimeout) above
nextLastTimeout = setTimeout("nextLastCount()",keyboardDelay + 500);
}
});
// keyup listener
document.addEventListener('keyup',function(e) {
if(!e) e = window.event;
// listen for alt key released
if (!e.altKey) {
// clear any outstanding timeouts
clearTimeout(nextLastTimeout);
// reset the counter and the html fields when the keys are released
keyDownCount = 0;
document.getElementById('display-count').innerHTML = keyDownCount;
document.getElementById('matched-next-last').innerHTML = "";
}
});
</script>
</head>
<body>
<p>Hold down the alt key to start the counter, release to reset.</p>
<p>In Firefox, pressing the spacebar whilst the alt key is down will simulate a non keyup event</p>
<p>keyDownCount is: <span id="display-count"></span></p>
<p>Matching next and last detected on key count of: <span style="color:blue;"id="matched-next-last"></span></p>
</body>
</html>

This seems like something that should have already been solved. Here is a SO question on the best input libraries out there: which is the best Javascript Keyboard event library.(Hotkeys,Shortcuts )
Ideally you don't want to reinvent the wheel.

Related

JavaScript KeyUp() event for more than single-digit

I'm building this simple JavaScript project where if I input number N then it will show 1 to N. I'm using keyup() event for this. If I remove N from the input field then It will show nothing, which is fine! Because I'm using the empty() function. It works for 1-9. But when I input 10, 11, 12... it first shows 1 then it shows 1 to 10 or 1 to 11 accordingly. I only need to see 1 to N(more than single-digit). I don't want to use button for this.
Here is my code:
$(document).ready(function() {
$('#code').keyup(function() {
let myCode = $('#code').val();
if (myCode == '') {
$('#output').empty();
}
for (let i = 1; i <= myCode; i++) {
$('#output').append(i + '<br>');
}
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="number" id="code">
<br>
<br>
<div id="output"></div>
</body>
</html>
If this problem has better solution kindly share.
You need to use the concept of debouncing using setTimeout.
Your event is getting fired twice, once when you press '1' and when you press '0'. You need to hold the event until you are done with entering the numbers. The below code would work
var timer;
$(document).ready(function() {
$('#code').keyup(function() {
clearTimeout(timer)
timer = setTimeout(function(){let myCode = $('#code').val();
if (myCode == '') {
$('#output').empty();
}
for (let i = 1; i <= myCode; i++) {
$('#output').append(i + '<br>');
}},1000)
})
});
As Barmar pointed out in the comments, you need to reset the output every time the event is fired.
The keyup event happens immediately after the release a keyboard key.
So your listener function is executed every digit you enter (after the release of the key).
So if you insert 155, it first will append number to 1-1, then from 1-15 (because when you type the second digit and release the key (event fired) your input contains 15), and at last digit it will print number from 1- to the current input value that is 155 (input contains 155) and so on if you add digits.
Thus your code would be:
$(document).ready(function () {
$('#code').on('keyup', function () {
let myCode = $('#code').val();
// when event happens reset the output field, so it is overridden with the new serie
$('#output').empty();
for (let i = 1; i <= myCode; i++) {
$('#output').append(`${i}<br>`);
}
});
});
Small suggestions:
Use a "buffer" for the output because the append method is a bit expensive to call every cycle. Better build the string apart and append it when you're done.
Use the input event, it's more semantic and related to input tag. And the event is fired whenever the input content change, so it's more immediate.
$(document).ready(function () {
$('#code').on('input', function () {
let myCode = $('#code').val();
$('#output').empty();
let string = '';
for (let i = 1; i <= myCode; i++) {
string += `${i}<br>`;
}
$('#output').append(string);
});
});

Native callback previous value of text input using JavaScript?

Edited:
I forgot to add a 'native' (for JS or browser) word to questions, as browsers (or JS i'm not sure) have a undo/redo feature in inputs, but it don't work with programmatically edited input and my main question is, if it is possible to add a code to trigger that native callback to previous value feature.
I tried to do this with document.execCommand paste/insertText but it didn't work and is marked as obsolete.
Old:
I have a custom action on keypress in input, for example where number have changed sign(+-) when '-' button is pressed.
I want to add that action to native undo/redo (ctrl+z/y) history stack, with preventing others default actions triggered when button responsible for my action is clicked.
Is this possible?
If no, to remove current, native undo/redo input feature, using event.preventDefault in crtl+z/y click detection would be enough? To replace it by custom undo/redo.
Is this dependable on browser?
I experimented with code on Firefox and Edge.
Is there something like History API for input available for JS and where i can read about it and how it is named in code?
As for similar topics in stack are old and i tried them but they didn't work (or i used them in wrong way).
$(document).ready(function() {
$(":input").on('keypress', function(e) {
//On minus button click, reverse sign for number in input:
if (e.key === '-') {
e.preventDefault();
//TODO: Add this change in input to undo/redo changes history:
$(this).val(-$(this).val());
}
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
Number: <input type="text" name="num"><br>
</body>
</html>
i3z slighty enchanted answer:
Ctrl+z instead of '-' button for Undo action.
Fixed bug with 2 clicks needed to use undo action after adding new element.
Sign change action from my question is added to code.
Added empty "" as default in history stack.
// Global Varaibles
// Edited: Added empty undo element, fixed undo working from 2nd click after adding new element to history.
var historyValues = [''];
var undoSteps = 2;
var maxSteps = 1;
var currentUndo = 1;
// Add event listener to track input and update historyValues
$(":input").on('input', function (evt) {
historyValues.push(this.value);
maxSteps = historyValues.length;
//console.log(historyValues);
// Check if 'Undo' been used if yes reset cause input been changed
if (undoSteps !== 2) {
undoSteps = 2;
}
});
$(document).ready(function() {
$(":input").on('keydown', function(e) {
if (undoSteps > maxSteps) {
// When you run out of backward steps, reset steps
undoSteps = 1;
}
// check for key (Edited: changed to z) and ensure 'currentUndo' not less than 0
if (e.ctrlKey && e.key === 'z' && currentUndo >= 0) {
e.preventDefault();
// tracking steps backward for every-time key '-' pressed
currentUndo = (maxSteps - undoSteps);
//console.log(maxSteps+' maxSteps - undoSteps '+undoSteps);
// Get previous value from history array
var newValue = historyValues[currentUndo];
//console.log(currentUndo+' current - value '+newValue);
$(this).val(newValue);
// Add +1 steps as we used undo once
undoSteps++;
}
});
$(":input").on('keypress', function(e) {
//Edited: Added custom action on key '-' press
if (e.key === '-') {
e.preventDefault();
$(this).val(-$(this).val());
//Trigger history
$(this).trigger('input');
}
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
Number: <input type="text" name="num"><br>
</body>
</html>
Simple Undo JS Script
You'll be able to capture event of (⌘ + z) or (CTRL + z). Therefore, you'll be able to preform this Undo JS implementation to have history stack of values every-time input changes.
You should have Event Listener (input) either via DOM or jQuery e.g.
$(":input").on('input', function (evt) {
console.log(this.value)
}
Now, you can trace any changes in input been targeted using jQuery Selector.
You should also define global variables inside your document, where you can track following:
History Stack (historyValues)
Steps To Take (undoSteps)
Maximum Steps (maxSteps)
Current Step (currentUndo)
Source Code
// Global Varaibles (Controls)
var historyValues = [''];
var undoSteps = 2;
var maxSteps = 1;
var currentUndo = 1;
// Add event listener to track input changes and update historyValues
$(":input").on('input', function (evt) {
historyValues.push(this.value);
maxSteps = historyValues.length;
//console.log(historyValues);
// Check if 'Undo' been used if yes reset cause input been changed
if (undoSteps !== 2) {
undoSteps = 2;
}
});
$(document).ready(function() {
$(":input").on('keydown', function(e) {
if (undoSteps > maxSteps) {
// When you run out of backward steps, reset steps
undoSteps = 1;
}
// Edited: Supports (⌘ + z and CTRL + z)
if ( (e.ctrlKey && e.key === 'z') || (e.metaKey && e.key === 'z') ) {
e.preventDefault();
// Ensure 'currentUndo' not less than 0
if (currentUndo >= 0) {
// tracking steps backward
currentUndo = (maxSteps - undoSteps);
// Get previous value from history array
var newValue = historyValues[currentUndo];
$(this).val(newValue);
// Add +1 steps as we used undo once
undoSteps++;
}
}
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
Number: <input type="text" name="num"><br>
</body>
</html>

How to code a button that only works when clicked multiple times

I am trying to code a simple quiz app. I am trying to put a hidden screen at the end when one clicks on a button 3 times at the end. This is what I have tried:
for (var i = 0; i > 2; i++) {
onEvent("button26", "click", function() {
setScreen("TrollScreen");
playSound("sound://default.mp3", false);
});
}
I am fairly new to code, and I'm not sure how to do this. Help is appreciated.
You need to keep the count of the clicks outside of the event handler. Then inside it you can check that value and show the screen or increase the counter accordingly.
var count = 0;
onEvent("button26", "click", function(){
if(count > 2){
setScreen("TrollScreen");
playSound("sound://default.mp3", false);
}else{
count++;
}
});
Since all DOM elements are actually objects, you can attach a property to them that will serve as a counter, thus when a button gets clicked, you increment that property by 1 and then check if it reached 3 already.
A more subtle approach is to use a helper function that attaches the event and set up the counter as a closured variable, here is how:
function attachEventWithCounter(elem, func, maxClickCount) {
let count = 0;
elem.addEventListener("click", function(e) {
count++;
if(count >= maxClickCount) {
func.call(this, e);
// and probably reset 'count' to 0
}
});
}
You can then use it like so:
attachEventWithCounter(myButton, myEventListener, 3);
attachEventWithCounter just takes a DOM element, a function that will serve as the event listener and a number that will be the maximum amount of tries. It then attaches a click event listener (you could pass in the type of the event as well if you want) and then whenever that event happens, it increments a locally declared variable count (initially set to 0) and checks if it reached the maximum amount of tries, if so it just calls the function passed as parameter (using Function#call to pass a custom this and the event argument to mimic the actual event listener).
Example:
function attachEventWithCounter(elem, func, maxClickCount) {
let count = 0;
elem.addEventListener("click", function(e) {
count++;
if(count >= maxClickCount) {
func.call(this, e);
count = 0;
}
});
}
let btn = document.getElementById("myButton");
function listener() {
alert("Clicked at last!!!");
}
attachEventWithCounter(btn, listener, 3);
<button id="myButton">Click me 3 times</button>
this will click the button three times every time you press it (at least I think). instead, make a counter variable that starts at 0 and increment it up by 1 each time the button is pressed. the put the action you want to perform inside in an if statement ie
if(counter >= 3){
//do some action
}
hope that helps!
you want to keep a counter variable outside the scope of the event to keep track of how many times it was clicked. Ex.
let counter = 0;
onEvent("button26", "click", function() {
if(counter >= 3) {
setScreen("TrollScreen");
playSound("sound://default.mp3", false);
}
counter ++;
});
//create a variable to check how many times the button has been clicked
var buttonClick = 0;
function CheckCount() {
//Check if the buttonClick variable is three
if (buttonClick == 3) {
//if it is equal to three, display the screen and play the sound
//below commented out for sake of demo
//setScreen("TrollScreen");
//playSound("sound://default.mp3", false);
document.getElementById('buttonclickcount').innerHTML = "You clicked it three times";
} else {
//if it is not so, then increment the buttonClick variable by 1
buttonClick++
//so you can see how many times the button has been clicked
document.getElementById('buttonclickcount').innerHTML = buttonClick;
}
};
<!--I would create an onclick event on the button itself that runs a function when -->
<button onclick="CheckCount()">You Win!</button>
<div id="buttonclickcount"></div>
You should look at using closures. This is where you define a variable before returning a function; your returned function closes around this variable. You could do something like in this fiddle.
const button = document.getElementById('button');
const output = document.getElementById('output');
const click = (function() {
let count = 0;
return function() {
count++;
if(count > 3) {
output.innerHTML = 'Count is greater than 3: ' + count
}
}
})();
button.addEventListener('click', click);

Make JavaScript Detect Buttons That Are Pressed In a Certain Order

I am trying to make a number keypad from 0 to 9 and when certain numbers get pressed in a certain order an event will happen.
So something like this
if ( button1 gets pressed then button2 then button3 )
alert('You did the code!')
}
else {
alert('You did not do the code')
}
No jQuery please
Thanks!
//sequence is 358
//SOLUTION
sequence = {
check : function(e){
sequence.value += this.textContent;
if (sequence.value == sequence.sequence)
{
alert(1);
sequence.value = "";
}
else
{
if (sequence.timer)
{
clearTimeout(sequence.timer);
}
sequence.timer = setTimeout("sequence.value=''", 1000);
}
},
value : "",
sequence : "358"
}
//THIS CODE ATTACHES CLICK HANDLERS TO THE BUTTON, NOT PART OF THE SOLUTION
Array.prototype.map.call(document.querySelectorAll("button"), function(element){
element.addEventListener("click", sequence.check, false);
});
//end
<button>7</button><button>8</button><button>9</button><br/>
<button>4</button><button>5</button><button>6</button><br/>
<button>1</button><button>2</button><button>3</button><br/>
<button>0</button>
How does this work. I don't want to pollute the global scope with values so I used an object to store the variables and the check method in.
The object is called sequence.
It has three properties
check, the method that checks the input when a button is clicked.
value, that holds the sequence value until the correct sequence is found.
sequence, the property that holds the correct value.
Each button on the page is assigned with a click handler. When clicked it fires sequence.check. Via the this keyword (referring to the button) we extract the number (via textContent). We add that number to the value string. Then we check if the value matches the sequence. If so execute some code (in this case an alert) and reset the value.
There is a timer set. If the user doesn't enter a new number within a second the timer will reset the value. setTimeout does this. The 1000 stands for 1000 milliseconds = 1 second.
I would achieve this by monitoring the keydown event, and if the key is a number, add in to an array. At the same time, check the array contents to see if they are in a certain defined order. If they are, fire whatever you need to do, if not, do nothing but add the key to the array. Once your sequence has been completed, clear the array to make way for a new sequence.
You could get complicated with things like, clearing the array after a certain interval of not completing the sequence etc.
Here is a simple system that does part of what you are looking for:
var buttons = document.querySelectorAll('button'),
i;
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function() {
var pressed = document.getElementById('pressed');
pressed.value += this.value + "|";
if (pressed.value === '1|2|3|') {
alert('You unlocked it!');
}
if (pressed.value.length >= 6) {
//Start over
pressed.value = "";
}
}, false);
}
<input id='pressed' type='text' />
<button value='1'>One</button>
<button value='2'>Two</button>
<button value='3'>Three</button>

jQuery on 'double click' event (dblclick for mobile)

I have the following jquery event handling function:
$('.target').on('dblclick', function() {
//respond to double click event
});
My issue is that this event handler doesn't work on touch devices (iPhone, iPad...). Can anyone recommend a reliable alternative to dblclick that works on touch devices and still allows comfortable double click use on full size devices?
I ended up building a custom double click function that will work on both mobile and desktop:
var touchtime = 0;
$(".target").on("click", function() {
if (touchtime == 0) {
// set first click
touchtime = new Date().getTime();
} else {
// compare first click to this click and see if they occurred within double click threshold
if (((new Date().getTime()) - touchtime) < 800) {
// double click occurred
alert("double clicked");
touchtime = 0;
} else {
// not a double click so set as a new first click
touchtime = new Date().getTime();
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="target">Double click me</div>
Alternatively, here is the JSfiddle Demo.
Add this to your index.html
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
I found the mobile zoom function would throw off Jquery's dblclick. Basically it says your viewport wont change effectively shutting off the zoom. This works for me on my Nexus 5 running Chrome.
I know the question has been answered but thought it would be worth putting the solution I use all the time, cheers:
var doubleClicked = false;
$('.target').on('click', function() {
if (doubleClicked) {
//do what you want to do on double click here
}
doubleClicked = true;
setTimeout(() => {
doubleClicked = false;
}, 300);
});
You can bind multiple event listeners on the element and use jQuery's tap event for the touch devices.
$( ".target" ).on({
dbclick: function() {
//do stuff
}, touch: function() {
//do the same stuff
}
});
Thanks for the solution - the only thing I did was add a timeout so that they could be treated as separate events
var touchtime = 0;
var delay = 800;
var action = null;
$(".target").on("click", function() {
/*Double Click */
if((new Date().getTime() - touchtime) < delay){
clearTimeout(action)
alert('dbl');
touchtime=0;
}
/* Single Click */
else{
touchtime = new Date().getTime();
action = setTimeout(function(){
alert('single');
},delay);
}
}));
Although I haven't tested it, might also be worth adding the following to a header section of any HTML <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/> as per: To "user-scalable=no" or not to "user-scalable=no"
The marked answer of #JRulle seems to work only for a single object, if u have many instances with the same class they will be considered as a single object
see the exampleFiddle example
My solution seems to work in cases like that
var touchtime = 0;
$('.target').on('click', function() {
if (touchtime == 0) {
touchtime = new Date().getTime();
} else {
if (((new Date().getTime()) - touchtime) < 800) {
alert("double clicked");
touchtime = 0;
} else {
touchtime = 0;
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<p class="target">click me!</p>
<p class="target">then click me!</p>
click link
Multiple targets with own doubleclick counter. The accepted solution has 2 bugs, that are fixed here:
If you click on target and click outside and click on target again within 800 ms, then the doubleclick event fires.
If you have multiple targets, click on different targets within 800 ms, and the doubleclick event fires.
$(document).on("click", function(e)
{
var MAX_DELAY_IN_MS = 800;
var current_time = new Date();
var targets = $(".target");
if ((typeof last_target == "undefined") ||
(last_target == 0))
{
last_target = e.target;
last_click = current_time;
}
else
{
if ((last_target == e.target) &&
((targets.is(e.target) == true) ||
(targets.has(e.target).length !== 0)) &&
(current_time - last_click < MAX_DELAY_IN_MS))
{
alert("double clicked");
}
last_target = 0;
last_click = 0;
}
});
div{display:inline-block; width:30px; height:30px; margin:5px;}
.target{background-color:lime;}
.no_target{background-color:orange;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="target"></div>
<div class="target"></div>
<div class="no_target"></div>
<div class="target"></div>
Programmatically all of the answers given above are fine.
When you double click on mouse button it's just the mass off your finger involved,
so it can be fast...
On the other hand when tapping touch screen usually much larger physical mass is involved.
Larger mass means slower times .
So my approach is "click two times" instead of double click.
Means a global variable e.g var ClickCounter=0;
Inside the function scope
ClickCounter++;
Check if ClickCounter ==2.
Execute your Code.
Reset counter ClickCounter=0
else return false or execute another code
I have an improvement to the code above, that didn´t detect a doubleclick after a single click:
var touchtime = 0;
$(".target").on("click", function() {
if (((new Date().getTime()) - touchtime) < 500) {
alert("double clicked");
}
touchtime = new Date().getTime();
});
This code detects all doubleclicks. I also reduced the touchtime to 500ms (standard doubleclick-time).
The only way is to detect double touch yourselves. You can do it by persisting last touch event timestamp like below:
if (e.touches.length === 1) {
if (this.lastTouchEventTimeStamp) {
const timeInMillisecondsSinceLastTouch = e.timeStamp - this.lastTouchEventTimeStamp;
if (timeInMillisecondsSinceLastTouch > 80 && timeInMillisecondsSinceLastTouch < 400) {
// double tap will be detected here
this.lastTouchEventTimeStamp = undefined;
const dblClickEvent = new DragEvent('dblclick', {
view: window,
bubbles: true,
cancelable: true
});
e.target.dispatchEvent(dblClickEvent);
}
}
this.lastTouchEventTimeStamp = e.timeStamp;
}
Came across this thread and wanted to supply an updated answer.
function doubleClick(event, callback) {
var touchtime = $(event.target).data("touch-time");
if (touchtime == undefined || touchtime == 0) {
// set first click
$(event.target).data("touch-time", new Date().getTime());
} else {
// compare first click to this click and see if they occurred within double click threshold
if (((new Date().getTime()) - touchtime) < 800) {
// double click occurred
callback();
$(event.target).data("touch-time", 0);
} else {
// not a double click so set as a new first click
$(event.target).data("touch-time", new Date().getTime());
}
}
}
It can then be used as follows:
$(selector).click(function(event){
doubleClick(event, function(){
console.log("Hello World");
});
});
This uses the Data Attribute versus a global variable to get/set the Touch Time.
The standard dblclick should work in modern mobile browsers.
This is it... in CoffeeScript
onDblClick = -> "...your function to be fired..."
dbl_click = null
$(element).on 'mousedown', ->
onDblClick() if dbl_click
dbl_click = true
setTimeout () ->
dbl_click = false
, 250
You need to enter "return false" to the end of the function like below
var touchtime = 0;
$('.dbclickopen').click(function() {
if(touchtime == 0) {
//set first click
touchtime = new Date().getTime();
} else {
//compare first click to this click and see if they occurred within double click threshold
if(((new Date().getTime())-touchtime) < 800) {
//double click occurred
touchtime = 0;
window.location = this.href;
} else {
//not a double click so set as a new first click
touchtime = new Date().getTime();
}
}
return false;
});

Categories