0

I am currently stuck on a problem and not sure how to solve it. I am new to php and javascript coding so do please correct me if there is an easier way to do this.

I am making a football player auction website. It's like ebay except it's players instead of items. Basically you put players for sell and there will be a countdown timer.

My problem is that I am trying to get a countdown timer working for multiple players. I have already made a successful countdown time function that only works with one player, but when I try to do it with multiple players it doesn't work as intended. It only updates the last player.

This is the output for one player.

Player Name: Rooney
Hours:20 Minutes:16 Seconds:56

This is the output for two or more players

Player Name: Messi

Player Name: Beckham

Player Name: Rooney
Hours:20 Minutes:16 Seconds:56

I will explain what I have got so far.

A database which contains Player name and their end time. One php file for connecting to database. Finally a file which contains my script for countdown timer and where I am testing.

Database Structure

|Player Name|------------|End date/time|---------
   Messi               July 31 2015 05:00:00 PM
  Ronaldo              July 31 2015 10:00:00 PM

Note the end date time is a string and in the format shown above so I can retrieve the remaining time using strtotime function.

This is how my normal body works. I pick the table above using PHP with MySQL. Then I go in a loop printing out each player's name. During printing each players name I call the timer function to get the countdown time. This function takes in two parameters. First is the end date time. Second parameter is the unique id(div tag). I get the end date/time from the database and I create a unique id tag using an array.

My intention was to create a function which takes the end date and a unique id for the player and then editing it like

document.getElementById(uniqueID).innerHTML =... 

as that's the only way to edit the content inside a div I know off and I am creating multiple divs in a loop.

Here's the main script with some comments

//Connecting to database
<?php
    include 'connect.php';
?>

<!doctype html>

<html>

<head>
<?php
//array used to create unique id for our divs
$ids = array("one","two","three","four","five","six","seven","eight","nine");
$i =0;

function timer($date, $id){
//changing time to london(uk) time.
date_default_timezone_set("Europe/London");
//converting the string from database into time form
$endtime = strtotime($date);
//Returns the current time
$idtemp = $id;

?>
<script>
//convert server time to milliseconds 
var server_current = <?php echo time(); ?> * 1000;
var server_end_time = <?php echo $endtime; ?> * 1000;
var client_current_time = new Date().getTime();

//server end time - server current time + client current time
var finish_time = server_end_time - server_current + client_current_time; 

var timer;

var uniqueID = <?php echo json_encode($idtemp); ?> ;

function countdown()
{
    var now = new Date();
    var left = finish_time - now;

    //Following code convert the remaining milliseconds into hours, minutes and days.
    //milliseconds conversion
    //1000-second 60,000-minute 
    //3,600,000-hour  86,400,400-hour
    var hour = Math.floor( (left % 86000000 ) / 3600000 );
    var minute = Math.floor( (left % 3600000) / 60000 );
    var second = Math.floor( (left % 60000) / 1000 );

    document.getElementById(uniqueID).innerHTML = "Hours:"+hour+" Minutes:"+minute+" Seconds:"+second;
}
timer = setInterval(countdown, 1000);
</script>

<?php }?>
</head>

<body>
<h3>Auction House </h3>

<?php
//select table from database
$result = mysql_query("SELECT * FROM `current auction`");

while($row = mysql_fetch_array($result)){

    echo 'Player Name: '. $row['PlayerName'];
    $timeleft = $row['Time'];
    echo '<div id="c">';
    $temp = $ids[$i];
?>
    <script>
    //Change the div id to the next element in array
    document.getElementById("c").setAttribute("id",<?php echo json_encode($temp); ?>);
    </script>

<?php
    $i = $i +1;
    echo $temp;
    timer($timeleft, $temp);
    echo '</div>';
    echo "<br />";
}
?>


</body>
</html>

I am not sure why it isn't working.

Thanks

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
AndroidJava
  • 31
  • 2
  • 7
  • You might be able to work around this specific issue, but honestly to do this correctly you most likely need to leverage something like nodeJS, it is what eBay did. Only way to scale it out and actually have accurate data on the screen. – ficuscr Jul 30 '15 at 19:39
  • Thanks for the tip. Will check it out. – AndroidJava Aug 03 '15 at 23:38

2 Answers2

4

I'm feeling generous today, so I made this easy for you. Here's what I came up with:

<html>
<head>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>
<div class="container">
<h3>Auction House </h3>

<table id="table-auctions" class="table table-bordered table-hover table-striped">
    <tr>
        <th>Name</th>
        <th>Expiring</th>
    </tr>

</table>

</div> <!-- /container -->

