{"id":945,"date":"2013-08-15T18:15:21","date_gmt":"2013-08-15T12:45:21","guid":{"rendered":"http:\/\/ramkulkarni.com\/blog\/?p=945"},"modified":"2013-08-15T18:15:21","modified_gmt":"2013-08-15T12:45:21","slug":"pre-packaging-database-with-html5-mobile-application","status":"publish","type":"post","link":"http:\/\/ramkulkarni.com\/blog\/pre-packaging-database-with-html5-mobile-application\/","title":{"rendered":"Pre-packaging database with HTML5 Mobile Application"},"content":{"rendered":"<p>I was discussing with a couple of colleagues of mine yesterday about a HTML5 mobile application that we are developing, and one of the requirements was to pre-package database with the application. A few months back I had created an application that did just that. I thought the solution might be of interest to some of the readers of this blog.<\/p>\n<p>Mobile (or for that matter non-mobile) browsers can create databases for your HTML5 applications. HTML5 provides APIs to create and access the database. But how do you pre-package the database?<\/p>\n<p>The solution is \u00a0not really to pre-package the database, but package data that you want a database to initialize with. I don&#8217;t think you can really package a SQLite database and ask browser to use it for your HTML5 application. You need to create database and tables when the application is run the first time and then load data packaged with the application. Let&#8217;s say we want to create a table called &#8216;person&#8217; and want to populate this table when the application is run the first time.<!--more--><br \/>\n<span style=\"font-size: 16px;\">To keep the table simple, we will create only three fields in the table &#8211; id, name and picture_file. We could create a blob field to hold pictures in the table, but that will unnecessarily duplicate the data, one that we pre-package and another we insert in the table. So we will just save the file name in the database. We will use JSON to specify initial data, because it would be easy to convert that data to JS objects.<\/span><\/p>\n<p>In the www folder of our mobile application, we will create following folders and files &#8211;<br \/>\n_data<br \/>\n|&#8212;-images<br \/>\n| \u00a0 \u00a0 \u00a0|&#8212;-person1.jpeg<br \/>\n| \u00a0 \u00a0 \u00a0|&#8212;-person2.jpeg<br \/>\n|&#8212;-json_data.js<br \/>\nindex.html<br \/>\napp.js<\/p>\n<p>Let&#8217;s say we want to initialize the table with two records. So we will create an array with two objects in json_data.js<\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\">[\n\t{\n\t\tid<span style=\"color: #666666;\">:1<\/span>,\n\t\tname<span style=\"color: #666666;\">:<\/span><span style=\"color: #ba2121;\">\"Person1\"<\/span>,\n\t\tpicture_file<span style=\"color: #666666;\">:<\/span><span style=\"color: #ba2121;\">\"person1.jpeg\"<\/span>\n\t},\n\t{\n\t\tid<span style=\"color: #666666;\">:2<\/span>,\n\t\tname<span style=\"color: #666666;\">:<\/span><span style=\"color: #ba2121;\">\"Person2\"<\/span>,\n\t\tpicture_file<span style=\"color: #666666;\">:<\/span><span style=\"color: #ba2121;\">\"person2.jpeg\"<\/span>\n\t}\n]<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>In the app.js we will write JS code to create and access database &#8211;<!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #408080; font-style: italic;\">\/\/app.js<\/span>\ndb <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">null<\/span>; <span style=\"color: #408080; font-style: italic;\">\/\/Reference to open database<\/span>\ntableName <span style=\"color: #666666;\">=<\/span> <span style=\"color: #ba2121;\">\"persons\"<\/span>; <span style=\"color: #408080; font-style: italic;\">\/\/Table name<\/span>\n_onDBInitializedCallback <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">null<\/span>; <span style=\"color: #408080; font-style: italic;\">\/\/Callback function after DB is initialized<\/span>\n\n<span style=\"color: #008000; font-weight: bold;\">function<\/span> openDB()\n{\n\tdb <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000;\">window<\/span>.openDatabase(<span style=\"color: #ba2121;\">\"persons\"<\/span>, <span style=\"color: #ba2121;\">\"1.0\"<\/span>, <span style=\"color: #ba2121;\">\"Persons DB\"<\/span>, <span style=\"color: #666666;\">1000000<\/span>);\n\t<span style=\"color: #408080; font-style: italic;\">\/\/We will use a flag in localStorage to check if database is already<\/span>\n\t<span style=\"color: #408080; font-style: italic;\">\/\/populated with pre-packaged data.<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> (localStorage.tablesCreated <span style=\"color: #666666;\">==<\/span> <span style=\"color: #008000; font-weight: bold;\">undefined<\/span> <span style=\"color: #666666;\">||<\/span> localStorage.tablesCreated <span style=\"color: #666666;\">==<\/span> <span style=\"color: #ba2121;\">\"false\"<\/span>)\n\t{\n\t\t<span style=\"color: #408080; font-style: italic;\">\/\/Database is not initilized. Create tables and inserts initial records<\/span>\n\t\t<span style=\"color: #408080; font-style: italic;\">\/\/specified in _data\/json_data.js<\/span>\n\t\tcreateTable();\n\t}\n\t<span style=\"color: #008000; font-weight: bold;\">else<\/span> <span style=\"color: #008000; font-weight: bold;\">if<\/span> (_onDBInitializedCallback <span style=\"color: #666666;\">!=<\/span> <span style=\"color: #008000; font-weight: bold;\">null<\/span>)\n\t{\n\t\t<span style=\"color: #408080; font-style: italic;\">\/\/Person table is already created and initilized. <\/span>\n\t\t<span style=\"color: #408080; font-style: italic;\">\/\/Call callback function.<\/span>\n\t\t_onDBInitializedCallback();\n\t}\n}\n\n<span style=\"color: #408080; font-style: italic;\">\/\/Reads data from json_data.js and return aray of Person objects<\/span>\n<span style=\"color: #008000; font-weight: bold;\">function<\/span> getPackagedData()\n{\n\t<span style=\"color: #408080; font-style: italic;\">\/\/Get data from json_data.js using XHR<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> httpReq <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">new<\/span> XMLHttpRequest();\n\thttpReq.open(<span style=\"color: #ba2121;\">\"GET\"<\/span>,<span style=\"color: #ba2121;\">\"_data\/json_data.js\"<\/span>,<span style=\"color: #008000; font-weight: bold;\">false<\/span>);\n\thttpReq.send();\n\t<span style=\"color: #408080; font-style: italic;\">\/\/Convert string to JavaScript objects using eval<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">return<\/span> <span style=\"color: #008000;\">eval<\/span>(httpReq.responseText);\n}\n\n<span style=\"color: #408080; font-style: italic;\">\/\/Create Person table<\/span>\n<span style=\"color: #008000; font-weight: bold;\">function<\/span> createTable()\n{\n\tdb.transaction (<span style=\"color: #008000; font-weight: bold;\">function<\/span> (tx){\n\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> sql <span style=\"color: #666666;\">=<\/span> <span style=\"color: #ba2121;\">\"create table if not exists \"<\/span> <span style=\"color: #666666;\">+<\/span> tableName <span style=\"color: #666666;\">+<\/span>\n\t\t\t<span style=\"color: #ba2121;\">\" (id integer, name text, picture_file text)\"<\/span>;\n\t\ttx.executeSql(sql);\n\t},\n\tonError,\n\tinitializeTable);\n}\n\n<span style=\"color: #408080; font-style: italic;\">\/\/Inserts records in Person table after reading <\/span>\n<span style=\"color: #408080; font-style: italic;\">\/\/initial data from json_data.js<\/span>\n<span style=\"color: #008000; font-weight: bold;\">function<\/span> initializeTable()\n{\n\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> persons <span style=\"color: #666666;\">=<\/span> getPackagedData();\n\tinsertPerson(persons,<span style=\"color: #666666;\">0<\/span>);\n\tlocalStorage.tablesCreated <span style=\"color: #666666;\">=<\/span> <span style=\"color: #ba2121;\">\"true\"<\/span>;\n}\n\n<span style=\"color: #408080; font-style: italic;\">\/\/Inserts person at given index from persons array<\/span>\n<span style=\"color: #008000; font-weight: bold;\">function<\/span> insertPerson (persons, index)\n{\n\t<span style=\"color: #408080; font-style: italic;\">\/\/Checkif we have inserted all records<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> (index <span style=\"color: #666666;\">&gt;=<\/span> persons.length)\n\t{\n\t\t<span style=\"color: #408080; font-style: italic;\">\/\/Database is initialized. Call callback function<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> (_onDBInitializedCallback <span style=\"color: #666666;\">!=<\/span> <span style=\"color: #008000; font-weight: bold;\">null<\/span>)\n\t\t{\n\t\t\t_onDBInitializedCallback();\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">return<\/span>;\n\t\t}\n\t}\n\n\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> person <span style=\"color: #666666;\">=<\/span> persons[index];\n\n\tdb.transaction(<span style=\"color: #008000; font-weight: bold;\">function<\/span> (tx){\n\t\t<span style=\"color: #408080; font-style: italic;\">\/\/Got transaction<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> sql <span style=\"color: #666666;\">=<\/span> <span style=\"color: #ba2121;\">\"insert into \"<\/span> <span style=\"color: #666666;\">+<\/span> tableName <span style=\"color: #666666;\">+<\/span> <span style=\"color: #ba2121;\">\"(id,name,picture_file) values (?,?,?)\"<\/span>;\n\t\ttx.executeSql(sql,[person.id, person.name, person.picture_file]);\n\t},\n\tonError,\n\t<span style=\"color: #008000; font-weight: bold;\">function<\/span> () {\n\t\t<span style=\"color: #408080; font-style: italic;\">\/\/insert next person in persons array<\/span>\n\t\tinsertPerson(persons,<span style=\"color: #666666;\">++<\/span>index);\n\t});\n}\n\n<span style=\"color: #408080; font-style: italic;\">\/\/DB error handler<\/span>\n<span style=\"color: #008000; font-weight: bold;\">function<\/span> onError(err)\n{\n\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> (<span style=\"color: #008000; font-weight: bold;\">typeof<\/span> err.message <span style=\"color: #666666;\">!=<\/span> <span style=\"color: #ba2121;\">'undefined'<\/span>)\n\t\terr <span style=\"color: #666666;\">=<\/span> err.message;\n\talert(err);\n}\n\n<span style=\"color: #408080; font-style: italic;\">\/\/Get all persons from Person table. <\/span>\n<span style=\"color: #408080; font-style: italic;\">\/\/Calls callbackFunc with array of person object as argument<\/span>\n<span style=\"color: #008000; font-weight: bold;\">function<\/span> getPersons(callbackFunc)\n{\n\tdb.transaction(<span style=\"color: #008000; font-weight: bold;\">function<\/span> (tx){\n\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> sql <span style=\"color: #666666;\">=<\/span> <span style=\"color: #ba2121;\">\"select * from \"<\/span> <span style=\"color: #666666;\">+<\/span> tableName <span style=\"color: #666666;\">+<\/span> <span style=\"color: #ba2121;\">\" order by name\"<\/span>;\n\t\ttx.executeSql(sql,<span style=\"color: #008000; font-weight: bold;\">null<\/span>, <span style=\"color: #008000; font-weight: bold;\">function<\/span>(tx, result) {\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> persons <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">new<\/span> <span style=\"color: #008000;\">Array<\/span>();\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> rows <span style=\"color: #666666;\">=<\/span> result.rows;\n\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">for<\/span> (<span style=\"color: #008000; font-weight: bold;\">var<\/span> i <span style=\"color: #666666;\">=<\/span> <span style=\"color: #666666;\">0<\/span>; i <span style=\"color: #666666;\">&lt;<\/span> rows.length; i<span style=\"color: #666666;\">++<\/span>)\n\t\t\t{\n\t\t\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> person <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">new<\/span> <span style=\"color: #008000;\">Object<\/span>();\n\t\t\t\tperson.id <span style=\"color: #666666;\">=<\/span> rows.item(i).id;\n\t\t\t\tperson.name <span style=\"color: #666666;\">=<\/span> rows.item(i).name;\n\t\t\t\tperson.picture_file <span style=\"color: #666666;\">=<\/span> <span style=\"color: #ba2121;\">\"_data\/images\/\"<\/span> <span style=\"color: #666666;\">+<\/span> rows.item(i).picture_file;\n\t\t\t\tpersons.push(person);\n\t\t\t}\n\n\t\t\t<span style=\"color: #008000; font-weight: bold;\">if<\/span> (callbackFunc)\n\t\t\t\tcallbackFunc(persons);\n\t\t})\n\t},\n\tonError,\n\t<span style=\"color: #008000; font-weight: bold;\">null<\/span>);\n}<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>To test DB functions we have written in app.js, we will create index.html, in which will open the database, wait till it is initialized and then call\u00a0getPersons function to fetch records from the database and then display images and names of persons in a table &#8211;<\/p>\n<div style=\"background: white; overflow: auto; width: auto; color: black; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #bc7a00;\">&lt;!DOCTYPE html&gt;<\/span>\n<span style=\"color: #008000; font-weight: bold;\">&lt;html&gt;<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">&lt;head&gt;<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">&lt;title&gt;<\/span>Example - Pre-packaged HTML5 DB Demo<span style=\"color: #008000; font-weight: bold;\">&lt;\/title&gt;<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">&lt;script <\/span><span style=\"color: #7d9029;\">src=<\/span><span style=\"color: #ba2121;\">\"app.js\"<\/span><span style=\"color: #008000; font-weight: bold;\">&gt;&lt;\/script&gt;<\/span>\n\n\t\t<span style=\"color: #008000; font-weight: bold;\">&lt;script&gt;<\/span>\n\t\t\t<span style=\"color: #408080; font-style: italic;\">\/\/Specify function to call after database is initialized<\/span>\n\t\t\t<span style=\"color: #408080; font-style: italic;\">\/\/_onDBInitializedCallback is declared in app.js<\/span>\n\t\t\t_onDBInitializedCallback <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000; font-weight: bold;\">function<\/span> onDBInitialized() {\n\n\t\t\t\tgetPersons(<span style=\"color: #008000; font-weight: bold;\">function<\/span>(persons){\n\t\t\t\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> buf <span style=\"color: #666666;\">=<\/span> <span style=\"color: #ba2121;\">\"\"<\/span>;\n\t\t\t\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> tableElm <span style=\"color: #666666;\">=<\/span> <span style=\"color: #008000;\">document<\/span>.getElementById(<span style=\"color: #ba2121;\">\"personsTable\"<\/span>);\n\t\t\t\t\t<span style=\"color: #008000; font-weight: bold;\">for<\/span> (<span style=\"color: #008000; font-weight: bold;\">var<\/span> i <span style=\"color: #666666;\">=<\/span> <span style=\"color: #666666;\">0<\/span>; i <span style=\"color: #666666;\">&lt;<\/span> persons.length; i<span style=\"color: #666666;\">++<\/span>)\n\t\t\t\t\t{\n\t\t\t\t\t\t<span style=\"color: #008000; font-weight: bold;\">var<\/span> row <span style=\"color: #666666;\">=<\/span> <span style=\"color: #ba2121;\">\"&lt;tr&gt;&lt;td&gt;\"<\/span> <span style=\"color: #666666;\">+<\/span>\n\t\t\t\t\t\t\t<span style=\"color: #ba2121;\">\"&lt;img src='\"<\/span> <span style=\"color: #666666;\">+<\/span> persons[i].picture_file <span style=\"color: #666666;\">+<\/span> <span style=\"color: #ba2121;\">\"'&gt;&lt;\/img&gt;&lt;\/td&gt;\"<\/span> <span style=\"color: #666666;\">+<\/span>\n\t\t\t\t\t\t\t<span style=\"color: #ba2121;\">\"&lt;td&gt;\"<\/span> <span style=\"color: #666666;\">+<\/span> persons[i].name <span style=\"color: #666666;\">+<\/span> <span style=\"color: #ba2121;\">\"&lt;\/td&gt;&lt;\/tr&gt;\"<\/span>;\n\t\t\t\t\t\ttableElm.innerHTML <span style=\"color: #666666;\">+=<\/span> row;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t<span style=\"color: #408080; font-style: italic;\">\/\/Open the database<\/span>\n\t\t\topenDB();\n\t\t<span style=\"color: #008000; font-weight: bold;\">&lt;\/script&gt;<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">&lt;\/head&gt;<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">&lt;body&gt;<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">&lt;table<\/span> <span style=\"color: #7d9029;\">id=<\/span><span style=\"color: #ba2121;\">\"personsTable\"<\/span><span style=\"color: #008000; font-weight: bold;\">&gt;<\/span>\n\t\t<span style=\"color: #008000; font-weight: bold;\">&lt;\/table&gt;<\/span>\n\t<span style=\"color: #008000; font-weight: bold;\">&lt;\/body&gt;<\/span>\n<span style=\"color: #008000; font-weight: bold;\">&lt;\/html&gt;<\/span><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>-Ram Kulkarni<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was discussing with a couple of colleagues of mine yesterday about a HTML5 mobile application that we are developing, and one of the requirements was to pre-package database with the application. A few months back I had created an application that did just that. I thought the solution might be of interest to some &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/ramkulkarni.com\/blog\/pre-packaging-database-with-html5-mobile-application\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Pre-packaging database with HTML5 Mobile Application&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Pre-packaging database with HTML5 Mobile Application","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[10,78,1],"tags":[11,79,80],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2g9O8-ff","jetpack-related-posts":[],"_links":{"self":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts\/945"}],"collection":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/comments?post=945"}],"version-history":[{"count":0,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/posts\/945\/revisions"}],"wp:attachment":[{"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/media?parent=945"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/categories?post=945"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/ramkulkarni.com\/blog\/wp-json\/wp\/v2\/tags?post=945"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}