Differentiating between mouseup mousedown and click - javascript

I know that mousedown happens when a user depresses the mouse button, mouseup happens when the release the mouse and click is of course two events mousedown and mouseup. I have three different events each dealing with these three events mouseup down and click. My question is how to differentiate between the three, now my mouse down has a timer, so I was thinking of adding a boolean in that timer and testing it within the click I tried this and it didn't work to my standards.
Mousedown- timer checks for certain classes then if none of these classes exist within the targeted element proceed
Mouseup- clear the timer
Click- open a module
I may have not made the boolean a global variable that each can read or not, or I am missing something completely. Here is an example quick code of my full code:
var isDown = false;
ee[i].addEventListener('click',function(){
if(isDown===false){
openModule();
}
},false);
ee[i].addEventListener('mousedown',function(){
var timer;
var $this = this;
timer = setTimeout(function(){
if($this.className == "class"){
isDown=true;
createActive();
}
},500);
},true);
ee[i].addEventListener('mouseup',function(){
clearTimeout(timer);
},false);
That is just a quick example. I may have missed some coding but I hope you catch my drift in the code above. Anyone know of a good way to differentiate between the three events?

I've rewritten your code utilizing jQuery...
var isDown = false;
var timer;
$('.class').mousedown(function(){
isDown = false;
timer = setTimeout(function(){
isDown = true;
//createActive();
console.log('MOUSE DOWN');
}, 500);
}).mouseup(function(){
if(isDown === false){
//openModule();
console.log('CLICK');
}else{
console.log('MOUSE UP');
}
clearTimeout(timer);
});
If you simply add jQuery to your page, my code will automatically attach itself to any element in your document with a class of 'class'.
I've commented out your createActive(); and openModule(); calls so that you can play around with it (viewing your javascript console at runtime will show you the script in action - remove the console.log() stuff when you're done playing). This code could be optimised a bit more but it will give you the general idea.
Your timer variable needed to be created globally (I moved it out of the function).
In this case (declaring a mousedown time barrier) the click function will be rendered useless so I've improvised it into the mouseup function.
It's good to know core javascript, but jQuery is just too easy and powerful to ignore.

Try this:
const isDown = ref(false)
const timer = ref(0)
const mouseDown = () => {
isDown.value = true
timer.value = setTimeout(() => {
isDown.value = false
}, 120)
}
const mouseUp = () => {
if (isDown.value === true) {
hideModal()
} else {
return
}
clearTimeout(timer.value)
}

Related

Javascript detect keyspressed

I am trying to write a program that detects mouse movement and keys pressed conditions.
If run with html, this java script program can detect the mouse moving. I applied a similar strategy and found out that 'keydown' is the correct command to use, yet when I run the program, the keys are not changing the output to "keys are pressed."
var timer;
// mousemove code
var stoppedElement = document.getElementById("stopped");
function mouseStopped() { // the actual function that is called
stoppedElement.innerHTML = "Mouse stopped";
}
window.addEventListener("mousemove", function() {
stoppedElement.innerHTML = "Mouse moving";
clearTimeout(timer);
timer = setTimeout(mouseStopped, 300);
});
//keypress code
var keysElements = document.getElementById('keyPressed');
function keysPressed() {
keysElement.innerHTML = "Keys not Pressed";
}
window.addEventListener("keydown", function() {
keysElement.innerHTML = "Keys Pressed";
clearTimeout(timer);
timer = setTimeout("keysPressed", 300);
});
I have a feeling that my addEventListener for keydown isn't the correct method to use. Which would be the correct js method for checking for keys pressed?
Thanks
You assign a value to keysElements but then later reference keysElement, which would be undefined. Change the assignment from var keysElements = ... to var keysElement = ....
I'm also assuming you have an HTML document that contains elements stopped and keyPressed, e.g.:
<div id="stopped"></div>
<div id="keyPressed"></div>
those elements will be necessary in order for the Javascript to work properly.
Are you doing a keypress in the window or in a text field?
For window, try something like this with jQuery if you like
$(document).keypress(function(e) {
//do something
});
If you want it on an text field, try
$( "#target_input_field" ).keypress(function() {
//do something
});
https://api.jquery.com/keypress/

