Cannot set property 'textcontent' of null - javascript

for some reason with this I get the error: Cannot set property 'textcontent' of null for this line:
document.getElementById("days").textContent = d;
function countdown() {
var now = new Date();
var eventDate = new Date(2018, 1, 19);
var currentTime = now.getTime();
var eventTime = eventDate.getTime();
var remTime = eventTime - currentTime;
var s = Math.floor(remTime / 1000);
var m = Math.floor(s / 60);
var h = Math.floor(m / 60);
var d = Math.floor(h / 24);
h %= 24;
m %= 60;
s %= 60;
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
document.getElementById("days").textContent = d;
document.getElementById("days").innerText = d;
document.getElementById("hours").textContent = h;
document.getElementbyId("minutes").textContent = m;
document.getElementById("seconds").textContent = s;
}
countdown();
<li>
<span class="value">Ends in:
</span>
<p id="days">30</p>
<p id="hours">10</p>
<p id="minutes">5</p>
<p id="seconds">1</p>
</li>

The issue may be that the element may not exist at the time your "countdown" runs... Could you try calling countdown onload of the body / div that contains the set of elements you're querying?
<body onload="countdown()">

The only issue that I see is that your b needs to be uppercase on this line:
document.getElementbyId("minutes").textContent = m;
When fixing that the code works as expected:
function countdown() {
var now = new Date();
var eventDate = new Date(2018, 1, 19);
var currentTime = now.getTime();
var eventTime = eventDate.getTime();
var remTime = eventTime - currentTime;
var s = Math.floor(remTime / 1000);
var m = Math.floor(s / 60);
var h = Math.floor(m / 60);
var d = Math.floor(h / 24);
h %= 24;
m %= 60;
s %= 60;
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
document.getElementById("days").textContent = d;
document.getElementById("days").innerText = d;
document.getElementById("hours").textContent = h;
document.getElementById("minutes").textContent = m;
document.getElementById("seconds").textContent = s;
}
countdown();
<li>
<span class="value">Ends in:
</span>
<p id="days">30</p>
<p id="hours">10</p>
<p id="minutes">5</p>
<p id="seconds">1</p>
</li>
Make sure that your code is ran after the dom has finished loading.
you can do so like this:
document.addEventListener('DOMContentLoaded', () => countdown());

You have an error: getElementById instead of getElementbyId.
The new code will be:
function countdown() {
var now = new Date();
var eventDate = new Date(2018, 1, 19);
var currentTime = now.getTime();
var eventTime = eventDate.getTime();
var remTime = eventTime - currentTime;
var s = Math.floor(remTime / 1000);
var m = Math.floor(s / 60);
var h = Math.floor(m / 60);
var d = Math.floor(h / 24);
h %= 24;
m %= 60;
s %= 60;
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
document.getElementById("days").textContent = d;
document.getElementById("days").innerText = d;
document.getElementById("hours").textContent = h;
document.getElementById("minutes").textContent = m;
document.getElementById("seconds").textContent = s;
}
countdown();
<li>
<span class="value">Ends in:
</span>
<p id="days">30</p>
<p id="hours">10</p>
<p id="minutes">5</p>
<p id="seconds">1</p>
</li>

Related

How do I stop my countdown timer from executing after it has reached the deadline on refresh of my browser

