Good day I have database with 4 rows, each row has own time_to_expire time value. i have included javascript script to check time to expire and display the count down based on the time_to_expire for the row. The script is working perfectly the problem is IT ONLY DISPLAY COUNT DOWN FOR THE FIRST ROW AND IGNORE THE REST OF THE ROWS. Please check my code below and see what i might be missing. i am new to javascript i tried reading other solutions and i cant be able to find it working.
datapage.php
<?php
include_once 'dbconnect.php';
?>
<?php
// select data from the database
$usr_id = $_SESSION['usr_id'];
$sql = "SELECT * FROM orders WHERE customer_id='$usr_id' ";
$result=mysqli_query($con,$sql);
while($row = mysqli_fetch_array( $result ))
{
//ORDER REQUEST
if ($row['status'] == '0' && $row['is_confirmed'] == '1')
{?>
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="panel panel-danger">
<div class="panel-heading"><label>ORDER-PRICE :<?php echo "R"; echo $row['amount'];?> </label></div>
<div class="panel-body">
<form method="post" action="" id="register-form">
<div class="form-group">
<label for="name" color ="red" >TIME REMAINING: </label>
<div style="color:#e60000; text-align: center;font-size:16px; margin:0 auto" class="form-group">
<?php
include "countdown.php";
?>
</div>
<div>Click confirm once you have made a payment</div>
<div class="form-group">
<?php include "proof_upload.php";?>
<a href="address_confirm.php" style="float: right;"> Confirm your Address</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<?php
}
else //DISPLAY NOTHING.
{?>
<div class="col-md-4 col-md-offset-4"></div>
<?php
}
}
?>
countdown.php
<!-- Display the countdown timer in an element -->
<p id="demo"></p>
<script>
// Set the date we're counting down to
var countDownDate = new Date("<?php echo $row['time_to_expire'] ;?>").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="demo"
document.getElementById("demo").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "ORDER EXPIRED";
}
}, 1000);
</script>
There are many things to fix here.
Mixing PHP, HTML and JS doesn’t make this easier.
The forms will not work
From what I understand, you loop over the data fetched from your orders.
Why do you need multiple forms? Why do you need forms at all if there is no input fields and no data to submit (and no submit button)? I guess this is part of the proof_upload.php file.
However, you should have address_confirm.php as form action if you are using a form. and then have a simple submit button. This way you will actually submit data and you will be able to retrieve the data via $_POST in that php file.
You target IDs
Javascript does work a bit different than php. You can’t assume that when you loop over some data, that using only one ID will work. Javascript works with the DOM (your HTML) on a global scope. Javascript doesn’t know, that the id “demo” belongs to this or another element.
To solve this problem, you should have unique IDs (e.g. based on the row ID).
So for your <p> element, you use:
<p id="demo<?=$row['id']?>"></p>
And for your getElementById function, you have to re-use that id. I think it is best to save it somewhere. So you can use that again in JS.
However, you will not fix the entire problem here. Because you overwrite the countDownDate variable for every row, you set the Interval every time.
Why don’t you write a function that you use just once? No need to include it with EVERY row! This way, your HTML sent to the user will blow up very quickly.
Create a function that takes the element ID and time to expire as params (function createCountdown(elementId, timeToExpire) {} and in the countdown.php, you call that function together with the id and the time to expire.
I hope this helps!
Please let me know if this fixes the problem. It is tough to combine back-end and front-end this way. There are way more comfortable ways doing this, without mixing up js and php.
Thank you very much for your response, i have removed all unnecessary forms and included a unique ID on my p element, Now i am atlease getting count down on my rows but SAME COUNT DOWN on all the rows and When i view page source it shows each javascript with different times to expire and different id’s take a look on my javascript from view page source.
<p id="demo5"></p>
<script>
// Set the date we're counting down to
var countDownDate = new Date("2017-07-25 14: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="demo"
document.getElementById("demo5").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo5").innerHTML = "ORDER EXPIRED";
}
}, 1000);
</script> </div>
<p id="demo430"></p>
<script>
// Set the date we're counting down to
var countDownDate = new Date("2017-07-25 17:25:26").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="demo"
document.getElementById("demo430").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo430").innerHTML = "ORDER EXPIRED";
}
}, 1000);
</script> </div>
Now i only need help on displaying a row’s own timer not same one for all.
Hey there!
As I already said: you are overwriting the variable over and over again. Whenever the interval asks for countDownDate, the next row will have overwritten it already. This is because - as already said - javascript variables are globally, and do not magically know that they are in a php rendering context for a row.
I created a little codepen so you can see how you can solve this:
I created one function (that you do not include for every rendered row!)
but for each row, you can call that function with the demo ID and time. So only one line of JS needed: