Javascript detect keyspressed - javascript

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/

Related

Delay execution after eventlistener is triggered

I'm new to javascript, and have a lot of confusions...
I'm trying to write a script in Tampermonkey which would allow to put the cursor at the end of the input area once "copy" event listener is triggered.
This is the site where I want to apply it: https://voicenotebook.com/#medtrdiv
The original code is:
var input = document.querySelector('#docel');
var textarea = document.querySelector('#docel');
var reset = function (e) {
var len = this.value.length;
this.setSelectionRange(len, len);
};
input.addEventListener('copy', reset, false);
textarea.addEventListener('copy', reset, false);
The problem is that if I click copy, it doesn't copy the text, though it puts the cursor at the end. So I guess the problem is that the function executes too soon.
I wanted to add some delay to this function, but nothing seems to work. So I think the solution would be to delay the function by 100ms once an eventlistener is triggered.
This is what I tried:
var input = document.querySelector('#docel');
var textarea = document.querySelector('#docel');
var reset = function (e) {
var len = this.value.length;
this.setSelectionRange(len, len);
};
textarea.addEventListener('copy', setTimeout(reset, 100), false);
input.addEventListener('copy', setTimeout(reset, 100), false);
I know this probably doesn't make sense at all. I've tried different things also. I've researched many topics about this, but nothing works for me. Can you please help me to figure it out?
Thank you in advance!
There are couple of issues in the code you have written.
id is supposed to be unique on the page.
You intent is to delay the setSelectionRange. This happens when the copy event is triggered. Move the setTimeout to inside the reset function.
Also you if you want to select the text from the start your first argument should be 0.
Your event gets triggered sometime in the future and wrapping reset function reference in the event handler really does nothing other than binding the event handler.
var input = document.querySelector('#docel1');
var textarea = document.querySelector('#docel2');
var reset = function(e) {
var context = this;
setTimeout(function() {
var len = context.value.length;
context.setSelectionRange(0, len);
}, 100);
};
input.addEventListener('copy', reset, false);
textarea.addEventListener('copy', reset, false);
<input id="docel1" />
<textarea id="docel2" />

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.

Differentiating between mouseup mousedown and click

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)
}

Categories

Resources