This is how the JavaScript looks like. I tried searching for solutions but couldn't find. Please I need detailed solutions. Online I kept seeing cookies but I don't know how to use it in this case.
function countDown() {
var now = new Date();
var eventDate = new Date(2020, 5, 22);
var currentTime = now.getTime();
var eventTime = eventDate.getTime();
var remTime = eventTime - currentTime;
var s = Math.floor(remTime / 1000);
var m = Math.floor(s/60);
var h = Math.floor(m/60);
var d = Math.floor(h/24);
h %= 24;
m %= 60;
s %= 60;
h = (h < 10) ? "0" + h: h;
m = (m < 10) ? "0" + m: m;
s = (s < 10) ? "0" + s: s;
document.getElementById("days").textContent = d;
document.getElementById("days").innerText = d;
document.getElementById("hours").textContent = h;
document.getElementById("minutes").textContent = m;
document.getElementById("seconds").textContent = s;
var t = setTimeout(countDown, 1000);
if (d == 0 && h == 0 && m == 0 && s == 0) {
clearTimeout(t);
document.getElementById("demo").innerHTML = "Happy Birthday!"
}
}
countDown();
</script>
The trouble with your code is in the date checking logic.
Checking with == will only give you a truthy response if the datetime (or part thereof) is the same as the value you're checking it against.
However, you need to check whether the date is already past. To do this, you need to use a < or <= operator.
Here's an example of what I mean. The info is console.loged instead, you can re-implement the DOM editing you have in your question.
function countDown() {
var now = new Date();
var eventDate = new Date(2020, 4, 22); // 22 May 2020
var currentTime = now.getTime();
var eventTime = eventDate.getTime();
var remTime = eventTime - currentTime;
var s = Math.floor(remTime / 1000);
var m = Math.floor(s/60);
var h = Math.floor(m/60);
var d = Math.floor(h/24);
h %= 24;
m %= 60;
s %= 60;
h = (h < 10) ? "0" + h: h;
m = (m < 10) ? "0" + m: m;
s = (s < 10) ? "0" + s: s;
var t = setTimeout(countDown, 1000);
// This if statement only runs exactly on eventDate
if (d == 0 && h == 0 && m == 0 && s == 0) {
document.getElementById("demo").innerHTML = "Happy Birthday!"
}
// This if statement will run if we're past or exactly on eventDate
if (remTime <= 0) {
clearTimeout(t);
}
// This console.log shows that the numbers become negative after the date
console.log(remTime, d,h,m,s);
}
countDown();

jQuery Timer that refreshes a div element when the minute changes