escape from setInterval at end of game level

I'm writing a game using HTML5 canvas and Javascript. I'm using setInterval to animate the game and check for events at regular intervals. I've written multiple levels for the game, but I can't seem to escape the setInterval when a given level ends in order to start the next one. The code accurately detects when a level is won or lost and successfully clears the interval and renders the button, but the button does not fire.
Adding a button was my latest idea. I've also tried removing the canvas using jQuery and inserting a new one. I've also tried using clearRect on the canvas but it doesn't fire either.
Given that I can't return a value from setInterval, what are my options, if any? Is there another way to accomplish the same thing? Is there a separate error with my code that I've overlooked? Thanks!
Game.prototype.win = function(int) {
clearInterval(int);
var content = "<p style='color:white;'>You win</p><br><button id='next-level'>Next Level</button></menu>"
$('#controls').append(content)
};
Game.prototype.lose = function(int) {
clearInterval(int);
var content = "<p style='color:white;'>You Lose</p><br><button id='next-level'>Start Over?</button></menu>"
$('#controls').append(content)
};
Game.prototype.run = funtion () {
$('#start').click( function () {
$('#controls').empty();
var waveOne = new window.CrystalQuest.Wave(this.X_DIM, this.Y_DIM, this, Game.WAVE_ONE)
var game = this
var int = setInterval( function () {
if (waveOne.step() === "lost" ) {
game.lose(int);
} else if (waveOne.step() === "won") {
game.win(int);
}
waveOne.draw(this.ctx)
}, 20)
this.bindKeyHandlers(waveOne);
}.bind(this));
$('#next-level').click( function () {
$('#controls').empty();
...more code...
});
};
To stop a setInterval() you have to store the returned value from the original call to setInterval() in some persistent location and then call clearInterval() on that value.
Because you declared your interval with var as in var int, it was local only to that method and was not available anywhere else in the code.
There are a number of ways to do that in your code. I would probably suggest storing it as an instance variable like this:
Game.prototype.run = funtion () {
$('#start').click( function () {
$('#controls').empty();
var waveOne = new window.CrystalQuest.Wave(this.X_DIM, this.Y_DIM, this, Game.WAVE_ONE)
var game = this;
this.stop();
this.interval = setInterval( function () {
if (waveOne.step() === "lost" ) {
game.lose(int);
} else if (waveOne.step() === "won") {
game.win(int);
}
waveOne.draw(this.ctx)
}, 20)
this.bindKeyHandlers(waveOne);
}.bind(this));
$('#next-level').click( function () {
$('#controls').empty();
...more code...
});
};
Then, you can make a method that will stop the interval like this:
Game.prototype.stop = function() {
if (this.interval) {
clearInterval(this.interval);
this.interval = null;
}
}
And, change your other methods like this:
Game.prototype.win = function(int) {
this.stop();
var content = "<p style='color:white;'>You win</p><br><button id='next-level'>Next Level</button></menu>"
$('#controls').append(content)
};
Game.prototype.lose = function(int) {
this.stop();
var content = "<p style='color:white;'>You Lose</p><br><button id='next-level'>Start Over?</button></menu>"
$('#controls').append(content)
};
For your event handling issues, if you are destroying and recreating a button, then you will lose any event handlers that were attached to any DOM elements that got replaced.
You have two choices for how to fix it:
After you create the new DOM elements, you can again set the event handlers on the new DOM elements.
You can use "delegated event handling". This attaches the event handlers to a parent DOM object that is itself not replaced. The click event bubbles up to the parent and is handled there. The child can be replaced as many times as you want and the event handler will still work.
See these references for how to use delegated event handling with jQuery:
Does jQuery.on() work for elements that are added after the event handler is created?
jQuery .live() vs .on() method for adding a click event after loading dynamic html
JQuery Event Handlers - What's the "Best" method

