Author: <span class="vcard">Chris Tybur</span>

This is part 2 in a series of posts about creating a mobile web app for browsing music databases. Part 1 can be found here.

The first task in building the front end was testing my API to make sure I knew what was being returned by Rovi and that it had everything I wanted. I added some test JavaScript to the default MVC view that would call my API. It was a bit of trial and error going through the data and seeing where I needed to adjust my requests on the back end. My plan was to simply copy the test code into the official script files. The Rovi service itself is easy to use and well documented.

Next was setting up the base AngularJS implementation. I fired up Google to try and find a good online example of how to structure the app. The web site has a tutorial so I started stepping through it. But as I began to have questions on how to do certain things, and what the best practices are, I noticed the code I found online differed from what the tutorial was doing. More searching uncovered tools like angular-seed and angular-enterprise-seed. They were comprehensive but included way too much stuff to absorb for someone just learning the framework. They seem to be more for large scale web applications. I eventually came up with what looked like a good way to set up my module, controller, and service declarations, along with the source file structure to use. I followed suggestions from places like and various others found online. I don’t know if it’s exactly what is considered good by the Angular community but it’s close. My main app script ended up looking like this:

What to say about Angular? I like it. The framework strives to make it easy to separate your app logic from your markup from your data access, and largely succeeds. It includes tons of built-in stuff to further that goal. I ended up creating two custom Angular services, one for common code and one for data access. The latter looked like this:

The data service uses the built-in Angular $http service and does any required massaging of the data before handing it off to the controller that called it. The controllers then set various properties of the current scope as needed.

I created several different views based on what needed to be shown; one for artist search results, one for data on a specific artist, etc. Whenever I ran into a case where I needed the markup to be different based on the data, I was pleasantly surprised to find an Angular directive that would allow it to be driven by the model. Things like ng-show and ng-href were invaluable. The general rule in the Angular world is that you shouldn’t make any changes to the DOM in your controllers, and if you find yourself reaching for jQuery you might be doing something wrong. I’m happy to say I didn’t have any need to use jQuery to manipulate the DOM.

One of my favorite aspects of some directives is that Angular will react based on whether the expression in the directive is truthy. It makes me wonder if Stephen Colbert had some influence on the framework’s design, or at least the documentation.

Next is incorporating animations for view transitions, adding something to the options page, and filling out some missing features.


Note: my experience below happened in February of 2013, I’m just super late in publishing it.

There’s been a growing trend in the way corporations approach customer service. In industries that have become largely undifferentiated in the products or services they offer, the thing companies are trying to do is put forth the best possible customer experience. Which is great, you should always treat your customers well. But a recent experience has made me wish some of them would take a page out of the big book of common sense.

I recently had to contact Apple for technical support. As a very technical person, I don’t look forward to having to talk to tech support. I have to invest a certain amount of time going through the standard menu of questions about my problem. Sometimes the level 1 person can solve my issue, but often they can’t and things have to be escalated. Only they don’t always know (or are allowed?) to do that.

My Apple problem was strange and unexpected: I tried to buy an iTunes e-gift card for my mom’s birthday. I’m 99% positive I’ve made this kind of purchase before but it’s been a while. I hadn’t upgraded to iTunes 11 yet so that was the first thing I did. When I tried to complete the purchase I got a message saying it couldn’t be completed and that I’d need to contact Apple for assistance. So that’s fine. Only it was very not-fine.

I went to and filled out a request for support. I got a lengthy e-mail reply that started out with the words ‘A wonderful day to you!’ Why, thank you! The person indicated they were working on my problem, that I would get an e-mail after the matter has been investigated, etc. A day goes by and I get another reply, in which the same person says sorry but ‘my account is not authorized to obtain content from the U.S. iTunes Store. For this, we are unable to provide further information, but I strongly suggest you to review the iTunes Store Terms and conditions.’ Whaaa? That made no sense at all, and was entirely too cryptic.

