Javascript not executing immediately, delayed until a second after page load - javascript

After a quick cobbling together of a clock app to test the JavaScript linking ability of my Flask App hosted on Heroku, I'm stumbling on the clock text not immediately filling the .innerHTML of my element.
Javascript:
// This sets our ticker to execute the function once a second.
var myVar = setInterval(function() {
myTimer();
}, 1000);
function myTimer() {
var d = new Date();
document.getElementById("clock").innerHTML = d.toLocaleTimeString();
}
The HTML is very simple, just a small h4 element with the id of "clock". I've tried document.onload as well, but whatever I try, the website loads with an empty element then fills it about one second later.
While I have your attention, why is the standard procedure for setting an interval declaring it as a variable? Is it for later reference in the program? Would it work as a naked setInterval(xxxxx);?
Thank you in advance!

setInterval runs the funtion after a specified delay, if you would like to display time on window load for example, you could call your function once in window.onload. Declaring as a variable is needed if you would like to clear the interval, I added a button as an example.
window.onload = () => {
myTimer();
}
const btnStop = document.getElementById("btn-stop");
btnStop.addEventListener('click', () => {
console.log('stopped');
clearInterval(myInterval);
})
var myInterval = setInterval(function() {
myTimer();
}, 1000);
function myTimer() {
var d = new Date();
document.getElementById("clock").innerHTML = d.toLocaleTimeString();
}
<p id="clock"></p>
<button id="btn-stop">stop</button>

Related

Having difficulty finishing this time-based code snippet

