Development notes: HTML5-based mobile app

A few months ago the company I work for released, a search experienced tailored for tablet use. After the tablet version’s successful release I had the good fortune to be asked to create the mobile phone experience.

As a web developer accustomed to using server side templates and “traditional” web development (i.e. web MVC frameworks), this was my first foray into building a pure JavaScript single-page app. It turned out to be a long a hard-earned learning experience.

Luckily, the JavaScript web app development space has been exploding for the past few years. I think the rise of smartphones and native apps have been particularly powerful in driving the development of client-side web apps because users have come to expect more app-like experience. IMO it’s difficult to produce that feel with traditional web page-based navigation because of load times and page refreshes.

The project

It took an embarrassing amount of time to make the phone portion of the app — almost 5 months. I started work on the first prototype (first of three) in the middle of January 2013 and the app has just been released to iTunes and Google Play as of mid-June 2013. I would attribute about 6 weeks of throwaway work, 8 weeks full-time product development and another 6 weeks of part-time development for handling scope creep, bugs fixes, and native integration.

Prototype 1

The first prototype was difficult. We wanted to have a “card-like” experience where you would do a search and your results would be a series of decks of cards. Each category was a deck and each search result was a card. On your search you would see a single result (the top card of the first category). You would then swipe horizontally to change categories or vertically to see cards below.

Prototype 1

Prototype 1

The first prototype probably took almost 1 month to build and when I was done with it, it sucked. People didn’t really understand how to use it and the in-office response was luke warm. Problem was, it had no resemblance to the tablet app. The user experience wasn’t cohesive in tablet vs phone. We scrapped the whole thing. Looking back, we probably should have done more Photoshop prototyping for that one.

It sucked from a code perspective as well. I was working off a copy of existing code from the tablet version. The tablet  code itself was fine but I was trying to jerry-rig Backbone.js into the existing code because I wanted to learn Backbone. The result was a pile of puke.

Additionally, CSS animations became the bane of my existence.  I had no idea how hard it would be to coerce a web page into behaving similar to a native mobile app through CSS animations. CSS animations are a real brain drain and I still don’t fully understand how to use them. It’s still difficult and a hat-tip to the guy at forecast.io who appears to have a very good understanding of touch-handling and CSS transforms.

Prototype 2

After the luke warm response from Prototype 1 we went back to the drawing board and aimed for something that looked more like the tablet. The first iteration took maybe 2 days to slap together in a very basic way. We liked the results and moved forward.

izik_proto2

Prototype 2

Marionette re-write

After suffering through trying to jam Backbone into some existing JavaScript I came to the realization that, although the system was working it would be increasingly difficult to add new features. I was running into problems with my scattered code base and I really wanted to create nested views for my Backbone app but I couldn’t devise a reasonable way to manage subviews — Marionette stepped in to save the day.  Marionette provided the framework I needed to reasonably manage nested views without killing myself. It took a couple days of looking at Marionette tutorials until it finally clicked. Once I understood the framework I decided that the only reasonable thing for me to do would be a complete code rewrite. I threw out about 85% of the old code and started my Marionette app fresh. The few pieces I kept were a Backbone view that I knew would integrate well with Marionette and some convenience functions from the tablet code. After one full week of intense Marionette action I had full blow web app. Thankfully the time horizons for product were pretty loose while I was working on this app, it gave me a lot of time to learn some pretty important fundamentals to a client side MVC.

After the Marionette re-write everything fell in place afterwards. We did a few user testing sessions with people at Starbucks and around town. We got a lot of good honest feedback that changed the app UI considerably. We tacked on Local search, maps, news, and a bunch of other goodies.

iOS and Android Wrappers

To get a truly native feel on the tablet we had hired contractors to make us a native wrapper that would allow the app to slide in new windows and share pages via social media. They also did the phone version of the native wrapper. Let it be known that the browsers within a wrapper report all kinds of different numbers with regard to viewport size and ability to scroll smoothly. It took a while to nail the bugs but I think we got the app into a state where it looks pretty consistent across Web-iOS-Android.

