Blog

Blog Archives - 7 Record(s)

Year: '2015' - Month: '1'

31
January 2015

Gavin Pickin

Using WebSQL - Pulling Data - Start Thinking Async vs Sync

Javascript, WebSQL

In today's post on WebSQL, I’m going to show you how I had to refactor my application, to move from sync LocalStorage functions and storage, over to using WebSQL, which has an ASYNC API for transactions. In the last few posts, I have gone over why I chose WebSQL for this Application, and how to get Started with WebSQL etc, and had to post a correction to some assumptions I had made, so now we’re ready to move on and get some data out of the db, and thrown into our application.

So first we’ll start with my localStorage version of the code. I admit, I’m not a veteran Javascript programmer, so I am not up to speed on all the best practices etc, although, I’m learning all the time, so hopefully its not the worse code you’ve seen. If you think I should do things differently, let me know, this is part of the reason I blog, to get code out there, and get feedback, or alternative solutions etc.

This method is my renderTrainingList, its basically in a View/View Model Layer… and it calls the trainingService to get a list of trainings, and outputs them using a Mustache Template, and throws it into the dom. I am not 100% happy with the mix of duties here, I will probably move these into a controller now that I think of it. Save that for another post now though.

//trainingService.js
renderTrainingList: function( ){
               var template = $('#trainingListRowTemplate').html();
               console.log('start render function');
               trainingListData = app.trainingService.getTrainings();
               console.log('got the training data');
               Mustache.parse(template);   // optional, speeds up future uses
               $('#training-list tbody').html('');
               for (var i = 0; i < trainingListData.length; i++){
                    var rendered = Mustache.render(template, trainingListData[i] );
                    $('#training-list tbody:last').append( rendered ).trigger('create');                                                    
               }
}

Trying to employ equivalent separation of concerns, my service (behaving like a DAO almost) looked like this

//trainingService.js
getTrainings: function() {
               try {
                    return JSON.parse(localStorage['trainings']);    
               }
               catch (e){
                    return [];
               }   
},

So the first thing I have to do it change the function that actually gets the data… I decide to split the service, and the DAO out a little more, incase I want to do more Service like processing, but I want the DAO just to be simple data in or out. So updating my service, looks more like this.

//trainingService.js
getTrainings: function() {
     return app.trainingDAO.getTrainings();
}

I can add extra processing here if needed, but the guts of the sql, and the implementation details will be black boxed in the DAO, how they should have been.

getTrainings: function() {
     app.db.readTransaction(function (tx) {
          tx.executeSql('SELECT * FROM training',
               [],
               successCall,
                              errorCall
                 );
          });
     });
}

Now, we have a problem… I cannot return the list of trainings, because its an async call. I do not have anything to return, but I can call something else. Maybe I should create another method in the service, and then call that.

This smells funky to me… and for good reason. I would be calling from the DAO back to the Service or ViewModule with the data, to do something with. I want my DAO to be independent of whats calling it, right? So, how do we do this?

Javascript has something called Promises, which will become Native in ES6, but for now, are usable within libraries like Q or jQuery etc. How they work is essentially, you create an object, called a deferred, which essentially has has a promise - a piece of work to be done, and then code to be run when it is complete, or when it fails. Of course, that is a simple explanation, and you should definitely read more about Promises and Deferred, but I’m going to show you how I use them.

So, lets start at the ViewModule. Instead of the following line of code, which asks for trainings, and stores them in a variable called trainingListData, we want to use a WHEN construct.

//old
trainingListData = app.trainingService.getTrainings();
//new
$.when( app.trainingService.getTrainings() ).done( function( trainingListData ){
     //DO SOMETHING
});

Essentially, we’re saying, When the request for app.trainingService.getTrainings() is completed or RESOLVED in this context, if it is DONE, then do something. Done takes a function, and in this case, we want to use the trainingListData and then do something with it. We put all of our previous sync code into this when block, and instead of it running right away, before the getTrainings() is complete, it waits, and the deferred processes it after we have the data back.

To use a deferred object, in the DAO we need to make one, and we return the deferred object to the WHEN, so it can track when its done. The When is subscribing for a RESOLVED event, essentially like PUB SUB, but Promises can only be resolved 1 time, but read the docs for more information. Here is the DAO using Promises.