How to detect if mouse button is held down for a certain amount of time after click

Hi I am quite new to javascript. I want to be able to fire an event when a user clicks on point in canvas(short press), and if holds that click down for 1500 ms, i should have another functionality. I should recognize the long press before the mouseup is done.
For ex:
el.addEventListener("mousedown", doMouseDown, false); el.addEventListener("mouseup", update, false);
function doMouseDown()
{
if (short press)
functionality of shortpress
if (longpress)
functionality of long press
}
function update()
//do some update of coordinates
There are a couple of keys that needs to be considered for this to work properly:
An element can only detect mouse events for itself when the mouse is over it. For mouseup to work properly it has to be monitored "globally" (on window or document), and the button status tracked.
A status for type the long-press must be tracked and respected in all stages. For example: if long press, make sure mouseup eventually respect the new status and is itself overridden (or you will get a mouseup on top of a longpress). If you do want the mouseup in any casejust ignore this point of course.
Functionality for multiple elements (see comment below)
You can make the handlers generic by referencing this inside the handler code. This way you can attach it to any element. The global handler for mouseup is only added once and will use a tracked target to distinguish which element caused the mousedown. The timer invoked code will have the element context bound (bind()) so we can use the generic longpress handler addressing the source element as well (see demo below).
Example
var d = document.querySelectorAll("div"),
isDown = false,
isLong = false,
target, // which element was clicked
longTID; // so we can cancel timer
// add listener for elements
d[0].addEventListener("mousedown", handleMouseDown);
d[1].addEventListener("mousedown", handleMouseDown);
d[2].addEventListener("mousedown", handleMouseDown);
// mouseup need to be monitored on a "global" element or we might miss it if
// we move outside the original element.
window.addEventListener("mouseup", handleMouseUp);
function handleMouseDown() {
this.innerHTML = "Mouse down...";
isDown = true; // button status (any button here)
isLong = false; // longpress status reset
target = this; // store this as target element
clearTimeout(longTID); // clear any running timers
longTID = setTimeout(longPress.bind(this), 1500); // create a new timer for this click
};
function handleMouseUp(e) {
if (isDown && isLong) { // if a long press, cancel
isDown = false; // clear in any case
e.preventDefault(); // and ignore this event
return
}
if (isDown) { // if we came from down status:
clearTimeout(longTID); // clear timer to avoid false longpress
isDown = false;
target.innerHTML = "Normal up"; // for clicked element
target = null;
}
};
function longPress() {
isLong = true;
this.innerHTML = "Long press";
// throw custom event or call code for long press
}
div {background:#ffe;border:2px solid #000; width:200px;height:180px;
font:bold 16px sans-serif;display:inline-block}
<div>Click and hold me...</div>
<div>Click and hold me...</div>
<div>Click and hold me...</div>
This will work for you (no jQuery here):
var mouseStatus = 'up';
var mouseTimeout;
myElement.addEventListener("mousedown",function() {
clearTimeout(mouseTimeout);
mouseStatus='down';
mouseTimeout = setTimeout(function(){
mouseStatus='longDown';
doSpecialStuffBecauseOfLongDown(); // put your secret sauce here
}, 1500);
}, false);
myElement.addEventListener("mouseup",function() {
clearTimeout(mouseTimeout);
mouseStatus='up';
}, false);

Call function once from multiple events

