Passing Razor Variable into JavaScript Function - javascript

I am working on an Auction site in Asp.net MVC and I am trying to be able to display how a timer of how much time is left on each item's auction. I pass a list of items to my cshtml page with my Model and then iterate through them like so:
My javascript function to start timer:
function countdown(time) {
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = time - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element with id="timeLeft"
document.getElementById("timeLeft").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
}, 1000);
Then my iterator of my Model, calling js function with the item's end date
#foreach (var item in Model)
{
//code here
countdown(#item.EndDate)
<text id="timeLeft"></text>
}
I have my script referenced by <script src="~/Scripts/countdown.js" />
The problem I am having is how to call this js function with a c# razor variable. Doing something basic for one item like:
<body onload= "countdown('#item.EndDate')">
When I put my razor variable it greys out my function.
How do I need to go about passing my variable into my js function?
EX: (with singular Model item)

Try with this syntax:
#foreach (var item in Model)
{
//code here
countdown(`${#item.EndDate}`)
}

If you want to make a timer in javascript, I would use window.setInterval function, then set the second parameter to be time interval.
This function countdown need to pass three parameter
End Year
End Month
End Day
function countdown(endYear,endMonth,endDay) {
window.setInterval(function () { StartCount(endYear, endMonth, endDay, 'andy timer'); }, 1000);
}
function StartCount(endYear,endMonth,endDay){
var now=new Date();
var endDate=new Date(endYear,endMonth-1,endDay);
var leftTime=endDate.getTime() - now.getTime();
var leftSecond=parseInt(leftTime/1000);
var day=Math.floor(leftSecond/(60*60*24));
var hour=Math.floor((leftSecond-day*24*60*60)/3600);
var minute=Math.floor((leftSecond - day * 24 * 60 * 60 - hour * 3600) / 60);
var second = Math.floor(leftSecond - day * 24 * 60 * 60 - hour * 3600 - minute * 60);
document.getElementById("timeLeft").innerHTML = day + "d " + hour + "h "
+ minute + "m " + second + "s ";
}
countdown(2018,10,5)
<div id='timeLeft'></div>
You can use this on the body tag
<body onload= "countdown(#Model.EndDate.Year,#Model.EndDate.Month,#Model.EndDate.Day)">
EDIT
It worked on c# MVC online: https://dotnetfiddle.net/ERcwAb

I figured out a crazy way to do what I was trying to do, might not be efficient, might be a sin to the entire coding community, but here it is:
#foreach (var item in Model)
{
<script>
function countdown(endYear, endMonth, endDay, endHours, endMin, num) {
window.setInterval(function () { StartCount(endYear, endMonth, endDay, endHours, endMin, num); }, 1000);
}
function StartCount(endYear, endMonth, endDay, endHours, endMin, num) {
var now = new Date();
var endDate = new Date(endYear, endMonth - 1, endDay, endHours, endMin);
var leftTime = endDate.getTime() - now.getTime();
var leftSecond = parseInt(leftTime / 1000);
var day = Math.floor(leftSecond / (60 * 60 * 24));
var hour = Math.floor((leftSecond - day * 24 * 60 * 60) / 3600);
var minute = Math.floor((leftSecond - day * 24 * 60 * 60 - hour * 3600) / 60);
var second = Math.floor(leftSecond - day * 24 * 60 * 60 - hour * 3600 - minute * 60);
var id = "timeLeft" + num;
document.getElementById(id).innerHTML = day + "d " + hour + "h "
+ minute + "m " + second + "s ";
}
countdown(#item.EndDate.Year, #item.EndDate.Month, #item.EndDate.Day,#item.EndDate.Hour, #item.EndDate.Minute, #num)
</script>
#{string countNum = "timeLeft" + num;}
<text id= #countNum></text>
#{num++;}
//code
}
But it still loads asynchronously where the items will all load, then the clocks all appear a second later and all content is moved accordingly. May be due to my initial issue of not doing able to call body onload.

Related

Why does this code do not work? (countdown)

I would like to write a code and a function that takes the name of the event and the date/time of the event and returns the time till the event. I would like to know what is wrong with the code.
<p style="color:red;font-size:20px;" id="C1_Counter"></p>
<script>
CD1(New_Year, "January 1, 2022 00:00:00")
function CD1(event_name, event_date) {
var C1 = "event_name = ";
var C1_Date = new Date(event_date).getTime();
var C1_Counter = document.getElementById("C1_Counter");
setInterval(() => countDown(C1, C1_Date, C1_Counter), 1000);
}
function countDown(x,time, elm) {
// Get today's date and time
var now = new Date().getTime();
// Find the distance between now and the time parameter
var distance = time - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element we got from the parameter elm
elm.innerHTML = x + days + " days " + hours + " hours "
+ minutes + " minutes " + seconds + " seconds ";
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(x);
console.log(elm);
elm.innerHTML = "EXPIRED";
}
}
</script>
Currently, your code throws the error ReferenceError: New_Year is not defined (you can see it in the browser console). If I understand correctly, you just forgot the quotes around the string. So try to replace:
CD1(New_Year, "January 1, 2022 00:00:00")
with:
CD1("New_Year", "January 1, 2022 00:00:00")
Also, you need to interpolate an argument into a string. So try to replace:
var C1 = "event_name = ";
with:
var C1 = event_name + " = ";
or with:
var C1 = `${event_name} = `;

JavaScript and content change after load - countdown timer from date

I'm trying to have a simple countdown timer that converts a time given on a page to a countdown.
It works, but my current issue is how the normal date is shown and then later it's parsed by the JavaScript. I want it parsed by JS right away so a user doesn't see it flicking between the date and the countdown timer.
It converts this to the countdown:
<span class="countdown">12/10/20 13:10:00</span>
This is the code:
if ($('.countdown').length)
{
$.each( $('.countdown'), function( key, value )
{
var time_listed = $(value).text();
var countdown_object = $(value);
// Set the date we're counting down to
var countDownDate = new Date(time_listed).getTime();
// Update the count down every 1 second
var x = setInterval(function()
{
// Get today's date and time
var now = new Date().getTime();
// Find the distance between now and the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element with id="demo"
countdown_object.text (days + " days " + hours + "h "
+ minutes + "m " + seconds + "s ");
// If the count down is finished, write some text
if (distance < 0)
{
clearInterval(x);
countdown_object.text("EXPIRED");
}
}, 1000);
});
}
What I am asking for, is suggestions on how to get around this problem. Is the only way to have it loaded before the HTML or what? I'm confused on the best practices for this. Everywhere keeps telling me to defer JavaScript loading...but what about stuff like this that changes the content?
In cases like this, is it a good idea to have a "core" file for content-changing stuff that loads right away, then the rest after the content or what?
The problems comes from setInterval not executing automatically , which is normal. Here's a work around it:
if ($('.countdown').length)
{
$.each( $('.countdown'), function( key, value )
{
var time_listed = $(value).text();
var countdown_object = $(value);
// Set the date we're counting down to
var countDownDate = new Date(time_listed).getTime();
var counterFunction = function()
{
// Get today's date and time
var now = new Date().getTime();
// Find the distance between now and the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element with id="demo"
countdown_object.text (days + " days " + hours + "h "
+ minutes + "m " + seconds + "s ");
// If the count down is finished, write some text
if (distance < 0)
{
clearInterval(x);
countdown_object.text("EXPIRED");
}
return counterFunction;
}
// Update the count down every 1 second
var x = setInterval(counterFunction(), 1000);
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="countdown">12/10/20 13:10:00</span>
I suggest to put the date in data-date attr, like this:
<span data-date="12/10/20 13:10:00" class="countdown"></span>
than the script:
if ($('.countdown').length)
{
$.each( $('.countdown'), function( key, value )
{
var time_listed = $(value).attr("data-date");
var countdown_object = $(value);
// Set the date we're counting down to
var countDownDate = new Date(time_listed).getTime();
// Update the count down every 1 second
var x = setInterval(function()
{
// Get today's date and time
var now = new Date().getTime();
// Find the distance between now and the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element with id="demo"
countdown_object.text (days + " days " + hours + "h "
+ minutes + "m " + seconds + "s ");
// If the count down is finished, write some text
if (distance < 0)
{
clearInterval(x);
countdown_object.text("EXPIRED");
}
}, 1000);
});
}
https://jsfiddle.net/750o1neh/

JavaScript timer stuck when adding PHP script to footer

I'm trying to convert the 0 in stock text on my website (held within a <p> tag) to a countdown timer, once the stock level hits 0. So I've added this code to the footer - however it seems to just stick, and not count down at all. It also takes a few seconds to replace the 0 in stock text - can I make this quicker/instant? Here's the code so far:
// Set the count down date
var countDownDate = new Date("Feb 21, 2021 15:26:00").getTime();
// Update the count every 1 second
var x = setInterval(function() {
// Get today's date and time
var now = new Date().getTime();
// Distance between now and the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result if stock = 0
list = document.getElementsByClassName("stock in-stock");
if (list[0].innerHTML == "0 in stock") {
list[0].innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
}
// If the count down is finished, write text
if (distance < 0) {
clearInterval(x);
list = document.getElementsByClassName("stock in-stock");
list[0].innerHTML = "Item expired!";
}
}, 1000);
<p class="stock in-stock">1 in stock</p>
You were trying to populate the P with new data and somehow trying to read out the old data, I've just separated that into 2 spans so you can work with each one individually and updated your JS to reflect the new structure.
To speed up the first call, extract the function:
Please note that we're treating "stock" and "countdown" as 2 different things now.
// Set the count down date
var countDownDate = new Date("Feb 21, 2021 15:26:00").getTime();
function ctd() {
// Get today's date and time
var now = new Date().getTime();
// Distance between now and the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
//console.log(days + " " + hours + " " + minutes + " " + seconds);
// Display the result if stock = 0
countdown = document.getElementsByClassName("countdown");
stock = document.getElementsByClassName("stock-level");
if (stock[0].innerHTML == "1") {
countdown[0].innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
}
// If the count down is finished, write text
if (distance < 0) {
clearInterval(x);
countdown.innerHTML = "Item expired!";
}
}
ctd(); // run now
// Update the count every 1 second
var x = setInterval(ctd, 1000);
<p class="stock-level" style="display:none">1</p>
<p class="countdown"></p>
I got it to work. Here's the code:
<script>
//Set the count down date
var countDownDate = new Date("Feb 20, 2019 18:26:00").getTime();
var startTimer=false;
list = document.getElementsByClassName("stock in-stock");
if(list[0].innerHTML=='1 in stock') {
startTimer=true;
}
//Check if 1 left
list = document.getElementsByClassName("stock in-stock");
//Update the count every 1 second
var x = setInterval(function() {
//Get today's date and time
var now = new Date().getTime();
//Distance between now and the count down date
var distance = countDownDate - now;
//Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
//Update the counter
if(startTimer) {
list[0].innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
}
//If the count down is finished, write text
if (distance < 0) {
clearInterval(x);
list = document.getElementsByClassName("stock in-stock");
list[0].innerHTML = "Item expired!";
}
}, 1000);
</script>

NaN on Javascript countdown timer in Internet Explorer

I'm using the following JavaScript for a countdown timer and it has been working great in most browsers, I've just double checked Internet Explorer however and I am getting 'NaN' displayed in place of each number.
Can anyone help to explain where this goes wrong in IE not seeing the individual variables as a number?
// Set the date we're counting down to
var countDownDate = new Date("2018-05-25 12:00:00").getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
if (days.toString().length < 2) {
days = "0" + days;
}
if (hours.toString().length < 2) {
hours = "0" + hours;
}
if (minutes.toString().length < 2) {
minutes = "0" + minutes;
}
if (seconds.toString().length < 2) {
seconds = "0" + seconds;
}
// Display the result in the element with id="countdown"
document.getElementById("countdown").innerHTML = days + " : " + hours + " : " +
minutes + " : " + seconds;
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("countdown").innerHTML = "<a href='/register'>Countdown Expired</a>";
}
}, 1000);
<span id="countdown"></span>
MDN discourages the use of a string in the date constructor because not all browsers implement this the same way.
If you do want to use date strings, I would recommend using a third party library like momentjs to parse these strings to make sure this works in every browser.
Just normalise the date and time
function getNormalisedDatetime(dString) { // yyyy-mm-dd hh:mm:ss
var parts = dString.split(" ");
var dParts = parts[0].split("-");
var tParts = parts[1].split(":");
return new Date(dParts[0],dParts[1]-1,dParts[2],tParts[0],tParts[1],tParts[2]);
}
function pad(num) {
return ("0"+num).slice(-2);
}
// Set the date we're counting down to
var countDownDate = getNormalisedDatetime("2018-05-25 12:00:00").getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element with id="countdown"
document.getElementById("countdown").innerHTML = "" + pad(days) + " : " + pad(hours) + " : " +
pad(minutes) + " : " + pad(seconds);
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("countdown").innerHTML = "<a href='/register'>Countdown Expired</a>";
}
}, 1000);
<span id="countdown"></span>

