Creating off-line HTML5 Mobile Apps with Mobile Helix SDK

57
Open Source SDK Mobile Helix September 12, 2014

description

jQuery and jQuery Mobile together are a compelling platform for building mobile user experiences, but on their own they are missing one of the most important ingredients of native mobile apps – offline access. The good news is that all modern mobile browsers support one of the competing standards for HTML5 offline storage; the bad news is that there are competing standards, and the tools available for managing persistence in JavaScript are poor at best. In this talk we will present a practical approach to building offline-enabled, data-driven applications using jQuery, jQuery Mobile, and PersistenceJS as an O-R-M abstraction on top of HTML5’s varying offline storage standards. Using this combination, we introduce a simple data synchronization paradigm that allows mobile HTML5 apps to download data, store and manipulate that data locally, and re-synchronize that data whenever the device is online. In addition, we present some of the benefits of viewing data stored in a database, including sorting, grouping, filtering, and full text indexing lists of data objects. With offline storage added to the mix, mobile HTML5 starts to deliver on the promise of a fully cross-platform, browser driven experience that is just as good as any native app.

Transcript of Creating off-line HTML5 Mobile Apps with Mobile Helix SDK

  • 1. Mobile HelixOpen Source SDKSeptember 12, 2014

2. Qbasic10: HTML5 Mobile Apps20: Why?30: State of the state40: Offline is key100: The Mobile Helix SDK110: Why?120: A fundamental shift in design model130: Data sync ( what and how )140: Improved UI components200: Mobile Helix?300: GOTO 10SDK for offlinestorage,synch, anddisplay2 3. Now here's a little story I've got to tell20082009201020112012201320143 4. So many app stores so little time What is the main driver for writing HTML5 mobile apps in an Enterprise setting?4 5. My apps5 6. @HTML5AppMans Timeline of HTML52009: www.w3.org/2009/dap/2012: the partys over2014: or wait, is it?www.telegraph.co.ukBefore 2009 2012ish 2014 Soon6 7. So where are we now? Broken promises of HTML5 and what's next?2012 Chris Heilmann, @codepo8 http://icant.co.uk/talks/h5/html5devcon.html7 8. So where are we now? HTML5: Doomed to fail or just getting started? 2014 Matt Asay, @mjasay http://www.techrepublic.com/article/html5-doomed-to-fail-or-just-getting-started/8 9. We set out to solve some challenges:9 10. Offline with HTML5 HTML5 Browser Storage: the Past, Present and FutureOct 2013 Craig Buckler,@craigbuckler http://www.sitepoint.com/html5-browser-storage-past-present-future/ Variables, Cookies, window.name, etc WebSQL robust client-side data storage and access uses SQL like many server side applications support on Webkit/Blink desktop and mobile browsers WebSQL Disadvantages: the database schema must be defined up-front marginal browser support and the Webkit/Blink teams may eventually drop it the W3C specification was abandoned in 201010 11. WebSQL Support August 12, 2014http://caniuse.com/#feat=sql-storage11 12. Offline with HTML5 HTML5 Browser Storage: the Past, Present and FutureOct 2013 Craig Buckler,@craigbuckler http://www.sitepoint.com/html5-browser-storage-past-present-future/ Variables, Cookies, window.name WebSQL robust client-side data storage and access uses SQL like many server side applications support on Webkit/Blink desktop and mobile browsers WebSQL Disadvantages: the database schema must be defined up-front marginal browser support and the Webkit/Blink teams may eventually drop it the W3C specification was abandoned in 201012 13. Common implementation of client/serverLogin user ilya success?Get conversation threadsLoad chat with sethGet first X messagesChange sort orderget new X msgsNext page, loadnext X msgsSearch for test2113 14. Common implementation of client/serverLogin user ilya success?Get conversation threads14 15. Mobile Helix SDK What we have here is a failure to communicate15 16. Our SDK and jQuery Mobile16 17. A new paradigmLogin user ilya success?get new X msgsGet conversation threadsOpen chat with sethDisplay first X messagesChange sort orderNext page, load next X msgsSearch for test2117 18. Our SDK and jQuery Mobile jQuery Mobile has a great mechanism and ecosystem forcreating and extending widgets18 19. Mobile Helix SDK19 20. Mobile Helix SDK20 21. Mobile Helix SDK1. Off line data store2. UX / UI3. Sync21 22. Mobile Helix SDK Object relational mapping (SQL) Abstract away HTML storage standard High performance Dynamic schema updates Incremental updates / synch22 23. Mobile Helix SDK Architecture23 24. How it works Specify a schema object Send JSON objects from the server and syncthem to local storage Updated jQMobile controls to pull data from localstorage24 25. Mobile Helix SDK Demo AppDemo App25 26. Object-Relational mapping{User: {user_id: 1,user: ilya}}26 27. Object-Relational mapping{uid: '1',user: 'empty',__hx_schema_name: "User",__hx_key: "uid",__hx_sorts:{},__hx_filters:{},__hx_global_filters:{},__hx_text_index:[]}27 28. Object-Relational mappingvar server_input = {User: {user_id: 1,user: ilya}};schema = Helix.DB.prepareSchemaTemplate(server_input,User,user_id,{}, // no sorts{} // no filters);28 29. Object-Relational mapping Last step is to generate the appropriate table structure inthe underlying persistence layerHelix.DB.generatePersistenceSchema(schema,User",function () {console.log(local DB is ready);});29 30. Store the data Ok, now we can store real data from the server:Helix.DB.synchronizeObject(< object from server >,Helix.DB.getSchemaForTable(User"),function(persistentObj) {// callback: local data is ready},null,null,null);30 31. Store the datavar d = $.parseJSON(data);if ( d.success === true ) {Helix.DB.synchronizeObject(d.payload,Helix.DB.getSchemaForTable("User"),function( persistentObj ) {alert( "user " +d.payload.User.user +" stored in DB);});}31 32. Retrieve the dataHelix.DB.loadAllObjects(Helix.DB.getSchemaForTable("User"),function(obj) {var u = $("#username").val();obj.filter( 'user', 'like', u).newEach( {. . .});});32 33. Use the dataeachFn: function(elem) {alert ("offline user: " + elem.user );},doneFn: function(ct) {},startFn: function(ct) {if (ct == 0)alert("user not provisioned for offline use");}33 34. Retrieve the dataHelix.DB.synchronizeObjectByKey(stateManager.thread_id,Helix.DB.getSchemaForTable("Thread),function(obj){if ( obj ){var u = $("#username").val();obj.filter( 'user', 'like', u).newEach( {. . .});});34 35. Automatic schema migrations Oh no now we need to audit our users logins{User: {user_id: 1,user: ilya,last_login: date time,login_ip: 192.168.1.1}}35 36. Automatic schema migrations Client changes: 0.0 The SDK resolves changes to the schema andupdates all internal tables accordingly36 37. Something more meaningful Chat client implements Threads ( thread_id, to, from, ) Messages ( thread_id, message_id, to, from,message ) Threads hasMany Messages Message belongsTo Thread37 38. Mobile Helix SDKvar m = {message_id: '1',thread_id: '1',msg_to: 'empty',msg_from: 'empty',message: 'empty',};var msgSchema =Helix.DB.prepareSchemaTemplate(m, Message",message_id", {}, {});38 39. Object-Relational mappingvar t = {thread_id: '1',thread_user1: 'empty',thread_user2: 'empty',Message: msgSchema};var threadSchema =Helix.DB.prepareSchemaTemplate(t, Thread", thread_id",{}, {});39 40. Mobile Helix SDK So we have 1,000 messages how many are we pullingacross the ether each time?Delta Objects40 41. Mobile Helix SDKvar delta = {__hx_type: 1001,adds: '',deletes: '',updates: [{thread_id: d.payload.Thread.thread_id,Message: {__hx_type: 1001,adds: d.payload.Message,deletes: '',updates: ''}}]};41 42. Adds Examplevar new_messages = {thread_id: d.payload.Thread.thread_id,thread_user1: d.payload.Thread.thread_user1,thread_user2: d.payload.Thread.thread_user2,created: d.payload.Thread.created,modified: d.payload.Thread.modified,Message: {__hx_type: 1001,adds: d.payload.Message,deletes: '',updates: ''}};42 43. Adds ExampleHelix.DB.synchronizeObject(new_messages,Helix.DB.getSchemaForTable("Thread"),function(obj) {console.log(new messages received");confirmSync(); // update server with synch key}});43 44. Deletes examplevar delta = {__hx_type: 1001,__hx_schema_type: 'Message',adds: '',deletes: window.d3.payload, // list of IDs to deleteupdates: '};Helix.DB.synchronizeObject(delta, Helix.DB.getSchemaForTable(Message"),function(obj) { console.log(Messages delleted"); }});44 45. listview? No, this is a Datalist(function($) {$.widget("helix.helixDatalist", {options: {. . . // soooo many options},_create: function() {. . .// implements infinite scrolling list which pulls from local DB,not from a large array in memory45 46. listview? No, this is a Datalist

. . .

46 47. listview? No, this is a Datalist$(document).on('pageinit', '#thread-page', function(){threadlist = $(#Threads').helixDatalist({itemList: null,condition: Helix.DB.getSchemaForTable("Thread"),rowRenderer: function(parentDiv, list, row) {. . .}});});47 48. listview? No, this is a Datalistvar s = Helix.DB.getSchemaForTable("Thread");Helix.DB.loadAllObjects( s, function(obj){if (obj){threadlist.helixDatalist("refreshList",obj,s, s, function(){Helix.Layout.layoutPage();console.log ( "refresh for threadlist" );});}});48 49. Local search1. Add this to the schema:__hx_text_index:["msg_to", "msg_from", "message"]2. Add this to the Datalist initialization:var msg = Helix.DB.getSchemaForTable("Message");indexedSearch: function (searchText, completion){if (!searchText)return;completion( msg.search(searchText) );}49 50. Datalist other options selectAction, swipeLeftAction swipeRightAction itemContextMenu Context menu to display if the user tap-holds (for touch devices) ordouble clicks (for non-touch devices) holdAction Action to perform if the user tap-holds (for touch devices) or doubleclicks (for non-touch devices) on a list item Pull to refresh itemsPerPage50 51. Mobile Helix SDK AND MORE!51 52. Minimize page loads from the server CSS sprites We use Smart Sprites: (http://csssprites.org/) and YUIsminifier, but Googles Webkit is another option we like Concat and minify all JS and CSS load a single JS/CSS file for all of your code Use query params to handle versioning and makeJS/CSS infinitely cacheable change the name of the URL used to load theJS/CSS/Sprite so that you dont need to put a cacheexpiration or force revalidation of your JS/CSS/Sprite52 53. Minimize DOM changes - they are so slow! Our Datalist paginates and refreshes the underlying databy making the smallest number of DOM changes possible Much faster to show and hide elements than add or deletethem All of the markup needed to view and edit a single dataobject is rendered up front. Toggling between view/edit modes only shows or hidesunderlying elements53 54. Tread lightly on memory A list with > 200 items in jQM starts to get awfullyslow on a phone Use pagination ALWAYS, but make scrolling fast andseamless to the user Be careful what you keep in memory PersistenceJS by default keeps a reference to eachinserted object PersistenceJS runs everything with SELECT * FROM54 55. Mobile Helix SDK The SDK is available here (on Github)github.com/shallem/LinkHTML5SDK.git Demo chat project is a work in progress55 56. Join in the fun make this even better! Contact me with any questions, comments,@[email protected] 57. Give me anonymous feedback here: http://bit.ly/1tPOacx57