It’s been a while, but I’m still alive. For my yob I had to create a webapp which also had to be fully working without network. To manage this, within HTML5 there’s the great appcache. For the app I was working on there were some challenges with some form of dynamic content like images and data to show. Within this post I would like to show you how I managed all these challenges.

First of all, I’m not going to tell you how appcache works. There has been written more and better on it then I could do. The main resources I used were an article from Eric Bidelman on and an article on  So, what’s the story morning glory? Well, I had to build a small kiosk-style webapp to show different kind of cars. The car information is served from another server which is also serving the images. For getting the information of the cars and some other information I wrote my own little api build on the Slim Framework. The car information and the images to show are dynamic and can change any time our marketeers wants it to change.

To handle this I did a few small things.

  • Dynamically change the appcahe manifest
  • Loading the new manifest an files without a page reload

First I start with the most important part, the images. The images needs to be loaded by the appcache to be sure they will be visible if there’s no connection. But because they’re not in the manifest they wil never be loaded. Of course we can add them by hand every time they change an image but that’s not really user friendly and has a great potential of making typo’s. A better way of doing this is by rewriting the manifest and that’s what I did.

Everytime the api is called for fetching the car information I’m looping through the info and add the images to the manifest. Before adding items to the cache just add some placeholders. This way you’re able to place them in any part of the manifest. I used ##IMAGES## & ##/IMAGES##  as placeholders. This may look like this:

private function addIMagesToAppcache($models) {
    $filename = $filename-with-full-path;
    $file = file_get_contents($filename);
    $images = '##IMAGES##' . "\n";
    foreach ($cars as $car) {
        // Add the default image of the car to the result string
        $images .= $car->default_image->url . '/600' . "\n";
    $images .= '##/IMAGES##';
    $file = preg_replace('/(##IMAGES##\n(.*\n)*##\/IMAGES##)/m', $images, $file);
    file_put_contents($filename, $file);
    return false;

I started getting the content of the manifest and started looping through the different cars for the images. Every image is added to the $result string which starts an ends with the placeholders. After the loop I needed to change the old images with the new images. And this is where the placeholders made life a lot easier. With a simple regular axpression I was able to replace the content of the images. Now Just save the new content back into the manifest and it’s done.

The manifest now is changed and we need it to be reloaded. Normaly everytime the page reloads the new manifest will be loaded and the content will be fetched. But the kiosk app will not be reloaded for quite a long time so the new manifest will not be loaded. Within appcache  there are some events which can come in handy to solve this issue. First of all there is the event updateready which runs after all the new cachefiles have been loaded. After this event has been triggered I reload the page to use all of the latest files from the cache.

 * Check if the manifest has been checnged and fetch it's data
window.applicationCache.addEventListener('updateready', function () {
    if (window.applicationCache.status === window.applicationCache.UPDATEREADY) {
     * There has been downloaded some new cache.
     * We're now reloading the page to show the new content
}, false);

But because the page will normaly not reload by itself we need to trigger this event. While I only fetch the car information on the home page this is the distincted place for triggering this event. Just run the next piece of code to let the browser check for a new manifest and get all the files needed.


That’s all. I hope this will help you out.