Cancel touchend if touchmove fires - javascript

I'm building something mainly for use on tablets, where the user can tap an item on the screen and a class is applied to it. This is what I have so far:
The problems:
I want to use touch events to remove the class and add the class on touch end (to make it faster).
I don't want it to do anything if the user swipes (touchmoves).
I've tried a number of things, none of which have worked. The simplest I've tried (unsuccessfully) is this:
var dragging = false;
$(".items").on("touchmove", function(){
dragging = true;
});
$('.items').on("click touchend", function(event){
if (dragging = true){
}
else{
$('.items').removeClass('selected');
$(this).addClass('selected');
}
});

I would argue this is a more safe way of doing it
Setting variable to false
var dragging = false;
Setting var to true ontouchmove (allows you to reuse this code everywhere in your app)
$("body").on("touchmove", function(){
dragging = true;
});
Your button
$("#button").on("touchend", function(){
if (dragging)
return;
// your button action code
});
Resetting variable (important)
$("body").on("touchstart", function(){
dragging = false;
});

You want to use either of the following:
if(dragging == true)
Or, simply:
if(dragging)
You should only use a single = sign when you are setting a value, whereas two == signs should be used when checking a value. Therefore, your code should look like:
$('.items').on("click touchend", function(event){
if(!dragging)
{
$('.items').removeClass('selected');
$(this).addClass('selected');
}
});
Notice how you do not need to check if dragging == true because you are not running any code in this case. Instead you can simply check if dragging == false or, !dragging

You can just check if event is cancelable. It's false after touchmove
$('.items').on("click touchend", function(event){
if (event.cancelable){
$('.items').removeClass('selected');
$(this).addClass('selected');
}
});

where you have dragging check put
if (dragging == true){
dragging = false;
}
else{
$('.items').removeClass('selected');
$(this).addClass('selected');
}
it will reset it on release
also watch out for double calls on events as they sometimes trigger twice on some platforms best to check platform with first the following will help with checks
var clickEventType=((document.ontouchstart!==null)?'click':'touchend');
or
var clickEventType = 'touchend';
if(document.ontouchstart!==null)
{
clickEventType = 'click';
}

Related

Correct way to prevent triggering `click` if inner element is not hovered when mouse is released

