How to create a timer in javascript that limits an action - javascript

I would like to limit the use of the space bar in an application to once every second but I don't know how to implement it, this is my function
document.addEventListener('keyup', event => {
if (event.code === 'Space') {
console.log('Space pressed')
this.y-=1;
}
})

Below code is probably the easiest solution without additional Timing Events.
Every time your keyup event is fired you check if your delay time (e. g. 2 seconds -> 2000 ms) have passed. If that is the case you can go on and set now to the new latest value the space-bar has been clicked.
const delay = 2000;
let now = Date.now();
document.addEventListener('keyup', event => {
if (Date.now() > now + delay) {
if (event.code === 'Space') {
console.log('Space pressed')
this.y -= 1;
}
now = Date.now();
}
})

Simple solution to do that would be,
let disable = false;
document.addEventListener('keyup', event => {
// If disabled then do nothing
if( disable ){
return;
}
// Set disable to true to prevent future actions
disable = true;
if (event.code === 'Space') {
console.log('Space pressed')
this.y-=1;
}
// Turn off disable after 1 second
setTimeout( function(){ disable = false; },1000);
})

You can use setInterval()
function limiter() {
document.addEventListener('keyup', event => {
if (event.code === 'Space') {
console.log('Space pressed')
this.y -= 1;
}
}, {
once: true
})
}
setInterval(limiter, 1000);

Related

How can I make the webpage slow down autoscrolling on a button press?

As the title says - I'm looking to add some auto-scrolling on a specific webpage but the script that I have at the moment stops it completely from scrolling, which doesn't look visually appealing during presentations IMHO.
Is there a possibility to slow down instead of harshly stopping the auto-scrolling of the webpage on a specific keystroke?
This is the JS that I tried.
let scrollerID;
let paused = true;
let speed = 2; // 1 - Fast | 2 - Medium | 3 - Slow
let interval = speed * 5;
function startScroll(){
let id = setInterval(function() {
window.scrollBy(0, 2);
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
// Reached end of page
stopScroll();
}
}, interval);
return id;
}
function stopScroll() {
clearInterval(scrollerID);
}
document.body.addEventListener('keypress', function (event)
{
if (event.which == 13 || event.keyCode == 13) {
// It's the 'Enter' key
if(paused == true) {
scrollerID = startScroll();
paused = false;
}
else {
stopScroll();
paused = true;
}
}
}, true);
Thanks in advance!

How to control the interval of time between triggering of mousewheel event

I'm currently writing a website for a movie making company, which shows their different movies in full-screen.
I put each video in a list, and wrote a function that takes the user to the next video everytime a mousewheel event is triggered. The problem is that when the user is mousewheeling with a trackpad, it triggers multiple events at once, so I figured, I just had to set an interval between each triggering, depending on a variable "animating" that would be either true or false.
So here's my code :
let animating = false
$(window).bind('mousewheel', function (event) {
if (event.originalEvent.wheelDelta >= 0 && actuallyPlaying === false && animating === false) {
animating = true;
goToPreviousVideo();
setInterval(function () {
animating = false
}, 2000)
}
else {
if (actuallyPlaying === false && animating === false) {
animating = true;
goToNextVideo();
setInterval(function () {
animating = false
}, 2000)
};
}
});
And this piece of code works fine, but only for a few video "swipes". I noticed that after two or three times, this function stops working, and many events get triggered at the same time, which results in skipping all the videos and going from the top of the page straight to the bottom.
Do you guys have any idea why this isn't working ?
I'm also adding the code of goToNextVideo() and goToPreviousVideo() in case the problem is with them :
let i = 1 //
const goToNextVideo = function () {
if (i === 4) { // because I've got 4 videos
return;
} else {
$('html, body').animate({
scrollTop: $(`.video-${i + 1}`).offset().top
}, 500);
$(`.video-${i + 1}`).get(0).play();
i += 1
$(`.video-${i - 1}`).get(0).pause();
}
};
const goToPreviousVideo = function () {
if (i === 1) {
return
} else {
$('html, body').animate({
scrollTop: $(`.video-${i - 1}`).offset().top
}, 500);
$(`.video-${i}`).get(0).pause();
i -= 1
$(`.video-${i}`).get(0).play();
}
};
Thanks for your help !
Wish you all a great day
its seems your error is coming from the fact you dont clear the setInterval,
let animating = -1;
$(window).bind('mousewheel', function (event) {
if (event.originalEvent.wheelDelta >= 0 && actuallyPlaying === false && animating < 0) {
animating = setInterval(function () {
clearInterval(animating);
animating = -1;
}, 2000)
goToPreviousVideo();
}
else {
if (actuallyPlaying === false && animating < 0) {
animating = setInterval(function () {
clearInterval(animating);
animating = -1;
}, 2000)
goToNextVideo();
}
}
});
I am not able to understand where the problem is lying but
I have a cleaner and better approach to doing this Please tell if it works
var lastVideoChangeAnimation = Date.now()-2001;
$(window).bind('mousewheel', function (event) {
if (event.originalEvent.wheelDelta >= 0 && actuallyPlaying === false && Date.now()-lastAlertTime>2000) {
lastVideoChangeAnimation = Date.now();
goToPreviousVideo();
}
else if (actuallyPlaying === false && Date.now()-lastAlertTime>2000) {
lastVideoChangeAnimation = Date.now();
goToNextVideo();
};
});
THERE CAN ALSO BE A PROBLEM THAT THERE OCCURS SOME SORT OF ERROR AND YOUR CODE STOPS EXECUTING.
SO JUST CHECK IF THE CONSOLE IS GIVING SOME ERROR WITH POINTING TOWARDS THE FILE WHERE THESE TWO CODES ARE SAVED.
Also please tell in the comment that did it worked

