clearIntervall don't stop scrolling set with timer - javascript

I'm a js newbie but from what I read, using clearInterval with id returned previously by setInterval should reset the timer.
On a pedal push I receive a midi event with a positive value and then same event with a zero value on pedal release.
Using the code below, I can see my page turning red on release but the page keeps scrolling. Any idea why ?
function handleMIDIMessage(event) {
var scroll_id;
if (event.data.length === 3) {
if (event.data[0] == 176 && event.data[1] === 67) {
if (event.data[2] > 0) {
scroll_id = setInterval(function() {
window.scrollBy({
top: 50,
behaviour: "smooth"
});
}, 1000);
document.body.style.background = 'green';
} else {
document.body.style.background = 'red';
clearInterval(scroll_id);
}
}
}
}

You need to declare the interval outside so you do not keep creating a new variable and losing the id. You should probably also check to make sure you are not creating more than one interval.
//declare it so it is not overwritten
var scroll_id;
function handleMIDIMessage(event) {
if (event.data.length === 3) {
if (event.data[0] == 176 && event.data[1] === 67) {
if (event.data[2] > 0) {
// if we were defined before, cancel the last one
if (scroll_id) window.clearInterval(scroll_id);
scroll_id = setInterval(function() {
window.scrollBy({
top: 50,
behaviour: "smooth"
});
}, 1000);
document.body.style.background = 'green';
} else {
document.body.style.background = 'red';
clearInterval(scroll_id);
}
}
}
}

Related

Detect multiple keypresses and trigger an action once in p5.js

