setInterval function not stopping - javascript

Level1();
var lvl1count = 0;
function Level1() {
var x = setInterval(function () {
lvl1count++;
var x = 84 + (Math.random() * (cw - 27));
var y = 84 + (Math.random() * (ch - 27));
Enemies.add(new Enemy(x, y, 1, 90));
}, 1000);
if (lvl1count == 4) {
console.log("finish");
clearInterval(x);return;
}
}
i am trying to add an object to a collection every 1000 ms when there is 4 object added i want to clear the Interval and stop the function but i am having the problem and the setInterval function is not stopping

Because the if check is not inside of the code that is being updated. if (lvl1count == 4) is only checked when Level1 is called. Move the check inside of your interval and it will work. You also need to change your variable names so they do not conflict.
function Level1() {
var timer = setInterval(function () {
lvl1count++;
var x = 84 + (Math.random() * (cw - 27));
var y = 84 + (Math.random() * (ch - 27));
Enemies.add(new Enemy(x, y, 1, 90));
if (lvl1count == 4) {
console.log("finish");
clearInterval(timer);
return;
}
}, 1000);
}
var lvl1count = 0;
Level1();

in your case u can use the setTimeout instead the setInterval like this
Level1();
var lvl1count = 0;
function Level1() {
setTimeout(function () {
lvl1count++;
//stuff
if(lvl1count++ <= 5) {
Level1();
}
}, 1000);
}