Tools & Frameworks Used:

Easy build script

With the help of some of our superstar build engineers at the company I had an auto-compiling script that would roll up all of the assets into one huge file that included HTML, CSS, JS, and even images (base64-encoded).  All of the minified assets cram into about 600kB minified = 175kB gzipped. After the initial startup all network I/O is related to API calls and images. Pretty cool! The benefits of this build system can be similarly achieved with the bootstrap tools that I identified in a previous article.

jQuery Mobile: a minor mis-step

I initially used jQuery Mobile to organize my HTML into pages and use its CSS+animation routines to mimic smartphone styling. However, as the prototype grew and matured jQuery Mobile didn’t quite fit the needs of this project. jQuery Mobile didn’t fit for these reasons:

  • The goal was to support some pretty low-end Android devices I had to ditch the nice sliding animations.
  • I ended up styling 90% of the app with my own styles because we didn’t want to look too iPhone-y in the Android experience. (The app still has remnants of the iOS styling)
  • Given that I’m probably using about 10% of the library’s features it may not warrant its size of 140kB minimized + image sprites. Granted, I could use its package builder tool but then I’d have to figure out each feature that I’m using and test & test. blah.

Assuming I had more time I feel like I should have built something myself to copy the features that I’m using. The app looks and functions differently from the standard jQuery Mobile experience.

Alternatives to jQuery Mobile: I considered using jQT (formerly jQuery  Touch) for its animations but it seems like the project has gone stale and development and maintenance trailed off. Besides that, I couldn’t really figure out how to use it. Ratchet looks really sexy but it falls into the same problem as jQuery Mobile in that it looks too much like iOS.

Backbone.js + Marionette

I wrote a previous post a while ago about using Marionette & Backbone to lay the foundation for the Web App. All in all I am very satisfied with the combination and feel compelled to do another project with these libraries/frameworks.

Somebody left me a Facebook comment asking why I chose Marionette over the other popular JS frameworks like Angular or Ember.  In a nutshell, I chose Marionette because I already learned a little bit about Backbone and Marionette solved a lot of the problems I had with Backbone.

SwipeView + iScroll 4

SwipeView and iScroll 4 were essential in the app’s development. Although these libraries took some time for me to understand and wrestle with a few bugs the result is quite smooth. The code is easy-to-read so I was able to fix & tailor it to my needs readily. I donated $10 euros to thank the author of these libraries because there is no way I would have figured out any of this stuff so elegantly.

CoffeeScript

CoffeeScript made JavaScript feel more like Python which was fantastic for me. It took a while to get used to the lack of curly braces and semi-colons but once I figured out the CoffeeScript syntax everything has been smooth. It has been difficult writing vanilla JavaScript lately because of my numerous syntax errors.

Jade template language

Jade javascript templates have a kind of peculiar whitespace-dependent syntax but turns out to be pretty good. I guess it’s HAML for node? I like that I can use vanilla JS within the templates without much hassle. I find that the Jade templates are much easier to write than underscore.js templates (which are pretty difficult to write) or handlebars.js templates. Handlebars has kind of a quirky syntax and I like that when using Jade I don’t have to worry about balancing my HTML tags.

Stylus CSS

Not much to say about Stylus. It’s like LESS or SASS and gets installed through npm packages.

Get Izik for your smartphone today!

Izik for iOS (Universal app)

Izik for Android (Universal app)

Toolkits to bootstrap a basic mobile prototype

I’m embarking a building out a new iOS HTML5 prototype.

Libraries:

PhoneGap 2.7.0

Ratchet HTML/CSS bootstrap for mobile app prototypes. Made by the guys that created Twitter Bootstrap. (Man, they are good at this CSS stuff.)

Junior HTML mobile app framework? (uses Ratchet extensively). Using Junior may not be worthwhile since it requires Zepto. I may choose to use Backbone Marionette which requires jQuery.

