Closing popovers in Ratchet

Ratchet is a css/js library for prototyping iOS apps. Maintained by Twitter, it looks similar to its more established older brother Bootstrap but is much less mature and has an anemic API.

Simple things like closing its popovers don’t seem to exist. If you need to do this, digging into the source reveals

element.addEventListener('touchend', function () {  
      popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
      popover.classList.remove('visible');
      popover.parentNode.removeChild(backdrop);
});

for the popover backdrop, so doing something like

var backdrop = document.querySelector('div.backdrop');  
if (backdrop) {  
  // sad there's not real way to close this
  // https://github.com/twbs/ratchet/issues/625
  var evt = document.createEvent('TouchEvent');
  evt.initUIEvent('touchend', true, true);
  evt.target = backdrop;
  backdrop.dispatchEvent(evt);
}

to dispatch the touch event was sufficient for my purposes.

See https://github.com/twbs/ratchet/issues/625 for a short discussion on this.

Uncaught Error: DATA_CLONE_ERR: DOM Exception 25

If you’re using IndexedDB in Chrome and getting this exception, AND you’re not using web workers like this StackOverflow question, you might have members of type Functions on the object you’re saving.

See MDN’s article on structured clones for more info on what’s allowed. Also worth noting are that prototype chains and property features are not cloned.

Hope this helps 🙂

Browser storage options, specifically Cordova, Android + iOS

Specifically cordova, Android + iOS

Interesting alternatives:

getBBox returns a 0 sized rect

TL;DR: Your svg has to be visible for getBBox to be useful

While working with d3 recently, I was trying to calculate the width of some elements using getBBox , except it kept returning a 0-sized rect.

It turned out that the svg was being rendered when its parent <div> was not visible. Calling getBBox when the svg is visible gives the right results.

Apparently webkit used to some have issues with this but was patched a long time ago.

Hope this helps.

Hands on with Ionic, part 1

I’ve been playing with a nifty framework called Ionic recently. Ionic is a framework for developing hybrid apps that is tied to AngularJS. Since I’d previously worked with AngularJS it seemed right up my alley.

I’m going to walk through building an app using the framework. In particular, I’m going to build an application called BGG Scanner that will look up Board Games on Board Game Geek based on a barcode scan. Through this, we’ll cover getting started, using libraries, native device features and testing. More on this later, but first, what is it I’m actually talking about.

It’s going to take a few posts, so this will be a brief introduction and making sure you’ve got things set up before going any further. In this post we’re going to:

  • Introduce Ionic and Angular
  • Make sure you can run the emulator
  • Introduce our board game problem

.. so we’re all set up for part 2!

What is Ionic?

Ionic is like Bootstrap for hybrid apps – it has CSS styles and elements that mimic native mobile platform elements, as well as javascript components specifically for use in Angular applications. Most of its javascript components deal with UI elements, such as modals, tabs and loading screens, but it also has utilities such as gesture detection and history management.

Here’s a kitchen sink example:

See the Pen winLd by Steven Iseki (@StevenIseki) on CodePen.

Ionic uses Cordova for native support, giving it access to the plethora of Cordova/Phonegap plugins. The same folks behind Ionic, Drifty, also have a project called ngCordova that exposes a number of popular Cordova plugins as Angular components.

You can find a more detailed introduction over at the Ionic framework website.

What is Angular?

If you build web applications, you’ve probably already heard of AngularJS. AngularJS is a framework for building single-page web applications. It seems heavily inspired by Spring and JSP-style webapps as it makes use of dependency-injection and an MVC-like architecture involving routes, controllers and views.

Here’s a set of route declarations, which include the mapping between views, routes and controllers.

The views are HTML templates (hence templateUrl), and are tied together with controllers by a $scope object. Any properties available on the scope object are available in the view through the use of {{}} interpolations.

Unlike JSPs, the views cannot directly include code blocks <% %> style, but you can write your own equivalent of custom tag libraries.

Controllers in turn do much of the heavy lifting for each view. They get their dependencies injected at run time, dependencies being Angular constructs such as factories, services, constants and so on. The $scope object is injected in this fashion. It’s very spring-ish and provides similar testability benefits.

and altogether now:

See the Pen xbENeR by Min’an (@mtan) on CodePen.

There’s tons more that Angular provides, including crown jewels like two-way binding. I started off with Angular after watching an hour-long video introducing various Angular constructs.

If you prefer a just-let-me-code approach, the Angular project also has a step-by-step tutorial available that covers not only the basics but how to test each step along the way. They’ve recently added a codeschool course that I haven’t tried but looks pretty cool.

Ionic and Angular, sitting in a tree