I want the user to be able to press a+d once and my game should increase the score, not hold it to increase score, similar to when pressing a+d causes a special effect to occur in a game.
This code did not work so I didn't bother to call it fail attempts test.
function keyPressed() {
if (key == 'a' && key == 'd')
score += 1;
}
This is my first failing attempt:
function keyPressed() {
if (key == 'a' || key == 'd')
score += 1;
}
This is my second failing attempt.
The reason for it is because when I press 1 button, it still increases the score and when pressing 2 buttons and holding them to increase faster but does not stop, which is not what I have in mind.
Score2keypress.js:
let RightButtom = false;
let LeftButtom = false;
let character = {
"score": 0
}
function setup() {
createCanvas(600, 600);
}
function draw() {
background(220);
// draw score character
fill(0, 0, 255); //move6
text("Score: " + character.score, 20, 120);
// update score increase character
if (RightButtom) {
character.score += 1;
} //move8
if (LeftButtom) {
character.score += 1;
} //move10
/////////////ScoreExtra
// show boolean values onscreen for clarity
textSize(20);
text("RightButtom = " + RightButtom +
"\nLeftButtom = " + LeftButtom, 10, 10, width / 2, height / 2);
}
//////////////ScoreExtra
function keyPressed() {
if (key == 'a') {
LeftButtom = true;
}
if (key == 'd') {
RightButtom = true;
}
}
function keyReleased() {
if (key == 'a') {
LeftButtom = false;
}
if (key == 'd') {
RightButtom = false;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>
There are a few approaches. The event-driven approach is using p5's keyPressed and keyReleased callbacks, pulling the key's code string from the native KeyboardEvent object. Adding and removing these key codes to a pressed set lets you implement variants of single-trigger logic.
const character = {score: 0};
const pressed = new Set();
function setup() {
createCanvas(600, 600);
textSize(20);
}
function draw() {
background(220);
text("Score: " + character.score, 20, 50);
}
function keyPressed(evt) {
const {code} = evt;
if (!pressed.has(code)) {
pressed.add(code);
if (pressed.has("KeyA") && pressed.has("KeyD")) {
character.score++;
}
}
}
function keyReleased(evt) {
pressed.delete(evt.code);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
If you want to detect and take action purely in draw, p5.js provides keyIsDown which accepts a parameter keycode.
const character = {score: 0};
const pressed = new Set();
function setup() {
createCanvas(600, 600);
textSize(20);
}
function draw() {
background(220);
text("Score: " + character.score, 20, 50);
if (keyIsDown(65) && keyIsDown(68)) {
if ((keyIsDown(65) && !pressed.has(68)) ||
(!pressed.has(65) && keyIsDown(68))) {
character.score++;
}
pressed.add(65);
pressed.add(68);
}
if (!keyIsDown(65)) {
pressed.delete(65);
}
if (!keyIsDown(68)) {
pressed.delete(68);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
As mentioned, there are multiple behavioral variants you can implement. Here's a variant that prevents retriggers with the same key:
const character = {score: 0};
const pressed = new Set();
function setup() {
createCanvas(600, 600);
textSize(20);
}
function draw() {
background(220);
text("Score: " + character.score, 20, 50);
if (keyIsDown(65) && !pressed.has(65) && // 'a' and 'd'
keyIsDown(68) && !pressed.has(68)) {
character.score++;
pressed.add(65);
pressed.add(68);
}
if (!keyIsDown(65)) {
pressed.delete(65);
}
if (!keyIsDown(68)) {
pressed.delete(68);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
In all above cases, the behavior lets the user press and hold one key indefinitely, then press the other. If you want these keys to be pressed on the exact same frame, or within n frames, you could remove the key from the set after it's been in there for n frames and add it to a requireRetrigger set that will prevent it from firing an action until it's been released. keyReleased might be handy here.
To detect to keys pressed together you need to monitor their state using keydown and keyup events.
var obj_down = {}
window.addEventListener("keydown", function(ev) {
if (obj_down[event.key]) {
// prevent multiple triggering
return
}
obj_down[event.key] = true;
if (obj_down["a"] && obj_down["d"]) {
console.log("a and d were pressed together! score++");
}
})
window.addEventListener("keyup", function(ev) {
delete obj_down[event.key];
})
Focus me with mouse then you can press "a" and "d" together

I created a stopwatch using JavaScript, and I'm trying to start/stop the timer by space key, but it doesn't stop but always became more faster

I created a stopwatch using JavaScript, and I'm trying to start/stop the timer by space key, but it doesn't stop but always became more faster.
'''
var timer_start = "S";
var time;
document.body.onkeyup = function (e) {
if (e.keyCode == 32) {
time = setInterval(timer, 10);
if (timer_start == "S") {
timer_start = "F";
} else if (timer_start == "F") {
clearInterval(time);
timer_start = "S";
}
}
};
,,,
Once the spacebar is pressed, you are starting the timer again regardless of the current value of timer_start. You need to move this to be inside the if statement. I'd also recommend using a Boolean instead of the string "S" and "F".
Here is my proposed rewrite of your code:
var timer_start = true;
var time;
document.body.onkeyup = function (e) {
if (e.keyCode == 32) {
if (timer_start) {
time = setInterval(timer, 10);
timer_start = false;
} else {
clearInterval(time);
timer_start = true;
}
}
};
You could also shorten it a bit by doing this if you wanted
var timer_start = true;
var time;
document.body.onkeyup = function (e) {
if (e.keyCode == 32) {
if (timer_start) {
time = setInterval(timer, 10);
} else {
clearInterval(time);
}
timer_start = !timer_start
}
};
You set the interval regardless of the timer_start state, so you keep piling up new intervals and remove only half of them. You should set the interval only in the timer_start == "S" branch.

How to determine if mouse is not over an element?

I know that there are many similar questions, but I can't understand what is the mistake in my if statement.
So basically I want to stop clicking nextBtn once I hover over timeoutArea,
but this: timeoutArea.mouseover != true doesn't seems to work.
const timeoutArea = document.getElementById("slider");
var time = 1;
let interval = setInterval(function() {
if (time <= 20 && window.pageYOffset < 393) {
if (timeoutArea.mouseover != true) {
nextBtn.click();
};
time++;
}
else {
time = 1;
}
}, 2000);
if u are using jquery u can use $('#slider').is(':hover') in if statement.
if u use only pure javascript u can use with one function
example fiddle https://jsfiddle.net/9x5hjpk3/
function isHover(e) {
return (e.parentElement.querySelector(':hover') === e);
}
so change
if (timeoutArea.mouseover != true) {
nextBtn.click();
};
to
if (!isHover(timeoutArea)) {
nextBtn.click();
};

Stop jquery event

I want if I call my second if else work then first one should stop. But that also keep running. If first one running second should stop.
if(e.keyCode == 39) {
setInterval(function(){
//
}, 10);
} else if(e.keyCode == 37) {
setInterval(function(){
//
}, 10);
}
setInterval() returns the ID of the set timer, that can be used to stop it.
Something like this should work:
var intervalId1, intervalId2;
if(e.keyCode == 39) {
intervalId1 = setInterval(function() { ... }, 10);
if (intervalId2) {
clearInterval(intervalId2);
}
} else if(e.keyCode == 39) {
intervalId2 = setInterval(function() { ... }, 10);
if (intervalId1) {
clearInterval(intervalId1);
}
}
You need to use a variable which is in a shared scope
//in a shared scope, probably outside teh function where this code is placed
var interval;
if (e.keyCode == 39) {
if (interval) {
clearInterval(interval);
}
interval = setInterval(function () {
//
interval = undefined;
}, 10);
} else if (e.keyCode == 37) {
if (interval) {
clearInterval(interval);
}
interval = setInterval(function () {
//
interval = undefined;
}, 10);
}
setInterval returns a handle which you can use to stop/clear the interval.
It is also important that you store this handle outside the function itself, or else it will be cleared next time the function runs.
Since you only care about one interval to run, you also only need to store one handle.
//define globally outside your function
var interval = null;
//your function starts here
interval && clearInterval(interval); // (same as if(interval){clearInterval(interval);})
if(e.keyCode == 39) {
interval = setInterval(function(){
//
}, 10);
} else if(e.keyCode == 37) {
interval = setInterval(function(){
//
}, 10);
}
Using one variable interval to store the return id of setInterval and whenever call to function clear that interval you will get what you need.
var interval;
$("#text_box").keydown(function(e){
e.preventDefault();
if(e.keyCode == 39){
clearInterval(interval);
interval=setInterval(sample1,1000);
}
else if(e.keyCode == 37){
clearInterval(interval);
interval=setInterval(sample2,1000);
}
});
function sample1(){
console.log("1");
}
function sample2(){
console.log("2");
}

How can i clearInterval(myFunc) after myFunc has executed 5 times?

The purpose of the code below is to alert online shoppers that they must select a color (via a select/option menu) before putting an item into their basket. If they don't select a color (ie, make a selection) some blinking text displays alerting them.
I'm trying to have the text blink 3 times then stop. I tried using some counter vars but didn't work. How can I re-write this so the blink executes 3 times only?
function blink() {
if ($('.pleaseSelect').css('visibility') == 'hidden') {
$('.pleaseSelect').css('visibility', 'visible');
} else {
$('.pleaseSelect').css('visibility', 'hidden')
}
}
function showNotice() {
timerId = setInterval(blink, 200);
}
$('#addToCart').click(function() {
if ($("select > option:first").is(":selected")) {
showNotice();
} else {
clearInterval(showNotice);
$('.pleaseSelect').css('visibility', 'hidden');
}
})
Well you can have counter declared and incremented each time blink is called. then check if you have called blink three times, clear the interval. Also your showNotice function is not defined properly.
var counter = 0,
timerId;
function blink() {
if ($('.pleaseSelect').css('visibility') == 'hidden') {
$('.pleaseSelect').css('visibility', 'visible');
} else {
$('.pleaseSelect').css('visibility', 'hidden')
if (counter > 4) {
showNotice(false);
}
}
counter++;
}
function showNotice(show) {
if (show) {
timerId = setInterval(blink, 200);
} else {
clearInterval(timerId);
counter = 0;
}
}
$('#addToCart').click(function () {
if ($("select > option:first").is(":selected")) {
showNotice(true);
} else {
showNotice(false);
$('.pleaseSelect').css('visibility', 'hidden');
}
})
Here is working fiddle
function blink(){
var blinkCount = 0;
return function () {
if($('.pleaseSelect').css('visibility')== 'hidden'){
$('.pleaseSelect').css('visibility', 'visible');
} else {
$('.pleaseSelect').css('visibility', 'hidden')
}
blinkCount = blinkCount + 1;
if (blinkCount === 3) {
clearInterval(timerId);
}
}
}
the only thing is that timeId is global - bad practice... however you would have to refactor more of your code in order to correct that issue.
another option is to just fadIn and fadeOut rather than what you're doing.
It would look something like:
if(element.val() == ''){
element.fadeOut("fast");
element.fadeIn("fast");
element.fadeOut("fast");
element.fadeIn("fast");
element.fadeOut("fast");
element.fadeIn("fast");
}
How about this example? Use an anonymous function to call your blink method and keep decrementing a counter.
id = setInterval(function () {
counter--;
if (!counter) {
clearInterval(id);
}
blink();
}, 200);
See the JSFiddle for the complete context.
You can accomplish the desired behavior using variables within a private scope:
$('#addToCart').click(function(e) {
blink(e);
});
function blink(e) {
var blink_count = 0;
var timer = setInterval(function(e) {
blink_count++;
$('.pleaseSelect').toggle();
if (blink_count >= 6) {
clearInterval(timer);
blink_count = 0;
}
}, 200);
}

Categories