Js Stopwatch dont start again once i reset - javascript

i start studying Js and i made this Stopwatch, but if i press reset, the stopwatch dont start again, unless i f5. I've tried some things but nothing seems to work, dont know what to do. I've seen others Js Stopwatch but they didnt help me to correct my mistake.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="cronometro.css">
<script src="cronometro.js"></script>
<title>Online Stopwatch</title>
</head>
<body>
<div class="main">
<header>
<p class="hText">Let's see your performance</p>
</header>
<div id="watch">
<span id="minutes">00</span>:<span id="seconds">00</span>:<span id="hundredths">00</span>
</div>
<br>
<div class="buttons">
<button onclick="startCron()" > Start</button>
<button onclick="pauseCron()" > Pause</button>
<button onclick="resetCron()" > Reset</button>
</div>
</div>
</body>
</html>
var hund = 0;
var sec = 0;
var min = 0;
var interval
function clockDigits(digit) {
if (digit<10) {
return ('0' + digit)
} else {
return digit
}
}
function startCron() {
interval = setInterval(watchTime,10);
}
function pauseCron() {
clearInterval(interval)
}
function resetCron() {
clearInterval(interval)
hund = 0
sec = 0
min = 0
document.getElementById('watch').innerText='00:00:00';
}
function watchTime() {
hund++
document.getElementById('hundredths').innerText=clockDigits(hund);
if (hund==100) {
sec++
hund=0
document.getElementById('seconds').innerText=clockDigits(sec);
} if (sec==60) {
min++
sec=0
document.getElementById('minutes').innerText=clockDigits(min);
}
}
i try to call function startCron() inside resetCron(), but didnt work

on reset, you set the inner text of
document.getElementById('watch')
it replaces minutes, second, and hundredths span.
because of that when you want to start the stopwatch again startCron does not find minutes, second, and hundredths span. that's why it gives an error.
replace document.getElementById('watch').innerText='00:00:00'; with
document.getElementById('minutes').innerText='00';
document.getElementById('seconds').innerText='00';
document.getElementById('hundredths').innerText='00';
and one more thing, disable the start button when the watch is started and enable it when the watch is paused or reset.

In the resetCron function, you set document.getElementById('watch').innerText = 00:00:00, this changed whole elements inside, it should be:
function resetCron() {
clearInterval(interval);
hund = 0;
sec = 0;
min = 0;
document.getElementById('watch').innerHTML='<span id="minutes">00</span>:<span id="seconds">00</span>:<span id="hundredths">00</span>';
}

Related

Scope of Function variable in Javascript: Looping through background colors

