Forcing AngularJS to reload updated value on html end - javascript

I have a timer that I am writing as my first application in AngularJS. I have been trying to teach myself angular but I believe there may be a fundamental disconnect in how I have my model set up. Although I can see the updated values in the web console via my console.log print outs, the timer on the html side is not appearing to update.
var myApp = angular.module('countdownTimer', []);
myApp.service('timerService',['$http','$timeout', function($http, $timeout){
var time = 180;
var self = this;
this.getPrettyTime = function(){
var minutes = time/60;
var seconds = time - minutes * 60;
if (seconds < 10){
myDateObject.date = minutes + ":0" + seconds;
}
else{
myDateObject.date = minutes + ":" + seconds;
}
return myDateObject;
}
var myDateObject = {
date: null
}
var onTimeout = function() {
time = time - 1;
if (time > 0){
console.log(time);
mytimeout = $timeout(onTimeout, 1000);
}
else{
time = 180;
mytimeout = $timeout(onTimeout, 1000);
}
}
this.start = function() {
$timeout(onTimeout, 1000);
}
}]);
myApp.controller('CounterController', ['$timeout','$scope', 'timerService', function($timeout, $scope, timerService){
/**$scope.counter = 180;
**/
//var date = new Date(null);
//date.setSeconds(timerService.getTime());
$scope.myDateObject = timerService.getPrettyTime();
$scope.start = function(){
timerService.start();
}
$scope.stop = function(){
$timeout.cancel(mytimeout);
}
}]);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Example </title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script src="app2.js"></script>
</head>
<body data-ng-app="countdownTimer">
<div data-ng-controller="CounterController">
{{myDateObject.date}}
<button data-ng-click="stop()">Stop</button>
<button data-ng-click="start()">Start</button>
</div>
</body>
</html>
As you can see in the example above, the timer is not updating on the webpage. Is there a disconnect in my logic (I am new to angular so I would love to learn where I went wrong) or am I misinterpreting angular functionality altogether?
Thanks