Ionic provides a number of UI components through Angular constructs. In JSP parlance, it not only includes custom tag libraries, but also components that can be dependency injected.

Note the presence of the status bar and back button, as well as the larger, mobile friendly buttons below:

See the Pen MYjRGX by Min’an (@mtan) on CodePen.

If we compare the Ionic example with the barebones Angular example we had earlier, we see a number of differences.

  • Controllers look almost the same, except when mapping out routes Ionic doesn’t use $routeProvider but uses something else called $stateProvider. It’s because Ionic uses the more UI-router which allows for more flexible routing rules. That said, the syntax is mostly similar.
  • Ionic introduces custom elements like <ion-nav-view> and <ion-content>. These elements provide the default mobile-themed styling as well as additional javascript behaviour. If you are interested in how this is done in Angular, check out its custom directives

Apart from that, it looks pretty similar and you get mobile-themed styling for free.

Actually getting started

Diego Netto has provided a yeoman generator for ionic that does a number of things out of the box. Yeoman is a scaffolding tool for setting up projects and boilerplate code. Different yeoman generators are available for different projects. I’ll go into some of the cool things the ionic generator does as we cover testing, but for now, let’s get started!

Prerequisites

To test locally:

To actually create an app,

If you’re using Android, you’ll also need to set an ANDROID_HOME env var to point to where the SDK is installed

I’ll also assume you have Chrome to help with mobile device previews and Safari if you’re doing iOS.

I’m using

npm -v 1.4.23  
node -v 0.10.31  
ionic -v 1.2.13  
cordova -v 3.6.3-0.2.13  
yo -v 1.3.3  
npm list -g ionic-generator 0.6.1  

Once you’ve got them installed, let’s dive in

Creating an ionic project

mkdir bgg-scanner  
yo ionic:app bgg-scanner  

You’ll end up with a project structure like so:

├── Gruntfile.js            - Configuration of all Grunt tasks
├── package.json            - Dev dependencies and required Cordova plugins
├── bower.json              - Lists front-end dependencies
├── config.xml              - Global Cordova configuration
├── .gitignore              - Best practices for checking in Cordova apps
├── resources/              - Scaffolded placeholder Icons and Splashscreens
│   ├── ios/
│   ├── android/
├── app/
│   ├── index.html          - Main Ionic app entry point
│   ├── lib/                - Libraries managed by Bower
│   ├── scripts/            - Custom AngularJS Scripts
│   ├── styles/             - Stylesheets
│   ├── templates/          - HTML views
├── platforms/              - Targeted operating systems
├── plugins/                - Native plugins
├── hooks/                  - Cordova lifecycle hooks
├── merges/                 - Platform specific overrides
├── coverage/               - Istanbul reports
├── test/                   - Unit tests
│   ├── spec/
├── www/                    - Copied from app/ to be used by Cordova 

Most things you’ll need to touch will be in the app subfolder. For now, let’s check out how our app looks.

grunt serve  

which will open a browser with your spanking new app. You can then use something like Chrome’s developer tools to preview mobile browsers.

Seeing it on an actual device

Let’s see how it looks like on a native platform. You’ll first have to add an appropriate platform to the project:

grunt platform:add:ios  

and then

grunt emulate:ios  

Replacing ios with android if needed.

If you leave off the platform, e.g. grunt emulate, it will emulate all the platforms you have added.

If you have a device, you can run the app directly using

grunt run  

You will need the npm module ios-deploy to to do direct deploys on iOS devices. npm install -g ios-deploy will do the trick.

That said, the ios emulator is pretty snappy and should be sufficient for most cases (and quicker!)

If you want to distribute archives for installation, you will need to build them first. To build an apk for Android

grunt build:android  

and you will find it in platforms/android/ant-build

If you want to build an archive for iOS, it’s a little more complicated. You’ll still have to do

grunt build:ios  

which will create an Xcode project in platforms/ios. You can then open it in Xcode, from which you can create archives or make use of iTunes Connect for distribution.

A really cool feature of Ionic is its live reload capability. If you add --livereload to your emulate command, i.e.

grunt emulate --livereload  

It will run emulators with the app for all project platforms AND reload them when a change is detected. Now that we’ve got that out of the way, let’s get started!

Our problem

We don't often shop for board games...but when we do we buy the whole shop

Ok, not the whole shop, but it’s a tiresome affair. We usually walk into game stores with hundreds of games, and it’s not obvious which ones will be good. We want a way to pick up a game and tell if it’s worth getting there and then.

The usual solution to this is to search on Board Game Geek. Smartphones have come a long way but it’s still no walk in the park to enter in a dozen or so titles and pore through a mobile-unfriendly site to get the information you want.

A solution

