Dynamically Trigger HTML5 Cache Manifest file?
Asked Answered
E

4

21

I am using the new cache manifest functionality from HTML5 to cache my web app so it will work offline. The content is cached automatically when the page is loaded with the following html element:

<html lang="en" manifest="offline.manifest">

This works fine. However, I want to give my users the option of whether they want the content cached offline. So, here is my question:

Is there any way to trigger that an application be cached at runtime, using JavaScript, and not have it automatically done when the page is loaded.

For example, something like this (using jquery):

----------------index.html--------------

<head>
 <meta charset="utf-8" />

 <script src="http://code.jquery.com/jquery-1.4.4.min.js"></script> 
 <script type="text/javascript" src="Main.js"></script> 

</head>
<body>

 <button id="cacheButton">Cache Page</button>

</body>
</html>

---------Main.js---------

$(document).ready(
 function()
 {
  $('#cacheButton').click(onCacheButtonClick);
 }
)

function onCacheButtonClick(event)
{
 console.log("Setting Offline Manifest");
 $('#htmlRoot').attr("manifest","offline.manifest");
}

-------------offline.manifest-------------

CACHE MANIFEST

#version .85

#root
index.html
scripts/main.js

#jquery assets
http://code.jquery.com/jquery-1.4.4.min.js

Basically, when the button is clicked, I dynamically set the manifest attribute of the html element. This works (in the sense the element is set), but it does not cause the browser to then cache the page.

Any suggestions?

Eunaeunice answered 28/12, 2010 at 18:23 Comment(7)
Firefox prompts before caching (ie the functionality you want is built in). Not sure about other browsers.Nihil
Thanks. Safari and Google Chrome dont appear to prompt, at least not on Mac and iOS.Eunaeunice
Are you trying to do this as file:/// or http://?Libertine
Im doing it as : http://Eunaeunice
I'd love for this to work as well.Lipase
Did you try this <script>document.write('<html manifest=offline.appcache">');</script>Piquet
Super-late, but in case someone stumbles over this in 2021: creating a Progressive Web App (PWA) might be the best way to handle this scenario now.Fasciation
O
5

After many weeks spent with offline caching, the answer is no, you either cache or don't cache, setting the cache attribute on the client side has no effect.

You could consider offering an alternate url for the caching version, be aware that the page is also implicitly cached as a "master entry".

I am at a loss to understand why you would want to offline cache jquery though, since it is likely to be served with very long expiry anyway.

You may wish to consider offline storage as an alternative. Store the text of the scripts and inject them into the DOM on load. If not cached fetch using Ajax and inject the response, as creating a script tag with the src won't load the script.

Outleap answered 9/1, 2011 at 0:40 Comment(3)
You would probably want to offline cache jquery if you want your web app to be available when the browser is offline. Putting the source of javascript code into offline storage is probably the wrong way to achieve this goal - the cache manifest is the proper way.Sweatbox
The way I ended up doing it was to was make a button thats says "Use/Get Offline Cache" which goes to another HTML file that is served identically, but with the manifest. I found users even preferred this because they could tell when they were online and off-line. Using the javascript events of cache you can even put a progress bar showing them the download progress (in terms of files completed) and when the cache is up to date.Sides
You MUST cache jQuery in the manifest. Browser Cache can be cleared at all times and is therefore unreliable. This can be especially problematic for mobile browsers (less memory)Diatomic
B
10

You dynamically trigger caching by adding an iframe that points to an empty page containing the actual cache manifest.

offline.html:

<!DOCTYPE html>
<html manifest="offline.appcache">
<head>
    <title></title>
</head>
<body>
</body>
</html>

Make sure to add index.html to the cache manifest. Then just add something like:

<iframe src="offline.html" width="0" height="0">

to document.body dynamically to trigger caching.

Blackdamp answered 12/4, 2013 at 12:20 Comment(1)
Yes, that does trigger the cache. But when the parent page tries to access a cached resource, it misses the cache and makes a real request. (Tested in Chrome 39.) So no benefit to doing this.Woadwaxen
O
5

