One of the more interesting new features in PhoneGap 2.2 iss the inclusion of a globalization plugin into the core of the SDK itself. This plugin has many features, but basically boils down to the ability to get the user’s locale and language as well as being able to format numbers and dates. You can read the full API docs for a complete guide, but I thought it would be interesting to build a simple proof of concept application that tested out this feature. I began with a simple idea. I’d build an application that showed a table of product orders. There would be a column of dates, a column of order quantities, and an order of profit. This would give me a chance to demonstrate localization formatting of dates, numbers, and currencies. (Note that you can also do percentages as well. Again, check the docs!)
The result is pretty much as you would expect:
So - obviously the solution would be to make use of the API to format those columns. Unfortunately, here is where I ran into a snag. The API calls are all asynchronous. Ouch. Normally this isn’t a big deal, I can handle callbacks, but we’ve got N*3 cells of data all of which must be fired off asynchronously. In order to create our display we have to wait for these to finish.
Luckily there is a solution for this. Unluckily, for me, it involves jQuery Deferreds. This is one of the most powerful features of jQuery and also the one that makes my brain bleed.
The solution comes down to creating an array of deferred promises, essentially, an array of things that finish in an unknown time. This array can then be passed to the jQuery when() and then() operators which handles all of the chaining/waiting/collecting for me. Ready? Here’s the updated coded.
Taking this step by step, what I’ve done is this:
- First, create the array that will store the promises.
- For each order, we create three deferred objects. One for the date. One for the quantity. And one for the price. Notice that the Globalization API supports a failure callback if it can't format the value. For this application I simply then default to the original value.
- I pass this to when(), and then use then() to begin working with my result.