/ Published in: JavaScript
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
/** * HTML5 offline manifest preloader. * * Load all manifest cached entries, so that they are immediately available during the web app execution. * Display some nice JQuery progress while loading. * * @copyright 2010 mFabrik Research * * @author Mikko Ohtamaa <[email protected]> */ /** * Preloader class constructor. * * Manifest is retrieved via HTTP GET and parsed. * All cache entries are loaded using HTTP GET. * * Local storage attribute "preloaded" is used to check whether loading needs to be performed, * as it is quite taxing operation. * * To debug this code and force retrieving of all manifest URLs, add reloaded=true HTTP GET query parameter: * * * * @param {Function} endCallback will be called when all offline entries are loaded * * @param {Object} progressMonitor ProgressMonitor object for which the status of the loading is reported. */ function ApplicationCachePreloader(endCallback, progressMonitor, debug) { if(!progressMonitor) { throw "progressMonitor must be defined"; } this.endCallback = endCallback; this.progressMonitor = progressMonitor; this.logging = debug; // Flag to control console.log() output this.eventCount = 0; } ApplicationCachePreloader.prototype = { translateEventCode : function(eventCode) { var cacheStatusValues = []; cacheStatusValues[0] = 'uncached'; cacheStatusValues[1] = 'idle'; cacheStatusValues[2] = 'checking'; cacheStatusValues[3] = 'downloading'; cacheStatusValues[4] = 'updateready'; cacheStatusValues[5] = 'obsolete'; return cacheStatusValues[eventCode]; }, trapEvents : function(cache, handler) { cache.addEventListener('progress', handler, false); try { cache.addEventListener('cached', handler, false); } catch(e) { // FF 3.5 won't allow } cache.addEventListener('checking', handler, false); cache.addEventListener('downloading', handler, false); cache.addEventListener('error', handler, false); cache.addEventListener('noupdate', handler, false); cache.addEventListener('obsolete', handler, false); cache.addEventListener('updateready', handler, false); }, waitUntilAllowed : function() { try { cache.addEventListener('cached', handler, false); } catch(e) { // FF 3.5 needs user permission "Allow" in pop-up dialog this.debug("Not allowed yet"); setTimeout(jQuery.proxy(this.waitUntilAllowed, this), 1000); } this.start(); }, deferEndCallback : function(success) { function timemout() { this.endCallback(success); } setTimeout(jQuery.proxy(timemout, this), 100); }, /** * Do everything necessary to set-up offline application * * @return true if applicationCache loading performed succesfully */ load : function() { //alert("load"); if (window.applicationCache) { this.debug("ApplicationCache status " + window.applicationCache.status); this.debug("Please see http://www.w3.org/TR/html5/offline.html#applicationcache"); } else { // This could be probably worked around on Google Chrome using Gears extension somehow this.silentError("applicationCache object not supported"); this.deferEndCallback(true); return true; } // Can't update if(!navigator.onLine) { this.debug("Not online"); this.deferEndCallback(true); return true; } if(jQuery.browser.mozilla) { // Mozilla won't work until user answers "Allow" to pop-up dialog, // put dialog seems to be broken this.deferEndCallback(true); return false; //this.waitUntilAllowed(); } else { this.start(); } return true; }, start : function() { //alert("Started"); this.debug("Preloading starting - xxxx"); this.progressMonitor.start(); this.trapEvents(window.applicationCache, jQuery.proxy(this.handleEvent, this)); var cache = window.applicationCache; if(cache.status == 4) { this.debug("Update complete"); this.end(true); } if (cache.status == 1) { this.debug("Idle - manifest not changed"); this.end(true); } if (cache.status == 0) { this.debug("Uncached - offline mode not enabled (prolly not saved on desktop/mainscreen and running straight from the browser)"); this.end(true); } //alert("Trapping"); this.debug("Trapping and waiting events, status:"+ cache.status); }, end : function(success) { //alert("Ended:" + success); // Trigger activation of new cache if available if(status) { if(!window.applicationCache) { // blaa... not supported } else { window.applicationCache.swapCache(); } } this.debug("Preloading ending to " + success); this.progressMonitor.end(success); this.endCallback(success); }, handleEvent : function(e) { var online, status, type, message; var cache = window.applicationCache; online = (navigator.onLine) ? 'yes' : 'no'; status = this.translateEventCode(cache.status); type = e.type; message = 'online: ' + online; message+= ', event: ' + type; message+= ', status: ' + status; if (type == 'error' && navigator.onLine) { message+= ' (prolly a syntax error in manifest)'; } // this.debug(message); // $("body").append("<p>" + message + "</p>"); this.eventCount++; if(status == "downloading" || status == "checking") { this.progressMonitor.update(type, this.eventCount, this.eventCount); } else { console.log("Got event " + this.eventCount + " " + status); //alert("event:" + status); } if(status == "error") { this.end(false); } // Google Chrome reports "uncached" when the application offline // mode is not enabled - allow still to run in the browser // without doing resource caching if(status == "cached" || status == "updateready" || status == "idle" || status == "uncached") { this.end(true); } }, /** * Write to debug console * * @param {String} msg */ debug : function(msg) { if(this.logging) { console.log(msg); } }, /** * Non-end user visible error message * * @param {Object} msg */ silentError : function(msg) { console.log(msg); } }; function ProgressMonitor() { }; ProgressMonitor.prototype = { /** * Start progress bar... initialize as 0 / 0 */ start : function(status, coldVirgin) { $("#web-app-updating").show(); if(window.navigator.standlone) { $("#web-app-updating .standalone").show(); } }, end: function(status) { $("#web-app-updating").hide(); }, update : function(status, currentEntry, maxEntries) { $("#web-app-updating .event-count").text(currentEntry); }, /** * Called when application has not been saved on the desktop. * * ...problems with Mobile Safari cache size. */ needWebAppMode : function() { $("#web-app-no-browser").show(); } };