Detecting two keyboard keys being down at the same time

I tried with this code to detect two keyboard arrows being simultaneously pressed:
document.addEventListener('keydown', event => {
if (event.keyCode === 38) {
console.log('up Arrow')
}
if (event.keyCode === 39) {
console.log('right Arrow')
}
})
But it doesn't work, however hard I try to press them at exactly the same time.
How can I cleanly fix this and detect when both keys are down ?
There's only one keyCode per event. You have to track the keys going down, and up:
// if you keep both up and down keys down, you'll get a message
let downKeys = {}; // the set of keys currently down
document.addEventListener('keydown', event => {
downKeys[event.keyCode] = true;
if (downKeys[38] && downKeys[40]) {
console.log("both down!");
}
});
document.addEventListener('keyup', event => {
downKeys[event.keyCode] = false;
});
(you have to go full page to test this snippet)
Here I use 2 flags to check if you are holding the keys.
If both flags are true then it means that you are holding both keys. So, you can perform anything inside the condition.
let holdKeyUp = false;
let holdKeyRight = false;
document.addEventListener('keydown', event => {
if (event.keyCode === 38) {
holdKeyUp = true;
}
if (event.keyCode === 39) {
holdKeyRight = true;
}
if (holdKeyUp && holdKeyRight) {
console.log("Both keys are pressed.");
}
})
document.addEventListener('keyup', event => {
if (event.keyCode === 38) {
holdKeyUp = false;
}
if (event.keyCode === 39) {
holdKeyRight = false;
}
})

grab both the right and the left clicks of a user simultaneously

So my problem is this,
I was wondering if there was a way to detect if a user right clicks and left clicks simultaneously and commit an action if doing so in jQuery. It seems like the code can only detect one right click or one left click at a time in mouse events.
UPDATE
Thanks for the answers, I decided ultimately that feature would be too funky to have for users when I was trying to implement it. Hopefully these answers will be able to help other people too.
You can create variables to hold the state of each mouse button individually and use that to determine whether both buttons are down:
window.isLeftMouseDown = false;
window.isRightMouseDown = false;
$(document).on('mousedown', function(e) {
if (e.which == 1)
window.isLeftMouseDown = true;
else if (e.which == 3)
window.isRightMouseDown = true;
if (window.isLeftMouseDown && window.isRightMouseDown) {
console.log('both down');
}
});
$(document).on('mouseup', function(e) {
if (e.which == 1)
window.isLeftMouseDown = false;
else if (e.which == 3)
window.isRightMouseDown = false;
});
https://jsfiddle.net/2j151tpt/
Something like this. It uses ES2015.
let left = false;
document.addEventListener('mousedown', e => {
if (e.button === 0) {
left = true;
} else if (e.button === 2 && left) {
fireYourFunctionForTwoButtons();
}
})
document.addEventListener('mouseup', e => {
if (e.button === 0) {
left = false;
}
});
My proposal is based on the elapsed time in milliseconds between the two consecutive clicks:
$(function () {
$('#btn').data('last-left-click', 0).on('mousedown contextmenu', function (e) {
var nowTime = Date.now();
if (e.which == 1) {
$(this).data('last-left-click', nowTime);
}
if (e.which == 3) {
// if less then 300 milliseconds....
if ((nowTime - $(this).data('last-left-click')) < 300) {
console.log('Both left and right clicked in sequence in less then 300 milliseconds!');
}
$(this).data('last-left-click', 0);
}
});
});
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<button id="btn">Click Me</button>

KeyDown doesn't continuously fire when pressed and hold