My first thought was that they think I’m doing something fraudulent. I know all about Mat Honan’s experience and I’m sure Apple is still feeling some paranoia from that. And I did notice that the credit card I had on file in iTunes had expired when I went to make my purchase. I updated my payment info, but maybe they still weren’t sure things were on the level. That’s understandable.

I replied back saying that doesn’t seem right, I’ve bought a lot of stuff over the years through the iTunes store, could they escalate my ticket. What proceeded was two weeks of back and forth over why they wouldn’t let me give them money, and why they wouldn’t tell me what was really wrong. I don’t expect them to tell me every little detail about what’s in their records or their processes for customer disputes. But at least give me the overall reason, like ‘the payment info we got from you appears bogus’. More information is usually better than less. Instead in each e-mail they kept using phrases like ‘I acknowledge that you want to have an explanation for this’, apologizing profusely, thanking me for being a customer, and giving me a link where I could leave feedback.

Eventually they flipped whatever switch would allow me to purchase an e-gift card via iTunes, but by then the birthday I was buying it for had passed and I had already gone with Amazon. So sorry Apple, but I may need to look elsewhere for my MP3-buying needs in the future. My suggestion is you try to be more open and forthright when helping customers, rather than include so many nice platitudes in your e-mails.


Adobe uses a novel though hardly unique approach to distributing certain software. If you want to install say, Acrobat Reader onto your Windows machine, you go to their web site and download an installer. Only you don’t download an installer, you download a bootstrapper that downloads the right thing for you, based on your OS version, language, and platform. More and more vendors have adopted this approach over the years as different version of Windows have proliferated, 64-bit has became more widespread, and they have wanted to make the process easier on the user.

What Adobe does that is unique and unbelievable on Windows is once you launch the bootstrapper, it deletes the file. The program is running in memory but the actual executable file is gone. This means if something goes wrong during the download of the real installer or the subsequent installation, you can’t just restart it. You have to re-download the bootstrapper. Needless to say, this completely sucks and shouldn’t be necessary.

The Acrobat Reader bootstrapper has been like this for years and after recently rebuilding my laptop and installing it, I started to wonder if there was perhaps some technical reason, however outlandish, for that behavior. Is it because it needs to be chained together with other installers, or maybe bundled with some other completely different one? It needs to run silently and can’t leave any footprint on disk? They are trying to keep your machine clean??

Apparently Adobe has a direct download page that doesn’t try to detect the specifics of your machine, and will let you download a full installer that doesn’t have this behavior. A quick Google search reveals that several people have noticed this and none of them like it. Maybe Adobe should put a link on the Acrobat Reader download page in big type that says something like ‘Why we delete this file after you launch it’, which takes you to a page with an explanation. That would be nice.


It’s been over a year since I last touched my bookmark browser, and it needed some attention. There were a couple of outstanding bugs to deal with, plus it seemed like a good time to update the various libraries it uses.

One bug that occasionally cropped up is logging in for the first time and changing to the bookmark page, but having nothing show up. If I did a full refresh of the page then everything would be fine. I never quite figured out what was going on, until now. I assumed there was something I wasn’t doing right with Knockout, so I tried moving the code that does the bindings from the PageBeforeShow event for the bookmark page to right after the AJAX call that gets the data. But that didn’t help. Turns out it was something simple: the bookmark container is initially hidden, and I was never showing it after the first successful login, assuming the app was started in a logged-out state. The solution was showing the container right after the bindings were applied.

And speaking of content not showing right, it suddenly became necessary to add an explicit jQuery Mobile refresh call on the list that holds the bookmark data, like this:

Without such a call none of the jQuery Mobile styles would be applied unless I did a full page refresh. Not sure why, but whatever. The latest version did resolve a weird style issue with the bookmark menu list showing a double border around each list item, so that’s good.


This is part 1 in a series of posts about creating a mobile web app for browsing music databases.

In my continuing quest to up my web/mobile game, I decided to build a web app for searching the All Music database. There are a number of music metadata repositories on the web, some robust and some paltry. The one I like the best is run by Rovi and powers All Music, along with iTunes and several other big name media products. They have an iOS app that allows you to access all parts of the data store. It’s a great thing, but the search portion is not very user friendly and doesn’t always work the way you expect.