After many weeks spent with offline caching, the answer is no, you either cache or don't cache, setting the cache attribute on the client side has no effect.

You could consider offering an alternate url for the caching version, be aware that the page is also implicitly cached as a "master entry".

I am at a loss to understand why you would want to offline cache jquery though, since it is likely to be served with very long expiry anyway.

You may wish to consider offline storage as an alternative. Store the text of the scripts and inject them into the DOM on load. If not cached fetch using Ajax and inject the response, as creating a script tag with the src won't load the script.

Outleap answered 9/1, 2011 at 0:40 Comment(3)
You would probably want to offline cache jquery if you want your web app to be available when the browser is offline. Putting the source of javascript code into offline storage is probably the wrong way to achieve this goal - the cache manifest is the proper way.Sweatbox
The way I ended up doing it was to was make a button thats says "Use/Get Offline Cache" which goes to another HTML file that is served identically, but with the manifest. I found users even preferred this because they could tell when they were online and off-line. Using the javascript events of cache you can even put a progress bar showing them the download progress (in terms of files completed) and when the cache is up to date.Sides
You MUST cache jQuery in the manifest. Browser Cache can be cleared at all times and is therefore unreliable. This can be especially problematic for mobile browsers (less memory)Diatomic
C
0

Depending on your application, it may be possible to use a modified version of @schibum's approach by breaking down your app into "mini" apps, then caching the sub-sections in an iframe. Consider this example:

index.html

<html manifest="indexx.manifest">
<head>
    <script src="jquery-2.1.4.min.js"></script>
    <script src="index.js"></script>
    <title>Index</title>
</head>
<body>
    <ul>
        <li><a href="1.html">One</a>
        <li><a href="2.html">Two</a>
        <li><a href="3.html">Three</a>
    </ul>
    <iframe id="if" />
</body>
</html>

index.manifest

CACHE MANIFEST
# 3
index.html
jquery-2.1.4.min.js 
index.js

index.js

$( document).ready(function() {
    var pages = ['1.html','2.html','3.html'];
    var LoadNext = function() {
        alert(pages[0]);
        page = pages.shift();
        alert(page)
        if ( page !== undefined ) {
            console.log("Attempting to load " + page);
            $('#if').attr('src', page)
        } else {
            console.log("All done");
        }
    };
    $('#if').load(function() {
        console.log("Finished loading");
        LoadNext()
    });
    LoadNext(); 
});

1.html

<html manifest="1.manifest">
<head>
    <title>One</title>
</head>
<body>
    <img src="1.jpg" width="50%">
</body>
</html>

1.manifest

CACHE MANIFEST
# 2
1.html
1.jpg

{2,3}.{html,manifest} follow 1.{html,manifest}'s form.

As a result, each sub-page (1.html, 2.html, 3.html) have their own manifest, and are thus cached independently. index.html has its own (minimal) manifest, so caching that unconditionally is not nearly as network-heavy as caching the entire app. Then the javascript is responsible for pre-loading every page in the iframe so that it gets cached.

Load index.html, then go offline and see how the sub-pages work. too.

An obvious drawback is that any assets shared between pages (e.g. jQuery) must be redundantly cached.

Casuistry answered 13/8, 2015 at 22:5 Comment(0)
I
0

One thing you must remember. Do not cache the manifest file itself. So all you need to do is refresh the page with a different version of the manifest file according for your user selection. You can dynamically generate the manifest file itself, any change to that file will cause a cache refreshment. Best practice to trigger re-caching is to change the version of the manifest file, something like: # ver1 - 01/01/2018 to # ver2 - 02/02/2018 will do the trick. So you cannot change it in client side but you can do it server side.

Isidoro answered 16/10, 2017 at 12:55 Comment(1)
In DreamWeaver, I use this comment to automatically modify manifest files: #<!-- #BeginDate format:IS1m -->2017-10-19 17:50<!-- #EndDate -->.Propagate

© 2022 - 2024 — McMap. All rights reserved.