var myVar = setInterval(myTimer, 1000);
var button = document.querySelector(".button");
function myVarFunction() {
setInterval(myTimer, 1000);
}
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
function clockButton(document.querySelector(".button").toggle(".clockOn")){
if(button.hasAttribute("class","clockOn")){
clearInterval(myVar);
}else{
myVarFunction();
}
}
<!DOCTYPE html>
<html>
<body>
<p>A script on this page starts this clock:</p>
<p id="demo"></p>
<button onclick="clockButton()" class = "button clockOn" >button</button>
</body>
</html>
I'm trying to execute a code snippet that will display the time in real-time (using the setInterval() method) and a button that when clicked will stop the time running in real-time, but if clicked again the time will run in real-time as it did before(using .toggle() to achieve this).
here is a link to the w3schools exercise where I got this idea from:
https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_win_setinterval_clearinterval
For some reason the time completely dissapears, none of my code works and I can't work out why
Skip to the end if you just want the answer
First thing's first, remove your onClick event from the HTML and place it in your script. This is the recommended way to set up events.
<button class="button clockOn">button</button>
and
var myVar = setInterval(myTimer, 1000);
var button = document.querySelector(".button");
// Add the event listener here
button.addEventListener("click", clockButton);
Now there's a couple of issues, but your most prominent one is the clockButton function. What you've got here is invalid JavaScript, you cannot execute code within the parameter list of a function:
function clockButton(document.querySelector(".button").toggle(".clockOn")){
...
}
You need to move this code to the body of the function instead.
function clockButton () {
document.querySelector(".button").toggle(".clockOn");
...
}
That fixes the first problem, which is just invalid code. But the next problem you're going to face is that toggle(...) is not a function of the button element, (You may be confusing a bit of jQuery here, which has happened to me a number of times). You don't actually need this line of code though anyway, so you can remove it, and write your own class toggle.
It's fairly straightforward to write a class toggle, and you're actually doing a check already for the buttons class in your if statement, so it's a naturally obvious place for you to write the class toggle:
if(button.hasAttribute("class","clockOn")){
...
}
But unfortunately, there's a problem with the code above. Calling the hasAttribute function on an element will just check whether that attribute exists, not if it actually has a certain value. So in your case it will always be true, as you're never removing the class attribute, only changing it to something different.
To fix this up, you can use the classList functionality, which is the standard these days to deal with element classes in the native DOM API. You want to check that the element has the class clockOn so you can change the if statement to this:
if (button.classList.contains("clockOn")) {
...
}
To remove the class, you can use the remove function on the classlist like so:
button.classList.remove("clockOn");
And you can add the class back using
button.classList.add("clockOn");
So all in all, your function becomes this
function clockButton(){
if(button.classList.has("clockOn"){
clearInterval(myVar);
button.classList.remove("clockOn");
}
else {
myVarFunction();
button.classList.add("clockOn");
}
}
Now that you're here, your button should work to stop the clock, and restart it again when you click it a second time, but it's not working properly yet, because you'll notice if you click it again, the time does not stop.
This is because myVarFunction does not reassign the new interval handle to the myVar variable. Every time you call setInterval you should get a new handle. So as an example, imagine that the first time you call setInterval it assigns the handle of 123.
var myVar = setInterval(myTimer, 1000);
// myVar === 123
Now clearInterval(myVar) will clear the running interval.
The next time you set the interval, it is within myVarFunction, lets say for example, it returns 456 the next time it's called.
function myVarFunction() {
// setInterval returns `456`
setInterval(myTimer, 1000);
// myVar is still equal to `123`
}
The next time you try to clear the interval, you are clearing 123 (since you never reassigned the myVar variable) which doesn't exist, you should be clearing 456 which was the new interval you just set up.
So it's an easy fix
function myVarFunction() {
myVar = setInterval(myTimer, 1000);
}
TL;DR
Your code should look something like this
<!DOCTYPE html>
<html>
<body>
<p>A script on this page starts this clock:</p>
<p id="demo"></p>
<!-- Remove the onclick event from here -->
<button class="button clockOn" >button</button>
</body>
</html>
var myVar = setInterval(myTimer, 1000);
var button = document.querySelector(".button");
button.addEventListener('click', clockButton);
function myVarFunction() {
myVar = setInterval(myTimer, 1000);
}
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
function clockButton(){
if(button.classList.contains("clockOn")){
clearInterval(myVar);
button.classList.remove("clockOn");
}
else {
myVarFunction();
button.classList.add("clockOn");
}
}
See it live
JSFiddle
You can check my implementation below, the time continues from the current realtimee after toggling, I guess this is what you want.
let time = document.getElementById("demo")
let myIntervalTimer;
function myStartFunction() {
if(myIntervalTimer){
clearInterval(myIntervalTimer)
}
myIntervalTimer = setInterval(myTimer, 1000)
}
function myStopFunction() {
clearInterval(myIntervalTimer)
}
function myTimer() {
let d = new Date();
let t = d.toLocaleTimeString();
time.innerHTML = t;
}
let timeClassList = time.classList
function toggleTime() {
if(timeClassList.contains('showTime')) {
myStopFunction()
}
else {
myStartFunction()
}
timeClassList.toggle("showTime")
}
myStartFunction()
<!DOCTYPE html>
<html>
<body>
<p>A script on this page starts this clock:</p>
<p id="demo" class='showTime'></p>
<button onclick="toggleTime()">Toggle time</button>
</body>
</html>

Boolean statement not evaluating in javascript

I'm writing a script, and there are two boolean statements that are very similar but giving different results, and I don't see why they conflict with one another.
My function looks like this:
SCRIPT:
(function() {
window.onload = function() {
let stopped = true;
let button = document.getElementById("start-stop");
if (stopped) {
setInterval(function() {
console.log("The timer is working.");
}, 1000);
}
button.addEventListener('click', function(){
if (stopped) {
stopped = false;
console.log(stopped);
} else {
stopped = true;
console.log(stopped);
}
});
}
}
}).call(this);
The basic idea is that when I push the button the setInterval function stops, however it keeps on going even when the if/else function switches stopped to false.
For example, my console.log looks like this:
I.e. stopped = false, but setInterval doesn't terminate.
Why is this not evaluating correctly?
The problem with your code is that you are trying to work on a piece of code that has already started to operate. In simpler words, the setInterval method will be called every 1000ms, no matter what the value of stopped variable is. If you wish to really stop the log, you can do any of these:
clearInterval()
to completely remove the interval or
setInterval(function() {
if (stopped) {
console.log("The timer is working.");
}
}, 1000);
to check if the value of stopped variable has changed or not (after the click) and act accordingly. Choose either of these for your purpose..
you are calling setinterval even before button is clicked .As the event is already triggered you cannot stop just by setting the variable to false ,you need to clear the interval using clearinterval
check the following snippet
var intervalId;
window.onload = function() {
let stopped = true;
let button = document.getElementById("start-stop");
var Interval_id;
button.addEventListener('click', function() {
if (stopped) {
Interval_id = callTimeout();
stopped = false;
} else {
clearInterval(Interval_id);
stopped = true;
}
});
}
function callTimeout() {
intervalId = setInterval(function() {
console.log("The timer is working.");
}, 1000);
return intervalId;
}
<input type="button" id="start-stop" value="click it">
Hope it helps
Put the if(stopped) statement inside the setInterval function because if you used this function once it will keep going..
Another way to stop setInterval function is by using clearInterval, like this
var intervalId = setInterval(function() { /* code here */}, 1000)
// And whenever you want to stop it
clearInterval(intervalId);
When you click the button stopped variable becomes false but the setInterval will not stop because the setInterval code is already executed.. it will not execute again on button click. And if you reload the page what will happen is that stopped variable will be again set to true as you have written at first line and setInterval will execute again ..
Now What you can do is store setInterval in a variable like this
var timer = setInterval(function,1000);
and then when you click the button use this method to clear interval
clearInterval(timer);
this should do the trick .. Hope it helps ..