Framer Quick way to create click prototypes from Photoshop.

Coding it up:

(Backbone) Building HTML5 Apps with Yeoman and Backbone

(Angularjs) Egghead.io Angular Video Series

Video: Addy Osmani shows how to use Yeoman to create an AngularJS app.

Google Universal Analytics happy and sad

Google recently release Universal Analytics. It requires some code changes but I think the new developer interface is going to be quite a bit more usable.

https://developers.google.com/analytics/devguides/collection/analyticsjs/

Happy

New API – The best change I see (in the first 10 minutes of looking) is the change from flat arrays to dictionary/hash/associative arrays for configuring options. Event tracking code just got much easier to follow. Cool!

Callbacks – Now can have better knowledge when tracking has completed its execution. I’m sure that lots of data got lost when trying to trigger custom events on form submission.

Variables/Namespaces -I do not have to rely on the mysterious _gaq variable. You can now name your own Analytics variable. I probably wasn’t ever going to create my own _gaq var.

User Timing – it appears that Universal Analytics has some features for tracking the time it takes for pages to load. Rather than diving into my own logs, Analytics will profile performance for me? Excelente!

Sad

I may have to re-code some significant stuff that uses the old Google Analytics.

undefined is not a function when Dynamically loading Google Maps API v3

Long story short: Don’t be fancy when you dynamically inject your Google API script call into the DOM. Inject it to the BODY of your document using plain javascript.

I was struggling mightily with getting the Google Maps API to load on-demand today for my wife’s old Android 2.1.x device. The maps worked on every other conceivable device. Everything would load but mysteriously the maps would never load. I looked at it a long time but it’s really tough to debug older Android browsers because I can only look at the console output through the terminal using adb.

Every time the map tried to load I would get this message in the adb terminal.

Console: TypeError: Result of expression 'n.google.maps.Load' [undefined] is not a function. http://maps.gstatic.com/cat_js/intl/en_us/mapfiles/api-3/12/8a/%7Bmain,places%7D.js:42

I was trying to inject the Google script into the HEAD portion of DOM using jQuery. THIS DID NOT WORK!

script = document.createElement("SCRIPT")
script.src = "http://maps.googleapis.com/maps/api/js?key=#{APIKEY}&libraries=places&sensor=true&callback=#{callback}"
script.type = "text/javascript"
script.id = "googlemapscript"
$("head").append(script) // < -- this will NOT WORK!!!
document.body.appendChild(script) // <-- use regular injection to fix your Woes!

My boilerplate setup for WordPress

When setting up a WordPress site, these are the first plugins that I install on every project.

  • Google Analyticator
  • Google XML sitemaps – for SEO
  • Social (by MailChimp) – to cross post into Twitter & Facebook
  • Google Adsense PLugin (by BestWebSoft)

Lately as my WordPress needs have grown I am finding these plugins to be more and more useful

  • Posts 2 Posts – many-to-many relationship for WP. 
  • RSS Multi importer
  • Comprehensive Google Map plugin
  • Related posts (by Zemanta)

Reference

WordPress vs Django for content prototype

Smashing Magazine has an article on how to create a custom post type in WordPress.

I was considering building out a content website with Django+Mezzanine but I think it will be much more cost effective if I can get away with a custom post type on WordPress.

I would much prefer to use Python + Django but the time and costs are prohibitive and it would only make sense if I were going to go heavy-duty on with the relational databases. Optimistically with my beginner to mid-level experience it would take 5-6 hours to set up a proper Django server. Here’s what I would have to do to create a Django based system:

  • get a VPS ($15/month)
  • Install all necessary Python + Django packages [1 hour to for virtualenvs & finding all dependencies]
  • setup nginx/apache with proper proxies etc [2 hours because I haven’t set this up in a while]
  • install & configure Postgres database [2 hours because Postgres is always messed up]
  • remain open to all kinds of security flaws since I don’t know how to lock down firewalls and other VPS stuff.
  • Now I can start development.