I've been working on webpages for a range of touch screen devices, and one of the most consistent problems is how touch events are handled.
Is there a nice way to only call a function once even when multiple (roughly) simultaneous events call it?
e.g.
$("body").on("mousedown touchstart MSPointerDown", function () {
alert("This message will appear multiple times on some devices.");
})
I've thought about using a timeout so the function can only be called once every 200 milliseconds or something similar (off the top of my head and untested):
var allowed = true;
$("body").on("mousedown touchstart MSPointerDown", function () {
if(allowed){
allowed = false;
alert("This message will hopefully only appear once!");
setTimeout(function () { allowed = true }, 200);
}
})
(For this question, I am NOT looking for plugin suggestions, I am aware there are lots of touch event plugins)
Is there a proper/nicer way to use multiple events as possible triggers for a single function? Could I alias the events in some way without breaking their other uses?
In effect, you're looking to take only the first event type that comes through and ignore all the others. This will still fire for future clicks/touches. Enter closures.
$(document).ready(function() {
function alertClosure() {
var eventType = null;
function doAlert(e) {
if (!eventType) {
eventType = e.type; // only the first eventType we get will be registered
}
if (e.type == eventType) {
alert("This message will hopefully only appear once!: " + e.type);
}
}
return doAlert;
}
$("body").on( "mousedown touchstart MSPointerDown", alertClosure() );
});
http://plnkr.co/edit/oz48d3
You could use $.one (rather than $.on)
Here : $.one documentation on jquery.com
If you want it to be subsequently called then you could rebind the handler on a timeout, something like this:
function handler(){
var called = false;
return function(ev){
if(!called){
called = true;
$("ul#messages").append($("<li>").text("event"));
setTimeout(bind, 1000); // rebind after a suitable pause
}
}
}
function bind(){
$("ul#messages").one("click", new handler())
};
$(function(){
bind();
});
https://jsfiddle.net/p3t6xo48/5/
This allows each bound handler to be run once, and once only, for multiple events, then it's rebound after a suitable pause.

How can I execute a setTimeout() only when the user is present (with the mouse movement) with jQuery

I have a function that updates a <div /> via AJAX:
function update() {
<!-- .ajax() -->
setTimeout(update(), 3000);}
}
What I need is that this is not executed when the user is not present on the website, so if there is no movement of the mouse (we will suppose that if move it is in the website) it will not update .mousemove(). By the way, there is any other thing that we can do to know is someone is active on the website?
How can this be done? Thank you in advance!
Edit: probably I explained bad. I need to know the way to only update when there is activity. Like Facebook does with his news feed, the front page. Thanks!
You could use a mousemove handler to track when the user last moved, and then have the process only happen if they last moved the mouse within X seconds. But of course, if the user is sitting there reading something, or if they're a keyboard-oriented kind of person, that will tend to miss that they are there... So you'd probably want to look at keydown as well.
Here's a mousemove example:
jQuery(function($) {
var count = 0, lastmove = new Date();
$(document).mousemove(function() {
++count;
lastmove = new Date();
$('#display').html("Moved " + count + " times");
});
});​
Then your update code could do this:
function update() {
if (new Date() - lastmove < 60000) { // 60 seconds
// Really do the update
}
else {
// Check back in a few seconds
setTimeout(update, 3000);
}
}
Off-topic, but you have an error in your update code. You have:
setTimeout(update(), 3000);
...which will call update immediately and then try to use its return value to schedule something to happen in three seconds. If you want the call to update to be scheduled to happen in three seconds, leave off the () after it:
setTimeout(update, 3000);
I think I might have ended up with something such as this. Avoids date arithmetic. Only cares whether there's been some activity since the last update().
window.activeFlag = false;
window.updateDelay = 3000;
$(document).bind('mousemove scroll keydown', function(){ activeFlag = true; });
function update() {
if(activeFlag) {
doWork();
activeFlag = false;
}
}
window.setTimeout(update, updateDelay);
edit: I've discovered a flaw in the code. The following is more appropriate:
window.activeFlag = false;
window.updateDelay = 3000;
$(document).bind('mousemove scroll keydown', function(){ activeFlag = true; });
function update() {
if(activeFlag) {
doWork();
activeFlag = false;
}
window.setTimeout(update, updateDelay);
}
update();
I think there is no easy way to determine if the user is present
I would use a combination of mousemove, scroll, keypress.
var bUpdate = false;
function update() {
if(bUpdate){
///perform your ajax request
}
}
$(document).mousemove(function(){
bUpdate = true;
setTimeout(function(){bUpdate=false;}, 3000);}
});

Categories

Resources