I have this Plunkr,
This contains a div, on which I bind a keydown event. On pressing right or left arrow, the div should start moving.
This works, in all browsers, but when the key is pressed and hold, the first keydown event is fired immediately (div once moves), and it waits for a time gap, and then it continues to move.
So this means the keydown event is once fired, then the browser waits to detect if there is a subsequent keyUp event as well, then after a short time (when there is no keyup), it continues to fires keydown events.
(to see the problem, focus on window, press right arrow and hold, div should move once 5px, then wait, and then again continue to move)
Question: Is there a way around, so I can just keep the key pressed, and div should immediately start moving, without waiting to detect subsequent keyup (once)?
$(function() {
$(window).keydown(function(e) {
console.log(e.keyCode)
if (e.keyCode == 39)
move(5, 'left', $('.mover'))
else if (e.keyCode == 37)
move(-5, 'left', $('.mover'))
})
})
function move(offset, direction, target) {
console.log($(target))
$(target).css(direction, (parseInt($(target).css(direction)) + offset) + 'px')
}
.mover {
height: 50px;
width: 50px;
display: inline-block;
background: black;
position: absolute;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='mover'></div>
I would suggest something on a timeout, like this
http://codepen.io/kevrowe/pen/qEgGVO
$(function() {
var direction,
movingTimeout = -1;
$(window).on('keydown', function(e) {
if (e.keyCode == 39) {
direction = 'right';
} else if (e.keyCode == 37) {
direction = 'left';
}
startMoving(direction);
});
function stopMoving() {
clearTimeout(movingTimeout);
movingTimeout = -1;
}
function startMoving(direction) {
if (movingTimeout === -1) {
loop(direction);
}
}
function loop(direction) {
move(direction === 'left' ? -5 : 5, $('.mover'));
movingTimeout = setTimeout(loop, 10, direction);
}
function move(offset, $target) {
$target.css('left', (parseInt($target.css('left')) + offset) + 'px')
}
$(window).on('keyup', function(e) {
stopMoving();
});
})
When keydown event occurs on the key you want to track, then store this information in a mapping or a flag somewhere.
When keyup event occurs, then clear the flag for the given key.
Then, on a timer, you could poll the state of the key mapping, and move the object for whatever key direction is being pressed.
Possibly there is a better solution then polling, but I don't know of a way to test if a key is down other than polling.
On keyup, would also need to check if needed to interrupt moving the object.
One solution would be to just continuously run the move function in a loop until keyup happens
if (e.keyCode == 39){
var stop = setInterval(function(){
move(5, 'left', $('.mover'))
}, 25);
window.on("keyup", function(){
//stop the loop
clearInterval(stop);
//and remove the keyup listener
window.off("keyup", arguments.callee);
})
} else if //etc...
For those that might interest, here is another approach to handle bi-directional movement. Ex: up + right keys = "North East" direction :
const FPS = 60;
const STEP = 5;
const UP_KEY = 90; // Z
const DOWN_KEY = 83; // S
const LEFT_KEY = 81; // Q
const RIGHT_KEY = 68; // D
const pressedKeys = [];
let movingTimeout = null;
function handleKeyDown(e) {
pressedKeys[e.keyCode] = true;
switch(e.keyCode) {
case DOWN_KEY:
case LEFT_KEY:
case RIGHT_KEY:
case UP_KEY:
e.preventDefault();
startMoving();
}
}
function handleKeyUp(e) {
pressedKeys[e.keyCode] = false;
const shouldStop = !pressedKeys[UP_KEY]
&& !pressedKeys[DOWN_KEY]
&& !pressedKeys[LEFT_KEY]
&& !pressedKeys[RIGHT_KEY]
;
if(shouldStop) {
stopMoving();
}
}
function startMoving() {
if(!movingTimeout){
loop();
}
}
function stopMoving() {
clearTimeout(movingTimeout);
movingTimeout = null;
}
function loop() {
const x = pressedKeys[RIGHT_KEY] ? STEP
: pressedKeys[LEFT_KEY] ? -STEP : 0;
const y = pressedKeys[DOWN_KEY] ? STEP
: pressedKeys[UP_KEY] ? -STEP : 0;
move(x, y);
movingTimeout = setTimeout(loop, 1000 / FPS);
}
function move(x, y) {
// Implement you own logic here for positioning / handling collisions
// Ex: store.dispatch({ type: "MOVE_PLAYER", x, y });
console.log(`Moving ${x} ${y} !`);
}
window.addEventListener('keydown', e => handleKeyDown(e));
window.addEventListener('keyup', e => handleKeyUp(e));
Hope this helps.
Cheers !
pure javascript
<input id="some" type="text">
var input=document.getElementById("some");
input.addEventListener("keydown",function(e){
if (e.which == 40) {
var stop = setInterval(function(){
console.log("ss:");
}, 60);
window.addEventListener("keyup", function(){
//stop the loop
clearInterval(stop);
//and remove the keyup listener
window.removeEventListener("keyup", arguments.callee);
})
}
})

Categories

Resources