Having difficulty finishing this time-based code snippet - javascript

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>

Related

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

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>

Unable to get simple countdown program to run

My Son is trying to get this code to work as he applying for College course. He neeeds to give an explanation of how it works from the Youtube example. The problem he has & I have is we cant get the code to run.
Youtube example he is working from.
https://www.youtube.com/watch?v=u_6CqjQ-L8Q&authuser=0
This should be a simple countdown timer from 10 to zero - any ideas what I am doing wrong. Using Notepad++ to create the example & run.
<script type="text/javascript">
function countdown(secs,elem) {
var element = document.getElementById(elem);
element.innerHTML = "Please wait for "+secs+" seconds";
if(secs<1){
clearTimeout(timer);
element.innerHTML = '<h2>Countdown Complete!</h2>';
element.innerHTML += 'Click here now';
}
secs = secs--;
var timer = setTimeout('countDown('+secs+',"'+elem+'")',1000);
}
</script>
<div id="status"></div>
<script type="text/javascript">countdown(10,"status");</script>
Some issues:
secs = secs-- will not modify secs. Just secs-- would be ok.
The spelling of the function is not consistent
Some more issues, which are also present in the link you provided:
When the timer is supposed to stop, the code still continues to call setTimeout
This code uses a bad practice to pass a string to setTimeout while it is perfectly possible to pass a function.
calling clearTimeout is useless where it happens, as at that moment there is no pending one.
Working code:
function countdown(secs,elem) {
var element = document.getElementById(elem);
if(secs<1){
element.innerHTML = '<h2>Countdown Complete!</h2>'
+ 'Click here now';
return; // <---- don't call setTimeout again
}
element.textContent = "Please wait for "+secs+" seconds";
// Spelling of countdown is important. Don't use string, but bind:
setTimeout(countdown.bind(null, secs-1, elem), 1000);
}
countdown(10, 'status');
<div id="status"></div>

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

clearInterval function not clearing setInterval function

I utilized this resource to structure my code: http://www.w3schools.com/jsref/met_win_clearinterval.asp
var intervalID = setInterval(function(){ ogpeWrapper() }, 10);
function ogpeWrapper() {
$("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper").wrapAll('<div id="colWrapperContainer"></div>');
}(jQuery);
function myStopFunction() {
if (document.getElementById('colWrapperContainer')) {
clearInterval(intervalID);
setIntervalID = undefined;
}
}
My ogpeWrapper function is running, but the clearInterval function is not.
Basically, once $("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper").wrapAll(''); runs, I want the interval to stop running it.
Edit - 12:24pm CST:
This is the base code I utilize to wrap the listed elements -
(function($) {
$("#breadcrumbAds, #breadcrumbWrapper, #containerTopParsys, #leftColWrapper, #rightColWrapper").wrapAll('<div id="colWrapperContainer"></div>');
})(jQuery);
This code works, but it doesn't process the change until after the DOM has completely loaded. I need the function to work as soon as those elementals are all available. So I need to use a setInterval to process the function, then clear the interval once the function is processed.
If anyone knows of another way to do this, besides a setIterval, please let me know.
You need to create a definite if else condition within the variable so you know exactly when it will start and when it will stop. Also, because the minimum millisecond interval timing is not consistent across browsers, although you want it to detect really fast, I would recommend a "safer" number and use 100 as the minimum instead. The .length method is a handy little way for you to check if an element is on a page; You can use it as a pseudo dynamic true/false conditional. Lastly, in your .wrapAll() tag, I swapped your single and double quotes, as it is best practice to do such.
var colWrapper = setInterval(function(){
if ($('div#colWrapperContainer').length > 0) {
var doNothing = "";
clearInterval(colWrapper);
} else {
$("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper").wrapAll("<div id='colWrapperContainer'></div>");
}
}, 100);
Here is a working example for your reference Wrap Example
Update:
Example for putting the script inside the <body> tag (no window.load/document.ready) so that it runs independently as soon as it is loaded.
<script type="text/javascript">//<![CDATA[
//http://stackoverflow.com/questions/33483000/clearinterval-function-not-clearing-setinterval-function/33483267#33483267
//Auto Wrap Solution
//Alexander Dixon [11-02-2015]
var wrapThese = $("#breadcrumbWrapper, #leftColWrapper, #rightColWrapper");
var colWrapper = setInterval(function () {
if ($('div#colWrapperContainer').length > 0) {
var doNothing = "";
clearInterval(colWrapper);
} else {
wrapThese.wrapAll('<div id="colWrapperContainer"></div>').addClass('success');
}
}, 100);
//]]>
</script>

How to kill a javascript redirect if button is pressed?

I have come up with the following code, which allows users to view a page with a movie embed for 30 seconds before redirecting them away from the page. Additionally, they can click a link to hide the div with this countdown. What I need help with is canceling the redirect (stopping it from happening) if that link is clicked, so users can continue to watch the full movie. Thanks in advance for your help!
Javascript:
<script type="text/javascript">
var settimmer = 0;
$(function(){
window.setInterval(function() {
var timeCounter = $("b[id=show-time]").html();
var updateTime = eval(timeCounter)- eval(1);
$("b[id=show-time]").html(updateTime);
if(updateTime == 0){
window.location = ("redirect.php");
}
}, 1000);
});
</script>
<script type="text/javascript">
$(document).ready(function(){
$(".slidingDiv").show();
$(".show_hide").show();
$('.show_hide').click(function(){
$(".slidingDiv").slideToggle();
});
});
</script>
HTML:
<div id="my-timer" class="slidingDiv">
You have <b id="show-time">30</b> seconds to decide on this movie.
Yes, I want to watch this one!
</div>
setInterval returns a value you can use to cancel the interval timer via clearInterval. So:
$(function(){
// +--- Remember the value from `setInterval
// |
// v
var timerHandle = window.setInterval(function() {
var timeCounter = $("b[id=show-time]").html();
var updateTime = eval(timeCounter)- eval(1);
$("b[id=show-time]").html(updateTime);
if(updateTime == 0){
window.location = ("redirect.php");
}
}, 1000);
// + Hook up a handler for the link that uses the handle to clear it
// |
// v
$("selector_for_the_link").click(function() {
clearInterval(timerHandle);
timerHandle = 0;
});
});
Note that I've put the variable inside your ready function, so it isn't a global.
Off-topic: You don't need or want to use eval in the above (in fact, you virtually never want to use eval at all, for anything). If you want to parse a string to make a number, use parseInt (and there's never any reason to eval a literal like 1). So this line:
var updateTime = eval(timeCounter)- eval(1);
becomes
var updateTime = parseInt(timeCounter, 10) - 1;
(The 10 means the string is in decimal — e.g., base 10.)
You need to use the clearInterval method.
Maybe you can use setTimeout() to do so rather than setInterval().Here is a sample.

Categories