With WordPress I can (hopefully) build my plugins and have everything hosted by standard webhosts that are much more affordable. WordPress plugin on the other hand

  • pick a cheap shared webhost [$5/month]
  • install WordPress through cPanel->Fanstastico [10 minutes]
  • Find & install 5-6 plugins in my personal “boilerplate” [1 hour with WP plugin system]
  • start my own plugin development

Obviously these two systems are not an apples-to-apples comparison. A shared webhost WP site could probably only handle a small fraction of the traffic that even a half-assed Django setup would be able to handle. And, if traffic started to grow you could get kicked off that shared webhost (this has happened to me). Plus, your site would never survive a slashdot (reddit) tidal wave.

But at the end of the day I just need a CMS on which I can add some basic bells and whistles. WordPress will satisfy that need cheaply and easily for 95% of my purposes.

jQuery Deferred

The jQuery concept of Deferred objects feels a bit more complicated than what I used to do with MochiKit‘s Async library. It could simply be the naming conventions that jQuery has chosen.

Deferred asynchronous calls can be used for more than AJAX!

Most of the jQuery examples is that the authors choose AJAX-based calls for examples on how the Deferred objects work. Rather than doing a series of setInterval and setTimeout things to check for animations to be completed or animations to finish I can use Deferred calls to reliably tell me that the variables that I want are ready to rock and roll.

Best tutorials so far

Deferred is kind of hard to explain but this is the simplest way I can try:

  • You instantiate a Deferred object in a function that you want to be asynchronous. (AJAX calls are Deferred but not all Deferred are AJAX)
  • a [promise()] allows other variables & functions subscribe to notifications that Deferred is done or failed
  • Deferred.resolve() tells all subscribers of the Deferred that the Deferred is done executing
  • Functions passed into Deferred.done() will be executed if

In various parts of your code you can allow other variables to wait for an outcome Deferred

doSomethingWhenDeferredIsDoneDoingWhatItNeedsToDo = d.promise()

Notes from first project using Backbone Marionette

I really enjoy using Backbone.Marionette.

I was recently tasked with a pretty exciting opportunity at work: build a cross platform mobile web app. This project has been (still is) incredibly challenging for me because I’ve never built anything like this before. It’s probably the most complex JavaScript I’ve ever written and I was able to build a reasonably decent app from the ground up thanks to a few technologies and frameworks that made my life infinitely easier:

  • Backbone.js framework
  • Backbone.Marionette framework
  • Jade javascript templates
  • (Iced) CoffeeScript
  • Stylus CSS
  • jQuery Mobile
  • jQuery + underscore (prereqs anyway)
  • Mobile Boiler Plate
  • Modernizr
  • cdnjs (This has almost all of the above libraries on a CDN! Free! Magnificent.)
  • a handful of utilities (makefiles, etc.) that our build engineer created in-house to package things up real nicely.

Figuring out how to use Backbone and Marionette took a long time for me to grasp but now that I’m comfortable using them I feel like I have the tools and skills necessary to build some cool stuff in the future. Maybe not GMail in complexity nor 8-bit Nintendo Emulator coolness but give me an API and some time, I’ll be able to whip up something that could be pretty neat.

 

Important Resources that helped me understand Marionette

These tutorials and code samples helped me the most when trying to pick up a new framework. I don’t watch a lot of screencasts because they tend to be really slow and I can’t copy-paste the code samples.

Tutorial: a full Backbone.Marionette application – is the first tutorial that I found that actually helped me wrap my head around Marionette. The code is easy to read and well explained. Downside — the structure and style are slightly different from the patterns that Derrick Bailey, creator of Marionette,  uses in his examples. The tutorial is slightly old and does not take advantage of newer features that have been added to Marionette (for instance, AMD-style loading). Nevertheless, this tutorial is what got me used to the basic elements of Marionette. Mr. Bailey’s blogs regarding Marionette are well written but they only started to make sense after 1-2 days of staring at this tutorial first.