Javascript countdown timer is erratic

I have a raspberry pi that initiates a garage door close event after a 90s delay. I have been successful in showing the countdown timer dynamically update on a web page but for some reason the countdown is erratic and constantly flickers with lower and then higher numbers.
Clearly I must be refreshing something but needless to say I have spent many hours on forums but to no avail. I am hoping that someone can look at my code and give me some direction.
<?php
$pinInput = trim(shell_exec("gpio read 26"));
$pinOutput = trim(shell_exec("gpio read 2"));
if ($pinInput!=$pinOutput){
echo "Timing for auto reclose...";
?>
<br>
<b><span id="countdown">90</span> Seconds</b>
<script type="text/javascript">
var timer = 90,
el = document.getElementById('countdown');
(function t_minus() {
'use strict';
el.innerHTML = timer--;
if (timer >= 0) {
setTimeout(function () {
t_minus();
}, 1000);
} else {
// do stuff, countdown has finished.
}
}());
</script>
<?php
}
elseif ($pinInput=1)
{
echo "Monitoring input...";
}
else
{
echo "Garage door is closing...";
}
?>
I should also mentioned that the above piece of code is within a file called timing.php. This is called on index.php as follows:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
<script type="text/javascript">
var auto_refresh = setInterval(
function ()
{
$('#Input').load('timing.php');
}, 1000); // refresh every 1000 milliseconds
</script>
So in summary, what I would like is for "Timing for auto recluse..." to remain static if ($pinInput!=$pinOutput) but dynamically shown the countdown from 90s.
First let's look at this code, the last bit in your question:
var auto_refresh = setInterval(
function () {
$('#Input').load('timing.php');
}, 1000); // refresh every 1000 milliseconds
That sets up an interval timer that will load the "timing.php" URL into the page once per second.
Now, here's part of what you say is returned from "timing.php":
var timer = 90,
el = document.getElementById('countdown');
(function t_minus() {
'use strict';
el.innerHTML = timer--;
if (timer >= 0) {
setTimeout(function () {
t_minus();
}, 1000);
} else {
// do stuff, countdown has finished.
}
}());
So when the browser receives the response from "timer.php", jQuery will run that code. That sets up a repeating timer function — essentially the same thing as an interval timer, except that it stops itself after a while).
Now, when that code is reloaded, you don't get new global variables timer and el. The global variables already defined by the last load of "timer.php" will simply have their values overridden. That means that the already-in-process previous timeout sequence will suddenly see timer set back to 90.
It's not clear exactly what it is you intend to do. Perhaps that setInterval() is just superfluous, and all you need to do is just load "timeout.php" once. Or, perhaps when the "timeout.php" code loads, it first needs to wipe out any already-running timeout loops, though that seems odd since those are set up to wind down only after 90 seconds.