My goal was to create a basic search form that allows you to look up an artist, album, or song title. The native app had an all-in-one search feature where it tried to dynamically show you results for what it thought you were looking for, but it often failed to return what I wanted. I understand the ease and utility of having a single field for different types of information, but I wanted to run specific searches.

The first step was creating an API that would essentially wrap the calls to Rovi’s RESTful API. I didn’t want to interface directly with Rovi for several reasons: to allow the results to be formatted differently if I wanted, to make it easier to switch to a different data store in the future, and so I wouldn’t have to allow cross-origin requests. I went with the standard Web API project in Visual Studio 2013.

Getting the routing to work properly was the only real hurdle with the API. The default Visual Studio template sets up routes that include /api/<controller>. But I just wanted /api and not the <controller> part. It’s tricky because the base controller class is ApiController. The MVC convention is controller class names are of the form <my_ctl_name>Controller and then my_ctl_name becomes part of your route. Having my own class called ApiController wasn’t possible, so I called it SiteApiController. But how to tell all requests to use that controller? Enter WebApiConfig.

I removed all the default routes and added two new ones: one for searching and one for lookups. I was able to specify the exact controller class and a route template that only included /api and not a controller designation. Bonus points to Microsoft for allowing lots of route configuration options.

Even though I only needed to make single, synchronous requests to Rovi, I used HttpClient to do it. There might be a need in the future to make multiple simultaneous requests to build a query result, if so it will be easy to make them async. The next step was the front end.


I’ve been waiting to upgrade my iPhone 4S to iOS 6 until there was a maps app available other than the new native one that Apple built. And by ‘other’ I really mean one from Google. I only use maps for directions about half the time; the other half is spent searching, which is precisely where the Apple app falls down hard. So it was with great pleasure that I installed the official Google native maps app shortly after it was released. It’s beautiful, and definitely works as well as the pre-iOS 6 one. A couple days after loading it I pulled the iOS 6 trigger. Everything I used on a regular basis was working great…or so I thought.

I use my bookmark browser every day. It has an option to refresh bookmark data each time you start a new session, but I’m not using it at the moment. That means I must manually refresh the data, which I do every week or so. But after the OS upgrade the refresh process started acting weird. Normally it takes a few seconds to get the data from Mozilla Sync. Once the data is downloaded the last refresh timestamp is updated along with the total bookmark count. What was happening is the refresh seemed to happen instantly. It would update the timestamp but the count never changed. I knew this was not right because I happened to do a bunch of bookmark organizing and the number should have been very different.

I found that clearing all website data for Safari would allow the refresh to work properly. But that blows away any data from other web sites, which is bad. I finally got annoyed enough that I opened up the code to see if maybe I was doing something wrong. My investigation lead to the cause of the problem: Apple had messed up again.

Here is what seems to be happening, based on this really popular question at Stack Overflow: Apple is servicing POST requests from its cache rather than sending them to the server if no cache-control header is included and the request data is unchanged. It appears to be a bug. The AJAX call the bookmark browser makes to the server uses the same parameters each time: username, password and key. So the browser was basically not making the call to the server, and my post-request code was executing as if it had.

The solution was to set the ‘cache-control’ header in the POST to ‘no-cache’. It seems to have solved the problem. The good news is an official fix is supposed to be in the up-and-coming iOS 6.1. It seems like version 6 is on track to be the most problematic iOS release yet.


As I was putting the final touches on my Bookmark browser project, I came across this:

That’s delicious, because I strongly suspected Mozilla wasn’t interested in improving Home or fixing any issues with it. Yet another reason I wanted to build a replacement. They have published the iOS Sync client source code that Home was built upon at GitHub. It would be fun to use that code and learn Objective-C while building a new app, but first I need to get a Mac. Maybe next year…

It seems a developer has taken that ball and run with it. He posted a new app in the app store that is essentially the same as Home. I’ll be giving it a try.

