Reputation: 85
I have written a foreach loop code to iterate through list of products (products are rotating via jquery content slider) and i want to add a javascript countdown inside this loop but the problem is the countdown only appears in the first product of this loop like below:
But when it iterates through other products it is not appearing
Here's my code i have written
<div id="rightBox">
@foreach (var product in Model)
{
<div id="[email protected]" class="ui-tabs-panel" style="">
<div style="float: right">
<div class="banner"></div>
<img class="img-content" src="~/Content/ProductImages/@product.Image" alt="" />
</div>
<div class="content">
<div class="column">
<span class="fa" style="text-decoration: line-through; font-size: 1.9rem">@product.MainPrice.ToString("N0") تومان</span>
<div style="margin: 10px 10px 10px 10px;"></div>
<span class="fa" style="color: #ef5661; font-size: 1.9rem">@string.Format("{0:N0}", product.DiscountPrice) تومان</span>
</div>
<div class="columnleft fa">
٪@Math.Floor((1 - (product.DiscountPrice / product.MainPrice)) * 100) 
<span> تخفیف </span>
</div>
<div class="title">
<p>@product.Name</p>
</div>
<br />
<div class="desclist">
@Html.Raw(product.Description)
</div>
<div class="fa" style="bottom: 50px; position: absolute">
<hr />
<div class="fa" style="font-size: x-large">
<span class="fa" id="hrRemaining"></span>:<span id="minRemaining"></span>:<span id="secRemaining"></span>
</div>
<p>زمان باقیمانده تا پایان سفارش</p>
</div>
</div>
</div>
}
</div>
And this is javascript countdown code
<script>
var remSeconds = Math.floor(@timeRemaining);
var secondsCounter = Math.floor(remSeconds % 60);
var minutesCounter = Math.floor((remSeconds / 60) % 60);
var hoursCounter = Math.floor((remSeconds / 3600));
function formatNumber(number) {
if (number < 10)
return '0' + number;
else
return '' + number;
}
function startTick() {
document.getElementById('secRemaining').innerText = formatNumber((secondsCounter));
document.getElementById('minRemaining').innerText = formatNumber((minutesCounter));
document.getElementById('hrRemaining').innerText = formatNumber((hoursCounter));
//document.getElementById('tRemaining').innerText = formatNumber((remSeconds));
var _tick = setInterval(function () {
if ((remSeconds) > 0) {
if (hoursCounter > 0) {
if (minutesCounter == 0) {
minutesCounter = 60;
hoursCounter = hoursCounter - 1;
}
}
if (secondsCounter == 0) {
secondsCounter = 60;
minutesCounter = minutesCounter - 1;
}
secondsCounter = secondsCounter - 1;
remSeconds = remSeconds - 1;
document.getElementById('secRemaining').innerText = formatNumber((secondsCounter));
document.getElementById('minRemaining').innerText = formatNumber(parseInt(minutesCounter));
document.getElementById('hrRemaining').innerText = formatNumber(parseInt(hoursCounter));
document.getElementById('clock').innerHTML = "Hello" + "<span class='fa' id='hrRemaining'>" + "</span>:<span id='minRemaining'></span>" + "<span id='secRemaining'></span>";
//document.getElementById('tRemaining').innerText = formatNumber(parseInt(remSeconds));
} else {
clearInterval(_tick);
//document.getElementById("tRemaining").innerHTML = "EXPIRED";
}
}, 1000);
}
startTick();
</script>
Upvotes: 0
Views: 245
Reputation: 21231
The first, and primary issue, is that you have duplicate ID values in your rendered HTML. That's going to cause issues when you try selecting those elements with getElementById. So, let's fix that first:
<div id="rightBox">
@foreach (var product in Model)
{
<div id="[email protected]" class="ui-tabs-panel" style="">
<div style="float: right">
<div class="banner"></div>
<img class="img-content" src="~/Content/ProductImages/@product.Image" alt="" />
</div>
<div class="content">
<div class="column">
<span class="fa" style="text-decoration: line-through; font-size: 1.9rem">@product.MainPrice.ToString("N0") تومان</span>
<div style="margin: 10px 10px 10px 10px;"></div>
<span class="fa" style="color: #ef5661; font-size: 1.9rem">@string.Format("{0:N0}", product.DiscountPrice) تومان</span>
</div>
<div class="columnleft fa">
٪@Math.Floor((1 - (product.DiscountPrice / product.MainPrice)) * 100) 
<span> تخفیف </span>
</div>
<div class="title">
<p>@product.Name</p>
</div>
<br />
<div class="desclist">
@Html.Raw(product.Description)
</div>
<div class="fa" style="bottom: 50px; position: absolute">
<hr />
<div class="fa countdown-timer" style="font-size: x-large">
<span class="fa hrRemaining"></span>:<span class="minRemaining"></span>:<span class="secRemaining"></span>
</div>
<p>زمان باقیمانده تا پایان سفارش</p>
</div>
</div>
</div>
}
</div>
I've replaced your id
attributes with classes, which we can leverage in the code I'll add below.
Since you've tagged this with jQuery, I've re-written your example to use jQuery rather than vanilla JavaScript:
var remSeconds = Math.floor(@timeRemaining);
var secondsCounter = Math.floor(remSeconds % 60);
var minutesCounter = Math.floor((remSeconds / 60) % 60);
var hoursCounter = Math.floor((remSeconds / 3600));
function formatNumber(number) {
if (number < 10)
return '0' + number;
else
return '' + number;
}
function startTimers(){
// The variables prefixed with `$` represent jQuery objects. Using $ isn't necessary, but it
// makes it a bit more obvious that it's not a "data" variable
// This will select all elements with the class 'countdown-timer'
var $timers = $('.countdown-timer');
// See https://api.jquery.com/each/
$timers.each(function(){
// `this` is the current `.countdown-timer` being iterated by jQuery.each()
var $timer = $(this);
var $seconds = $timer.find('.secRemaining');
var $minutes = $timer.find('.minRemaining');
var $hours = $timer.find('.hrRemaining');
$seconds.text(formatNumber((econdsCounter));
$minutes.text(formatNumber(minutesCounter));
$hours.text(formatNumber(hoursCounter));
var _tick = setInterval(function () {
if (remSeconds > 0) {
if (hoursCounter > 0) {
if (minutesCounter == 0) {
minutesCounter = 60;
hoursCounter = hoursCounter - 1;
}
}
if (secondsCounter == 0) {
secondsCounter = 60;
minutesCounter = minutesCounter - 1;
}
secondsCounter = secondsCounter - 1;
remSeconds = remSeconds - 1;
$seconds.text(formatNumber((econdsCounter));
$minutes.text(formatNumber(minutesCounter));
$hours.text(formatNumber(hoursCounter));
} else {
clearInterval(_tick);
//document.getElementById("tRemaining").innerHTML = "EXPIRED";
}
}, 1000);
}
}
startTimers();
So, a review of the changes:
countdown-timer
to the <div>
elements which you use to contain your hours, minutes, and seconds elements.id
attributes for class
attributes, which lets us re-use our "selectors" - the classes that identify our timer elementsstartTimers
, but that's just because (to me) it more accurately describes the function's usage.startTimers
, I use jQuery to select each of the timer elements (denoted by countdown-timer
), which will return something I can treat as an array.$('selector').each()
function to iterate through the array of timers, setting the matching element's text values and kicking off the setInterval
loops.Upvotes: 1
Reputation: 89
This is because you are using an id. Ids must be unique in HTML. If each of these items have the same time remaining, then just change the ids to a class. If they are unique countdowns then you should probably add them to your model and generate a unique id for each product. Then obviously you would need to modify your javascript to keep track of the ids.
Upvotes: 1