AS3 - Using ExernalInterface.call To Reset JS Timer

I'm trying to build a 'dead mans switch' into a flash app. When the app crashes, or slows down significantly, I would like the webpage to refresh. From what I've read and seen here, it's possible to use ExernalInterface to call a resetTimer JS function.
Heres my AS3..
//External Timer and Handler
var externaltimer: Timer = new Timer(1000);
externaltimer.addEventListener(TimerEvent.TIMER, callTimerJS);
externaltimer.start();
function callTimerJS(event : Event):void{
ExternalInterface.call("window.clearTimeout");
ExternalInterface.call("timeoutHandle");
}
Heres my JS in my HTML page...
var timeoutHandle = window.setTimeout(function() {
window.location.reload(1);
}, 15000);
window.clearTimeout(timeoutHandle);
timeoutHandle = window.setTimeout(function() {
window.location.reload(1);
}, 15000);
I'm not sure how to test this to verify it's working. I do know when I build, the webpage refreshes every 15 seconds. I'm not able to get flash to reset the timer.
Use normal function-declarations and be sure that is not a js-core-function-name.
You can call only functions.
AS
//External Timer and Handler
var externaltimer: Timer = new Timer(1000);
externaltimer.addEventListener(TimerEvent.TIMER, callTimerJS);
externaltimer.start();
function callTimerJS(event : Event):void{
if (ExternalInterface.available) {
ExternalInterface.call("clearTimeoutfromExtern");
}
}
JS
var timeoutHandle;
function clearTimeoutfromExtern(){
clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(refresh, 15000);
}
function refresh(){
window.location.reload(1);
}
I just wrote it here in the editor...
Greetings.

function is looped according to setinterval but with different parameters

i have a simple question, there is a function with parameter emp_id that opens up a form for a chat with different attributes, i want it to be refreshed automatically each 10 sec, now it works a bit wrongly, since there is a parameter emp_id that is can be changed, and once i change it, the chat with messages and form are refreshed double time or triple times :) depend on how many times u change the emp_id, i hope i was clear )) anyway here is the javascript function:
function load_chat(emp_id) {
var url = "#request.self#?fuseaction=objects2.popup_list_chatform"
url = url + "&employee_id=" + emp_id;
document.getElementById('form_div').style.display = 'block'; AjaxPageLoad(url,'form_div',1,'Yükleniyor');
setInterval( function() {
load_chat(emp_id);
},10000);
}
there a list of names, once i click on one of them, this form is opened by this function, but if i click another user, i mean if i change the emp_id, it refreshes, the previous and present form. how do i change it so that it will refresh only the last emp_id, but not all of id's which i've changed
thank you all for the help, i really appreciate it!
This would nicely encapsulate what you're doing. The timer id (tid) is kept inside the closure, so when you call load_chat it will stop the interval if there was one running.
Once the new url is set up, it will start the interval timer again.
var ChatModule = (function() {
var tid,
url;
function refresh()
{
AjaxPageLoad(url, 'form_div', 1, 'Yükleniyor');
}
return {
load_chat: function(emp_id) {
if (tid) {
clearInterval(tid);
}
// setup url
url = "#request.self#?fuseaction=objects2.popup_list_chatform"
url = url + "&employee_id=" + emp_id;
document.getElementById('form_div').style.display = 'block';
// load ajax
refresh();
// set timer
tid = setInterval(refresh, 10000);
}
}
}());
ChatModule.load_chat(123);
Use setTimeout instead. Each time your function is executed, it will set up the next execution (you could also make it conditional):
function load_chat(emp_id) {
... // do something
if (condition_still_met)
setTimeout(function() {
load_chat(emp_id); // with same id
}, 10000);
}
load_chat("x"); // to start
Or you will have to use setInterval outside the load_chat function. You can clear the interval when necessary.
function get_chat_loader(emp_id) {
return function() {
... // do something
};
}
var id = setInterval(get_chat_loader("x"), 10000); // start
// then, somewhen later:
clearInterval(id);

Categories