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
Related
Currently trying to make an app using html and Javascript. the goal is to have a timer countdown a session duration, then trigger an alarm and count down a break duration. after the break the session countdown starts again, then break again...repeat infinitely until user interference.
I created a button to start/pause the countdown and added event listener to give it a setinterval to count down, where I pass through the initial session time in a countdown function to display time:
counter = setInterval(()=>{
timedisplay = countdown(sessiontime);
}, 1000)
with the counter function i set up a bunch of conditions to display correct time format. and stop counting at 00:00 to initiate break:
function countdown(timeString){
console.log("run cd")
let countdowntime = timeString.split(":");
let mintogo = parseInt(countdowntime[0]);
let sectogo = parseInt(countdowntime[1]);
sectogo -= 1;
if (sectogo === -1 && timerlabel.innerText === "Session"){
sectogo = 6;
mintogo -= 1;
}
if (sectogo <= 9 && timerlabel.innerText === "Session"){
sectogo = "0" + sectogo
}
if (mintogo <= 9 && timerlabel.innerText === "Session"){
mintogo = "0" + mintogo
}
if (mintogo === "00" && sectogo === "00" && timerlabel.innerText === "Session"){
audiotest()
timerlabel.innerText = "Break"
mintogo = "00";
sectogo = "00";
clearInterval(counter)
so now I'm trying to toss in a breakcountdown function almost identical to the original countdown function except it passes breaktime as parameter instead of sessiontime. also as the breakcountdown reaches 00:00 it will do the exact same code as above except to stop and loop it back to the original countdown function this time (this is still within the countdown function):
breakcounter = setInterval(()=>{
timeleft.innerText = breakcd(breaklen.innerText + ":" + "00");
}, 1000)
}
return mintogo + ":" + sectogo
}
But obviously it doesn't quite work or i wouldn't be here. I think the logic is sound and this is executable but IDK where I made the mistake.
it currently runs fine until the alarm. at which point the display switches from "session" to "break" but the numbers displayed are bug. when i console log it shows that the second setinterval is triggered and ticking but although timedisplay is frozen and not updated. this is my breakcd function if you are interested, basically the same:
function breakcd(timeString){
console.log("run breakcd")
let breakcdtime = timeString.split(":");
let breakmintogo = breakcdtime[0];
let breaksectogo = breakcdtime[1];
breaksectogo = breaksectogo - 1;
if (breaksectogo === -1 && timerlabel.innerText === "Break"){
breaksectogo = 12;
breakmintogo -= 1;
}
if (breaksectogo <= 9 && timerlabel.innerText === "Break"){
breaksectogo = "0" + breaksectogo
}
if (breakmintogo <= 9 && timerlabel.innerText === "Break"){
breakmintogo = "0" + breakmintogo
}
if (breakmintogo === "00" && breaksectogo === "00" && timerlabel.innerText === "Break"){
timerlabel.innerText = "Session"
breakmintogo = "00";
breaksectogo = "00";
clearInterval(breakcounter)
counter = setInterval(()=>{
timeleft.innerText = countdown(timeleft.innerText);
}, 250)
}
console.log(breaksectogo)
return breakmintogo + ":" + breaksectogo
}
some of the values are hardcoded to make it faster for me to test but shouldn't reflect functionality.
How to convert a time string like 1m15s to 75s, 75 or 75000 ideally using momentjs.
I attempted to parse that string using new Date('1m1s') but it gives Invalid Date.
I don't want to resort to regex:
const second = (function () {
const countdownStep = '1h1m1s'.match(
/(?:(?<h>\d{0,2})h)?(?:(?<m>\d{0,2})m)?(?:(?<s>\d{0,2})s)?/i
);
return (
(countdownStep.groups.h
? parseInt(countdownStep.groups.h) * 3600
: 0) +
(countdownStep.groups.m
? parseInt(countdownStep.groups.m) * 60
: 0) +
(countdownStep.groups.s ? parseInt(countdownStep.groups.s) : 0)
);
})();
You can use the duration interface of momentjs:
let s = '1m15s';
// convert to duration format and pass to momentjs
let secs = moment.duration('PT' + s.toUpperCase()).as("seconds");
console.log("seconds: ", secs);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
Without library, it could be:
const unit = { s: 1, m: 60, h: 60*60 };
let s = '1m15s';
let secs = s.toLowerCase().match(/\d+./g)
.reduce((acc, p) => acc + parseInt(p) * unit[p.at(-1)], 0);
console.log("seconds: ", secs);
Another approach using plain js:
const getSecondsFromString = (str) => {
const hourIndex = str.indexOf("h")
const minuteIndex = str.indexOf("m")
const secondIndex = str.indexOf("s")
let hours = 0
let minutes = 0
let seconds = 0
if (hourIndex !== -1) {
hours = Number(str.substring(0, hourIndex))
}
if (minuteIndex !== -1) {
if (hourIndex !== -1) {
minutes = Number(str.substring(hourIndex + 1, minuteIndex))
} else {
minutes = Number(str.substring(0, minuteIndex))
}
}
if (secondIndex !== -1) {
if (minuteIndex !== -1) {
seconds = Number(str.substring(minuteIndex + 1, secondIndex))
} else if (hourIndex !== -1) {
seconds = Number(str.substring(hourIndex + 1, secondIndex))
} else {
seconds = Number(str.substring(0, secondIndex))
}
}
return hours * 3600 + minutes * 60 + seconds
}
Another approach without substring/replace, in O(n);
const getSecondsFromTimeString = (timeString) => {
let numberBeforeNextChar = 0;
let seconds = 0;
const symbolToSecondMap = {
"s" : 1,
"m" : 60,
"h" : 60*60,
"d" : 60*60*24
};
for (let i = 0; i < timeString.length; i++) {
let char = timeString.charAt(i);
if((+ char) <= 9 && (+ char) >= 0 ){
numberBeforeNextChar = (numberBeforeNextChar * 10) + parseInt(char);
continue;
}
if(char.toLowerCase() == char.toUpperCase()){
throw "Non alphanumeric symbol encountered";
}
if(symbolToSecondMap[char] === undefined){
throw "Invalid date alphabet encountered";
}
seconds = seconds + (numberBeforeNextChar * symbolToSecondMap[char]);
numberBeforeNextChar = 0;
}
return seconds;
}
console.log(getSecondsFromTimeString('1s'))
console.log(getSecondsFromTimeString('10s'))
console.log(getSecondsFromTimeString('1s4m10d3h'))
console.log(getSecondsFromTimeString('1s4m03h1h'))
console.log(getSecondsFromTimeString('10d'))
I tried this, is it helpful to you
let d = '1H1s';
d = d.toLowerCase();
let sec = 0;
if(d.indexOf('h') > -1) {
if (d.indexOf('m') == -1) {
d = d.substring(0, d.indexOf('h') + 1) +"0m"+d.substring(d.indexOf('h') + 1);
}
}
let newDs = d.replace('h',':').replace('m',':').replace('s','').split(':');
newDs.forEach((v, i) => sec += Math.pow(60, (newDs.length - i - 1)) * v);
console.log(sec);
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).
I use mousewheel event for some purpose, the functionality works fine though it gives error "property deltaY does not exist on type event". For which I couldn't build my project. Any help will be appreciated
H.addEvent(chart.container, 'mousewheel', function (event) {
console.log('whwel',e);
var xAxis = chart.xAxis[0];
var extremes = xAxis.getExtremes();
var step = 12 * 3600 * 1000;
var newMin = extremes.min;
var date = new Date(newMin);
if (event.deltaY < 0) {
date.getUTCDay() === 5 ? newMin += 3 * step : newMin += step;
} else {
date.getUTCDay() === 1 ? newMin -= 3 * step : newMin -= step;
}
xAxis.setExtremes(newMin, extremes.max, true);
});
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.