Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refresh div, but only if there is new content from php file

Background Info

I'm fiddling around with some PHP and AJAX at the moment, to try and get the code working for an auto refreshing div (every 10 seconds), that contains comments.

Here is javascript code I am using to refresh the div..

<script type="text/javascript">// <![CDATA[
$(document).ready(function() {
        $.ajaxSetup({ cache: false }); 
            setInterval(function() {
                    $('#content_main').load('/feed_main.php');
        }, 5000);  
});
// ]]></script>

The code that will populate the div called "content_main", which is in feed_main.php, essentially accesses the database and echo's out the latest comments ...

Question

Is it possible, to only load the div "content_main" if the data inside of it, hasn't changed since the last time it was loaded?

My logic

Because I'm relatively new to javascript and AJAX I don't quite know how to do this, but my logic is:

For the first time it is run..

  • load data from feed_main.php file
  • Create a unique value (perhaps a hash value? ) to identify say 3 unique comments

Every other time it is run...

  • load the data from feed_main.php file
  • create a NEW unique value
  • check this value with the previous one
  • if they're the same, don't refresh the div, just leave things as they are, but if they're different then refresh..

The reason why I want to do this is because the comments usually have pictures attached, and it is quite annoying to see the image reload every time.

Any help with this would be greatly appreciated.

like image 952
sotirios9 Avatar asked Nov 27 '12 06:11

sotirios9


2 Answers

I've faced similar problem not too long ago, i assume that you using mysql or something for your comments storage serverside ?

I solved my problem by first adding timestamp integer column to my mysql table, then when i added a new row, i'd just simply use time() to save the current time.

mysql row insert example:

$query = "INSERT INTO comments (name, text, timestamp) VALUES ('". $name ."', '". $text ."',". time() .");";

step two would be to json_encode the data you sending from serverside:

$output = array();

if ($html && $html !== '') {   // do we have any script output ?
  $output['payload'] = $html;  // your current script output would go in this variable
}
$output['time'] = time();      // so we know when did we last check for payload update

$json = json_encode($output, ((int)JSON_NUMERIC_CHECK)); // jsonify the array
echo $json;                    // send it to the client

So, now instead of pure html, your serverside script returns something like this:

{
  "payload":"<div class=\"name\">Derpin<\/div><div class=\"msg\">Foo Bar!<\/div>",
  "time":1354167493
}

You can grab the data in javascript simply enough:

<script type="text/javascript"> // <![CDATA[

var lastcheck;
var content_main = $('#content_main');

pollTimer = setInterval(function() {
  updateJson();
}, 10000);

function updateJson() {
  var request = '/feed_main.php?timestamp='+ (lastcheck ? lastcheck : 0);

  $.ajax({
    url: request,
    dataType: 'json',
    async: false,
    cache: false,
    success: function(result) {
      if (result.payload) {        // new data
        lastcheck = result.time;   // update stored timestamp
        content_main.html(result.payload + content_main.html()); // update html element
      } else {                     // no new data, update only timestamp
        lastcheck = result.time;
      }
    }
  });
}

// ]]> </script>

that pretty much takes care of communication between server and client, now you just query your database something like this:

$timestamp = 0;
$where = '';

if (isset($_GET['timestamp'])) {
  $timestamp = your_arg_sanitizer($_GET['timestamp']);
}

if ($timestamp) {
  $where = ' WHERE timestamp >= '.$timestamp;
}

$query = 'SELECT * FROM comments'. $where .' ORDER BY timestamp DESC;';

The timestamps get passed back and forth, client always sending the timestamp returned by the server in previous query.

Your server only sends comments that were submitted since you checked last time, and you can prepend them to the end of the html like i did. (warning: i have not added any kind of sanity control to that, your comments could get extremely long)

Since you poll for new data every 10 seconds you might want to consider sending pure data across the ajax call to save substantial chunk bandwidth (json string with just timestamp in it, is only around 20 bytes).

You can then use javascript to generate the html, it also has the advantage of offloading lot of the work from your server to the client :). You will also get much finer control over how many comments you want to display at once.


I've made some fairly large assumptions, you will have to modify the code to suit your needs. If you use my code, and your cat|computer|house happens to explode, you get to keep all the pieces :)

like image 150
Dingo Avatar answered Nov 15 '22 04:11

Dingo


How about this:

<script type="text/javascript">
    // <![CDATA[
    $(function () {

        function reload (elem, interval) {
            var $elem = $(elem);
            // grab the original html
            var $original = $elem.html();
            $.ajax({
                cache : false,
                url : '/feed_main.php',
                type : 'get',
                success : function (data) {
                    // compare the result to the original
                    if ($original == data) {
                        // just start the timer if the data is the same
                        setTimeout(function () {
                            reload(elem, interval)
                        }, interval);
                        return;
                    }
                    // or update the html with new data
                    $elem.html(data);
                    // and start the timer
                    setTimeout(function () {
                        reload(elem, interval)
                    }, interval);
                }
            });
        }

        // call it the first time
        reload('#content_main', 10000);
    });
    // ]]>
</script>

This is just an idea to get you going it doesn't deal with errors or timeouts.

like image 38
Dale Avatar answered Nov 15 '22 04:11

Dale