I need to prevent hiding of a modal dialog when user clicks on the dialog, then moves the mouse outside of the dialog, and releases it. The dialog is placed inside outer div on which the click event is registered. Here is the example of the modal dialog and its setup.
So I've done the following:
var pointerDownElement = null;
$('.d1').on('mousedown', function(event) {
// this is how I do it to prevent triggering of click event
pointerDownElement = event.target;
// this is how a browser does it
pointerDownElement = event.currentTarget;
});
$('.d1').on('mouseup', function(event) {
var element = event.target;
if (element === pointerDownElement) {
console.log('triggering click');
}
});
Is this approach correct?
You're definitely on the right track. Slightly modified code:
var pointerDownElement = null;
$('.d1').on('mousedown', function(event) {
event.preventDefault();
pointerDownElement = event.currentTarget;
return false;
});
$('.d1').on('mouseup', function(event) {
if (event.target=== pointerDownElement) {
console.log('triggering click');
}
});
No need to assign a value to a variable if you're only going to use it once. Also, event.preventDefault(); and return false; will guarantee the default behavior of the event doesn't take place (not that there typically is one for mousedown, but I'm assuming you have a reason for including this code).

How to detect control+click in Javascript from an onclick div attribute? [duplicate]

This question already has answers here:
How can I check if a key is pressed during the click event with jQuery?
(5 answers)
Closed 5 years ago.
I need to know if the user is clicking or CONTROL CLICKING a div element.
I have seen examples on how to do it using event listeners.. but my code is already set in place, and is using an on-element onclick method..
HTML
<div id='1' onclick='selectMe()'>blah</div>
JS
function selectMe(){
//determine if this is a single click, or a cntrol click
}
...also would love to know if it was a left or right mouse button click.
In your handler, check the window.event object for the property ctrlKey as such:
function selectMe(){
if (window.event.ctrlKey) {
//ctrl was held down during the click
}
}
UPDATE:
the above solution depends on a proprietary property on the window object, which perhaps should not be counted on to exist in all browsers. Luckily, we now have a working draft that takes care of our needs, and according to MDN, it is widely supported. Example:
HTML
<span onclick="handler(event)">Click me</span>
JS
function handler(ev) {
console.log('CTRL pressed during click:', ev.ctrlKey);
}
The same applies for keyboard events
See also
KeyboardEvent.getModifierState()
2021 UPDATE: There are better ways to do this now. Please be sure to check out the other answers
I'd recommend using JQuery's keyup and keydown methods on the document, as it normalizes the event codes, to make one solution crossbrowser.
For the right click, you can use oncontextmenu, however beware it can be buggy in IE8. See a chart of compatibility here:
http://www.quirksmode.org/dom/events/contextmenu.html
<p onclick="selectMe(1)" oncontextmenu="selectMe(2)">Click me</p>
$(document).keydown(function(event){
if(event.which=="17")
cntrlIsPressed = true;
});
$(document).keyup(function(){
cntrlIsPressed = false;
});
var cntrlIsPressed = false;
function selectMe(mouseButton)
{
if(cntrlIsPressed)
{
switch(mouseButton)
{
case 1:
alert("Cntrl + left click");
break;
case 2:
alert("Cntrl + right click");
break;
default:
break;
}
}
}
Because it's been a several years since this question was first asked, the other answers are outdated or incomplete.
Here's the code for a modern implementation using jQuery:
$( 'div#1' ).on( 'click', function( event ) {
if ( event.ctrlKey ) {
//is ctrl + click
} else {
//normal click
}
} );
As for detecting right-clicks, this was correctly provided by another user but I'll list it here just to have everything in one place.
$( 'div#1' ).on( 'contextmenu', function( event ) {
// right-click handler
} ) ;
When there is a mouse click ctrlKey is event attribute which can be accessed as e.ctrlKey.
Look down for example
$("xyz").click(function(e)){
if(e.ctrlKey){
//if ctrl key is pressed
}
else{
// if ctrl key is not pressed
}
}
note: https://www.w3schools.com/jsref/event_key_keycode.asp
Try this code,
$('#1').on('mousedown',function(e) {
if (e.button==0 && e.ctrlKey) {
alert('is Left Click');
} else if (e.button==2 && e.ctrlKey){
alert('is Right Click');
}
});
Sorry I added e.ctrlKey.
Try this:
var control = false;
$(document).on('keyup keydown', function(e) {
control = e.ctrlKey;
});
$('div#1').on('click', function() {
if (control) {
// control-click
} else {
// single-click
}
});
And the right-click triggers a contextmenu event, so:
$('div#1').on('contextmenu', function() {
// right-click handler
})
You cannot detect if a key is down after it's been pressed. You can only monitor key events in js. In your case I'd suggest changing onclick with a key press event and then detecting if it's the control key by event keycode, and then you can add your click event.
From above only , just edited so it works right away
<script>
var control = false;
$(document).on('keyup keydown', function (e) {
control = e.ctrlKey;
});
$(function () {
$('#1x').on('click', function () {
if (control) {
// control-click
alert("Control+Click");
} else {
// single-click
alert("Single Click");
}
});
});
</script>
<p id="1x">Click me</p>
pure javascript:
var ctrlKeyCode = 17;
var cntrlIsPressed = false;
document.addEventListener('keydown', function(event){
if(event.which=="17")
cntrlIsPressed = true;
});
document.addEventListener('keyup', function(){
if(event.which=="17")
cntrlIsPressed = true;
});
function selectMe(mouseButton)
{
if(cntrlIsPressed)
{
switch(mouseButton)
{
case 1:
alert("Cntrl + left click");
break;
case 2:
alert("Cntrl + right click");
break;
default:
break;
}
}
}

How to track modifier keys using javascript/jquery?

My requirement is just easy: user press Ctrl key some notification appear on my page, and when released the notifications just disappear, so i need to track modifier keys such as Ctrl. Unfortunately i google and didn't find any clues, some famous keyboard libs such as Mousetrap and keymaster seem also does not cover this topic.
Any ideas?
Modifier keys trigger keydown (but not keypress). Then you can simply check the flags defined on the event object. shiftKey, altKey, ctrlKey, metaKey, etc.
A full list is here: http://api.jquery.com/category/events/event-object/
With jQuery, you can just use the keydown and keyup event handlers and you will see the Ctrl key go down and up. If you want to keep track of whether it's down or up, then just set a global flag when it goes down and clear the flag when it goes up.
Example code:
$(document).keydown(function(e) {
if (e.which == 17) {
$("#result").append("ctrl key pressed<br>");
}
});
JQuery doc on e.which: http://api.jquery.com/event.which/
Working demo: http://jsfiddle.net/jfriend00/mezwF/
Try this-
var ctrlKey = false;
window.onkeydown = function(e) {
if(e.keyCode == 17) {
ctrlKey = true;
}
};
window.onkeyup = function(e) {
if(e.keyCode == 17) {
ctrlKey = false;
}
};
function notify() {
if(ctrlKey) {
$('#notification').show();
} else {
$('#notification').hide();
}
}
function main() {
var _inter = setInterval(notify, 100);
}
main();

Keydown effect, alert if keyup before effect finishes

My goal: Press and HOLD space key while an effect occurs (to simulate a fingerprint scan). If user releases key before effect finishes, I want to display a confirm message. The keydown part works fine and proceeds to function "process", but no error message is displayed on keyup if it is released before the effect finishes. This is what I have...
var active = false;
$(document).one("keydown", function(e) {
if ((e.keyCode == 32) && (active == false)) {
active = true;
$(".panel_1").slideDown(5000, function() {
active = false;
$(".panel_1").slideUp(2000, function() {process(); })
});
}
});
$(document).one("keyup",function(e) {
if ((e.keyCode == 32) && (active == true)) {
var r=confirm("Oops! You must HOLD down the space key until scan is complete. Press OK to try again, or Cancel to return to homepage.");
if (r==true) {
reset();
}
else {
window.location.replace("home.html");
}
}
});
Verify that you are releasing the key during the first slideDown animation. According to your code, once it starts to slide up your active gets set to false and then makes it so the keyup event will not trigger.
Also as a side note I'd recommend using triple = in JavaScript.
Your code seems to work here: http://jsfiddle.net/D52eq/ but note that the confirmation message occurs only if the space bar is released during the .slideDown() phase of the effect - you're setting active = false; before the .slideUp() call.
If you want the confirmation if the space bar is released before completion of the entire animation and process() call then try this:
$(document).one("keydown", function(e) {
if ((e.keyCode == 32) && (!active)) {
active = true;
$(".panel_1").slideDown(5000).slideUp(2000, function() {
process();
active = false;
})
}
});
Note that then you can just chain the .slideDown() and .slideUp(), you don't need to supply a callback function to .slideDown(). Also I've replaced active == false with !active.
Demo: http://jsfiddle.net/D52eq/1/

JavaScript: Check if mouse button down?

Is there a way to detect if a mouse button is currently down in JavaScript?
I know about the "mousedown" event, but that's not what I need. Some time AFTER the mouse button is pressed, I want to be able to detect if it is still pressed down.
Is this possible?
Regarding Pax' solution: it doesn't work if user clicks more than one button intentionally or accidentally. Don't ask me how I know :-(.
The correct code should be like that:
var mouseDown = 0;
document.body.onmousedown = function() {
++mouseDown;
}
document.body.onmouseup = function() {
--mouseDown;
}
With the test like this:
if(mouseDown){
// crikey! isn't she a beauty?
}
If you want to know what button is pressed, be prepared to make mouseDown an array of counters and count them separately for separate buttons:
// let's pretend that a mouse doesn't have more than 9 buttons
var mouseDown = [0, 0, 0, 0, 0, 0, 0, 0, 0],
mouseDownCount = 0;
document.body.onmousedown = function(evt) {
++mouseDown[evt.button];
++mouseDownCount;
}
document.body.onmouseup = function(evt) {
--mouseDown[evt.button];
--mouseDownCount;
}
Now you can check what buttons were pressed exactly:
if(mouseDownCount){
// alright, let's lift the little bugger up!
for(var i = 0; i < mouseDown.length; ++i){
if(mouseDown[i]){
// we found it right there!
}
}
}
Now be warned that the code above would work only for standard-compliant browsers that pass you a button number starting from 0 and up. IE uses a bit mask of currently pressed buttons:
0 for "nothing is pressed"
1 for left
2 for right
4 for middle
and any combination of above, e.g., 5 for left + middle
So adjust your code accordingly! I leave it as an exercise.
And remember: IE uses a global event object called … "event".
Incidentally IE has a feature useful in your case: when other browsers send "button" only for mouse button events (onclick, onmousedown, and onmouseup), IE sends it with onmousemove too. So you can start listening for onmousemove when you need to know the button state, and check for evt.button as soon as you got it — now you know what mouse buttons were pressed:
// for IE only!
document.body.onmousemove = function(){
if(event.button){
// aha! we caught a feisty little sheila!
}
};
Of course you get nothing if she plays dead and not moving.
Relevant links:
MouseEvent's button (DOM 2)
MSDN's button
Update #1: I don't know why I carried over the document.body-style of code. It will be better to attach event handlers directly to the document.
This is an old question, and the answers here seem to mostly advocate for using mousedown and mouseup to keep track of whether a button is pressed. But as others have pointed out, mouseup will only fire when performed within the browser, which can lead to losing track of the button state.
However, MouseEvent (now) indicates which buttons are currently pushed:
For all modern browsers (including Safari v11.1+ [v11.3+ on iOS]), use MouseEvent.buttons
For Safari < 11.1 (11.3 on iOS), use MouseEvent.which (buttons will be undefined for Safari) Note: which uses different numbers from buttons for Right and Middle clicks.
When registered on document, mousemove will fire immediately as soon as the cursor reenters the browser, so if the user releases outside then the state will be updated as soon as they mouse back inside.
A simple implementation might look like:
var primaryMouseButtonDown = false;
function setPrimaryButtonState(e) {
var flags = e.buttons !== undefined ? e.buttons : e.which;
primaryMouseButtonDown = (flags & 1) === 1;
}
document.addEventListener("mousedown", setPrimaryButtonState);
document.addEventListener("mousemove", setPrimaryButtonState);
document.addEventListener("mouseup", setPrimaryButtonState);
That code tracks the state of the primary mouse button (typically the left), ignoring the state of other mouse buttons.
If more complicated scenarios are required (different buttons/multiple buttons/control keys), check out the MouseEvent docs.
I think the best approach to this is to keep your own record of the mouse button state, as follows:
var mouseDown = 0;
document.body.onmousedown = function() {
mouseDown = 1;
}
document.body.onmouseup = function() {
mouseDown = 0;
}
and then, later in your code:
if (mouseDown == 1) {
// the mouse is down, do what you have to do.
}
the solution isn't good.
one could "mousedown" on the document, then "mouseup" outside the browser, and on this case the browser would still be thinking the mouse is down.
the only good solution is using IE.event object.
I know this is an old post, but I thought the tracking of mouse button using mouse up/down felt a bit clunky, so I found an alternative that may appeal to some.
<style>
div.myDiv:active {
cursor: default;
}
</style>
<script>
function handleMove( div ) {
var style = getComputedStyle( div );
if (style.getPropertyValue('cursor') == 'default')
{
// You're down and moving here!
}
}
</script>
<div class='myDiv' onmousemove='handleMove(this);'>Click and drag me!</div>
The :active selector handles the mouse click much better than mouse up/down, you just need a way of reading that state in the onmousemove event. For that I needed to cheat and relied on the fact that the default cursor is "auto" and I just change it to "default", which is what auto selects by default.
You can use anything in the object that is returned by getComputedStyle that you can use as a flag without upsetting the look of your page e.g. border-color.
I would have liked to set my own user defined style in the :active section, but I couldn't get that to work. It would be better if it's possible.
If you're working within a complex page with existing mouse event handlers, I'd recommend handling the event on capture (instead of bubble). To do this, just set the 3rd parameter of addEventListener to true.
Additionally, you may want to check for event.which to ensure you're handling actual user interaction and not mouse events, e.g. elem.dispatchEvent(new Event('mousedown')).
var isMouseDown = false;
document.addEventListener('mousedown', function(event) {
if ( event.which ) isMouseDown = true;
}, true);
document.addEventListener('mouseup', function(event) {
if ( event.which ) isMouseDown = false;
}, true);
Add the handler to document (or window) instead of document.body is important b/c it ensures that mouseup events outside of the window are still recorded.
The following snippet will attempt to execute the "doStuff" function 2 seconds after the mouseDown event occurs in document.body. If the user lifts up the button, the mouseUp event will occur and cancel the delayed execution.
I'd advise using some method for cross-browser event attachment - setting the mousedown and mouseup properties explicitly was done to simplify the example.
function doStuff() {
// does something when mouse is down in body for longer than 2 seconds
}
var mousedownTimeout;
document.body.onmousedown = function() {
mousedownTimeout = window.setTimeout(doStuff, 2000);
}
document.body.onmouseup = function() {
window.clearTimeout(mousedownTimeout);
}
In case someone else runs into this, you can use .matches with the :active selector:
function mouseDown() {
return document.body.matches(":active");
}
Using the MouseEvent api, to check the pressed button, if any:
// Mouse buttons
document.addEventListener('mousedown', e => console.log(e.buttons))
// Keyboard keys
document.addEventListener('keydown', e => console.log(e.key))
Return:
A number representing one or more buttons. For more than one button
pressed simultaneously, the values are combined (e.g., 3 is primary +
secondary).
0 : No button or un-initialized
1 : Primary button (usually the left button)
2 : Secondary button (usually the right button)
4 : Auxilary button (usually the mouse wheel button or middle button)
8 : 4th button (typically the "Browser Back" button)
16 : 5th button (typically the "Browser Forward" button)
You can combine #Pax and my answers to also get the duration that the mouse has been down for:
var mousedownTimeout,
mousedown = 0;
document.body.onmousedown = function() {
mousedown = 0;
window.clearInterval(mousedownTimeout);
mousedownTimeout = window.setInterval(function() { mousedown += 200 }, 200);
}
document.body.onmouseup = function() {
mousedown = 0;
window.clearInterval(mousedownTimeout);
}
Then later:
if (mousedown >= 2000) {
// do something if the mousebutton has been down for at least 2 seconds
}
You need to handle the MouseDown and MouseUp and set some flag or something to track it "later down the road"... :(
Short and sweet
I'm not sure why none of the previous answers worked for me, but I came up with this solution during a eureka moment. It not only works, but it is also most elegant:
Add to body tag:
onmouseup="down=0;" onmousedown="down=1;"
Then test and execute myfunction() if down equals 1:
onmousemove="if (down==1) myfunction();"
Using jQuery, the following solution handles even the "drag off the page then release case".
$(document).mousedown(function(e) {
mouseDown = true;
}).mouseup(function(e) {
mouseDown = false;
}).mouseleave(function(e) {
mouseDown = false;
});
I don't know how it handles multiple mouse buttons.
If there were a way to start the click outside the window, then bring the mouse into the window, then this would probably not work properly there either.
As said #Jack, when mouseup happens outside of browser window, we are not aware of it...
This code (almost) worked for me:
window.addEventListener('mouseup', mouseUpHandler, false);
window.addEventListener('mousedown', mouseDownHandler, false);
Unfortunately, I won't get the mouseup event in one of those cases:
user simultaneously presses a keyboard key and a mouse button, releases mouse button outside of browser window then releases key.
user presses two mouse buttons simultaneously, releases one mouse button then the other one, both outside of browser window.
var mousedown = 0;
$(function(){
document.onmousedown = function(e){
mousedown = mousedown | getWindowStyleButton(e);
e = e || window.event;
console.log("Button: " + e.button + " Which: " + e.which + " MouseDown: " + mousedown);
}
document.onmouseup = function(e){
mousedown = mousedown ^ getWindowStyleButton(e);
e = e || window.event;
console.log("Button: " + e.button + " Which: " + e.which + " MouseDown: " + mousedown);
}
document.oncontextmenu = function(e){
// to suppress oncontextmenu because it blocks
// a mouseup when two buttons are pressed and
// the right-mouse button is released before
// the other button.
return false;
}
});
function getWindowStyleButton(e){
var button = 0;
if (e) {
if (e.button === 0) button = 1;
else if (e.button === 1) button = 4;
else if (e.button === 2) button = 2;
}else if (window.event){
button = window.event.button;
}
return button;
}
this cross-browser version works fine for me.
Below jQuery example, when mouse is over $('.element'), color is changing depending on which mouse button is pressed.
var clicableArea = {
init: function () {
var self = this;
('.element').mouseover(function (e) {
self.handlemouseClick(e, $(this));
}).mousedown(function (e) {
self.handlemouseClick(e, $(this));
});
},
handlemouseClick: function (e, element) {
if (e.buttons === 1) {//left button
element.css('background', '#f00');
}
if (e.buttons === 2) { //right buttom
element.css('background', 'none');
}
}
};
$(document).ready(function () {
clicableArea.init();
});
Well, you can't check if it's down after the event, but you can check if it's Up... If it's up.. it means that no longer is down :P lol
So the user presses the button down (onMouseDown event) ... and after that, you check if is up (onMouseUp). While it's not up, you can do what you need.

Categories

Resources