Later update
OK, this is lame. He basically took the Firefox Home source code, removed all references to Mozilla, slapped on a new name, and submitted it to the App Store. All the same flaws are there, including the re-arrangement bug that I hate.


This is part 4 in a series of posts about creating a web-based replacement for the Firefox Home iOS app. Part 3 can be found here.

Now that I had an ironclad way of getting bookmark data, I needed to display it and provide a clean method of navigating through it. I looked around the web for a suitable client-side data binding solution, and KnockoutJS seemed like a good way to go. I wasn’t familiar with the MVVM pattern but thought it would be a good learning experience. In a nutshell, the way I understand MVVM is you have a model of your data that is kept strictly separate from the client-side view of it. A view model lives on the client that takes in the data itself and knows where to put it in the UI (admittedly, I may be simplifying or leaving something out).

A quick note about how Firefox organizes bookmarks: it stores them in two high-level containers, the bookmarks toolbar and the bookmarks menu. No big mystery where these are: it’s the built-in toolbar for single-click access to bookmarks, and the Bookmarks menu in the main menu bar at the top of the window.

I set up an unordered list for the bookmarks that looked like this:

I went with the foreach binding in Knockout, since it made the most sense for what I was doing. I briefly tried the template binding but it turned out to be more involved than necessary. I initially tried to have a single unordered list that held everything, including the dividers for toolbar bookmarks and menu bookmarks. But I had a hard time changing the theme for the divider items on the fly, which I wanted to be a different color. Knockout lets you define binding event handlers, like this one:

Here I’m basically setting attributes on the elements in each list item based on whether it’s a directory or an actual bookmark. I tried modifying the data-theme attribute used by JQM to indicate a list divider, but the change never seemed to get applied. Fortunately Knockout lets you apply the binding logic to a subset of items in a ul via containerless control flow syntax. There was some duplication of markup, but not enough to worry about.

The various samples at and the web at large had two different ways of setting up the view model: as a JavaScript variable or a function. I went the function route since I needed to do a bit of data manipulation before assigning the bookmark data. Knockout has the capability of updating the UI automatically when the bound data changes, such as in response to a user clicking on something. That sort of fit my usage pattern, though I would be updating the data via code. The mechanism Knockout uses is observables, and you simply declare them in your view model. Mine looked like this:

The initial state of the app would always be to show everything in the bookmarks toolbar followed by everything in the bookmarks menu, which matches how Firefox Home shows things. I set up two observable arrays holding each of those sets. The trickiest part was how to go about updating that data when the user wanted to navigate into a directory. The rule in Knockout is you only apply the bindings once, then let the framework update the UI for you when things change. And since references to the two observable arrays will be maintained by the framework, I would need to replace their contents rather than assign completely new arrays.

Several failed attempts ensued. I tried using the removeAll() method that is available on observable arrays, then the push() method which is also available on observable arrays but is slightly different than the native JavaScript one (it turns out to only take single elements rather than an array of elements). I finally found the best way to do it via a blog post from Ryan Niemeyer, who totally has the title of Knockout expert locked up.

So the setBookmarks() function in my view model allows me to update the bound data at any time. I wrote the following function to handle the navigation when the user selected a directory rather than an actual bookmark:

The bookmark data itself was an object that contained a list of directories and bookmarks. Each directory had a list of subdirectories and bookmarks, while bookmarks had just a name and URL. The list was stored as an array on the client, so it was just a matter of finding the right one to use in my Knockout view model. The idea in doNavigation() was to take the path to the node the user just pressed and get the bookmark items assigned to it, or if Back was pressed get the bookmark items for its parent.

Each time the user selected a bookmark a new page would be opened, and if they selected a directory I needed to bind to the proper array in my main data object. I wrote the following function to search that object to find the exact items to display:

Putting it all together gave me a reasonable imitation of the navigation in Firefox Home. The speed of the navigation wasn’t too bad, though I have an idea of how I might improve it (Update: the ‘idea’ was a CSS rule to reduce the animation duration. It didn’t work, but I suspect it might be because my rule is incomplete). I’d like to get as close to native app response time as possible. The full source is posted at GitHub.