// trainingDAO.js
getTrainings: function() {
     return $.Deferred(function (d) {
          app.db.readTransaction(function (tx) {
               tx.executeSql('SELECT * FROM training',
                    [],
                    function(tx, data){ d.resolve(data); },
                    function(tx, error){ d.reject(error);}
               );
          });
     });
}

Basically we are returning a $.Deferred jQuery object. We wrap the WebSQL transaction inside a function, and the successCallback and errorCallbacks using the d variable (the deferred), and either resolve it, passing the data, or reject it, passing the error.

So now, our WHEN code waits patiently async, and if the query is successful, the deferred get resolved, and the When’s .DONE() is run. If it errors, if we have a .fail() on the When it would run. For the when to work, the call must get a Deferred object… but since our ViewModule calls our service which calls our DAO, so how do we pass the deferred? Easy, just return what the DAO returns. If we were wanting to do more processing, we’d have to wrap the processing, including the DAOs deferred in another deferred, but this works, for now :)

//trainingService.js
getTrainings: function() {
     console.log('getTrainings - returning the deferred');
     return app.trainingDAO.getTrainings();
}

So lets look at our render function again, using the WHEN

//trainingService.js
renderTrainingList: function( ){
     var template = $('#trainingListRowTemplate').html();
     console.log('start render function');
      $.when( app.trainingService.getTrainings() ).done( function( trainingListData ){
               console.log('got the training data');
               Mustache.parse(template);   // optional, speeds up future uses
               $('#training-list tbody').html('');
               for (var i = 0; i < trainingListData.length; i++){
                    var rendered = Mustache.render(template, trainingListData[i] );
                    $('#training-list tbody:last').append( rendered ).trigger('create');                                                    
               }
      }); //END OF THE WHEN
}

We replaced the trainingListData statement with the WHEN line, and then app the rest of the code in the DONE block.
There is one more adjustment we have to make. Previously, the localStorage was passing back an array of objects, but WebSQL by default gives you back a WebSQLResult set, so you have to deal with the data differently. If I was trying to be really DAO independent, I would use some conversion service to return an array of objects too, maybe with some metedata from the sql, but I want to use the WebSQL format, especially when I am learning more about it… so lets convert our View Module code, so it knows how to iterate over it.

For length… instead of trainingListData.length we need to reference the rows object, so we use trainingListData.rows.length.

For the actual item, we need to reference trainingListData.rows.item(i) instead of trainingListData[i]. The beauty of WebSQL is, that each item is stored as a javascript object, so at that point, they are the same.

// trainingService.js
renderTrainingList: function( ){
     var template = $('#trainingListRowTemplate').html();
     console.log('start render function');
     $.when( app.trainingService.getTrainings() ).done( function( trainingListData ){
               console.log('got the training data');
               Mustache.parse(template);   // optional, speeds up future uses
               $('#training-list tbody').html('');
               for (var i = 0; i < trainingListData.rows.length; i++){
                    var rendered = Mustache.render(template, trainingListData.rows.item(i) );
                    $('#training-list tbody:last').append( rendered ).trigger('create');                     
               }
     });
}

There isn’t a lot of code to change for the switch, but its a different way of thinking, especially coming from a ColdFusion background, when you call a DAO it waits for the data to proceed, Deferreds and Promises are very cool and elegant way to solve the problem, and keep you out of CALLBACK HELL as most people call it.

Hope it helps.
Thanks for reading.
 

30
January 2015

Gavin Pickin

Pre-mature Optimization - Pre-mature Blog - Gotcha WebSQL Open Database

Javascript, Techie Gotchas, WebSQL

I have written a few posts so far about WebSQL, why I like it, especially in this cross platform Cordova / Phonegap App development world, and a getting started post, where I was wrong. Yes, I Pre-maturely posted that Blog, so this is me fixing it, of course, I edited the original post right away, but here, I’ll go into what I stated wrong, and how it took me way too long to figure out I was wrong, and how sometimes Pre-mature Optimization isn’t needed, but sometimes, it will help show you how wrong you were.

I incorrectly stated that the openDatabase call took 4 arguments + 2 callbacks, 6 total arguments. The openDatabase call actually takes 5 total arguments, the 5th being a callback. I had assumed there was a onSuccess callback, and onError callback, but there was only one callback. I looked through some of my history, and I believe I just ASSUMED those two callbacks existed, since most examples don’t use a callback, and all the other callbacks in the API have onSuccess and onError, so I must have merged them. I think the process I went through, although painful at the time, was pretty interesting, and is worth writing, therefore, worth reading, so I’ll tell you my story.