<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script>
    $(function() {
        var times = [
            {
                'id': '1',
                'name': 'Messi',
                'end': new Date('July 31, 2015 13:00:00'),
            },
            {
                'id': '2',
                'name': 'Ronaldo',
                'end': new Date('August 1, 2015 10:00:00'),
            },
            {
                'id': '3',
                'player': 'JJ',
                'end': new Date('August 7, 2015 13:00:00'),
            },
        ];

        // Initialize the table values
        $.each(times, function( key, value ) {
            $('#table-auctions').append('<tr><td>'+value.name+'</td><td><span id="player-'+value.id+'-expiration" class="label label-primary">Loading...</span></td></tr>');
        });


        function countdown()
        {
            var now = new Date();
            console.log('updating time');

            $.each(times, function( key, value ) {
                var left = value.end - now;
                var days = Math.floor( left / (1000 * 60 * 60 * 24) );
                var hours = Math.floor( (left % (1000 * 60 * 60 * 24) ) / (1000 * 60 * 60) );
                var minutes = Math.floor( (left % (1000 * 60 * 60)) / (1000 * 60) );
                var seconds = Math.floor( (left % (1000 * 60)) / 1000 );

                displayTime = '';
                if (days > 0) {
                    displayTime = "Days: " + days;
                }
                displayTime = displayTime + " Hours: " + hours + " Minutes: " + minutes + " Seconds: " + seconds;

                $('#player-'+value.id+'-expiration').text(displayTime)
            });

        }
        timer = setInterval(countdown, 1000);        

    });
</script>
</body>
</html>

If you just copy and paste that code into its own html file, it will work great by itself and you'll get something like this:

enter image description here

The only thing left to do is to tie it to the database, and the best way to do that is to insert a foreach loop in the var times = part of the javascript.

Please note that you really should be using something other than PHP mysql_query because it allows for all sorts of headaches, primarily SQL injection. Here's a post about an easy way to implement PDO (which is a current and proper way to query your database).

Community
  • 1
  • 1
JasonJensenDev
  • 2,377
  • 21
  • 30
2

Just to iron out a couple of things on why your solution is not working:

PHP evaluates all of its constituents to render an HTML document that your browser can read, thus it's all done before your javascript can take over and change the id attribute (from your while loop)

With that being said, you can only really have 1 HTML id with the same name on the page, and depending on the browser it will either be that the first id is the real one, or the last is. Since you're creating multiple '<div id="c">' it's only applying your js to the true id="c".

Last but not least, you were setting a global variable timer that constantly got overwritten each time the PHP function timer() was called, forcing the very last element to be the only timer on the page. turning your javascript portion into a self-executing function (binding the scope of timer to a volatile state) lets new instances be created without being overwritten

try doing this instead:

<?php include 'connect.php'; //Connecting to database ?>
<!DOCTYPE html>
<html>
    <head>
        <?php
        function timer($date, $id){
            date_default_timezone_set("Europe/London"); //changing time to london(uk) time.
            $endtime = strtotime($date); //converting the string from database into time form
            $idtemp = $id; //Returns the current time
            ?>
            <script>
            (function(){
                //convert server time to milliseconds 
                var server_current = <?php echo time(); ?> * 1000,
                    server_end_time = <?php echo $endtime; ?> * 1000,
                    client_current_time = new Date().getTime(),
                    finish_time = server_end_time - server_current + client_current_time, //server end time - server current time + client current time
                    timer,
                    uniqueID = '<?php echo json_encode($idtemp); ?>';

                function countdown(){
                    var now = new Date();
                    var left = finish_time - now;

                    //Following code convert the remaining milliseconds into hours, minutes and days.
                    //milliseconds conversion
                    //1000-second 60,000-minute 
                    //3,600,000-hour  86,400,400-hour
                    var hour = Math.floor( (left % 86000000 ) / 3600000 );
                    var minute = Math.floor( (left % 3600000) / 60000 );
                    var second = Math.floor( (left % 60000) / 1000 );

                    document.getElementById(uniqueID).innerHTML = "Hours:"+hour+" Minutes:"+minute+" Seconds:"+second;
                }
                timer = setInterval(countdown, 1000);
            })();
            </script>
        <?php } ?>
    </head>

    <body>
        <h3>Auction House </h3>
        <?php
        $ids = array("one", "two", "three", "four", "five", "six", "seven", "eight", "nine"); //array used to create unique id for our divs
        $i = 0;
        $result = mysql_query("SELECT * FROM `current auction`"); //select table from database
        while($row = mysql_fetch_array($result)){
            $timeleft = $row['Time'];
            $temp = $ids[$i++];
            timer($timeleft, $temp);
            echo 'Player Name: '.$row['PlayerName'].'<div id='.json_encode($temp).'>loading...</div><br />';
        }
        ?>
    </body>
</html>

Also:

Please be careful! the mysql_* functions are deprecated for quite a few VERY good reasons and will be completely removed after the release of PHP 7, you should give this a read when you have some time: Why shouldn't I use mysql_* functions in PHP?

rahul singh Chauhan
  • 323
  • 1
  • 4
  • 15
iam-decoder
  • 2,554
  • 1
  • 13
  • 28