I am trying to get a div element to update once one minute goes by from.
I have a function in Javascript that counts down to a specific time in the day, however, I would like to use JQuery so that as the timer is counting down when the minute changes instead of having to refresh the browser it does it without refreshing.
I had a timer that displayed hours, minutes, seconds counting down to a specific setHours() using a setTimout to countdown.
function countdown() {
var now = new Date();
var eventDate = new Date();
var currentTiime = now.getTime();
var eventTime = eventDate.setHours(16, 30, 0);
var remTime = eventTime - currentTiime;
var s = Math.floor(remTime / 1000);
var m = Math.floor(s / 60);
var h = Math.floor(m / 60);
h %= 24;
m %= 60;
s %= 60;
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
document.getElementById("hours").textContent = h;
document.getElementById("minutes").textContent = m;
document.getElementById("seconds").textContent = s;
if (now.getHours() >= 9 && currentTiime < eventTime) {
setTimeout(countdown, 1000);
}
At the moment I have a countdown that countdown to 16:30 but displays as:
Hours: minutes: seconds: I would like Hours:xx minutes:xx and when the minute goes down 1 minute it shows in the div without refreshing the page.
Here is a solution that has a bit of JQuery strewn in. Please note that your Javascript solution will work as well. The only difference is that this calls setInterval instead of setTimeout ('setInterval' vs 'setTimeout')
Please try running the code snippet here or on JSFiddle: https://jsfiddle.net/raghav710/tbvmj4px/ . This updates the value without refreshing the page.
EDIT: Added condition to handle when the current time is greater than event time
function get_elapsed_time_string(total_seconds) {
var now = new Date();
var eventDate = new Date();
var currentTime = now.getTime();
var eventTime = eventDate.setHours(17, 00, 0);
var remTime = eventTime - currentTime;
if(remTime <= 0){
clearInterval(interval_id);
$("#hours").html(0);
$("#minutes").html(0);
$("#seconds").html(0);
}
var s = Math.floor(remTime / 1000);
var m = Math.floor(s / 60);
var h = Math.floor(m / 60);
h %= 24;
m %= 60;
s %= 60;
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
$("#hours").html(h);
$("#minutes").html(m);
$("#seconds").html(s);
}
var elapsed_seconds = 0;
var interval_id =
setInterval(function() {
elapsed_seconds = elapsed_seconds + 1;
get_elapsed_time_string(elapsed_seconds);
console.log(interval_id);
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="hours"></div>
<div id="minutes"></div>
<div id="seconds"></div>
function countdown(){
var now = new Date();
var eventDate = new Date();
var currentTiime = now.getTime();
var eventTime = eventDate.setHours(16, 30, 0);
var remTime = eventTime - currentTiime;
var s = Math.floor(remTime / 1000);
var m = Math.floor(s / 60);
var h = Math.floor(m / 60);
h %= 24;
m %= 60;
s %= 60;
h = (h < 10) ? h +" hrs" : h + "hrs";
h = (h <= 1) ? "" : h;
m = (m < 10) ? "0" + m + " mins" : m + " mins ";
if(now.getHours() >= 9 && currentTiime < eventTime){
setTimeout(countdown, 1000);
document.getElementById("timer").textContent = h + " " + m;
}
else if(now.getHours() < 9 || currentTiime >= eventTime){
var t = document.getElementsByClassName("order-day")[0];
t.getElementsByClassName("order-day")[0].textContent = "Order by 4:30pm for same day dispatch";
hideCountdown();
}

javascript compare Two Times

Trying to get it to change between 16:30:00 and 17:30:00, to change the text font colour
Tried nested if statements as well
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById('txt').innerHTML =
h + ":" + m + ":" + s;
var t = setTimeout(startTime, 500);
if ((h>=16 && m >=30) && (h<=17 && m<=30))
{
document.getElementById("txt").style.color = "red";
}
else
{
document.getElementById("txt").style.color = "black";
}
}
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
try to use setInterval() it's look more clear:
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
if((h==16 && m>=30) || (h==17 && m<=30)){
document.getElementById("txt").style.color = "red";
}
else
{
document.getElementById("txt").style.color = "black";
}
};
setInterval(startTime, 500);
The main bug in your logic is looking for minutes where it is both less than and equal to 30 AND greater than and equal to 30. The only way that part evaluates to true is if minutes is 30.
I would normalize the time (so that each combination of hour, minute and second can be represented by a unique number) and use that for comparisons.
function startTime(el) {
var today = new Date();
var hour = today.getHours(),
minute = today.getMinutes(),
second = today.getSeconds();
var normalized_time = normalizeTime(hour, minute, second);
document.getElementById(el).innerHTML
= hour + ":" + padTime(minute) + ":" + padTime(second);
document.getElementById(el).style.color
= normalized_time >= normalizeTime(16, 30, 0)
&& normalized_time <= normalizeTime(17, 30, 0)
? 'red'
: 'black';
}
/*
* Add a 0 to the beginning of the number if one-digit number
*/
function padTime(i) {
return i < 10 ? '0' + i : i;
}
/*
* Converts the time to a normalized version
*/
function normalizeTime(h, m, s) {
return s + (60 * m) + (60 * 60 * h);
}
var t = setInterval(startTime, 500, 'txt');
<span id="txt"></span>
Edit: As per you question you want to take hour and minute into account for comparison, So i have not included the second's part.
The following function get an integer value against time , that later used for the comparison.
function getSeconds(hh,mm,ss)
{
return (Number(hh) * 60 * 60) + (Number(mm) * 60) + Number(ss);
}
Complete code :
function getSeconds(hh,mm,ss)
{
return (Number(hh) * 60 * 60) + (Number(mm) * 60) + Number(ss);
}
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById('txt').innerHTML =
h + ":" + m + ":" + s;
var t = setTimeout(startTime, 500);
var timeNow = getSeconds(h,m,s);
//if ((h>=16 && m >=30) && (h<=17 && m<=30))
if (timeNow >= getSeconds(16,30,0) && timeNow <= getSeconds(17,30,00))
{
document.getElementById("txt").style.color = "red";
}
else
{
document.getElementById("txt").style.color = "black";
}
}
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
startTime();
Updated Fiddle
Previous Response
Try the Fiddle
The problem with your code is you are comparing m with contradictory conditions.
I have concatenated the hour and minutes like following and used that for time comparison
var hrs = Number(h+'.'+m);
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById('txt').innerHTML =
h + ":" + m + ":" + s;
var t = setTimeout(startTime, 500);
var hrs = Number(h+'.'+m);
//if ((h>=16 && m >=30) && (h<=17 && m<=30))
if (hrs >= 16.30 && hrs <= 17.30)
{
document.getElementById("txt").style.color = "red";
}
else
{
document.getElementById("txt").style.color = "black";
}
}
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
startTime();