your latest if statement is executed just once, when you call the Level1 function. So you need to check the counter (the lvl1count variable) everytime you call the function inside setInterval:
var x = setInterval(function () {
lvl1count++;
var x = 84 + (Math.random() * (cw - 27));
var y = 84 + (Math.random() * (ch - 27));
Enemies.add(new Enemy(x, y, 1, 90));
if (lvl1count == 4) {
console.log("finish");
clearInterval(x);
return;
}
}, 1000);
Note: as pointed out by #epascarello this would require a change for a variable name. Since you already use x inside the anonimous function, change the setInterval assignment using another variable e.g.
var anotherVariable = setInterval(function () {
and
clearInterval(anotherVariable);

Related

Change value by two functions

I have functions which change value variable totalTime.
When I use first func value equals 189 - 50 (139).
After using second func I want to receive current value - 8 (131) but I have 189 - 8.
What am I doing wrong?
let totalTime = 189; // *
function calcTime(){
let hours = Math.trunc(totalTime/60);
let minutes = totalTime % 60;
let formatted = hours + 'h ' + minutes + 'm';
fullTimeDefault.innerHTML = formatted;
}
function workTimeDecrease() {
if(valueElem[0]) {
if (+valueElem[0].innerHTML === 15) {
return false
} else{
valueElem[0].innerHTML = parseInt(valueElem[0].innerHTML, 10) - step;
}
for(i = 0; i < barElem.length; i++) {
barElem[i].style.width = parseInt(valueElem[0].innerHTML, 10) + '%';
}
totalTime -= 50 // (1!)
}
}
function shortBreakDecrease() {
if(valueElem[2]) {
if (+valueElem[2].innerHTML === 3) {
return false
} else {
valueElem[2].innerHTML = parseInt(valueElem[2].innerHTML, 10) - step;
}
for(i = 0; i < barElem2.length; i++) {
barElem2[i].style.width = parseInt(valueElem[2].innerHTML, 10) + '%';
}
totalTime -= 8 // (2!)
}
}
elem.onclick = function(event) {
if (event.target.closest('.down-time')) {
workTimeDecrease();
calcTime();
} else if (event.target.closest('.up-time')) {
workTimeIncrease();
calcTime();
}
if (event.target.closest('.down-short-break')) {
shortBreakDecrease();
calcTime();
} else if (event.target.closest('.up-short-break')) {
shortBreakIncrease();
calcTime();
}
}
My thoughts are that this line isn't assigning totalTime to your output, though it is being modified internally (also "step" is defined nowhere)
valueElem[0].innerHTML = parseInt(valueElem[0].innerHTML, 10) - step;
Maybe if you pass in step as 50 then 8 in the 2 calls (change headers to take as parameter):
function workTimeDecrease(int step) {
function shortBreakDecrease(int step) { ...
Change:
valueElem[0].innerHTML = parseInt(valueElem[0].innerHTML, 10) - step;
...
valueElem[2].innerHTML = parseInt(valueElem[0].innerHTML, 10) - step;
To:
valueElem[0].innerHTML = totalTime - step;
...
valueElem[2].innerHTML = totalTime - step;
And change both totalTime assignemts to:
totalTime -= step;
You could also do an alert or log to console right after totalTime assignment to make sure that's not the problem (or all over, helps to check values - I use those extensively for debugging, sometimes every single line).

How Can I Subtract The Value Of A Object By The Value Of Another Object?

I'm new to coding so I might not have the best code but I have a object called computer and another called player. I want to subtract the value of the computers health by the value of the players attack power. Here is the code I currently have:
var player = {
health: 100,
attackPower: function () {
return Math.round(Math.random() * 10)
},
turnId: 0
}
var computer = {
health: 1,
attackPower: function () {
return Math.round(Math.random() * 10)
},
turnId: 1
}
function playerAttack() {
computer.forEach(e => e.health -= player.attackPower)
console.log(computer.health)
}
function computerChoice() {
ranNum = Math.round(Math.random() * 2)
if (ranNum == 1) {
return player.health - computer.attackPower
} else if (ranNum == 2) {
return computer.health + computer.attackPower
}
}
Any help will be appreciated
Thanks

Scroll with animation a WKWebView using pure Javascript

I use the following code which should scroll a webview at the given offset with given animation duration. But it doesn't work. I'm not very experienced with Javascript
- (NSString *)jsCodeScrollTo:(NSInteger)offset withAnimationDuration:(NSInteger)animationDuration
{
return [NSString stringWithFormat:#" scrollTo(document.documentElement, %ld, %ld); function scrollTo(element, to, duration) { if (duration < 0) return; var difference = to - element.scrollTop; var perTick = difference / duration * 10; setTimeout(function() { element.scrollTop = element.scrollTop + perTick; if (element.scrollTop === to) return; scrollTo(element, to, duration - 10); }, 10); }", offset, animationDuration];
}
It outputs:
scrollTo(document.documentElement, 2841, 2000);
function scrollTo(element, to, duration) { if (duration < 0) return;
var difference = to - element.scrollTop;
var perTick = difference / duration * 10;
setTimeout(function() { element.scrollTop = element.scrollTop + perTick;
if (element.scrollTop === to) return;
scrollTo(element, to, duration - 10); }, 10); }
I've used code posted in this thread: Cross browser JavaScript (not jQuery...) scroll to top animation
Is here a problem with JS code? or it has issues when running in WebKit (compatibility issues) ?
The solution is, first to insert JS function definition then to call it.
- (void)scrollTo:(NSInteger)offset withAnimationDuration:(NSInteger)animationDuration {
[self insertJavascriptAnimationFunction];
[webView evaluateJavaScript:[NSString stringWithFormat:#"scrollTo(document.body, %ld, %ld);", offset, animationDuration]
completionHandler:nil];
}
- (void)insertJavascriptAnimationFunction
{
[webView evaluateJavaScript:#"function scrollTo(element, to, duration) { var start = element.scrollTop, change = to - start, currentTime = 0, increment = 20; var animateScroll = function(){ currentTime += increment; var val = Math.easeInOutQuad(currentTime, start, change, duration); element.scrollTop = val; if(currentTime < duration) { setTimeout(animateScroll, increment); } }; animateScroll(); } Math.easeInOutQuad = function (t, b, c, d) { t /= d/2; if (t < 1) return c/2*t*t + b; t--; return -c/2 * (t*(t-2) - 1) + b; };"
completionHandler:nil];
}

audio files will not work outside of javascript switch statement

I am building an app that allow the user to set a duration to work (workSecs) and when completed a sound alerts the user (buzzer.mp3) and then a break duration (breakSecs) also set by the user begins, and when the break is completed a sound alerts the user (timer.mp3). I am using a switch statement to test when workSecs === 0 and when breakSecs === 0 and the unique alerts go off when either condition is true.
I have a setInterval function for my clock, strangely when I place my switch statement in the setInterval the sound works but it's repetitive because it's in the setInterval function, but when I remove it from within the setInterval function the alert does not work when the condition is true in the switch statement.
I am not sure if it's a scope issue because there are no errors in chrome's developer or firebug.
//audiotype object declare and sound method property
var Audiotypes = {
"mp3": "audio/mpeg",
"mp4": "audio/mp4",
"ogg": "audio/ogg",
"wav": "audio/wav",
soundbits: function (sound) {
var audio_element = document.createElement('audio')
if (audio_element.canPlayType) {
for (var i = 0; i < arguments.length; i++) {
var source_element = document.createElement('source')
source_element.setAttribute('src', arguments[i])
if (arguments[i].match(/\.(\w+)$/i)) source_element.setAttribute('type', Audiotypes[RegExp.$1])
audio_element.appendChild(source_element)
}
audio_element.load()
audio_element.playclip = function () {
audio_element.pause()
audio_element.currentTime = 0
audio_element.play()
}
return audio_element
}
}
}
// Clock object declared
var Clock = {
workSeconds: 0,
breakSeconds: 0,
// startTimer function begins here
startTimer: function () {
var self = this,
workSecs = this.workSeconds + 1,
breakSecs = this.breakSeconds + 1;
//workSecs and breakSecs switch statement begins here
switch (true) {
case (workSecs === 0):
alert('workSecs now 0')
var buzz = Audiotypes.soundbits('sounds/buzzer.mp3');
buzz.play();
break;
case (breakSecs === 0):
alert('breakSecs now 0')
var timer = Audiotypes.soundbits('sounds/timer.mp3');
timer.play();
}
// startTimer interval function begins here
this.interval = setInterval(function () {
if (workSecs > 0) {
workSecs--;
mins.html(Math.floor(workSecs / 60 % 60));
secs.html(parseInt(workSecs % 60));
} else if (breakSecs > 0) {
breakSecs--;
mins.html(Math.floor(breakSecs / 60 % 60));
secs.html(parseInt(breakSecs % 60));
} else if (breakSecs === 0) {
workSecs = self.workSeconds + 1;
breakSecs = self.breakSeconds + 1;
}
self.workSeconds = workSecs;
if (mins.html().length === 1) {
mins.html('0' + mins.html());
}
if (secs.html().length === 1) {
secs.html('0' + secs.html());
}
}, 1000)
}, //there is more code after this point but it's irrelevant to the problem
From your code, I assume you want to count down workSecs again after breakSecs ends and self.workSeconds = workSecs; is unintentional, since next time workSecs basically starts from 0.
The problem with your code is, that the switch statement only gets executed once when you call startTimer, but at that time your workSecs and breakSecs are this.workSeconds + 1 and this.breakSeconds + 1 which will never be zero (except if you set this.workSeconds and this.breakSeconds to -1).
When you put your switch statement into the interval handler, you didn't use proper conditions, and that's why it played it repetitively.
When it was counting breakSecs down to 0, workSecs was always zero and your sound played every second.
I changed your startTimer function to properly count down and use the proper conditions to play the sounds.
var Clock = {
workSeconds: 6,
breakSeconds: 3,
startTimer: function () {
var self = this,
workSecs = this.workSeconds,
breakSecs = this.breakSeconds;
this.interval = setInterval(function () {
if (breakSecs == self.breakSeconds && workSecs === 0) {
var buzz = Audiotypes.soundbits('sounds/buzzer.mp3');
buzz.play();
} else if (breakSecs == 0 && workSecs === 0) {
var timer = Audiotypes.soundbits('sounds/timer.mp3');
timer.play();
workSecs = self.workSeconds,
breakSecs = self.breakSeconds;
}
if (workSecs > 0) {
var m = Math.floor(workSecs / 60 % 60);
var s = workSecs % 60;
mins.text(m < 10 ? '0'+m : m);
secs.text(s < 10 ? '0'+s : s);
workSecs--;
} else if (breakSecs > 0) {
var m = Math.floor(breakSecs / 60 % 60);
var s = breakSecs % 60;
mins.text(m < 10 ? '0'+m : m);
secs.text(s < 10 ? '0'+s : s);
breakSecs--;
}
}, 1000);
},
};
I hope that's what you wanted.

JSLint: how not to make THIS function within a loop

In my angular application, I am using a loop to find in an object the nearest value to a given number and return its key.
For example, I want the closest values to 0.5:
for (var j in nums) {
if (0.5 > nums[j]) var prev = nums[j];
else if (0.5 <= nums[j]) {
// If the current number is equal to 0.5, or immediately higher, stores that number
// and stops the for each() loop
var next = nums[j];
// Get the value
var percentage = (Math.abs(0.5 - prev) < Math.abs(next - 0.5)) ? prev : next;
// Get the key from the value
$scope.seventyfive = parseInt('0' + Object.keys(nums).filter(function(key) {return nums[key] === percentage;})[0], 10);
break;
}
}
JSLint is pointing out that I shouldn't make functions within a loop, so I am trying to avoid that with:
filterPct = function (nums, pct) {
return function () {
return nums[key] === pct;
};
}
and
for (var j in nums) {
if (0.5 > nums[j]) var prev = nums[j];
else if (0.5 <= nums[j]) {
// If the current number is equal to 0.5, or immediately higher, stores that number
// and stops the for each() loop
var next = nums[j];
// Get the value
var percentage = (Math.abs(0.5 - prev) < Math.abs(next - 0.5)) ? prev : next;
// Get the key from the value
$scope.seventyfive = parseInt('0' + Object.keys(nums).filter(filterPct(nums, percentage))[0], 10);
break;
}
}
But this is returning 0 instead of the right value. I am positive I am missing something obvious, but I obviously need another pair of eyes...
UPDATE: Thanks to the support I received, this is the error-proof version of the code above:
filterPct = function (nums, pct) {
return function (key) {
return nums[key] === pct;
};
};
// Store the value with 50% Confidence
for (i in nums) {
if (nums.hasOwnProperty(i)) {
if (0.5 > nums[i]) {
prev = nums[i];
} else if (0.5 <= nums[i]) {
// If the current number is equal to 0.5, or immediately higher, stores that number
// and stops the for each() loop
next = nums[i];
// Get the value
percentage = (Math.abs(0.5 - prev) < Math.abs(next - 0.5)) ? prev : next;
// Get the key from the value
$scope.fifty = parseInt('0' + Object.keys(nums).filter(filterPct(nums, percentage))[0], 10);
break;
}
}
}
filterPct = function (nums, pct) {
return function () {
return nums[key] === pct;
};
}
You forgot to define key (it should be the first argument of the inner function).

Categories