audio files will not work outside of javascript switch statement - javascript

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.

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

Html5 audio brief NaN time while building a custom player

My MinutesDuration and SecondsDuration gets set to NaN for a brief second and then switches to music duration as intended.
I am not using tag in my HTML the method is triggered onclick of a button.
How can i stop this NaN from happening?
previousSong () {
if (sound) {
if (this.isPlaying && sound.currentTime > 5) {
sound.currentTime = 0
} else {
sound.pause()
sound = new Audio(require('assets/YES.mp3'))
sound.play()
// I assume some if statement is needed before eventListener
sound.addEventListener('timeupdate', (update) => { this.updateTime(sound) })
}
}
},
updateTime (sound) {
const timeMinutes = Math.floor(sound.currentTime / 60).toFixed()
const timeSeconds = (sound.currentTime - timeMinutes * 60).toFixed()
this.TimeMinutes = (timeMinutes >= 10) ? timeMinutes.toString() : '0' + timeMinutes.toString()
this.TimeSeconds = (timeSeconds >= 10) ? timeSeconds.toString() : '0' + timeSeconds.toString()
const durationMinutes = Math.floor(sound.duration / 60).toFixed()
const durationSeconds = (sound.duration - durationMinutes * 60).toFixed()
this.DurationMinutes = (durationMinutes >= 10) ? durationMinutes.toString() : '0' + durationMinutes.toString()
this.DurationSeconds = (durationSeconds >= 10) ? durationSeconds.toString() : '0' + durationSeconds.toString()
}
You can use an inverse if statement for duration minutes and duration seconds.
Then if NaN, just don't finish the updateTime function and return.
if(!(DurationMinutes >= 0 || DurationMinutes < 0)){ /*is NaN*/ return; }
I have fixed this by adding this line of code at the beginning of updateTime() method:
const duration = sound.duration || 0

setInterval not repeating

I'm trying to change the background each 4 seconds but it jumps directly to the second condition and doesn't change anymore. Why is this happening?
var time = 1;
var func = function () {
'use strict';
if (time === 1) {
document.getElementById("top-background").style.backgroundColor = "#000";
time += 1;
}
if (time === 2) {
document.getElementById("top-background").style.backgroundColor = "#aaa";
time += 1;
}
if (time === 3) {
document.getElementById("top-background").style.backgroundColor = "#d5d5d5";
time -= 2;
}
};
setInterval(func, 4000);
Try using else if
var func = function () {
'use strict';
if (time === 1) {
document.getElementById("top-background").style.backgroundColor = "#000";
time += 1;
}
else if (time === 2) {
document.getElementById("top-background").style.backgroundColor = "#aaa";
time += 1;
}
else if (time === 3) {
document.getElementById("top-background").style.backgroundColor = "#d5d5d5";
time -= 2;
}
};
When time equals 1, you add 1 to time. This makes time equal 2. After that, you check if time equals 2, which it is! This makes you continue upwards until you reach the point where time equals to 3, and then you reset it to 1 again.
You need a way to check for only one condition. You could do this using if and elseifs:
if (time == 1) {
// Code...
} else if (time == 2) {
// Code...
} else {
// Code...
// Because it's not equal to 1 or 2, it must be 3.
}
Or, you can also use Javascript's Switch statements.
switch(time) {
case 1:
// Code...
break;
case 2:
// Code...
break;
case 3:
// Code...
break;
default:
// Something went wrong and it's not 1, 2, or 3
}

Javascript: How to increment only by 1 (instead of 1+1+1+1+...) while condition is true in a draw loop?

I'm attempting to build an app in Processing.js that rotates an array of objects every 15 min (seconds for now). My idea was to just increment the index every time the second hand strikes 0/15/30/45, but since it's inside a draw loop it executes +1 times every frame in that second, setting my index to like, 30. How can I ensure only one increment gets through?
var i = 0;
var draw = function() {
background(148, 221, 255);
var s = second();
var m = minute();
var h = hour();
text(h + " : " + m + " : " + s, 5, 395);
var Rotation = function() {
if (s === 0 || s === 15 || s === 30 || s === 45) {
i+= 1;
Array[i];
}
};
Rotation();
text(i,50,50);
};
Thanks
Add a variable that checks if the current inverval (0,15,30,45) has already been used / set.
var i = 0;
var last_interval;
var draw = function() {
background(148, 221, 255);
var s = second();
var m = minute();
var h = hour();
text(h + " : " + m + " : " + s, 5, 395);
var Rotation = function() {
if (s === 0 || s === 15 || s === 30 || s === 45) {
if(last_interval === undefined || last_interval != s){
last_interval = s;
i+= 1;
Array[i];
}
}
};
Rotation();
text(i,50,50);
};

setInterval function not stopping

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

Categories