Javascript only working for one item in the list

I have a script that counts from now till due_date. I made a .each to list reservations. each reservation has a due_date. The counter i made only works for the first row.. and seems to not work for the remaining rows.
also i noticed when i added a new record, the new record added/ replaced with the other. because my timer changes dramatically when I added/ removed the record.
Here is the code that follows:
<% #reservations.where( "completed = ?", false).where( "due_date >= ?", DateTime.now).each do |reservation| %>
<div id="dueDate-counter">
<table>
<tr>
<td>days</td>
<td>hrs</td>
<td>mns</td>
<td>secs</td>
</tr>
<tr>
<td id="days"></td>
<td id="hours"></td>
<td id="minutes"></td>
<td id="seconds"></td>
</tr>
</table>
<script type="text/javascript">
function countdown() {
var now = new Date( <% DateTime.now %> );
// var year = <%= reservation.due_date.strftime("%Y")%>;
// var month = <%= reservation.due_date.strftime("%m") %>;
// var day = <%= reservation.due_date.strftime("%d") %>;
// var time = <%= reservation.due_date.strftime("%r") %>;
// var eventDate = new Date(year, month, day, time);
var eventDate = new Date("<%= reservation.due_date.localtime.strftime(" % m / % d / % Y % l: % M % P ") %>");
<%= puts "this is the reservation format below!!!!!!!" %>
<%= puts "#{reservation.due_date.localtime.strftime(" % m / % d / % Y % l: % M % P ")}" %>
console.log(now);
var currentTime = now.getTime();
var eventTime = eventDate.getTime();
console.log(currentTime);
var remTime = eventTime - currentTime;
var s = Math.floor(remTime / 1000);
var m = Math.floor(s / 60);
var h = Math.floor(m / 60);
var d = Math.floor(h / 24);
h %= 24;
m %= 60;
s %= 60;
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
document.getElementById("days").textContent = d;
document.getElementById("days").innerText = d;
document.getElementById("hours").textContent = h;
document.getElementById("minutes").textContent = m;
document.getElementById("seconds").textContent = s;
setTimeout(countdown, 1000);
};
countdown();
</script>
</div>
<% end %>
Instead of id use class
document.getElementsByClassName("example");
Identifiers in HTML must be unique. getElementById() will always get the first element, thus the code works for first row.
You can use specific CSS class then Class Selector can be used to target the elements. $.fn.find() can be used to target the TD element in the parent element context.
In the snippet below arbitrary data is associated with element using data-* custom attributes, which can be fetched using $.fn.data()
function countdown(elem) {
var now = new Date(elem.data('now'));
var eventDate = new Date(elem.data('date'));
var currentTime = now.getTime();
var eventTime = eventDate.getTime();
console.log(currentTime);
var remTime = eventTime - currentTime;
var s = Math.floor(remTime / 1000);
var m = Math.floor(s / 60);
var h = Math.floor(m / 60);
var d = Math.floor(h / 24);
h %= 24;
m %= 60;
s %= 60;
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
elem.find(".days").text(d);
elem.find(".hours").text(h);
elem.find(".minutes").text(m);
elem.find(".seconds").text(s);
setTimeout(function(){
countdown(elem);
}, 1000);
};
$('.dueDate-counter').each(function(){
countdown($(this))
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<% #reservations.where( "completed = ?", false).where( "due_date >= ?", DateTime.now).each do |reservation| %>
<div class="dueDate-counter" data-now='<% DateTime.now %>' data-date='<%= reservation.due_date.localtime.strftime(" % m / % d / % Y % l: % M % P ") %>'>
<table>
<tr>
<td>days</td>
<td>hrs</td>
<td>mns</td>
<td>secs</td>
</tr>
<tr>
<td class="days"></td>
<td class="hours"></td>
<td class="minutes"></td>
<td class="seconds"></td>
</tr>
</table>
</div>
<% end %>

JS Timer is not starting when button pushed

I have been looking at this for a few hours and cant seem to see why my code isnt starting the timer countdown when the button is pressed. Any help would be much appreciated, thanks!
HTML
<div id="timerHours">00</div>
<div id="timerMins">00</div>
<div id="timerSecs">00</div>
<input type="button" value="Start" onclick="startTimer()"/>
JavaScript
var t;
var timerDefault = new Date();
timerDefault.setHours(0, 0, 0);
function setTimer(){
var element = document.getElementById("timerHours");
hours = parseFloat(element.innerHTML);
element = document.getElementById("timerMins");
minutes = parseFloat(element.innerHTML);
element = document.getElementById("timerSecs");
seconds = parseFloat(element.innerHTML);
timerDefault.setHours(hours, minutes, seconds);
}
function startTimer() {
setTimer();
var h = timerDefault.getHours();
var m = timerDefault.getMinutes();
var s = timerDefault.getSeconds();
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
document.getElementById("timerHours").innerHTML = h;
document.getElementById("timerMins").innerHTML = m;
document.getElementById("timerSecs").innerHTML = s;
timerDefault.setSeconds(timerDefault.getSeconds() - 1);
if (h == 0 && m == 0 && s == 0) clearTimeout(t)
t = setTimeout(startTimer, 1000);
}
Your "startTimer()" routine always calls "setTimer()", which (re-)initializes that Date object based on the contents of the HTML elements. The routine then backs the seconds down by 1, but it never updates the HTML. Thus, the next time the timer goes off, the Date instance ("timerDefault") is reset to 00:00:00.
With a couple changes to your code you can see it count down a bit.
<div id="timerHours">00</div>
<div id="timerMins">00</div>
<div id="timerSecs">50</div>
<input type="button" value="Start" onclick="startTimer()"/>
var t;
var timerDefault = new Date();
timerDefault.setHours(0, 0, 0);
function setTimer(){
var element = document.getElementById("timerHours");
hours = parseFloat(element.innerHTML);
element = document.getElementById("timerMins");
minutes = parseFloat(element.innerHTML);
element = document.getElementById("timerSecs");
seconds = parseFloat(element.innerHTML);
timerDefault.setHours(hours, minutes, seconds);
}
function startTimer() {
setTimer();
timerDefault.setSeconds(timerDefault.getSeconds() - 1);
var h = timerDefault.getHours();
var m = timerDefault.getMinutes();
var s = timerDefault.getSeconds();
console.log("Hi! " + h + " " + m + " " + s);
h = (h < 10) ? "0" + h : h;
m = (m < 10) ? "0" + m : m;
s = (s < 10) ? "0" + s : s;
document.getElementById("timerHours").innerHTML = h;
document.getElementById("timerMins").innerHTML = m;
document.getElementById("timerSecs").innerHTML = s;
if (h == 0 && m == 0 && s == 0) clearTimeout(t)
t = setTimeout(startTimer, 1000);
}

Categories

Resources