Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Please could somebody kindly show how the following results i have created and outputted into jsondata.php can be put into variables in JavaScript so that i can index through results and use them in Div's throughout my website.

VARIABLES REQUIRED ARE:

Everything in $lastplayed and the result of $secsemain

I have tried to access the data in Javascript using this code below, ... i know its bad!!

TEST1

<script>
url = jsondata.php;
var arr;
arr = <?php echo json_decode($lastplayed,TRUE); ?>;
</script>

BELOW ARE THE FILES TO GENERATE THE JSON DATA

FILE1 (dblastplayedarray.php)

<?php

date_default_timezone_set('Europe/London');

require_once("DbConnect.php");

$sql = "SELECT `artist`, `title`, `label`, `albumyear`, `date_played`, `duration`,
`picture` FROM historylist  ORDER BY `date_played` DESC LIMIT 5 ";

$result = $db->query($sql);

$lastplayed = array();
$i = 1;
while ($row=$result->fetch_object()) {
$lastplayed[$i]['artist']         = $row->artist;
$lastplayed[$i]['title']          = $row->title;
$lastplayed[$i]['label']          = $row->label;
$lastplayed[$i]['albumyear']      = $row->albumyear;
$lastplayed[$i]['date_played']    = $row->date_played;
$lastplayed[$i]['duration']       = $row->duration;
$lastplayed[$i]['picture']        = $row->picture;
$i++;
}

$starttime = strtotime($lastplayed[1]['date_played']);
$curtime = time();
$timeleft = $starttime+round($lastplayed[1]['duration']/1000)-$curtime;
$secsremain = (round($lastplayed[1]['duration'] / 1000)-($curtime-$starttime))
?>

FILE 2 (jsondata.php)

<?php
require_once("dblastplayedarray.php");
echo json_encode($lastplayed);
?>
share|improve this question
    
You can get a JSON object and deal with it through an AJAX request. –  Dan H Jan 20 at 19:22
1  
You shouldn't json_decode the JSON you are trying to send. Let JavaScript handle it. –  TiiJ7 Jan 20 at 19:24

2 Answers 2

up vote 1 down vote accepted

First, you don't want to generate continuous requests to your PHP script just to get the remaining time of the current song. Better let JavaScript handle that.

Your JavaScript must decide two things:

  1. when to fetch the next batch of song descriptions
  2. how to fetch it

A possible solution is:

Let your JS code compute the time to current song end. When this time reaches zero, query your DB via PHP to fetch the next batch of songs.
Once the update is received, compute the time to current song end again and wait for it to reach zero (using a timer).

To get the results from PHP, you would better use Ajax to avoid refreshing your page entirely.

Putting all this together, you should have something like that:

JavaScript

var PlayList = function (onUpdate, onError)
{
    // store user callbacks
    this.onUpdate = onUpdate; 
    this.onError  = onError;

    // setup internal event handlers
    this.onSongEnd = onSongEnd.bind (this);

    // allocate an Ajax handler
    try
    {
        this.ajax = window.XMLHttpRequest
            ? new XMLHttpRequest()
            : new ActiveXObject("Microsoft.XMLHTTP");
    }
    catch (e)
    {
        // fatal error: could not get an Ajax handler
        this.onError ("could not allocated Ajax handler");
    }
    this.ajax.onreadystatechange = onAjaxUpdate.bind(this);

    // launch initial request
    this.onSongEnd ();

    // ------------------------------------------
    // interface
    // ------------------------------------------

    // try another refresh in the specified amount of seconds
    this.retry = function (delay)
    {
        setTimeout (this.onSongEnd, delay*1000);
    }

    // ------------------------------------------
    // ancillary functions
    // ------------------------------------------

    // called when it's time to refresh the playlist
    function onSongEnd ()
    {
        // ask for a playlist update

        this.ajax.open('GET', 'playlist.php', // <-- reference your PHP script here
                       true);
        this.ajax.send(null);       
    }

    // called to handle Ajax request progress
    function onAjaxUpdate ()
    {       
        if (this.ajax.readyState != 4) return;
        if (this.ajax.status == 200)
        {
            // get our response
            var list = eval ('('+this.ajax.responseText+')');

            // compute milliseconds remaining till the end of the current song
            var start = new Date (list[0].date_played).getTime();
            var now   = new Date (                   ).getTime();
            var d = start - now
                  + parseInt(list[0].duration); // JSON data are plain strings, don't forget
                                                //  to convert then to numbers if need be
            if (d < 0)
            {
                // no new song started, retry in 10 seconds
                d = 10000;
            }
            else
            {
                // notify caller
                this.onUpdate (list);
            }

            // schedule next refresh
            setTimeout (this.onSongEnd, d);

        }
        else
        {
            // Ajax request failed. Most likely a fatal error
            this.onError ("Bloody Ajax request failed");
        }       
    }
}

Note that this is pure, vanilla JavaScript. This is meant as educational code, so you can use it to see an example of barebone Ajax use, if you're interested.

It will not work in IE8- due to the use of bind(), but you can easily add wrapper functions instead if you plan on supporting the old cow.

You can arguably do Ajax queries more easily with the JQuery goo. I never could stand the stuff myself, but no doubt you'll find a lot of people willing to show you how it's done.

Usage

var list = new PlayList (playlistupdate, playlisterror);

function playlistupdate (list)
{
    // do whatever you want with the playlist
    console.log ("Playlist update at "+new Date().toTimeString());
    for (var i = 0 ; i != list.length ; i++)
    {
        var song = list[i];
        console.log (i+" "+song.title);
    }
}

function playlisterror (msg)
{
    // display error message
    console.log ("Ajax error: "+msg);

    // may want to retry, but chances of success are slim
    list.retry (10); // retry in 10 seconds
}