First, in getPrettyTime you need to do :
var minutes = Math.floor(time/60);
Else you will get a float number.
After that you need to call your getPrettyTime function every time your time is updated, so you can do this in your onTimeout function like this :
var onTimeout = function() {
time = time - 1;
self.getPrettyTime();
...
Here is a working snippet :
var myApp = angular.module('countdownTimer', []);
myApp.service('timerService', ['$http', '$timeout', function($http, $timeout) {
var time = 180;
var self = this;
self.getPrettyTime = function() {
var minutes = Math.floor(time / 60);
var seconds = time - minutes * 60;
if (seconds < 10) {
myDateObject.date = minutes + ":0" + seconds;
} else {
myDateObject.date = minutes + ":" + seconds;
}
return myDateObject;
}
var myDateObject = {
date: null
}
var onTimeout = function() {
time = time - 1;
self.getPrettyTime();
if (time > 0) {
console.log(time);
mytimeout = $timeout(onTimeout, 1000);
} else {
time = 180;
mytimeout = $timeout(onTimeout, 1000);
}
}
this.start = function() {
$timeout(onTimeout, 1000);
}
}]);
myApp.controller('CounterController', ['$timeout', '$scope', 'timerService', function($timeout, $scope, timerService) {
/**$scope.counter = 180;
**/
//var date = new Date(null);
//date.setSeconds(timerService.getTime());
$scope.myDateObject = timerService.getPrettyTime();
$scope.start = function() {
timerService.start();
}
$scope.stop = function() {
$timeout.cancel(mytimeout);
}
}]);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Example </title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script src="app2.js"></script>
</head>
<body data-ng-app="countdownTimer">
<div data-ng-controller="CounterController">
{{myDateObject.date}}
<button data-ng-click="stop()">Stop</button>
<button data-ng-click="start()">Start</button>
</div>
</body>
</html>

Related

How to toggle a button with Javascript

I want to create a phone-like stopwatch using HTML, CSS, and vanilla JavaScript. The one I have already done does the task, but I don't want a separate button for stopping and starting. How could I make a button that changes from start to stop and stop to start?
Here is my HTML Code:
<!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>Document</title>
</head>
<body>
<div class="wrapper">
<h1>Stopwatch</h1>
<h2>Vanilla JavaScript Stopwatch</h2>
<p><span id="seconds">00</span>:<span id="tens">00</span></p>
<button id="button-start">Start</button>
<button id="button-stop">Stop</button>
<button id="button-reset">Reset</button>
</div>
</body>
</html>
Here is my JavaScript code:
window.onload = function () {
var seconds = 00;
var tens = 00;
var appendTens = document.getElementById("tens")
var appendSeconds = document.getElementById("seconds")
var buttonStart = document.getElementById('button-start');
var buttonStop = document.getElementById('button-stop');
var buttonReset = document.getElementById('button-reset');
var Interval ;
buttonStart.onclick = function() {
clearInterval(Interval);
Interval = setInterval(startTimer, 10);
}
buttonStop.onclick = function() {
clearInterval(Interval);
}
buttonReset.onclick = function() {
clearInterval(Interval);
tens = "00";
seconds = "00";
appendTens.innerHTML = tens;
appendSeconds.innerHTML = seconds;
}
function startTimer () {
tens++;
if(tens <= 9){
appendTens.innerHTML = "0" + tens;
}
if (tens > 9){
appendTens.innerHTML = tens;
}
if (tens > 99) {
console.log("seconds");
seconds++;
appendSeconds.innerHTML = "0" + seconds;
tens = 0;
appendTens.innerHTML = "0" + 0;
}
if (seconds > 9){
appendSeconds.innerHTML = seconds;
}
}
}
Define a boolean to track if the clock is running or not and combine the start and stop function into one: something like this:
var clockStarted = false;
buttonStart.onclick = function() {
clearInterval(Interval);
if (!clockStarted) {
Interval = setInterval(startTimer, 10);
clockStarted = true;
} else {
clockStarted = false;
}
}
buttonReset.onclick = function() {
clearInterval(Interval);
tens = "00";
seconds = "00";
appendTens.innerHTML = tens;
appendSeconds.innerHTML = seconds;
clockStarted = false;
}
You could make your play-button invisible after clicking on it (buttonStart.style.dispaly = "none") and enable your stop-button (buttonStop.style.dispaly = "block") and do the same in reverse in your stop function.
Another possible way would be to use only one button and save the state of your player in a variable (i.e. a boolen isPlaying). Then you'd only need one onPress method which starts or stops the player according to isPlaying. Youd also need to change the element or the icon on you button accoring to this variable.

Transforming minutes to ms giving unexpected result

Im developing a chess clock. The thing is that when Im retrieving the minutes and seconds from the DOM and transforming it with msToClockFormat I'm getting 100 times extra minutes. However, For more I look at the function, the more convinced I am that is working as it should be. The minutes are being divided by 60000, 1000 times 60`, and I dont see the error. Thanks.
let btn1 = document.getElementById("btn1");
let btn2 = document.getElementById("btn2");
let resetBtn = document.getElementById("reset");
let ms1 = stringTimeToMs(btn1.innerHTML);
let ms2 = stringTimeToMs(btn2.innerHTML);
let player1 = true;
let reset = false;
function tick() {
if (!reset) {
if (player1) {
btn1.innerHTML = msToClockFormat(--ms1);
} else {
btn2.innerHTML = msToClockFormat(--ms2);
}
}
}
function msToClockFormat(ms) {
let minutes = Math.floor(ms / 60000);
let seconds = Math.floor((ms % 60000) / 1000);
return minutes + ":" + (seconds < 10 ? "0" + seconds : seconds);
}
function stringTimeToMs(time) {
let minutes = time.split(":")[0];
let seconds = time.split(":")[1];
return (minutes * 60 + seconds) * 1000;
}
var myInterval = setInterval(tick, 1);
btn1.addEventListener("click", () => {
player1 = false;
reset = false;
})
btn2.addEventListener("click", () => {
player1 = true;
reset = false;
})
resetBtn.addEventListener("click", () => {
btn1.innerHTML = "05:00";
btn2.innerHTML = "05:00";
player1 = true;
ms1 = 5 * 60 * 1000;
ms2 = 5 * 60 * 1000;
reset = true;
})
<!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>Clock</title>
<link rel="stylesheet" href="https://unpkg.com/#picocss/pico#latest/css/pico.min.css">
<script src="script.js" defer></script>
</head>
<body>
<main class="container">
<div class="container1">
<button class="timers" id="btn1">3:00</button>
</div>
<div class="container2">
<button class="timers" id="btn2">3:00</button>
</div>
<div class="container3">
<button id="reset">RESET</button>
</div>
</main>
</body>
</html>
You'd probably have a better time keeping your state in your code, and just writing it into the DOM elements.
I changed the tick interval to 1000ms (because it's unlikely setInterval would work correctly with 1ms), but even so it's not guaranteed that your function will be called exactly 1000ms apart, so it would be better to look at the wall clock (+new Date()) to see how much time actually elapsed since the last "tick".
let btn1 = document.getElementById("btn1");
let btn2 = document.getElementById("btn2");
let resetBtn = document.getElementById("reset");
let ms1 = 300000;
let ms2 = 300000;
let player1 = true;
let reset = false;
function update() {
btn1.innerHTML = msToClockFormat(ms1);
btn2.innerHTML = msToClockFormat(ms2);
}
function tick() {
if (!reset) {
if (player1) {
ms1 -= 1000;
} else {
ms2 -= 1000;
}
}
update();
}
function msToClockFormat(ms) {
let minutes = Math.floor(ms / 60000);
let seconds = Math.floor((ms % 60000) / 1000);
return minutes + ":" + (seconds < 10 ? "0" + seconds : seconds);
}
update();
var myInterval = setInterval(tick, 1000);
btn1.addEventListener("click", () => {
player1 = false;
reset = false;
})
btn2.addEventListener("click", () => {
player1 = true;
reset = false;
})
resetBtn.addEventListener("click", () => {
player1 = true;
ms1 = 5 * 60 * 1000;
ms2 = 5 * 60 * 1000;
reset = true;
})
<!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>Clock</title>
<link rel="stylesheet" href="https://unpkg.com/#picocss/pico#latest/css/pico.min.css">
<script src="script.js" defer></script>
</head>
<body>
<main class="container">
<div class="container1">
<button class="timers" id="btn1"></button>
</div>
<div class="container2">
<button class="timers" id="btn2"></button>
</div>
<div class="container3">
<button id="reset">RESET</button>
</div>
</main>
</body>
</html>
Inside StringTimeToMs, seconds is being read as String input "00" as opposed to integer. As a result, adding seconds in return (minutes * 60 + seconds) * 1000; is concatenating "00" to the end of the number, making the number larger. Use parseInt to read the integer value.
function stringTimeToMs(time) {
let minutes = time.split(":")[0];
let seconds = parseInt(time.split(":")[1]);
return (minutes * 60 + seconds) * 1000;
}

Adding Start, Stop, Reset button for timer

I have this count-up timer code and want to add start, stop and reset button. It start right at the page load.
<script type="text/javascript">
var timerVar = setInterval(countTimer, 1000);
var totalSeconds = 0;
function countTimer() {
++totalSeconds;
var hour = Math.floor(totalSeconds /3600);
var minute = Math.floor((totalSeconds - hour*3600)/60);
var seconds = totalSeconds - (hour*3600 + minute*60);
document.getElementById("hour").innerHTML =hour;
document.getElementById("minute").innerHTML =minute;
document.getElementById("seconds").innerHTML =seconds;
}
</script>
It's just some simple manipulation of hour, minute and seconds and making use of clearInterval and setInterval. In my snipper, reset won't stop the timer, but it's easy to make that happen by a few lines of code.
window.onload = () => {
let hour = 0;
let minute = 0;
let seconds = 0;
let totalSeconds = 0;
let intervalId = null;
function startTimer() {
++totalSeconds;
hour = Math.floor(totalSeconds /3600);
minute = Math.floor((totalSeconds - hour*3600)/60);
seconds = totalSeconds - (hour*3600 + minute*60);
document.getElementById("hour").innerHTML =hour;
document.getElementById("minute").innerHTML =minute;
document.getElementById("seconds").innerHTML =seconds;
}
document.getElementById('start-btn').addEventListener('click', () => {
intervalId = setInterval(startTimer, 1000);
})
document.getElementById('stop-btn').addEventListener('click', () => {
if (intervalId)
clearInterval(intervalId);
});
document.getElementById('reset-btn').addEventListener('click', () => {
totalSeconds = 0;
document.getElementById("hour").innerHTML = '0';
document.getElementById("minute").innerHTML = '0';
document.getElementById("seconds").innerHTML = '0';
});
}
<div>Hour: <span id="hour"></span></div>
<div>Minute: <span id="minute"></span></div>
<div>Second: <span id="seconds"></span></div>
<button id="start-btn">Start</button>
<button id="stop-btn">Stop</button>
<button id="reset-btn">Reset</button>
Duplicate of Adding start, stop, and reset buttons for a timer
but just because there is not the HTML part, there is the full answer (html + js thanks to #closure )
(function() {
"use strict";
var secondsLabel = document.getElementById('seconds'),
minutesLabel = document.getElementById('minutes'),
hoursLabel = document.getElementById('hours'), totalSeconds = 0,
startButton = document.getElementById('start'),
stopButton = document.getElementById('stop'),
resetButton = document.getElementById('reset'), timer = null;
startButton.onclick = function() {
if (!timer) {
timer = setInterval(setTime, 1000);
}
};
stopButton.onclick = function() {
if (timer) {
clearInterval(timer);
timer = null;
}
};
resetButton.onclick = function() {
if (timer) {
totalSeconds = 0;
stop();
}
};
function setTime() {
totalSeconds++;
secondsLabel.innerHTML = pad(totalSeconds % 60);
minutesLabel.innerHTML = pad(parseInt(totalSeconds / 60));
hoursLabel.innerHTML = pad(parseInt(totalSeconds / 3600))
}
function pad(val) {
var valString = val + "";
if (valString.length < 2) {
return "0" + valString;
} else {
return valString;
}
}
})();
<p id='seconds'></p>
<p id='minutes'></p>
<p id='hours'></p>
<button id='start'>start</button>
<button id='stop'>stop</button>
<button id='reset'>reset</button>
//DOM CACHE
const startBtn = document.querySelector("#start-btn")
const stopBtn = document.querySelector("#stop-btn")
const resetBtn = document.querySelector("#reset-btn")
var minDigits = document.getElementById("min");
var secDigits = document.getElementById("sec");
//INITIALIZING VARIABLES
var hrs = 0;
var mins = 0;
var secs = 0;
var countSec = 0;
var timerVar = null;
//FUNCTIONS=============
function startCounter() {
++countSec;
hrs = Math.floor(countSec /3600);
mins = Math.floor((countSec - hrs*3600)/60);
secs = countSec - (hrs*3600 + mins*60);
if (secs < 10) {
secDigits.innerHTML = "0" + secs;
} else { secDigits.innerHTML = secs; }
minDigits.innerHTML = "0" + mins;
}
startBtn.addEventListener('click', () => {
timerVar = setInterval(startCounter, 1000);
})
stopBtn.addEventListener('click', () => {
if (timerVar)
clearInterval(timerVar);
});
resetBtn.addEventListener('click', () => {
countSec = 0;
secDigits.innerHTML = "00";
minDigits.innerHTML = "00";
clearInterval(timerVar);
});
<!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="style.css">
<title>Clock JS</title>
</head>
<body>
<div class="container">
<header>
<h1>SIMPLE COUNTER</h1>
<p>At A Time No Time To Check Time</p>
</header>
<div class="clock-face">
<div class="digital-time"></div>
<div class="greeting"></div>
<div class="screen">
<h1 class="digits">
<span id="min" class="minutes">00</span>:<span id="sec" class="seconds">00</span>
</h1>
</div>
<div class="clock-dial">
<button id="start-btn">start</button>
<button id="stop-btn">stop</button>
<button id="reset-btn">reset</button>
</div>
</div>
</div>
<script src="app.js" charset="utf-8"></script>
</body>
</html>

Why can't I see the countdown timer

I tried to make a countdown timer using setInterval(). I used code made by other people to learn how, but it failed. After searching to find the issue, I was not able to find it.
My code:
<!DOCTYPE html>
<html>
<head>
<title>Count</title>
<script="text/javascript">
var Stime = 10; //Set time(minute)
var Ssecond = Stime * 60;
var countdownID=0;
function inidown(){
countdownID = setInterval("Count()",1000);
}
function Count(){
if(Ssecond>0){
var rM=Ssecond/60;
var rS=Ssecond%60;
document.getElementById("count").innerHTML=rM+":"+rS;
Ssecond--;
}
else{
clearInterval(countdownID);
document.getElementById("out").innerHTML="time out";
}
}
</script>
</head>
<body onload="inidown()">
<div id="count"></div>
<div id="out"></div>
</body>
</html>
I saw that code on http://blog.niklasottosson.com/?p=665
var Stime = 10; //?? ??(?)
var Ssecond = Stime * 60;
var countdownID = 0;
function inidown() {
countdownID = setInterval("Count()", 1000);
}
function Count() {
if (Ssecond > 0) {
var rM = Ssecond / 60;
var rS = Ssecond % 60;
document.getElementById("count").innerHTML = rM + ":" + rS;
Ssecond--;
} else {
clearInterval(countdownID);
DivCount.innerHTML = "Time Out";
document.getElementById("out").innerHTML = "time out";
}
}
No error occurs in that code.
There was a problem with your script tag.
Use Math.floor for your minutes.
Pad the seconds for single digits.
<html>
<head>
<title>Count</title>
<script type="text/javascript">
var Stime = 10; //Set time(minute)
var Ssecond = Stime * 60;
var countdownID = 0;
function inidown() {
countdownID = setInterval("Count()", 1000);
}
function Count() {
if (Ssecond > 0) {
var rM = Math.floor(Ssecond / 60);
var rS = ("0" + (Ssecond % 60)).slice(-2);
document.getElementById("count").innerHTML = rM + ":" + rS;
Ssecond--;
} else {
clearInterval(countdownID);
document.getElementById("count").innerHTML = "";
document.getElementById("out").innerHTML = "Time Out";
}
}
</script>
</head>
<body onload="inidown()">
<div id="count"></div>
<div id="out"></div>
</body>
</html>
<script="text/javascript"> should have a type attribute <script type="text/javascript">
setInterval("Count()",1000); works, but can also be rewritten as setInterval(Count,1000);
With these changes it is working.

Activity counter in pure javascript without jquery

i have a problem with create activity script for 4 element on DOM.
I can't use JQuery, must be write in pure JavaScript - it's practice for school...
1. The counter what i'am done work good but in next step i must divide html site for 4 part and any part must have his counter... so it's logical that i must use obiective javascript and there is problem...
2. Any time when i try create 4 obiect the last, destroy another.
3. Generally does not work and I do not know why.
There is code:
<pre><!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="style.css">
<link href='http://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet' type='text/css'>
<title>Example #6</title>
<script>
function T(div){
var millis = 0;
var sec = 0;
var stopTime=0;
var totalTime =0;
var temp = 0;
var startTime=0;
var work = false;
setStopTime = function(){
stopTime = (new Date()).getTime() + 3000;
}
function setValue(value) {
millis = Math.floor ( value % 1000 );
value = Math.floor( value / 1000 );
sec = Math.floor ( value % 60 );
value = Math.floor( value / 60 );
if( value < 10 ) { value="0" + value;
if( sec < 10 ) { sec = "0" + sec; }
else if( millis < 100 ) { millis = "00" + millis; }
}
document.getElementById(div).innerHTML = value + ":" + sec +"." + millis;
}
go2 = function() {
if ( work == true ) return;
work = true;
document.getElementById(div).style.backgroundColor="red";
var currentTime = (new Date()).getTime();
startTime = currentTime;
var counter = setInterval(function() {
if(currentTime >= stopTime){
document.getElementById(div).style.backgroundColor="";
clearInterval(counter);
totalTime+= stopTime - startTime;
work = false;
setValue(totalTime);
return;
}
temp = currentTime - startTime;
setValue(temp+totalTime);
currentTime = (new Date()).getTime();
}, 1);
}
addEventListener("mousemove", function() {setStopTime();go2();});
addEventListener("keydown", function() {setStopTime();go2();});
}
var obj1 = new T('obj1');
var obj2 = new T('obj2');
var obj3 = new T('obj3');
var obj4 = new T('obj4');
</script>
</head>
<body>
<div id="obj1"><p>counter1</p></div>
<div id="obj2"><p>counter2</p></div>
<div id="obj3"><p>counter3</p></div>
<div id="obj4"><p>counter4</p></div>
</body>
</html></pre>
go2 and setStopTime must be local.
var setStopTime = function(){...
var go2 = function() {

Categories