37

I have three computers; Server, Client and Viewer. I am in control of the server and the viewer. workflow

  1. The user on the Client connects to the Server and is presented with a webpage.
  2. Through a php script the user uploads an image.
  3. The image is imbedded in some html.
  4. The Viewer is a computer totally without user interaction - there is no keyboard. The Viewer is always at all time running a web browser, displaying the picture page.

My problem now is that even though the picture changes on the server disk, the webpage is not updated. How do I refresh the web browser on the viewer, or part of the webpage?

I know html, css, javascript, php and ajax, but apparently not well enough.

hpekristiansen
  • 920
  • 3
  • 14
  • 34

10 Answers10

57

There are at least three ways to accomplish this.

Pure HTML

As pointed out by Amitd's comment, in "show.html" add the following <meta> tag to your document's <head> element:

<meta http-equiv="refresh" content="5" />

This will automatically refresh the page every 5 seconds. Adjust the value of the content attribute to the desired number of seconds.

Pure JavaScript:

As pointed out by MeNoMore, document.location.reload() will refresh the page when you call it.

<script type="text/javascript">
    //put this somewhere in "show.html"
    //using window onload event to run function
    //so function runs after all content has been loaded.
    //After refresh this entire script will run again.
    window.onload = function () {
        'use strict';
        var millisecondsBeforeRefresh = 5000; //Adjust time here
        window.setTimeout(function () {
            //refresh the entire document
            document.location.reload();
        }, millisecondsBeforeRefresh);
    };
</script>

And as pointed out by tpower AJAX requests could be used, but you'd need to write a web service to return a url to the desired image. The JavaScript to do an AJAX request would look something like this:

<script type="text/javascript">
    //put this somewhere in "show.html"
    //using window onload event to run function
    //so function runs after all content has been loaded.
    window.onload = function () {
        'use strict';
        var xhr,
            millisecondsBeforeNewImg = 5000;    // Adjust time here
        if (window.XMLHttpRequest) {
            // Mozilla, Safari, ...
            xhr = new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            // IE
            try {
                // try the newer ActiveXObject
                xhr = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    // newer failed, try the older one
                    xhr = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {
                    // log error to browser console
                    console.log(e);
                }
            }
        }
        if (!xhr) {
            // log error to browser console
            console.log('Giving up :( Cannot create an XMLHTTP instance');
        }
        xhr.onreadystatechange = function () {
            var img;
            // process the server response
            if (xhr.readyState === 4) {
                // everything is good, the response is received
                if (xhr.status === 200) {
                    // perfect!
                    // assuming the responseText contains the new url to the image...
                    // get the img
                    img = document.getElementById('theImgId');
                    //set the new src
                    img.src = xhr.responseText;
                } else {
                    // there was a problem with the request,
                    // for example the response may contain a 404 (Not Found)
                    // or 500 (Internal Server Error) response code
                    console.log(xhr.status);
                }
            } else {
                // still not ready
                // could do something here, but it's not necessary
                // included strictly for example purposes
            }
        };
        // Using setInterval to run every X milliseconds
        window.setInterval(function () {
            xhr.open('GET', 'http://www.myDomain.com/someServiceToReturnURLtoDesiredImage', true);
            xhr.send(null);
        }, millisecondsBeforeNewImg)
    };
</script>

Other methods:

Finally, to answer your question to tpower's answer... $.ajax() is using jQuery to do the AJAX call. jQuery is a JavaScript library that makes AJAX calls and DOM manipulation a lot simpler. To use the jQuery library, you'd need to include a reference to it in your <head> element (version 1.4.2 used as an example):

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

You could also download the "jquery.min.js" and host it locally instead but that would, of course, only change the url you are loaded the script from.

The AJAX function above, when written using jQuery would look more like this:

<script type="text/javascript">
    //put this somewhere in "show.html"
    //document.ready takes the place of window.onload
    $(document).ready(function () {
        'use strict';
        var millisecondsBeforeNewImg = 5000;    // Adjust time here
        window.setInterval(function () {
            $.ajax({
                "url": "http://www.myDomain.com/someServiceToReturnURLtoDesiredImage",
                "error": function (jqXHR, textStatus, errorThrown) {
                    // log error to browser console
                    console.log(textStatus + ': ' + errorThrown);
                },
                "success": function (data, textStatus, jqXHR) {
                    //get the img and assign the new src
                    $('#theImgId').attr('src', data);
                }
            });
        }, millisecondsBeforeNewImg);
    });
</script>