Assuming since most of the WebSQL API is async*, I wrapped my openDatabase call in a deferred / promise. 
Note there is a way to force sync but it seems counter productive these days to force it to be blocking, especially with UI like an App etc.

I wrapped the call, and it looked something like this.

I ran my app, the “done” wasn’t firing. I added a series of console logs, here, there and everywhere. It looked like I had something wrong with my promise, maybe I wasn’t returning the deferred correctly. I racked my brain for a long time. Eventually, I thought maybe I was erring in the openDatabase call itself, but if I removed it from the promise it worked. Frustrated, I ended up changing a lot of code, and eventually, it fired… but not again after that.

I tried to get the openDatabase call to fail, but my promise never failed and resolved with a reject… so then I realized, these callbacks are not behaving at all like I thought, I better check the documentation. 
There is no 6th argument, an onError callback, so of course my promise would never respond with d.reject(error) because there are no such callback. There is a 5th argument, a callback, but its not on success, its on Creation. So it only ever fires, when the DB is created. If it exists, it never fires.

So it seemed that I was wrapping this Async function in a Promise, that I couldn’t resolve. I wondered, maybe I can find another way to see that the Async has completed, and then resolve the deferred… again this was not easy. So I decided to test the openDatabase, and see if I could just check the object and maybe use a timeout to check for the resulting object.

I logged before the openDatabase call, and immediately after it, and I realized, that the API might be Async, the creation might be Async, but the call immediately returns a decorated object, and no matter what I did, I always had that object… so it seems that the API itself handles the async issue with the db internally. Even if the DB was not present, and had to be created, the DB object returned would be returned instantly, all the functions would be present, I can call them, and under the covers, if you call a query too soon, it waits until it is ready, and then calls it.

I could not break it, which is great design on their side, but it taught me 2 lessons, well at least 2 lessons:

  • RTFM - Read the FREAKING Manual (or something more vulgar)
  • Do not try to pre-maturely optimize - I was optimizing for a case that could never exist, probably more RTFM
  • Be careful not to blog too quickly, because sometimes you’re 1 chapter behind the teacher, and you’ll make a fool of yourself :)

Anyways, I thought it was an interesting story… long story short, openDatabase call is super quick and doesn’t need a Promise wrapper, but you can tell if the DB is being created with that callback… if you want to error catch it, you’ll have to Try Catch it.

Thanks for reading, now I need to finish that article on wrapping the WebSQL API calls using Promises.
 

30
January 2015

Gavin Pickin

Whats better than Firefox Developer Tools? Firefox Developer Edition

Javascript, Tools and IDEs

In the world we work in, the Web world, there are lots of IDEs and tools out there. One of the best tools to ever come out for Web / Javascript development, and made developing in Javascript even possible I thing, was Firebug. These days most modern browsers have web tools, and they're getting better every day. Some like Firefox's Dev tools, others prefer Chrome, and I have heard that IE 11s are actually pretty amazing. Each suite of test tools one ups the other, and the innovation is good for all of us.

I am probably very behind the times, but I only just learned of another option from Mozilla, which is better than Firefox's Dev Tools... a Firefox Developer Browser.

It's slick looking, it has that dark sublime look that is the "COOL" thing right now, apparently. It has a bunch of awesome tools baked right in, and the best thing is, they have a special feature called Valence, which allows you to debug your code, running on safari on iOS or chrome on Android, or Chrome on Desktop. One of the worst parts of testing all of the browsers is, you have to learn each of the tools, where do they hide this feature, do they have that feature, Valence is a special browser extension only found in Firefox Developer Edition, and it looks pretty slick.

The link below has all the information you need, including some little vidoes on the features, like Valence, Responsive Web Design Features, Web Audio Editor, WebIDE, and of course all the usual features we know and love like CSS Style Editor, Javascript Debugging, Network Monitor, Page Inspector etc.

https://www.mozilla.org/en-US/firefox/developer/

If you have heard of this before, why didn't you tell me?
If you haven't heard of this yet, then you are welcome.

What are you waiting for?
Go download it now

29
January 2015

Gavin Pickin

Lucee in the Clouds with Java - Hello World, from Lucee

CFML Language, CFML Server, Migrating to Railo, Server Admin

Less than 12 hours ago, we were on the dawn of a big announcement in the CFML world, and only a few knew it was coming. A few more knew something was coming, but were not sure what it was, myself, I was expecting some tools, or a new version, or something, to put it mildly, I was surprised to hear what the big announcement was.

