Offline strategies for HTML5 web applications - pfCongres2012
Upcoming SlideShare
Loading in...5
×
 

Offline strategies for HTML5 web applications - pfCongres2012

on

  • 1,173 views

 

Statistics

Views

Total Views
1,173
Views on SlideShare
1,173
Embed Views
0

Actions

Likes
3
Downloads
26
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Offline strategies for HTML5 web applications - pfCongres2012 Offline strategies for HTML5 web applications - pfCongres2012 Presentation Transcript

  • Offline strategies forHTML5 web applicationsStephan Hochdörfer, bitExpert AG
  • Offline strategies for HTML5 web applications About me  Stephan Hochdörfer, bitExpert AG  Department Manager Research Labs  enjoying PHP since 1999  S.Hochdoerfer@bitExpert.de  @shochdoerfer
  • Offline strategies for HTML5 web applications [...] we take the next step, announcing 2014 as the target for Recommendation. Jeff Jaffe, Chief Executive Officer, World Wide Web Consortium
  • Offline strategies for HTML5 web applications What does „offline“ mean?
  • Offline strategies for HTML5 web applications What does „offline“ mean? Application Cache vs. Offline Storage
  • Offline strategies for HTML5 web applications Application Cache for static resources <!­­ clock.html ­­> <!DOCTYPE HTML> <html>  <head>   <title>Clock</title>   <script src="clock.js"></script>   <link rel="stylesheet" href="clock.css">  </head>  <body>   <p>The time is: <output id="clock"></output></p>  </body> </html> /* clock.css */ output { font: 2em sans­serif; } /* clock.js */ setTimeout(function () {     document.getElementById(clock).value = new Date(); }, 1000);
  • Offline strategies for HTML5 web applications Application Cache for static resources cache.manifest - must be served using the text/cache-manifest MIME type. CACHE MANIFEST # 2012­09­16 clock.html clock.css clock.js
  • Offline strategies for HTML5 web applications Application Cache for static resources <!­­ clock.html ­­> <!DOCTYPE HTML> <html manifest="cache.manifest">  <head>   <title>Clock</title>   <script src="clock.js"></script>   <link rel="stylesheet" href="clock.css">  </head>  <body>   <p>The time is: <output id="clock"></output></p>  </body> </html>
  • Offline strategies for HTML5 web applications Application Cache for static resources CACHE MANIFEST # 2012­09­16 NETWORK: data.php CACHE: /main/home /main/app.js /settings/home /settings/app.js http://myhost/logo.png http://myhost/check.png http://myhost/cross.png
  • Offline strategies for HTML5 web applications Application Cache for static resources CACHE MANIFEST # 2012­09­16 FALLBACK: / /offline.html NETWORK: *
  • Offline strategies for HTML5 web applications Scripting the Application Cache // events fired by window.applicationCache window.applicationCache.onchecking = function(e)  {log("Checking for updates");} window.applicationCache.onnoupdate = function(e)  {log("No updates");} window.applicationCache.onupdateready = function(e)  {log("Update ready");} window.applicationCache.onobsolete = function(e)  {log("Obsolete");} window.applicationCache.ondownloading = function(e)  {log("Downloading");} window.applicationCache.oncached = function(e)  {log("Cached");} window.applicationCache.onerror = function(e)  {log("Error");} // Log each file window.applicationCache.onprogress = function(e) {   log("Progress: downloaded file " + counter);   counter++; };
  • Offline strategies for HTML5 web applications Scripting the Application Cache // Check if a new cache is available on page load. window.addEventListener(load, function(e) {   window.applicationCache.addEventListener(updateready,   function(e) {     if(window.applicationCache.status ==          window.applicationCache.UPDATEREADY) {       // Browser downloaded a new app cache.       // Swap it in and reload the page       window.applicationCache.swapCache();       if (confirm(New version is available. Load it?)) {         window.location.reload();       }     } else {       // Manifest didnt changed.     }   }, false); }, false);
  • Offline strategies for HTML5 web applications Application Cache – Some gotchas!
  • Offline strategies for HTML5 web applications Application Cache – Some gotchas! 1. Files are always(!) served from the application cache.
  • Offline strategies for HTML5 web applications Application Cache – Some gotchas! 2. The application cache only updates if the content of the manifest itself has changed!
  • Offline strategies for HTML5 web applications Application Cache – Some gotchas! 3. If any of the files listed in the CACHE section cant be retrieved, the entire cache will be disregarded.
  • Offline strategies for HTML5 web applications Application Cache – Some gotchas! 4. If the manifest file itself cant be retrieved, the cache will ignored!
  • Offline strategies for HTML5 web applications Application Cache – Some gotchas! 5. Non-cached resources will not load on a cached page!
  • Offline strategies for HTML5 web applications Application Cache – Some gotchas! 6. The page needs to be reloaded, otherwise the new resources do not show up!
  • Offline strategies for HTML5 web applications Application Cache – Some gotchas! 7. To avoid the risk of caching manifest files set expires headers!
  • Offline strategies for HTML5 web applications The Data URI scheme
  • Offline strategies for HTML5 web applications The Data URI scheme <!DOCTYPE HTML> <html>  <head>   <title>The Data URI scheme</title>   <style type="text/css">   ul.checklist li {     margin­left: 20px;     background: white  url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAA AFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAA O9TXL0Y4OHwAAAABJRU5ErkJggg==) no­repeat scroll left  top; }   </style>  </head>  <body>   <img  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAA AFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAA O9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot">  </body> </html>
  • Offline strategies for HTML5 web applications Storing dynamic data locally (in HTML5)
  • Offline strategies for HTML5 web applications Storing dynamic data locally (in HTML5) Web Storage, Web SQL Database, IndexedDB, File API
  • Offline strategies for HTML5 web applications Web Storage
  • Offline strategies for HTML5 web applications Web Storage Very convenient form of offline storage: simple key-value store
  • Offline strategies for HTML5 web applications Web Storage: 2 different types localStorage vs. sessionStorage
  • Offline strategies for HTML5 web applications Web Storage: localStorage example var myVar = 123; var myObj = {name: "Stephan"}; // write scalar value to localStorage localStorage[myVar] = myVar; // read scalar value from localStorage myVar = localStorage[myVar]; // write object to localStorage localStorage[myObj] = JSON.stringify(myObj); // read object from localStorage myObj = JSON.parse(localStorage[myObj]);
  • Offline strategies for HTML5 web applications Web Storage: sessionStorage example var myVar = 123; var myObj = {name: "Stephan"}; // write scalar value to sessionStorage sessionStorage[myVar] = myVar; // read scalar value from sessionStorage myVar = sessionStorage[myVar]; // write object to sessionStorage sessionStorage[myObj] = JSON.stringify(myObj); // read object from sessionStorage myObj = JSON.parse(sessionStorage[myObj]);
  • Offline strategies for HTML5 web applications Web Storage: Does my browser support it? function supports_local_storage() {   try {     return localStorage in window &&                window[localStorage] !== null;   } catch(e){     return false;   } }
  • Offline strategies for HTML5 web applications Web Storage: Pro Most compatible format up to now.
  • Offline strategies for HTML5 web applications Web Storage: Con The data is not structured.
  • Offline strategies for HTML5 web applications Web Storage: Con No transaction support!
  • Offline strategies for HTML5 web applications Web SQL Database
  • Offline strategies for HTML5 web applications Web SQL Database An offline SQL database based on SQLite, an general-purpose SQL engine.
  • Offline strategies for HTML5 web applications Web SQL Database function prepareDatabase(ready, error) {   return openDatabase(documents, 1.0,      Offline document storage, 5*1024*1024, function  (db) {     db.changeVersion(, 1.0, function (t) {       t.executeSql(CREATE TABLE docids (id, name));     }, error);   }); } function showDocCount(db, span) {   db.readTransaction(function (t) {     t.executeSql(SELECT COUNT(*) AS c FROM docids, [],        function (t, r) {          span.textContent = r.rows[0].c;       }, function (t, e) {          // couldnt read database          span.textContent = (unknown:  + e.message +  );     });   }); }
  • Offline strategies for HTML5 web applications Web SQL Database: ProIt`s a SQL database within the browser!
  • Offline strategies for HTML5 web applications Web SQL Database: ConIt`s a SQL database within the browser!
  • Offline strategies for HTML5 web applications Web SQL Database: Con SQLite is slooooow!
  • Offline strategies for HTML5 web applications Web SQL Database: Con The specification is no longer part of HTML5!
  • Offline strategies for HTML5 web applications IndexedDB
  • Offline strategies for HTML5 web applications IndexedDB A nice compromise between Web Storage and Web SQL Database giving you the best of both worlds.
  • Offline strategies for HTML5 web applications Web SQL Database vs. IndexedDB Category Web SQL IndexedDB Location Tables contain columns and objectStore contains Javascript objects and rows keys Query SQL Cursor APIs, Key Range APIs, and Mechanism Application Code Transaction Lock can happen on Lock can happen on database databases, tables, or rows VERSION_CHANGE transaction, on an on READ_WRITE objectStore READ_ONLY and transactions READ_WRITE transactions. Transaction Transaction creation is Transaction creation is explicit. Default is to Commits explicit. Default is to rollback commit unless we call abort or there is an unless we call commit. error that is not caught.
  • Offline strategies for HTML5 web applications IndexedDB – Creating an ObjectStore indexedDB.open = function() {   var request = indexedDB.open("todos");   request.onsuccess = function(e) {     var v = "2.0 beta";     todoDB.indexedDB.db = e.target.result;     var db = todoDB.indexedDB.db;     if (v!= db.version) {       var setVrequest = db.setVersion(v);       setVrequest.onfailure = todoDB.indexedDB.onerror;       setVrequest.onsuccess = function(e) {         if (db.objectStoreNames.contains("todo")) {           db.deleteObjectStore("todo");         }         var store = db.createObjectStore("todo",  {keyPath: "timeStamp"});         todoDB.indexedDB.getAllTodoItems();       };     } else {       todoDB.indexedDB.getAllTodoItems();     }   };   request.onfailure = todoDB.indexedDB.onerror; };
  • Offline strategies for HTML5 web applications IndexedDB – Adding data to ObjectStore indexedDB.addTodo = function() {   var db = todoDB.indexedDB.db;   var trans = db.transaction([todo],  IDBTransaction.READ_WRITE);   var store = trans.objectStore(todo);   var data = {     "text": todoText,     "timeStamp": new Date().getTime()   };   var request = store.put(data);   request.onsuccess = function(e) {     todoDB.indexedDB.getAllTodoItems();   };   request.onerror = function(e) {     console.log("Failed adding items due to: ", e);   }; };
  • Offline strategies for HTML5 web applications IndexedDB – Retrieving data function show() {   var request = window.indexedDB.open("todos");   request.onsuccess = function(event) {     var db = todoDB.indexedDB.db;     var trans = db.transaction(["todo"],  IDBTransaction.READ_ONLY);     var request = trans.objectStore("todo").openCursor();     var ul = document.createElement("ul");     request.onsuccess = function(event) {       var cursor = request.result || event.result;       // If cursor is null, enumeration completed       if(!cursor) {         document.getElementById("todos").appendChild(ul);         return;       }       var li = document.createElement("li");       li.textContent = cursor.value.text;       ul.appendChild(li);       cursor.continue();     }   } }
  • Offline strategies for HTML5 web applications IndexedDB – Deleting data indexedDB.deleteTodo = function(id, text) {   var db = todoDB.indexedDB.db;   var trans = db.transaction(["todo"],  IDBTransaction.READ_WRITE);   var store = trans.objectStore("todo");   var request = store.delete(id);   request.onsuccess = function(e) {     todoDB.indexedDB.getAllTodoItems();   };   request.onerror = function(e) {     console.log("Error Adding: ", e);   }; };
  • Offline strategies for HTML5 web applications File API
  • Offline strategies for HTML5 web applications File API FileReader API and FileWriter API
  • Offline strategies for HTML5 web applications File API – Requesting access function onInitFs(fs) {   console.log(Opened file system:  + fs.name); } function errorHandler(e) {   console.log(Error:  + e.code); } window.requestFileSystem(window.TEMPORARY, 5*1024*1024  /*5MB*/, onInitFs, errorHandler);
  • Offline strategies for HTML5 web applications File API – Requesting quota window.webkitStorageInfo.requestQuota(     PERSISTENT,      5*1024*1024 /*5MB*/,      function(grantedBytes) {       window.requestFileSystem(PERSISTENT, grantedBytes,           onInitFs, errorHandler);     },      function(e) {       console.log(Error, e); });
  • Offline strategies for HTML5 web applications
  • Offline strategies for HTML5 web applications File API – Creating a file function onInitFs(fs) {   fs.root.getFile(log.txt,    {create: true, exclusive: true},    function(fileEntry) {     // fileEntry.name == log.txt     // fileEntry.fullPath == /log.txt   }, errorHandler); } window.requestFileSystem(window.TEMPORARY, 5*1024*1024  /*5MB*/, onInitFs, errorHandler);
  • Offline strategies for HTML5 web applications File API – Reading a file function onInitFs(fs) {   fs.root.getFile(log.txt, {},    function(fileEntry) {     fileEntry.file(function(file) {        var reader = new FileReader();        reader.onloadend = function(e) {          var txtArea   =                document.createElement(textarea);          txtArea.value = this.result;          document.body.appendChild(txtArea);        };        reader.readAsText(file);     }, errorHandler);   }, errorHandler); } window.requestFileSystem(window.TEMPORARY, 5*1024*1024  /*5MB*/, onInitFs, errorHandler);
  • Offline strategies for HTML5 web applications File API – Writing to a file function onInitFs(fs) {   fs.root.getFile(log.txt, {create: true},    function(fileEntry) {     fileEntry.createWriter(function(fileWriter) {       fileWriter.onwriteend = function(e) {         console.log(Write completed.);       };       fileWriter.onerror = function(e) {         console.log(Write failed:  + e.toString());       };       var bb = new BlobBuilder();       bb.append(Lorem Ipsum);       fileWriter.write(bb.getBlob(text/plain));     }, errorHandler);   }, errorHandler); } window.requestFileSystem(window.TEMPORARY, 5*1024*1024  /*5MB*/, onInitFs, errorHandler);
  • Offline strategies for HTML5 web applications File API – Appending data to a file function onInitFs(fs) {   fs.root.getFile(log.txt, {create: false},    function(fileEntry) {     fileEntry.createWriter(function(fileWriter) {       fileWriter.seek(fileWriter.length);       var bb = new BlobBuilder();       bb.append(Hello World);       fileWriter.write(bb.getBlob(text/plain));     }, errorHandler);   }, errorHandler); } window.requestFileSystem(window.TEMPORARY, 5*1024*1024  /*5MB*/, onInitFs, errorHandler);
  • Offline strategies for HTML5 web applications File API – Deleting a file function onInitFs(fs) {   fs.root.getFile(log.txt, {create: false},    function(fileEntry) {     fileEntry.remove(function() {       console.log(File removed.);     }, errorHandler);    }, errorHandler); } window.requestFileSystem(window.TEMPORARY, 5*1024*1024  /*5MB*/, onInitFs, errorHandler);
  • Offline strategies for HTML5 web applications File API – Creating directories function onInitFs(fs) {    fs.root.getDirectory(MyFolder, {create: true},     function(dirEntry) {     // do stuff...     }, errorHandler); } window.requestFileSystem(window.TEMPORARY, 5*1024*1024  /*5MB*/, onInitFs, errorHandler);
  • Offline strategies for HTML5 web applications File API – Browser support? Up to now: Chrome only
  • Offline strategies for HTML5 web applications File API – Browser support? But: idb.filesystem.js
  • Offline strategies for HTML5 web applications Am I online?
  • Offline strategies for HTML5 web applications Am I online? document.body.addEventListener("online", function () {   // browser is online! } document.body.addEventListener("offline", function () {   // browser is not online! }
  • Offline strategies for HTML5 web applications Am I online? Another approach... $.ajax({   dataType: json,   url: http://myappurl.com/ping,   success: function(data){     // ping worked   },   error: function() {     // ping failed ­> Server not reachable   } });
  • Thank you!
  • http://joind.in/7073