I feel I have a fairly good grasp on jQuery Mobile now. It would be interesting to try to incorporate PhoneGap into the project and see how it works.


This is part 3 in a series of posts about creating a web-based replacement for the Firefox Home iOS app. Part 2 can be found here.

What I wanted to do next was write enough code to save Sync settings and load bookmarks, log out as the current Sync user and wipe out the locally stored bookmarks and credentials in the process, and refresh bookmark data, all without any problems of any kind. Basically everything the user could do on the settings page. I planned to do as much work on the client as possible, since that is where the bookmark data would be stored. When the user saved new credentials I wanted them to be directed to the bookmark page, and if they were simply refreshing they would stay on the settings page but would see an updated count of their bookmarks.

The biggest issue was doing the form submissions and getting the UI to behave accordingly, including when an error occurred on the server. What was tricky was the fact that to get bookmark data from the Sync servers I made an Ajax call to a server-side function, and JQM relies mainly on Ajax calls to do its thing. That coupled with the fact that my Ajax call was non-blocking made the UI flow have a bunch of niggling problems. Mostly it wouldn’t show the right things at the right time.

The best way I found to make it all work correctly was to disable the JQM Ajax handling of the button clicks. I added data-ajax=”false” to the form element, then canceled the posting to the server and did everything manually. Essentially I took JQM out of the equation. In keeping with the credo of the framework that you work with pure HTML elements and not server-based ones, I replaced the asp:Button controls with input elements and made the form element a regular client element, like so:

The Save onclick handler looked like this:

It called this common function for getting bookmark data:

I added a handler for the jQuery ajaxCompleted event and used that to handle the post-retrieval stuff, like hiding the input controls or updating the bookmark count.

At this point I tried everything out in Electric Plum to get an idea of how it might look on an actual iPhone. It was fairly good, only a couple of cosmetic issue came up that might not even be issues on a real phone.

Next, listviews and data binding.


This is part 2 in a series of posts about creating a web-based replacement for the Firefox Home iOS app. Part 1 can be found here.

I set up my bookmark browser web app project and started reading through the excellent jQuery mobile site. I planned to have a home page, a page for settings, an About page, and one to show the actual bookmarks. So I created separate .aspx pages, each set to use a single master page, and added a page template to each one. The master page had a link to a CSS file I created and links to all the jQuery mobile scripts hosted at It also had a single JQM header and footer since I didn’t want to have to duplicate markup over several pages. I put in a few text boxes on the settings page and added a button for saving Sync credentials to local storage. I made it so when your credentials were saved, it would hide the input controls via Javascript and show a button for refreshing the data.

When I ran it and tried out the navigation, things were not working as expected. The page state wasn’t being saved when I would browse from the settings page to the home page and back, meaning my hiding and showing of elements was failing. I had put links to each page in the main footer, and they would take you to the respective page, but old content was being shown. I was adjusting styles between each build, and those changes weren’t being reflected properly. In short, it was a mess.

After more reading through the JQM site, I realized I was going to have to change my approach. Probably the most unique thing about JQM is the navigation paradigm. It’s very different from what I was used to. Each time it needs to access content, it will make an AJAX call behind the scenes and insert that content into the DOM. There are ‘transitions’ between pages, but they are not pages in the sense of separate files in your project. They can be, but everything ends up in one big container anyway.

I ended up using multi-page templates, all housed in default.aspx. I ditched my master page and set up separate div elements for each page. I had to duplicate the header and footer markup, which I’m not thrilled about, but it isn’t much and I might find a better solution in the future. I experimented with using true single-page templates, but they just didn’t work how I wanted, whereas in the multi-page scenario everything flowed as I expected. DOM size wasn’t too much of a concern because apart from the page for bookmarks, the other pages have little markup in them. It may be possible to incorporate a master page into the JQM navigation model, but I’d rather press on with the actual functionality.

Next, how to handle transitions to the current page, and others in the DOM.