PHP (real database access)

// make this query non cacheable
/*
 * if you don't do this, your browser will cache
 * your first query and ignore the subsequent ones
 */
header("Cache-Control: no-cache");

// open your DB connection
require_once("DbConnect.php");

// fetch playlist
$result = $db->query(
    "SELECT `artist`, `title`, `label`, `albumyear`, `date_played`, `duration`, `picture` "
   ."FROM historylist  ORDER BY `date_played` DESC LIMIT 5 ");

// this little line replaces your bunch of code
while ($row=$result->fetch_object()) $list[] = $row;

// encode and send the result
echo json_encode ($list);

Note the no-cache header. This is the cleanest way of preventing the browser from caching your request.

The aforementioned JQuery goo will provide you with a poor solution consisting of adding some trash behind the query (i.e. replacing playlist.php with playlist.php?some_random_junk to force the browser to handle each request as unique, thus polluting your browser cache for no good reason).

Since you are in control of the PHP doing the query, better handle the problem at the source.

PHP (simulated)

I wrote a quick & dirty test harness to dispense with a database

// read our dummy DB
if (file_exists ("playlist.txt"))
{
    foreach (explode ("\n", file_get_contents ("playlist.txt")) as $i => $line)
    {
        $line = explode ('|', $line);
        foreach (array ('title', 'date_played', 'duration') as $k =>$f)
        {
            $db[$i]->$f = $line[$k];
        }
    }

    $last_ended = strtotime($db[count($db)-1]->date_played)
                    + $db[count($db)-1]->duration/1000;
}
else $last_ended = time();

function song_name ()
{
    return
        array_rand (array_flip(array("A", "Your", "Some", "This", "No"))). " ".
        array_rand (array_flip(array("beautiful", "weird", "delightful", "doomed", "pink"))). " ".
        array_rand (array_flip(array("love", "kiss", "baby", "monster", "dude", "car")));
}

// add a new dummy song to our DB if the last one has ended
if ($last_ended <= time())
{
    $changed = true;
    $db[] = array ("title" => song_name(), "date_played" => date("M d Y H:i:s", $last_ended), "duration" => rand(10,20)*1000);

        // store only the last 5 songs in the dummy DB
    $db = array_slice ($db, -5);
    foreach ($db as $k => $record)
    {
        $out[$k] = implode ('|', (array)$record);
    }
    file_put_contents ("playlist.txt", implode ("\n", $out));
}

// make this query non cacheable
header("Cache-Control: no-cache");

// get DB output
$list = array_slice (array_reverse ($db), 0, 5);

// encode and send it
echo json_encode ($list);

sample output (from browser console)

   Playlist update at 00:34:26 GMT+0100 (Paris, Madrid)
   0 Your doomed love
   1 Your doomed dude
   2 No beautiful kiss
   3 Some pink baby
   4 Your delightful car
   Playlist update at 00:34:38 GMT+0100 (Paris, Madrid)
   0 No doomed baby
   1 Your doomed love
   2 Your doomed dude
   3 No beautiful kiss
   4 Some pink baby

You can get both test files here.
I did not do a JSFiddle due to the difficulty of simulating Ajax requests in a readable way.

Actual HTML display

As per popular request, here is a sample code that does display something on a web page instead of simply prionting the list to the console.

You only need to change playlistupdate for something like this:

function playlistupdate (list)
{
    // display the playlist inside a table

    // table header
    var table = '<tr>';
    for (var j in list[0]) table += '<th>'+j+'</th>';
    table += '</tr>';

    // list items
    for (var i = 0 ; i != list.length ; i++)
    {
        table += '<tr>';
        for (var j in list[i])
        {
            table += '<td>'+list[i][j]+'</td>';
        }
        table += '</tr>';
    }

    // update table
    document.getElementById ('playlist').innerHTML = table;
}

And you need to define an empty table somewhere in your HTML:

<table id='playlist'></table>
share|improve this answer
    
What you have done here @kuroi neko is absolutely vast and i can not thank you enough... saying that i have zero[0] knowledge of what you have written but i am beginning to understand it a little...I have it up and running and can see the colsole log running through... i believe i need to convert duration which i believe is currently in milliseconds from a plain string to numbers as you mentioned... im guessing that if i do this the page will be able to refresh when the duration of the song ends... –  Justin Jan 21 at 0:48
    
It was quite fun doing it :). I would advise you to try and make it run with your real database instead of my dummy first, then play with it a bit (adding console logs here and there to get a feel of how it works). As for the refresh time, it should work fairly well as it is. The refresh time is computed so that it occurs at the end of the currently playing song. About char/string encoding, even if you convert your DB fields to numbers, there is a possibility the DB query will still return a plain string, so converting back to an integer is the safest way, IMHO. –  kuroi neko Jan 21 at 0:56
    
i have it running with my database. currently you are allowing me to see the "titles" of all results queried. Im guessing this is a loop that just continuously runs in the colsole for test purposes.. Shows how much knowledge i have on this... i think i need to go away and figure out how to display this data on a page for test purposes and get a good understanding of your code... thank you again –  Justin Jan 21 at 1:07
    
No problem. This is not a trivial task, so it needs a bit of thinking over. –  kuroi neko Jan 21 at 1:09
    
Well the data you are working with is a playlist. It will only change once a song is done playing. The only other things that change are the relative timings (like for instance a display of the seconds remaining for the current song), but they can be computed localy by JavaScript. –  kuroi neko Jan 21 at 21:07

change LIMIT 5 to LIMIT 1 or delete this .I think Your Code have Multi Array's And this Not usable in this source !!! Just i think . And I'm not try it...
TEST1 is php file?
change var arr to var arr = new Array();

Send information's by Ajax And Use it...

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.