Addy Osmani’s TodoMVC implemented in Marionette – A useful example of how to use Marionette but I find the JavaScript AMD code extremely hard to follow because all the code is spread around in different files. The order in which the various modules get included on the page matter.

Stack Overflow questions answered by Derrick Bailey – Back to Mr. Bailey… he is active/proactive in Stack Overflow and he often provides insightful answers and comments to many of the questions about backbone.marionette. It will benefit you to look beyond the big green check “Accepted Answer” blocks to seek out Mr. Bailey’s comments in any S.O. thread.

Backbone Marionette Docs in Github – the documentation is extensive and well written. The problem is that there are so many modules available to use it’s hard to know where to get started. In my first non-trivial Marionette app I only used half of the modules in my code (some of the modules are base classes but I didn’t specifically call them). The Marionette components that I used:

  • Marionette.ItemView
  • Marionette.CompositeView
  • Marionette.Layout
  • Marionette.Region
  • Marionette.AppRouter
  • Marionette.Application.Module
  • Marionette.Application — just 1 instance but it provides the foundation for everything else.
  • Backbone.View — I was easily able to adapt a View I had written before to work fine with Marionette. It would be possible to break my View into ItemView + CompositeView but not worth the time.
  • Backbone.Model — a building block
  • Backbone.Collection — a building block

I chose the jQuery Mobile (jQM) framework to help me organize my HTML and take advantage of its transitions and animation libraries. With a little bit of planning jQuery Mobile has turned out to compliment Marionette, I did however have to throw out a lot of jQM’s default JavaScript behavior.

My app architecture in a nutshell:

  • Marionette.Application is the starting point, basically a singleton to get things started.
  • My Marionette.Application provides a single point of contact for application-level event handling and tying together all of the component pieces of my various Backbone/Marionette Views and Controllers.

In the jQM paradigm Pages are a fundamental component. Each Page is demarcated by a <div data-role="page">. I have 3 basic jQM Pages. Each layout had a unique layout and imagine the wireframe looks something like below:

  • a start page (id=start)
  • a search page (id=search)
  • and a google map page (id=gmap)
Rough layout

Rough layout

Since I had these 3 pages, it made sense to define each as a Region in Marionette. Although a Region has all kinds of bells and whistles I can get a way with using these top-level Page Regions to only hide/show an individual page.

  • Each jQuery Mobile HTML block corresponds to its own Application.Module to maintain separation for the logic of my various views.
  • jQuery Mobile Page. Each Layout has multiple Region areas within. Notice how I have nested Regions by having Region > Layout > Region(s)
  • I get whatever content I need (in this case AJAX data from an API) whereby Backbone.Collection (i.e. a SQL table) contains many Backbone.Models (i.e. individual table rows)
  • ItemView is a View for individual Backbone.Model objects
  • In this case I use a CompositeView for my Backbone.Collection.
  • As a Collection contains multiple Models, so too does a CompositeView contain multiple ItemViews
  • A “show” call to Application.Region.Layout.SubRegion.show(CollectionCompositeView) will automatically cause the entire collection to render whereby the CompositeView wraps all of the individually rendered ItemView HTML. (think UL>LI*5, or TABLE>TR*5). The rendered aggregate HTML block will then be rendered into the region, replacing anything that was there before (may be override available)

2-way iscroll for tablets and phones

https://github.com/cubiq/2-way-iScroll

The maker of the excellent SwipeView and iScroll 4 library for touch-enabled browsers has a somewhat unpublicized standalone library that has two-axis scrolling. It snaps if you swipe/scroll horizontally across columns (pages) and scrolls smoothly with momentum when you scroll vertically within a column.

Without modification I am able to use the library to create a reasonable snap-to-scroll on both X and Y axes.

The best thing about the library is that it will lock into a single scroll axis as you are scrolling. Beautiful!