Can someone please explain to me why this doesn't work. I am aiming to loop through a javscript file to change the background colour of my html document on click. When I am to do this it doesn't loop through but then goes straight to yellow (the last of the loop)
const colors = ["blue", "green", "yellow"];
const btn = document.getElementById("btn");
function myFunction(){
for (let i=0; i<colors.length; i++){
document.body.style.backgroundColor = colors[i]
}
}
it automatically goes to i = 2 and creates a yellow background color
here is html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Colour Flipper</title>
<link rel="stylesheet" href="colourflipper.css">
</head>
<body>
<div class="top">
<ul>Colour Flipper</ul>
<ul>Simple Hex</ul>
</div>
<div class="main">
<button id="btn" onclick="myFunction()">
<h1>Background Colour</h1>
</button>
</div>
<script src="colourflipper.js"></script>
</body>
</html>
The problem you're having is that the entire myFunction code is being run on every click. Because your counter is defined in the function, it is reset every click, and the loop is running every time, and cycling through all of the colours, on every click. You're only seeing yellow because it is running too quickly for you to see the individual colours, and the loop is ending on yellow, as it is the last element in the colors array.
If you want to cycle colours on click, you need to store the state of the color outside of the function loop, because your event function should only needs to have code that will run every time a click happens.
Here is how I imagine you wanted it to work:
const colors = ["blue", "green", "yellow"];
const btn = document.getElementById("btn");
let colorIndex = -1;
function myFunction(){
colorIndex += 1;
if (colorIndex > colors.length-1) colorIndex = 0;
document.body.style.backgroundColor = colors[colorIndex]
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Colour Flipper</title>
<link rel="stylesheet" href="colourflipper.css">
</head>
<body>
<div class="top">
<ul>Colour Flipper</ul>
<ul>Simple Hex</ul>
</div>
<div class="main">
<button id="btn" onclick="myFunction()">
<h1>Background Colour</h1>
</button>
</div>
<script src="colourflipper.js"></script>
</body>
</html>
A slightly alternative approach to SubXaero's answer is to use a closure to maintain a local variable rather than creating a global one.
Note: I've used classes here instead of setting the background style directly.
const colors = ["blue", "green", "yellow"];
const btn = document.getElementById("btn");
const color = document.getElementById("color");
// Pass in `colors` to the handler which returns a new
// function that does all the work
btn.addEventListener('click', handleClick(colors), false);
// This function accepts colors as an argument
// initialises the array index, and then
// returns the function that will be used as the listener
function handleClick(colors) {
let index = 0;
return function() {
if (index < colors.length) {
color.classList.add(colors[index]);
++index;
}
}
}
.blue { background-color: blue; }
.green { background-color: green; }
.yellow { background-color: yellow; }
<div id="color">Colour</div>
<button id="btn">Background Colour</button>

Splicing/Removing selected array elements removes the other elements after the selected element

I am making an offline application of a music website using JS and I am handling song queues using arrays. I added song blocks with skip buttons so users can choose which song to skip without spamming another skip button that only allows them to skip the first song of the queue. The problem is, splicing the array with the index of the selected song the users wanted to skip removes the rest of the songs after it.
Example array: ["songA","songB","songC","songD","songE"]
If the user choose to skip songC, the song queue will become ["songA","songB"] and the songC to songE will be removed, but in reality the expected outcome should be ["songA","songB","songD","songE"].
I have no idea what is wrong with the code and I have searched similar topics regarding this problem but still no results. I am still new to JS and my code's a bit rough but I'm pretty sure that's not the cause of the issue.
JS:
//function of skip buttons on song blocks
songPlaylist.addEventListener("DOMNodeInserted", function() {
iconList = document.querySelectorAll(".deleteIcon");
iconList.forEach(function(element) {
element.addEventListener('click', function() {
var nameOfSong = this.parentNode.childNodes[0].dataset.name;
var indexByName = songQueue.indexOf(nameOfSong);
var selectedBlock = this.parentNode;
if (songQueue.length == 1) {
songQueue.shift();
songPlaylist.removeChild(songPlaylist.firstChild);
var emptyMsgSpan = document.createElement("div");
emptyMsgSpan.className += "emptyMsgSpan";
var emptyMsg = document.createTextNode("Playlist is empty! How 'bout adding some music?");
emptyMsgSpan.appendChild(emptyMsg);
document.getElementById("playlistContainer").appendChild(emptyMsgSpan);
setTimeout(function() {
audioPlayer.src = "";
}, 1000);
} else {
songQueue.splice(indexByName,1); // <--- press first block output delete everything
// press any block after first deletes everything beneath it
songPlaylist.removeChild(selectedBlock);
for (var blockIndex = indexByName; blockIndex <= songQueue.length; blockIndex++) {
document.getElementById("playlistContainer").children[blockIndex].childNodes[1].dataset.index -= 1;
}
};
});
});
});
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="index.css">
<link href="https://fonts.googleapis.com/css?family=Bai+Jamjuree" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Jost&display=swap" rel="stylesheet">
<!--<div>Icons made by Roundicons from www.flaticon.com</div>-->
<title>Mue - Custom Playlist</title>
</head>
<body>
<div id="bg">
<div class="titleBar">
<button style="background: none; border: none; cursor: pointer;" onclick="location.reload(); return false;">
<span>MUE</span>
</button>
</div>
<div class="songNameDisplay">
<span id="nowPlaying"></span>
</div>
<div class="trackContainer">
<div class="btn play"></div>
<div class="audioTrack">
<div class="trackBtn"></div>
</div>
<div id="skipBtn">
<div class="triangle1"></div>
<div class="triangle2"></div>
<div class="rect"></div>
</div>
</div>
<button id="fileBtn" class="fileBtn"><span>Upload</span></button>
</div>
<audio id="audioPlayer" controls autoplay></audio>
<input type="file" id="file" />
<div id="playlistContainer"></div>
</body>
<script src="index.js"></script>
<script>
const bg = document.getElementById("bg");
window.addEventListener('scroll' , function() {
let offset= window.pageYOffset;
bg.style.backgroundPositionY = offset * 0.5 + "px";
});
</script>
</html>
Thanks in advance.

Pomodoro seconds not showing up after first 60 seconds

I was trying out Pomodoro. Please refer to the snippet. The play and stop buttons are working fine but the second's element(var secEl = document.querySelector('.timesec');) doesn't show up after first 60 seconds.
<div class="timemin mt-4">25 <span>: </span><span class="timesec">00</span></div>
The function runs as expected but the seconds, stop showing up after the first 60sec. I assumed something wrong with document.querySelector.
Thank you.
var playEl = document.querySelector('.play');
var secEl = document.querySelector('.timesec');
var minEl = document.querySelector('.timemin');
var stopEl = document.querySelector('.stop')
playEl.addEventListener('click', startTime);
stopEl.addEventListener('click', stopTime);
let counter = 00;
let minCounter = 25;
var secCountDown;
function startTime(){
counter = 60;
secEl.innerHTML = counter;
// console.log('i am clicked', counter)
secCountDown = setInterval( countDown, 1000);
function countDown(){
counter--;
secEl.innerHTML = counter;
//console.log(secEl.innerHTML);
if( counter == 0){
clearInterval(secCountDown);
minCountDown();
// console.log('i am checked')
}
}
}
function minCountDown(){
minCounter --;
minEl.innerHTML = minCounter;
if( minCounter == 0 ){
//console.log('i am checked');
} else
{
startTime();
}
}
function stopTime(){
clearInterval(secCountDown);
minEl.innerHTML = 25;
secEl.textContent = 00;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<title>Document</title>
<style type = text/css>
.timerBorder{
border: 1px solid black;
min-height: 280px;
}
.time{
font-size: 60px;
}
</style>
</head>
<body>
<div class="row">
<div class="col">
<h1>Pomodoro</h1>
</div>
</div>
<div class="row">
<div class="col">
<div class="row justify-content-center">
<div class="col-5">
<div class="mt-4"><button>Working</button><button>Resting</button></div>
<div class="timemin mt-4">25 <span>: </span><span class="timesec">00</span></div>
<div class="mt-4">
<button class="play">Play</button>
<button class="stop">Stop</button>
<button>Pause</button>
</div>
</div>
<div id="time"></div>
</div>
</div>
</div>
<script src="./script.js"></script>
</body>
</html>
This happens because your HTML structure is not suitable for this. The .timemin element is the parent of the .timesec element, so as soon as you set the HTML of the first, the second is destroyed. Once that happens, the reference to the .timesec element is no longer attached to the document, and any update of its HTML has no visual effect any more:
<div class="timemin mt-4">25 <span>: </span><span class="timesec">00</span></div>
Instead, create a separate span for the minutes:
<div class="mt-4">
<span class="timemin">25</span> : <span class="timesec">00</span>
</div>

How to catch 'stop' event in HTML5 audio and then do something?

I'am beginner in HTML5 and not even middle in JS, but I'am trying to figure out how to correctly use <audio> and smth else... so i've got this question... my html:
<i class='some_icon' onclick='play();'>
<audio src='some_mp3.mp3' id='player'></audio>
</i>
Now when I click on the icon I want some mp3 file play and it works because I wrote this js:
function play() {
var my = document.getElementById('player');
if (my.paused) {
my.play();
} else {
my.pause();
my.currentTime = 0
}
}
BUT, besides, I want to change my icon WHEN that mp3 file ENDS... how can I do that? Any help will be greatly appreciated :)
Here is the code to trigger some code when your audio ( or video ) ends:
var my = document.getElementById('player');
my.addEventListener("ended", function(e){
// here goes your code to change the icon
}, false);
I know this was answered/accepted yesterday but i just thought I'd share a full working bit of code for future users benefit. (the sound clip is only 4 secs long)
function play() {
var my = document.getElementById('player');
my.currentTime = 0;
/**this one loops***/
if ($('.btn').find('span i').hasClass('fa-stop')) {
$('.btn').find('span i').removeClass('fa-stop').addClass('fa-play-circle');
$('.texto').text("Play");
}
if (my.paused) {
my.play();
} else {
my.pause();
my.currentTime = 0;
}
my.addEventListener("ended", function(e) {
$('.btn').find('span i').removeClass('fa-play-circle').addClass('fa-stop');
$('.texto').text("Stop");
});
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-1.11.3.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Audio Icon Toggle</title>
</head>
<body>
<div id="music">
<h2>Audio Icon Toggle</h2>
<button type="button" class="btn btn-success" data-toggle="collapse" data-target="#player" onclick="play();"><span><i class="fa fa-play-circle" aria-hidden="true"></i> <span class="texto">Play</span></span>
<audio src="http://www.rachelgallen.com/monkey.mp3" id="player" class="collapse"></audio>
</button>
</div>
</body>
</html>

Slideshow javascript play/pause button

I'm making a slideshow in Javascript with a play/pause button. When I press one time on the button, the slideshow starts to play. When I press a second time, the slideshow has to stop. I only have no idea how to put this function in one button.
Here's my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Oefening 19.7</title>
<link href="stijl_Oefening19_6.css" rel="stylesheet" />
<script>
var i = 0;
var foto = new Array(3);
var timer;
foto[0] = "images/slideshow/slideshow1.png";
foto[1] = "images/slideshow/slideshow2.png";
foto[2] = "images/slideshow/slideshow3.png";
foto[3] = "images/slideshow/slideshow4.png";
function slide() {
document.getElementById("slideshow").src = foto[i];
if (i < foto.length - 1) i++;
else i = 0;
timer = setTimeout("slide()", 3000);
}
</script>
</head>
<body>
<div id="portfolio">
<img src="images/slideshow/slideshow1.png" id="slideshow" alt="slideshow" />
</div>
<div id="button">
<a href="#" id="startcycle" onclick="slide()">
<img id="btnCycle" src="images/slideshow/cyclebutton.png" />
</a>
</div>
</body>
</html>
Use setInterval() instead. And separate the switch function and the slide function.
function slide() {
document.getElementById("slideshow").src = foto[i];
i = (i + 1)%foto.length;
}
function setTimer(){
if (timer) {
// stop
clearInterval( timer );
timer=null;
}
else {
timer = setInterval("slide()",1000);
}
}
Let the button call setTimer().

Categories

Resources