Timer countdown runs only once not following while loop?

Each time while loop run it create another table row and show related data, i want to show countdown timer in column of each row(to show time elapsing). My below script run only once. Do you have another idea how to do it or do something with this?? i wrote below code within the php while loop but runs only once. Please help
<script>
counter=0;
</script>
<?php
$count=0;
while($rowp = $resultp->fetch_assoc()) {
echo <td><p id='demo",$count,"'></p></td>
?>
<script>
var countDownDate = new Date("<?php echo $enterytime1; ?>").getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = now - countDownDate;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Output the result in an element with id="demo"
document.getElementById("demo" + counter).innerHTML = hours + "h " + minutes + "m " + seconds + "s ";
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "EXPIRED";
}
}, 1000);
</script>
<?php }
?>
yes you have to create new countdown for all column
Probably your if condition is true - countDownDate > now - and it terminates interval.
I am guessing it goes directly to EXPIRED right? You have the wrong order. It should be the other way around:
var distance = countDownDate - now;
I replaced the php code to the date and i changed the distance calculation. Try this if there is any change then let me know
var countDownDate = new Date(2017, 2, 10, 12, 9, 40, 0).getTime();
counter = 0;
// Update the count down every 1 second
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an the count down date
var distance = countDownDate - now;
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "EXPIRED";
}
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
counter++;
// Output the result in an element with id="demo"
var newDiv = document.createElement("div");
newDiv.setAttribute("id", "demo" + counter);
var node = document.createTextNode(days + "days " + hours + "h " + minutes + "m " + seconds + "s ");
newDiv.appendChild(node);
if (document.getElementById("demo" + counter) != null) {
document.getElementById("demo" + counter).innerHTML = days + "days " + hours + "h " + minutes + "m " + seconds + "s ";
} else {
document.body.appendChild(newDiv);
}
if (counter > 10)
counter = 0;
}, 1000);
div {
border: 1px black solid;
}
<div id='demo'></div>

Categories