Let’s scan barcodes instead. We can obtain information from BGG and Amazon – BGG to figure out how good the game is, and Amazon to figure out if the price is reasonable.

BGG Scanner mockup - scan, lookup and display info

After I showed something working to Marty things got more complicated but we’ll get to that 😉

In the next part we’ll sketch out how this might work and start making some actual mockups using Ionic.

Parents and the Karate Kid

Initial thoughts after browsing through the React docs –

AngularJS is like your parents, complicated relationship but can get the heavy lifting stuff done for you quickly. It can also have some performance issues because it’s trying to look out for things you don’t care for.

React is like a young karate kid. Capable of great things and performance but needs lots of training. Expensive upfront because you need to think through your models more.

To be fair I’ve used AngularJS alot more, but React is looking pretty interesting!

The Curse of Knowledge

Try this. Pick a tune in your head, something most people would easily recognise. Find someone and tap the tune out. Tap, not hum. See if they get it.

How annoyed or frustrated do you get if they can’t get something that seems so obvious to you? I am somewhat ashamed that I wasn’t able to recognise “Happy Birthday” when Marty tried it on me, though it did prove a point.

When you know something, and you know it well, it’s hard to imagine how someone else could possible not know about it. Until we develop ET-like powers of psychic connection, most experiential or knowledge exchange is carried out under context deficient conditions and restricted by language. Remember the mythical swing?

This is hardly an insight. What is perhaps less stated is its censorship effects. One of the common reasons I abandon an idea or poject is because it seems so obvious that I feel embarassed to mention it, or even write a whole article about it. Especially since someone could easily reach the same level of understanding if they spent enough time googling for it.

I think this self-censorship robs us twofold. It robs us of an opportunity to synthesise and refine our thoughts in writing, but also robs the rest of the world of your insight that may not be all that obvious to them.

One of the most visited pages on this blog is about an Android related build system problem. This is despite there existing a stackoverflow post about it that’s shorter and more concise. There is value in your unique synthesis and contextual insight.

So stop crossing out those ideas for projects and articles. It could even be about something as mundane as fried rice. 🙂

Fried Rice, Very Nice

Yesterday I cooked fried rice. It was probably the best fried rice I’ve cooked ever, and I’ve cooked a few.

I’ve never had any real education where cooking is concerned; when I was growing up in Singapore, my family had a domestic servant (read: maid) who did all the cooking, cleaning and washing. All the way up until I left Singapore for Uni in Sydney, I never had to cook.

Consequently, any cooking I did was very much the way I was brought up; by the book. Even today, my approach to cooking usually goes like this:

  • Find a recipe online
  • Measure out each of the ingredients in the recipe
  • Follow the recipe to the letter

As you can imagine, this didn’t always result in a dish that resembled the recipe, or tasted the way I had imagined it to be. Often things like “until fragrant”, “until cooked through”, or something which didn’t have a precise time or visual measurement associated with it didn’t work too well.

Yesterday was different. I still looked up a receipe, but not only did I have totally different ingredients for the recipe, I didn’t actually measure them out. Instead I just mixed stuff in and tasted as I went along.

Some years back, there was a popular sitcom on Singaporean TV called Under one roof, about a Singaporean family. In one of the episodes, the mother is trying to teach her daughter how to cook. She used phrases like “just put some oil”, or “add a bit of salt”, much to the chagrin of her scientific-method oriented daughter. The daughter then started measuring how much oil acutally corresponded to “some oil” and how much salt was “a bit of salt”, and found incredible consistency between trials attempted by her mother.

I think well-practised cooks get the same measurements and dosages consistently. Good cooks taste as they go and know how to adapt to different states of a dish. Better cooks have a wider range of ingredients to play with when adapting a dish, and the best cooks are consistent through practice, have a wide range of ingredients at their disposal, and efficiently execute quickly. Consqeuently, they are able to handle much more complicated dishes in the comparable amount of time as the average cook.

You can probably see where this is going. I think well-practised software developers produce consistent, familiar code. Good developers iterate quickly and adapt to customer feedback. Better developers have various techniques to use when adapting to change, and the best developers can do this in a much shorter period of time. Consequently, they are able to handle larger, more complicated projects than the average developer.

I got a glimpse of being a good cook yesterday, but my only tools are salt, pepper, soya sauce and oyster sauce. I certainly cannot produce consistently and am some ways away from amassing a reasonable body of knowledge to adapt to different states of a dish. Soya sauce, salt, pepper, oyster sauce, fish sauce and seasame oil are still the best cooking friends I have. But I’m getting there.

Still a long way to go, where software and cooking are concerned, but here’s a picture for posterity.

It also helps if you add a liberal dose of oil 🙂