There is a new server product on the CFML Engine market, LUCEE.

Adam Cameron, my fellow Kiwi, living in London was front and center for the big announcement, held at Pixl 8 headquarters. Adam of course blogged it all, and with the help of Mark Drew fielded questions from the internet to get answered by the Lucee team, so I will not repeat that information, but here are a couple of points I found interesting, and stood out, at the bottom are more links, so you can read all the rest yourself.

In short, Railo 4.2 was forked, and the lead developers from the Railo Project has joined a new organization, the Lucee Association, and today has announced their presence to the world, and Lucee 4.5 is available for download today.

Since it is a fork of Railo 4.2, it is an easy transition and several large and well known members of the community have already installed and migrated to Lucee.

The organization they choose to administer Lucee sounds intriguing, with voting positions available for individuals and businesses on different levels. It takes legal issues out of the way, and lets the community help drive the project in the direction it wants. Read more about that in the links below.

I will get this installed in the next day or two, and give you a quick breakdown, although, of course installing Lucee is as easy as Railo, and replacing it is even easier.

The website for Lucee is http://www.lucee.org
The Discourse blog / discussion board is available at http://lucee.org:8080/ (will be updated when the sub-domain kicks in)
Adam Cameron's main blog entry on Lucee - http://blog.adamcameron.me/2015/01/lucee.html
Adam Cameron's follow up entry "Lucee Launch - Thanks"  - http://blog.adamcameron.me/2015/01/lucee-launch-thanks.html

EDITED - Additional Link
Brad Wood wrote a nice post as well - "Railo And Lucee: Hunka Hunka Burning Questions" -  http://www.codersrevolution.com/blog/railo-and-lucee-hunka-hunka-burning-questions

Welcome Lucee, looking forward to getting to know you better.

22
January 2015

Gavin Pickin

Using WebSQL in my Mobile App - Lessons learned - The hard way

Javascript, Mobile Development, WebSQL

I have been working on my Multiple Platform App, using WebSQL for bigger storage needs, instead of simple Locale Storage, in which my App started with. My last blog post walked us through opening a db connection with WebSQL, creating tables, inserting data, inserting data and protecting your app from SQL Injection using placeholders, and the 2 types of transactions, .transaction() which locks the db, and .readTransaction() which does not lock the whole db, and can only be used for ready only sql… as the name suggests.

Of course, the more you dig into something, the more you learned, and I think I learned a few important things to share.
And Yes, that title is beyond a little dramatic.

Primary Keys

SQLite, which is what WebSQL is based off of, allows you some pretty nice primary key functions… and one of my tables has an id with the following flags.

ID INTEGER PRIMARY KEY ASC AUTOINCREMENT

The interesting thing with primary keys though… it seems as if they are REQUIRED fields in your inserts. Maybe I’m just spoiled with mySql, to be honest its been so long since I’ve done much dev with Postgres, MS Sql and Oracle to know how they behave, but in MySql, you don’t need the primary key if its auto increment, it just handles it under the covers.

So, lesson, even for a simple insert, you need something like this

INSERT INTO myTable ( ID ) values ( null );


Different Insert Syntax

In the last post, we shows a simple insert, and we showed a simple insert with placeholders, and followed them with an array of values for placeholders. Most DB tools give you a lot of flexibility, and you can insert many rows at a time, or change the insert syntax. WebSQL SQLite is a little more strict.

'INSERT INTO myTable ( ID ) values ( null )' - works

'INSERT INTO myTable ( ID ) values ( ? )’, [ null ]- works

‘INSERT INTO myTable set ID = null’ - DOES NOT WORK

Now, I have seen online some people mentioning you cannot insert multiple lines at once, but in Safari I have got the following to work

'INSERT INTO myTable ( ID ) values ( ? ), ( ? )’, [ null, null ]

But in Chrome, it didn’t support it, so I’m not sure if iOS, Android, or Windows8 will support it not either… I will have to test it… we’ll leave that for another day.


Our Friend Async

Now, for those developers new to Javascript, the world of sync and async can be a little strange at first… and dealing with Async is more Reactive Programming than a lot of Procedural Server Side languages that most of come from. I know with ColdFusion, unless you say so, its all Procedural, synchronous code, and it blocks.

The trick with Javascript is, what is Async and what is not Async. General rule is… if you reach outside Javascript VM… then it is Async, and you have to deal with it, using Callbacks, or Deferreds/Promises.