As I hope is evident, the jQuery version is much simpler and cleaner. However, given the small scope of your project I don't know if you'd want to bother with the added overhead of jQuery (not that it's all that much). Neither do I know if your project requirements allow the possibility of jQuery. I included this example simply to answer your question of what $.ajax() was.

I'm equally sure that there are other methods by which you can accomplish refreshing the image. Personally, if the image url is always changing, I'd use the AJAX route. If the image url is static, I'd probably use the <meta> refresh tag.

Community
  • 1
  • 1
pete
  • 21,669
  • 3
  • 34
  • 49
  • Nice recap of various options open to the OP, nice job crediting other people, too... and +1 especially for considering _not_ to use jQuery for just one of its many capabilities as that is, indeed, overkill. – Elias Van Ootegem Jan 18 '13 at 13:07
20

I have the exact same application. Just use WebSockets.

You can start a websocket connection and the server will inform the Viewer whenever it gets an update. You can send the updated image through websocket, fully asynchronous without disturbing the display or user interaction.

If you use timers, you will not get quick updates or you will keep refreshing page without use.


Details:

Will need a Websocket server like pywebsocket or phpwebsocket.

Client:

Will need HTML5 websocket support, all of the current browsers support it.

Need to register for a message when an image update happens. It is like registering a callback.

Example:

wSocket = new WebSocket('ws://' + serverIP + ':' + serverPort + '/images');

wSocket.onopen = function() {
    console.log("Primary Socket Connected.");

    connectedPrimary = true;

    wSocket.send("sendImageUpdates");
};

wSocket.onmessage = function(evt) {
    // evt is the message from server

    // image will be representated as a 64 encoded string

    // change image with new one
    $("#image").attr('src', 'data:image/png;base64,' + evt.data);
}

wSocket.onclose = function() {
    console.log("Primary Socket Closed.");

    wSocket = null;
};

wSocket.onerror = function(evt) {
    alert(evt);
}

Whenever the server sends an update, the function mapped to wSocket.onmessage will be called, and you can do whatever you need to do with it.

Server:

Will listen for a connection from client (can be made to support multiple clients). Once a connection is made and the message "sendImageUpdates" is received, the server will wait for any updates in image. When a new image is uploaded, server will create a new message and send to client.

Pros

  1. Will get updates as soon as an image is uploaded and only when an image is uploaded.
  2. Client will know that image has changed and can do additional functions.
  3. Fully asynchronous and server driven.
ATOzTOA
  • 30,490
  • 20
  • 83
  • 113
  • 2
    Web sockets is the way to go. You wouldn't even have to refresh the page, just update the content that you want updated and it's totally asynchronous and server driven as noted. Since you control the Viewer, you can determine if the Viewer supports this. – Leeish Jan 18 '13 at 17:43
  • I was going to suggest websockets but figured someone already did. This is the perfect scenario for websockets. With all the possible images, the page reload would take too long. The server would get too bombed down doing polling over and over. Add offline ability and your viewer is a nice app. – Ben Felda Jan 18 '13 at 20:15
  • Web sockets for the win. A polling approach is so inefficient in comparison. – Ben Smith Feb 19 '14 at 00:26
  • Cons: reconnecting websockets is tricky, especially for 'viewer should run for year without servicing' cases. – Tomáš Kafka Feb 21 '16 at 22:55
11

You can use AJAX requests to help. For example, what you are doing is polling the server for the image every five seconds. Instead you could poll the server for a new image id and use that id instead of the random number for the source of the image. In this case the src attribute will only change/reload when there is a new image.

<script language="JavaScript"><!--
function refreshIt() {
   if (!document.images) return;
   $.ajax({
      url: 'latest-image-id.json',
      success: function(newId){
          document.images['doc'].src = 'doc.png?' + newId;        
      }
   });
   setTimeout(refreshIt, 5000); // refresh every 5 secs
}
//--></script>
</head>
<body onLoad=" setTimeout(refreshIt, 5000)">
<img src="doc.png" name="doc">

An alternative is to get a notification from the server when the image changes via a web socket.

tpower
  • 53,004
  • 18
  • 65
  • 99
  • OK - I will look into AJAX. It would just be more elegant, if the server were told to refresh, e.g. by the uploading php script. – hpekristiansen Nov 14 '12 at 09:47
  • 1+ .. Also see this example for websockets http://net.tutsplus.com/tutorials/javascript-ajax/start-using-html5-websockets-today/ – Amitd Nov 14 '12 at 09:54
  • Even though the browser is on the same machine, from a web development point of view you still have to write the page like any other client page. Unless you want to tell the browser externally to refresh which could be very tricky depending on your browser and OS. – tpower Nov 14 '12 at 09:59
  • I have written http://www.w3schools.com/ajax/default.asp and more, but I am still not able to understand your example. What is `$.ajax(...`? – hpekristiansen Jan 12 '13 at 04:43
  • 1
    @Hans, $.ajax is a way to send ajax requests in jquery(an awesome JS library). Learn jquery [here](http://docs.jquery.com/Tutorials:Getting_Started_with_jQuery).
    And BTW, http://w3fools.com/
    – svineet Jan 12 '13 at 11:38
  • @Shmiddty Care to improve the answer? – tpower Jan 17 '13 at 13:49
  • There's no reason you can't simply use `setTimeout(refreshIt, 5000);` – Shmiddty Jan 17 '13 at 16:50
5

Reloading the page in a specific time interval might do the trick.

setTimeout(function(){
window.location.reload(1);
}, 5000);

The above code reload the current page in 5 seconds.

OR

You could also go for an ajax call which will be assynchronous and also you wont have to refresh the whole page. Checkout the following code:

$.ajax({
  url: "test.aspx",
  context: document.body
}).done(function() {
  $(this).addClass("done");
});

This can be used instaed of the window.location.reload(1);

[**test.html:**This page has to bring in all the image src on load into it ie, a service that brings in the images to the page.]

On doing this you will get the result as data in the done(function() which you can assingn to an html element in the current page. example:

done(function() {
$('#ImageId').attr('src', data);
 });

This will set the src of img tag to data from test.aspx

Advantage: The whole page does not gets refreshed and only the new image is added.

Go thorough this link to know more about jQuery Ajax...

marc_s
  • 675,133
  • 158
  • 1,253
  • 1,388
A J
  • 2,092
  • 13
  • 22
4

Use.

document.location.reload();

For Example to react to a button click:

<input type="button" value="Reload Page" onClick="window.location.reload()">
CloudyMarble
  • 34,949
  • 69
  • 92
  • 126
1

You need to implement client long-polling connection with server what is called COMET or make use of socket if your browser supports websocket.

Yuriy Bilogub
  • 377
  • 2
  • 10
1

In javascript, there are a few ways to refresh programmatically.

The preferred method is location.reload()

Another way is by setting the location.href property, the browser automatically goes to the new url, so location=location or location.href=location.href would also do that.

Though the second method probably looks weird.

To recap, that's:

location.reload();
//or
location.href=location.href;
//or
location=location;


I hope this helped.
Braden Best
  • 7,664
  • 3
  • 29
  • 42
1

The easiest is to use AJAX pooling.
For that in the php file handing the upload, when a new photo is uploaded save a unix timestamp in a file:

file_put_contents('lastupload.txt', strval(time())); // Save timestamp of upload

Create another php file (ex: polling.php) that will handle AJAX calls and return the unix timestamp of the last upload:

echo file_get_contents('lastupload.txt'); // Send last upload timestamp

In the Viewer javascript code make an AJAX polling that will detect a change in the timestamp and refresh the image when needed:

$(function() {
   setInterval(polling, 1000); // Call polling every second.
});
var lastupload = 0;
function polling() {
   $.ajax({
      url: 'polling.php',
      success: function(timestamp){
          if (timestamp > lastupload) { // Is timestamp newer?
              document.images['image'].src = 'image.png?' + timestamp; // Refresh image
              lastupload = timestamp;
          }
      }
   });
}

I haven't tested the code, so there might be mistakes but this is the idea.

qwertzguy
  • 10,735
  • 5
  • 53
  • 59
1

I don't think that you need lot of scripting for that. I solved that problem just adding a question mark and random number just after the image url. If you don't change the image url browser calls it from cache.

To display the newest pic on page:

<img src="<?php echo $image_url; ?>?<?php echo rand(10,99); ?>"/>

It prints something like:

http://static.example.com/myimage.jpg?56 

Your question and my solution is refreshing the image url by changing it with a random number using Jquery and javascript random number function in my problem. I think you got the point and would adapt it to your need.

$('#crop_image').live('click',function(){
    $(this).html(ajax_load_fb);
    var x = $('#x').val();
    var y = $('#y').val();
    var w = $('#w').val();
    var h = $('#h').val();
    var dataString = 'process=image_crop&x='+x+'&y='+y+'&w='+w+'&h='+h;
    $.ajax({
        type: 'POST',
        url: '<?php echo $siteMain;?>ajax/ajaxupload.php',
        data: dataString,
        cache: false,
        success: function(msg) {
            $('#crop_image').html('Crop Selection');
            $('.crop_success_msg').slideDown('slow');
            var numRand = Math.floor(Math.random()*101);
            $('#current_img').html('<img src="/images/large_<?php echo $user['username'];?>.jpg?'+numRand+'"/>');
        },
        error: function(response, status, error)
        { 
            $(this).html('Try Again');
        }
    });
});
Kemal
  • 1,009
  • 3
  • 16
  • 33
0

The best solution would be writing a small php script on the viewer web browser to periodically check the image and if its changed it will reload it. As the php code runs on server side you can do it easily. I hope this helps if you need code snippet let me know.

sumeet kumar
  • 2,526
  • 1
  • 12
  • 22