Local Storage is synchronous, because its in memory, essentially part of the VM, so all my code for Local Storage was written in sync. Now I am changing code over to WebSQL, calls are not in sync, they are async, and therefore something simple like the following, gets a lot messier.

userData = userDAO.getUser();
$(‘#firstName’).text(userData.firstName);

If you had this code in a method, the call would go out for getUser() and since you are expecting it to return data to act on, and it wouldn’t return in sync, userData.firstName would not be populated.

Its not that this Async is hard, its just something else to consider when you’re making the switch from Local Storage to WebSQL or NoSQL.

So how do you code for Async?
You’ll have to wait for the next post.

Leave me feedback if I’m off base, remember, I’m learning about this too.

Thanks for reading.

22
January 2015

Gavin Pickin

Getting Started with WebSQL in your Mobile App

Android, IOS, Javascript, Mobile Development, WebSQL

In my last Blog Post, I discussed an App I was building, and how it changed target from Windows 8, to iOS to Android, and back to Windows 8, and thanks to MS Open Tech, the Microsoft Open Source company, I could use the WebSQL API to talk to WebSQL on iOS and Android, and with the plugin, SQLite on Windows 8.

This post will give you the basics of actually creating a DB Connection, creating a table, and making a couple of queries against it.

First, we need to open / create a Database connection. If the DB exists, it will create a connection to it, otherwise, this command will create a new one.

 

This function, openDatabase takes 4 arguments, and has 2 1 optional callbacks WRONG WRONG WRONG - READ EDIT DETAILS BELOW

  • Database Name
  • Version Number
  • Text Description
  • Estimated Size of Database
  • Success Callback
  • Error Callback
  • onCreate Callback

EDIT BEGIN 
I was wrong... unlike all of the WebSQL Api calls to execute SQL etc, which have a Success and Error callback, openDatabase DOES NOT have those 2 callbacks. It has 1 callback, which is OPTIONAL in more than one meaning of the word. It is optional to provide it, and it is only optionally called, only if the Database did not exist, and was created.

More on this gotcha very soon... as I explain how it got me, and how I learned that RTFM applied in this case, and could have saved me hours. I wonder if I read this incorrectly from one of the resources I was using to learn, or if I did it wrong all by myself, but check back soon for a more detailed look into this.
EDIT END

The size is essentially an estimate, 5mb is the largest you can create without prompting the user for more space (although this support is a little patchy across browsers, I haven’t ran into the space issue in a WebView yet). You can make the size smaller, but, why not just got with 5mb.

Pretty straight forward, a couple of console logs, and we’ve got our db connection.

From the db connection, we can access a tx (transaction) object in which to execute our sql calls. To create a table, we can simply run the following code.

Of course, if this database table already exists, we would receive an error, so add “IF NOT EXISTS” just to be safe

Now we have our table, we can execute our sql, and the method/function to do that is appropriately named executeSQL()… as you could see above in the create table code.
We can use the same transaction as the create, or separate your calls into additional transactions, it is up to you. Shown together.

Being Javascript, SQL injection might be more of a problem than normal, so WebSQL gives you a way to provide SQL Arguments. Instead of the values, in the SQL statement, insert question marks and then pass an additional argument to the executeSQL method, an array of values.

Now we have some data in the db… we need to read it. The one thing I like about this api, is its intuitive… so if you want to execute some sql, to get some values… you can guess the method, executeSQL, but we need to add callbacks, to be able to process the result.

  • 1st argument is the sql to execute
  • 2nd argument is the array of values, in this case, just []
  • 3rd argument is a success callback
  • 4th argument is a error callback.

The success callback gives you tx, and results.

  • Results is a SQLResultSet.
  • Results.rows is a SQLResultSetRowList which you can get the length or record count from with .legnth
  • Results.rows.item( i ) where i is >= 0 and < .length gives you back a Javascript Object. You can choose to use that however you’d like.

So if you would like to loop through the doctors in our db, we can do the following.

I had hoped the result was a JS Array, but there are other methods if you explore the Prototype, but that is the only unintuitive item I found, and if I had read the documentation better, I would have spotted that pretty quickly.

I believe there are some mini libraries that can take a ResultSet and convert to a JSON array, or something similar, but row by row access is not that painful… even for a ColdFusion programmer like myself.

Now we have discussed the basics, I’ll let you know, there are 2 types of transactions… not just one like my code examples. A normal transaction locked the db while it is executing… but sometimes, when you are only reading, you don’t need to lock the db, so it would be great to have a way to do that, and that is exactly what readTransaction is. If you are not writing to the db, only reading, you can update your code to look like this

This runs the same to your app/client… but on the db side, its not locking, just reading and returning. So best practice, is use readTransaction except where you are inserting or creating. If you do try and insert in a read, it will trigger your onError callback, if you defined one.

Console will log this

SQLError {message: "could not prepare statement (23 not authorized)", code: 5, UNKNOWN_ERR: 0, DATABASE_ERR: 1, VERSION_ERR: 2…}

I am pretty excited to use WebSQL, and now I have this down, its ready to build tables, learn about Datatypes, add Indexes, Foreign Key restraints, maybe, and a few other of the FULLY FUNCTIONAL features of WebSQL and SQLite.

Note… if you look at caniuse.com http://caniuse.com/#feat=sql-storage you’ll see its not fully supported in desktop browsers, and its deprecated too… so in the future, we might need another technology, but for now, with mobile browsers, apps, and great wrappers, its a solid cross platform API, and I like it.

Thanks for reading.

20
January 2015

Gavin Pickin

Cordova Cross Platform Database Issue - The Solution Might Surprise You

Android, Cordova / Phonegap, IOS

There was a point when Local Storage key value pair just didn’t seem to be a good solution. Its great for small key and values, but when you’re starting to dump JSON Objects Arrays, which have children, and you do not have all the NoSQL goodness, its time to get something bigger and beefier.

This App I am working on is an interesting one. The project itself is tied to a bigger internal system we are building, and like that, this App has evolved, before even being released. We started off, planning to target a Surface, so I decided that JavaScipt and HTML5 is a good solution, since Windows 8 allows you to wrap those now, so off we went. After that, the target changed, from Surface to iPad, from iPad to Android, and now, Android back to Surface. Luckily for me, my project, with Cordova only had to adapt slightly, as we changed.

Now, the interesting part here is, although the App moves pretty smoothly from platform to platform… it does, assuming each platform has the same support for technology. Local storage, yes it does… but as I mentioned above, I am needing to migrate from Local Storage to a bigger data storage option. Since I have setup the app with JSON styled storage, I first look at NoSQL solutions… preferably with some type of sync built in, since this app is going to need it, and I would love the help.

Looking a CouchBase Mobile, Pouch, a lot of great options out there, I come to one sad conclusion… NO SUPPORT FOR WINDOWS 8. Now this might not be 100% true, but with respect to Cordova plugins… I see 0 Windows 8 compatible Cordova Plugins.

So, I try to get back to the basics, HTML5 supports WebSQL right?
Not on Windows 8

This is where Microsoft steps in?
I wonder what you are thinking here… Bad Microsoft, no support right?
Well, that is where you are wrong.

A lot of people bash on Microsoft… but there are changing, they even started a new company called MS Open Tech, which is their Open Source Company, which works on Open Source projects, and being its own company, all the legalities are easier etc. They have done a lot of great work, and one of those items is a Cordova Plugin… com.msopentech.websql - Web Sql Plugin for Apache Cordova

At the writing of this, it has over 5500 downloads, compared to 3 and 60 for other SQL plugins which do not do the same thing.

MS Open Tech, looking to bridge the gap decided to create this plugin, under the covers, use a SQLite Database, but they made the plugin so it uses all the WebSQL APIs, so my app will not have a clue if its using WebSQL or SQLite. For those that don’t know, a polyfill filled the gap, and your Application cannot tell.

So now, if I deploy to Windows, all my DB calls go to the WebSQL plugin, which makes the appropriate SQLite calls under the covers. If I deploy to iOS or Android, the Plugin doesn’t do anything, and all my DB calls go to the native WebSQL API.

Of course, the API might not be perfect, as I use it more and more, I might find quirks, but so far so good. Its great to see big companies like Microsoft seeing the importance of Open Source, and how something as small as this, allows their Products to do better. If they did not have a easy solution to this problem, it just makes it harder for developers to develop for Windows 8… and without Apps, they will not have the desire for their Products.

MS Open Tech is doing a lot of cool things, Microsoft in general is, with Azure Cloud Services, Free versions of Visual Studio in the form if VS Express 2013… and a lot more.

Time to dive into this WebSQL (SQLite) now.

Thanks for reading.

Blog Search