time

A great time and place to ask about diversity and inclusion

whiteboard code

There isn’t a single day going by right now where you can’t read a post or see a talk about diversity and inclusiveness in our market. And that’s a great thing. Most complain about the lack of them. And that’s a very bad thing.

It has been proven over and over that diverse teams create better products. Our users are all different and have different needs. If your product team structure reflects that you’re already one up against the competition. You’re also much less likely to build a product for yourself – and we are not our end users.

Let’s assume we are pro-diversity and pro-inclusiveness. And it should be simple for us – we come from a position of strength:

  • We’re expert workers and we get paid well.
  • We are educated and we have companies courting us and looking after our needs once we have been hired.
  • We’re not worried about being able to pay our bills or random people taking our jobs away.

I should say yet, because automation is on the rise and even our jobs can be optimised away sooner or later. Some of us are even working on that.

For now, though, we are in a very unique position of power. There are not enough expert workers to fill the jobs. We have job offers thrown at us and our hiring bonuses, perks and extra offers are reaching ridiculous levels. When you tell someone outside our world about them, you get shocked looks. We’re like the investment bankers and traders of the eighties and we should help to ensure that our image won’t turn into the same they have now.

If we really want to change our little world and become a shining beacon of inclusion, we need not to only talk about it – we should demand it. A large part of the lack of diversity in our market is that it is not part of our hiring practices. The demands to our new hires make it very hard for someone not from a privileged background or with a degree from a university of standing to get into our market. And that makes no sense. The people who can change that is us – the people in the market who tick all the marks.

To help the cause and make the things we demand in blog posts and keynotes happen, we should bring our demands to the table when and where they matter: in job interviews and application processes.

Instead of asking for our hardware, share options and perks like free food and dry cleaning we should ask for the things that really matter:

  • What is the maternity leave process in the company? Can paternity leave be matched? We need to make it impossible for an employer to pick a man over a woman because of this biological reason.
  • Why is a degree part of the job? I have none and had lots of jobs that required one. This seems like an old requirement that just got copied and pasted because of outdated reasons.
  • What is the long term plan the company has for me? We kept getting asked where we see ourselves in five years. This question has become cliché by now. Showing that the company knows what to do with you in the long term shows commitment, and it means you are not a young and gifted person to be burned out and expected to leave in a year.
  • Is there a chance for a 4 day week or flexible work hours? For a young person it is no problem doing an 18 hours shift in an office where all is provided for you. As soon as you have children all kind of other things add to your calendar that can’t me moved.
  • What does this company do to ensure diversity? This might be a bit direct, but it is easy to weed out those that pay lip service.
  • What is the process to move in between departments in this company? As you get older and you stay around for longer, you might want to change career. A change in your life might make that necessary. Is the company supporting this?
  • Is there a way to contribute to hiring and resourcing even when you are not in HR? This could give you the chance to ask the right questions to weed out applicants that are technically impressive but immature or terrible human beings.
  • What is done about accessibility in the internal company systems? I worked for a few companies where internal systems were inaccessible to visually impaired people. Instead of giving them extra materials we should strive for making internal systems available out-of-the-box.
  • What is the policy on moving to other countries or working remotely? Many talented people can not move or don’t want to start a new life somewhere else. And they shouldn’t have to. This is the internet we work on.
  • What do you do to prevent ageism in the company? A lot of companies have an environment that is catering to young developers. Is the beer-pong table really a good message to give?

I’ve added these questions to a repo on GitHub, please feel free to add more questions if you find them.

FWIW, I started where I am working right now because I got good answers to questions like these. My interviews were talking to mixed groups of people telling me their findings as teams and not one very aggressive person asking me to out-code them. It was such a great experience that I started here, and it wasn’t a simple impression. The year I’ve worked here now proved that even in interviewing, diversity very much matters.

Photo Credit: shawncplus

View full post on Christian Heilmann

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

New chapter in the Developer Evangelism handbook: keeping time in presentations

Having analysed a lot of conference talks lately, I found a few things that don’t work when it comes to keeping to the time you have as a speakers. I then analysed what the issues were and what you can do to avoid them and put together a new chapter for the Developer Evangelism Handbook called “Keeping time in presentations“.

Rabbit with watch
White Rabbit by Claire Stevenson

In this pretty extensive chapter, I cover a few topics:

All this information is applicable to conference talks. As this is a handbook, all of it is YMMV, too. But following these guidelines, I always managed to keep on time and feel OK watching some of my old videos without thinking I should have done a less rushed job.

View full post on Christian Heilmann

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Time to get hacking – Introducing Rec Room

It’s no secret that the best frameworks and tools are extracted, not created out of thin air. Since launching Firefox OS, Mozilla has been approached by countless app developers and web developers with a simple question: “How do I make apps for Firefox OS?” The answer: “It’s the web; use existing web technologies.” was—and still is—a good answer.

But if you don’t already have an existing toolchain as a web developer, I’ve been working on extracting something out of the way I’ve been creating web apps at Mozilla that you can use to write your next web app. From project creation to templating to deployment, Mozilla’s Rec Room will help you create awesome web apps in less time with more ease.

Rec Room is a Node.js utility belt you can wear to build client side web apps. It includes:

  • Brick to add components like appbars and buttons to your UI.
  • Ember for your app’s controllers, models, and views.
  • Handlebars to write your app’s templates.
  • Grunt to run the tasks for your app, including building for production.
  • I18n.js to localize your app.
  • Mocha to test your app.
  • Stylus to write your CSS.
  • Yeoman to scaffold new code for your app’s models and templates.

In this post I’ll walk through how to create a simple world clock web app with Rec Room, how to deploy it, and how you can try out Rec Room for yourself.

Where Does Rec Room Come From?

Much of Rec Room came from a recent rewrite of the HTML5 podcast app. I started working on this app well over a year ago, but its original version wasn’t as easy to work on; it had a lot of global state and a lot of by-hand data-binding. I liked the look of Ember for app development, but back when I started it didn’t quite feel mature enough. These days it’s much better, and I’ve tweaked it in Rec Room to work perfectly without a server.

I tried to take the best from that system and extract it into a set of tools and documentation that anyone can use.

Create your own Rec Room app

Rec Room has just recently been extracted from my experiences with Podcasts; it hasn’t been tested by more than a handful of developers. That said: we’d love your help trying to build your own app for Firefox OS using these tools. They integrate well with tools you probably already know and use–like Node.js and Firefox’s own Web IDE.

To get started, install Rec Room using Node.js:

npm install -g recroom

Clock App

We’ll create a simple clock app with (minimal) time zone support for our example. The app will let you have a clock and compare it with a few time zones.

The recroom binary is your entry point to all of the cool things Rec Room can do for you. First, create your app using recroom new world-clock. This creates the basic app structure. To see the basic app skeleton that Rec Room creates we can now enter that directory and run our app: cd world-clock and then type recroom run. The app will open in your default browser.

First, we’ll add the current time to the main tab. Rec Room supports Ember’s MVC app structure, but also offers simple “pages” for a controller without a 1:1 relationship to a model. We’ll generate a new page that will show our actual clock:

recroom generate page Clock

We can edit its template by opening app/templates/clock.hbs. Let’s change clock.hbs to include the variable that will output our local time:

<h2>Local Time: {{localTime}}</h2>

That won’t do much yet, so let’s add that variable to our ClockController, in app/scripts/controllers/clock_controller.js:

WorldClock.ClockController = Ember.ObjectController.extend({
    localTime: new Date().toLocaleTimeString()
});

You can see that any property inside the controller is accessible inside that controller’s template. We define the 1ocalTime property and it gets carried into our template context.

Now our clock app will show the current local time when we navigate to http://localhost:9000/#clock. Of course, it just shows the time it was when the controller was initialized; there is no live updating of the time. We should update the time every second inside the controller:

WorldClock.ClockController = Ember.ObjectController.extend({
    init: function() {
        // Update the time.
        this.updateTime();
 
    // Run other controller setup.
        this._super();
    },
 
    updateTime: function() {
        var _this = this;
 
        // Update the time every second.
        setTimeout(function() {
            _this.set('localTime', new Date().toLocaleTimeString());
            _this.updateTime();
        }, 1000);
    },
 
    localTime: new Date().toLocaleTimeString()
});

Now we can go to our clock URL and see our clock automatically updates every second. This is thanks to Ember’s data-binding between controllers and templates; if we change a value in a controller, model, or view that’s wired up to a template, the template will automatically change that data for us.

Adding Timezones

Next, we want to add a few timezones that the user can add to their own collection of timezones to compare against local time. This will help them schedule their meetings with friends in San Francisco, Buenos Aires, and London.

We can create a timezone model (and accompanying controllers/routes/templates) with the same generate command, but this time we’ll generate a model:

recroom generate model Timezone

We want each timezone we’re to include in our app to have a name and an offset value, so we should add them as model attributes. We use Ember Data for this, inside app/scripts/models/timezone_model.js:

WorldClock.Timezone = DS.Model.extend({
    name: DS.attr('string'),
    offset: DS.attr('number')
});

Next we’ll want a list of all timezones to offer the user. For this we’ll grab a copy of Moment Timezone. It’s an awesome JavaScript library for dealing with dates and times in JavaScript. We’ll install it with bower:

bower install moment-timezone --save

And then add it to our app inside app/index.html:

<!-- build:js(app) scripts/components.js -->
<!-- [Other script tags] -->
<script src="bower_components/moment/moment.js"></script>
<script src="bower_components/moment-timezone/builds/moment-timezone-with-data-2010-2020.js"></script>
<!-- endbuild -->

Adding that tag will automatically add moment-timezone-with-data-2010-2020.js to our built app. We’ll add a tab to the page that lets us edit our timezones, on a different screen than the clocks. To add a tab, we just need to open app/templates/application.hbs and add a tab. While we’re there, we’ll change the main tab from the useless {{#linkTo 'index'}} and point it to {{#linkTo 'clock'}}. The new application.hbs should look like this:

<x-layout>
  <header>
    <x-appbar>
      <h1>{{t app.title}}</h1>
    </x-appbar>
  </header>
  <section>
    {{outlet}}
  </section>
  <footer>
    <x-tabbar>
      <x-tabbar-tab>
        {{#link-to 'clock'}}Clock{{/link-to}}
      </x-tabbar-tab>
      <x-tabbar-tab>
        {{#link-to 'timezones'}}Timezones{{/link-to}}
      </x-tabbar-tab>
    </x-tabbar>
  </footer>
</x-layout>

Side note: notice the root URL points to a useless welcome page? We probably want the default route to be our ClockController, so we can set the index route to redirect to it. Let’s do that now, in app/scripts/routes/application_route.js:

WorldClock.ApplicationRoute = Ember.Route.extend({
    redirect: function() {
        this.transitionTo('clock');
    }
});

Interacting with Timezone models

We’ll keep things simple for our example and allow users to select a timezone from a <select> tag and add it with a button. It will show up in their list of timezones, and they can delete it if they want from there. The clock tab will show all times. First, we’ll add our timezone data from Moment.js into our TimezonesController in app/scripts/controllers/timezones_controller.js. We’re also going to implement two actions: “add” and “remove”. These will be used in our template:

WorldClock.TimezonesController = Ember.ObjectController.extend({
    init: function() {
        var timezones = [];
 
        for (var i in moment.tz._zones) {
          timezones.push({
              name: moment.tz._zones[i].name,
              offset: moment.tz._zones[i].offset[0]
          });
      }
 
      this.set('timezones', timezones);
 
      this._super();
  },
 
  selectedTimezone: null,
 
  actions: {
      add: function() {
          var timezone = this.store.createRecord('timezone', {
              name: this.get('selectedTimezone').name,
              offset: this.get('selectedTimezone').offset
          });
 
          timezone.save();
      },
 
      remove: function(timezone) {
          timezone.destroyRecord();
      }
  }
});

So we create a list of all available timezones with offsets. Then we add methods that allow us to add or remove timezones from our offline data store. Next we modify the timezones template in app/templates/timezones.hbs to use the actions and variables we created. All we need to utilize these variables is the Ember SelectView and the {{action}} helper to call our add and remove methods:

<h2>Add Timezone</h2>
 
<p>{{view Ember.Select content=timezones selection=selectedTimezone
       optionValuePath='content.offset' optionLabelPath='content.name'}}</p>
 
<p><button {{action add}}>Add Timezone</button></p>
 
<h2>My Timezones</h2>
 
<ul>
  {{#each model}}
    <li>{{name}} <button {{action remove this}}>Delete</button></li>
  {{/each}}
</ul>

Now we have a Timezones tab that allows us to add and remove Timezones we want to track. This data persists between app refreshes. The last thing we need to do is show these times relative to our local time in our clock tab. To do this we need to load all the Timezone models in the ClockRoute. They’re automatically loaded in the TimezonesRoute, but it’s easy to add them in the ClockRoute (in app/scripts/routes/clock_route.js):

WorldClock.ClockRoute = Ember.Route.extend({
    model: function() {
        return this.get('store').find('timezone');
    }
});

Because of the way our Ember app is wired up, we load all our models in the route and they are sent to the controller once the data store has asynchonously loaded all of the models. The request to find('timezone') actually returns a Promise object, but Ember’s router handles the Promise resolving for us automatically so we don’t have to manage callbacks or Promises ourselves.

Now we have access to all the user’s Timezones in the ClockController, so we can make times in each timezone the user has requested and show them in a list. First we’ll add each Timezone’s current time to our ClockController in app/scripts/controllers/clock_controller.js using Moment.js:

WorldClock.ClockController = Ember.ObjectController.extend({
    init: function() {
        // Update the time.
        this.updateTime();</p>
 
        // Run other controller setup.
        this._super();
    },
 
    updateTime: function() {
        var _this = this;
 
        // Update the time every second.
        setTimeout(function() {
            _this.set('localTime', moment().format('h:mm:ss a'));
 
            _this.get('model').forEach(function(model) {
                model.set('time',
                          moment().tz(model.get('name')).format('h:mm:ss a'));
            });
 
            _this.updateTime();
        }, 1000);
    },
 
    localTime: moment().format('h:mm:ss a')
});

Our final app/templates/clock.hbs should look like this:

<h2>Local Time: {{localTime}}</h2>
 
<p>{{#each model}}
  <h3>{{name}}: {{time}}</h3>
{{/each}}

And that’s it! Now we have an offline app that shows us time zones in various places, saves the data offline, and updates every second without us having to do much work!

Command Line Tools

The old Podcasts app used a (rather awful) Makefile. It wasn’t very useful, and I don’t think it ran on Windows without some serious effort. The new build system uses Node so it runs comfortably on Windows, Mac, and Linux. Commands are proxied via the recroom binary, also written in Node, so you don’t have to worry about the underlying system if you don’t need to modify build steps. recroom new my-app creates a new app; recroom serve serves up your new app, and recroom generate model Podcast creates a new model for you.

To build your app, you just need to run recroom build and a version with minified CSS, JS, and even HTML will be created for you in the dist/ folder. This version is ready to be packaged into a packaged app or uploaded to a server as a hosted app. You can even run recroom deploy to deploy directory to your git repository’s GitHub pages branch, if applicable.

See the app in action!

This entire sample app is available at worldclock.tofumatt.com and the source code is available on GitHub.

Try Using Rec Room for Your Next Web App

You can try out Rec Room on Github. Right now some docs and tools are still being abstracted and built, but you can start building apps today using it and filing bugs for missing features. We’d really love it if you could give it a try and let us know what’s missing. Together we can build a cohesive and polished solution to the all-too-common question: “How do I build a web app?”

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Do HTML5 apps have to be online all the time?

One would think that almost five years after the definition of HTML5 offline capabilities this question would be answered. As someone spending a lot of time on HTML5 panels and Q&A sessions at conferences I can tell you though that it gets asked every single time.

being offline

As part of the App Basics for Firefox OS video series we recorded a very short video that shows that HTML5 apps totally can work offline:

You can see the demo explained in the video in action here: non-offline version and offline enabled version.

So here it is: No, HTML5 apps don’t have to be online all the time, they do work offline if you write them the right way.

“But, but, but, but, but…”, I already here people go, “it is not that simple, as there are lots of issues with offline functionality”.

Yes, there are. Appcache is a less than perfect solution, as researched in-depth by Jake Archibald and published in non-minced words almost 2 years ago. There are also issues with localStorage being string based and synchronous and thus being less than optimal for large datasets. For larger datasets the issue is that indexedDB is not supported by all browsers, which is why you need to duplicate your efforts using WebSQL or use an abstraction library instead.

But: these are not insurmountable issues. I am very happy to see offline first becoming a UX starting point, I am super excited about discussions about replacing AppCache and the ServiceWorker proposal showing a much more granular approach to the issue.

For an in-depth showcase how offline can really work, check out Andrew Bett’s 2012 Full Frontal talk.

The problem is that these are details that don’t interest the business person considering using HTML5. All they hear is experts complaining and bickering and saying that offline HTML5 doesn’t work. Which isn’t true. It doesn’t work perfectly, but nothing on the web ever does. Many, many things in Android and iOS are broken, and many apps don’t work offline either. These shortcomings are not advertised though which makes native apps appear as a much more reliable alternative. We should stop showing our behind the scenes footage as a highlight reel.

I really, really want this question to not show up any longer. The documentation and proof is out there. Let’s tell people about that. Please?

View full post on Christian Heilmann

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

The Making of the Time Out Firefox OS app

A rash start into adventure

So we told our client that yes, of course, we would do their Firefox OS app. We didn’t know much about FFOS at the time. But, hey, we had just completed refactoring their native iOS and Android apps. Web applications were our core business all along. So what was to be feared?

More than we thought, it turned out. Some of the dragons along the way we fought and defeated ourselves. At times we feared that we wouldn’t be able to rescue the princess in time (i.e. before MWC 2013). But whenever we got really lost in detail forest, the brave knights from Mozilla came to our rescue. In the end, it all turned out well and the team lived happily ever after.

But here’s the full story:

Mission & challenge

Just like their iOS and Android apps, Time Out‘s new Firefox OS app was supposed to allow browsing their rich content on bars, restaurants, things to do and more by category, area, proximity or keyword search, patient zero being Barcelona. We would need to show results as illustrated lists as well as visually on a map and have a decent detail view, complete with ratings, access details, phone button and social tools.

But most importantly, and in addition to what the native apps did, this app was supposed to do all of that even when offline.

Oh, and there needed to be a presentable, working prototype in four weeks time.

Cross-platform reusability of the code as a mobile website or as the base of HTML5 apps on other mobile platforms was clearly prio 2 but still to be kept in mind.

The princess was clearly in danger. So we arrested everyone on the floor that could possibly be of help and locked them into a room to get the basics sorted out. It quickly emerged that the main architectural challenges were that

  • we had a lot of things to store on the phone, including the app itself, a full street-level map of Barcelona, and Time Out’s information on every venue in town (text, images, position & meta info),
  • at least some of this would need to be loaded from within the app; once initially and synchronizable later,
  • the app would need to remain interactively usable during these potentially lengthy downloads, so they’d need to be asynchronous,
  • whenever the browser location changed, this would be interrupted

In effect, all the different functionalities would have to live within one single HTML document.

One document plus hash tags

For dynamically rendering, changing and moving content around as required in a one-page-does-all scenario, JavaScript alone didn’t seem like a wise choice. We’d been warned that Firefox OS was going to roll out on a mix of devices including the very low cost class, so it was clear that fancy transitions of entire full-screen contents couldn’t be orchestrated through JS loops if they were to happen smoothly.

On the plus side, there was no need for JS-based presentation mechanics. With Firefox OS not bringing any graveyard of half-dead legacy versions to cater to, we could (finally!) rely on HTML5 and CSS3 alone and without fallbacks. Even beyond FFOS, the quick update cycles in the mobile environment didn’t seem to block the path for taking a pure CSS3 approach further to more platforms later.

That much being clear, which better place to look for best practice examples than Mozilla Hacks? After some digging, Thomas found Hacking Firefox OS in which Luca Greco describes the use of fragment identifiers (aka hashtags) appended to the URL to switch and transition content via CSS alone, which we happily adopted.

Another valuable source of ideas was a list of GAIA building blocks on Mozilla’s website, which has since been replaced by the even more useful Building Firefox OS site.

In effect, we ended up thinking in terms of screens. Each physically a <div>, whose visibility and transitions are governed by :target CSS selectors that draw on the browser location’s hashtag. Luckily, there’s also the onHashChange event that we could additionally listen to in order to handle the app-level aspects of such screen changes in JavaScript.

Our main HTML and CSS structure hence looked like this:

And a menu

We modeled the drawer menu very similarily, just that it sits in a <nav> element on the same level as the <section> container holding all the screens. Its activation and deactivation works by catching the menu icon clicks, then actively changing the screen container’s data-state attribute from JS, which triggers the corresponding CSS3 slide-in / slide-out transition (of the screen container, revealing the menu beneath).

This served as our “Hello, World!” test for CSS3-based UI performance on low-end devices, plus as a test case for combining presentation-level CSS3 automation with app-level explicit status handling. We took down a “yes” for both.

UI

By the time we had put together a dummy around these concepts, the first design mockups from Time Out came in so that we could start to implement the front end and think about connecting it to the data sources.

For presentation, we tried hard to keep the HTML and CSS to the absolute minimum. Mozilla’s GAIA examples being a very valuable source of ideas once more.

Again, targeting Firefox OS alone allowed us to break free of the backwards compatibility hell that we were still living in, desktop-wise. No one would ask us Will it display well in IE8? or worse things. We could finally use real <section>, <nav>, <header>, and <menu> tags instead of an army of different classes of <div>. What a relief!

The clear, rectangular, flat and minimalistic design we got from Time Out also did its part to keep the UI HTML simple and clean. After we were done with creating and styling the UI for 15 screens, our HTML had only ~250 lines. We later improved that to 150 while extending the functionality, but that’s a different story.

Speaking of styling, not everything that had looked good on desktop Firefox even in its responsive design view displayed equally well on actual mobile devices. Some things that we fought with and won:

Scale: The app looked quite different when viewed on the reference device (a TurkCell branded ZTE device that Mozilla had sent us for testing) and on our brand new Nexus 4s:

After a lot of experimenting, tearing some hair and looking around how others had addressed graceful, proportional scaling for a consistent look & feel across resolutions, we stumbled upon this magic incantation:

<meta name="viewport" content="user-scalable=no, initial-scale=1,
maximum-scale=1, width=device-width" />

What it does, to quote an article at Opera, is to tell the browser that there is “No scaling needed, thank you very much. Just make the viewport as many pixels wide as the device screen width”. It also prevents accidental scaling while the map is zoomed. There is more information on the topic at MDN.

Then there are things that necessarily get pixelated when scaled up to high resolutions, such as the API based venue images. Not a lot we could do about that. But we could at least make the icons and logo in the app’s chrome look nice in any resolution by transforming them to SVG.

Another issue on mobile devices was that users have to touch the content in order to scroll it, so we wanted to prevent the automatic highlighting that comes with that:

li, a, span, button, div
{
    outline:none;
    -moz-tap-highlight-color: transparent;
    -moz-user-select: none;
    -moz-user-focus:ignore
}

We’ve since been warned that suppressing the default highlighting can be an issue in terms of accessibility, so you might wanted to consider this carefully.

Connecting to the live data sources

So now we had the app’s presentational base structure and the UI HTML / CSS in place. It all looked nice with dummy data, but it was still dead.

Trouble with bringing it to life was that Time Out was in the middle of a big project to replace its legacy API with a modern Graffiti based service and thus had little bandwidth for catering to our project’s specific needs. The new scheme was still prototypical and quickly evolving, so we couldn’t build against it.

The legacy construct already comprised a proxy that wrapped the raw API into something more suitable for consumption by their iOS and Android apps, but after close examination we found that we better re-re-wrap that on the fly in PHP for a couple of purposes:

  • Adding CORS support to avoid XSS issues, with the API and the app living in different subdomains of timeout.com,
  • stripping API output down to what the FFOS app really needed, which we could see would reduce bandwidth and increase speed by magnitude,
  • laying the foundation for harvesting of API based data for offline use, which we already knew we’d need to do later

As an alternative to server-side CORS support, one could also think of using the SystemXHR API. It is a mighty and potentially dangerous tool however. We also wanted to avoid any needless dependency on FFOS-only APIs.

So while the approach wasn’t exactly future proof, it helped us a lot to get to results quickly, because the endpoints that the app was calling were entirely of our own choice and making, so that we could adapt them as needed without time loss in communication.

Populating content elements

For all things dynamic and API-driven, we used the same approach at making it visible in the app:

  • Have a simple, minimalistic, empty, hidden, singleton HTML template,
  • clone that template (N-fold for repeated elements),
  • ID and fill the clone(s) with API based content.
  • For super simple elements, such as <li>s, save the cloning and whip up the HTML on the fly while filling.

As an example, let’s consider the filters for finding venues. Cuisine is a suitable filter for restaurants, but certainly not for museums. Same is true for filter values. There are vegetarian restaurants in Barcelona, but certainly no vegetarian bars. So the filter names and lists of possible values need to be asked of the API after the venue type is selected.

In the UI, the collapsible category filter for bars & pubs looks like this:

The template for one filter is a direct child of the one and only

<div id="templateContainer">

which serves as our central template repository for everything cloned and filled at runtime and whose only interesting property is being invisible. Inside it, the template for search filters is:

<div id="filterBoxTemplate">
  <span></span>
  <ul></ul>
</div>

So for each filter that we get for any given category, all we had to do was to clone, label, and then fill this template:

$('#filterBoxTemplate').clone().attr('id', filterItem.id).appendTo(
'#categoryResultScreen .filter-container');
...
$("#" + filterItem.id).children('.filter-button').html(
filterItem.name);

As you certainly guessed, we then had to to call the API once again for each filter in order to learn about its possible values, which were then rendered into <li> elements within the filter‘s <ul> on the fly:

$("#" + filterId).children('.filter_options').html(
'<li><span>Loading ...</span></li>');

apiClient.call(filterItem.api_method, function (filterOptions)
{
  ...
  $.each(filterOptions, function(key, option)
  {
    var entry = $('<li filterId="' + option.id + '"><span>'
      + option.name + '</span></li>');

    if (selectedOptionId && selectedOptionId == filterOptionId)
    {
      entry.addClass('filter-selected');
    }

    $("#" + filterId).children('.filter_options').append(entry);
  });
...
});

DOM based caching

To save bandwidth and increase responsiveness in on-line use, we took this simple approach a little further and consciously stored more application level information in the DOM than needed for the current display if that information was likely needed in the next step. This way, we’d have easy and quick local access to it without calling – and waiting for – the API again.

The technical way we did so was a funny hack. Let’s look at the transition from the search result list to the venue detail view to illustrate:

?

As for the filters above, the screen class for the detailView has an init() method that populates the DOM structure based on API input as encapsulated on the application level. The trick now is, while rendering the search result list, to register anonymous click handlers for each of its rows, which – JavaScript passing magic – contain a copy of, rather than a reference to, the venue objects used to render the rows themselves:

renderItems: function (itemArray)
{
  ...

  $.each(itemArray, function(key, itemData)
  {        
    var item = screen.dom.resultRowTemplate.clone().attr('id', 
      itemData.uid).addClass('venueinfo').click(function()
    {
      $('#mapScreen').hide();
      screen.showDetails(itemData);
    });

    $('.result-name', item).text(itemData.name);
    $('.result-type-label', item).text(itemData.section);
    $('.result-type', item).text(itemData.subSection);

    ...

    listContainer.append(item);
  });
},

...

showDetails: function (venue)
{
  require(['screen/detailView'], function (detailView)
  {
    detailView.init(venue);
  });
},

In effect, there’s a copy of the data for rendering each venue’s detail view stored in the DOM. But neither in hidden elements nor in custom attributes of the node object, but rather conveniently in each of the anonymous pass-by-value-based click event handlers for the result list rows, with the added benefit that they don’t need to be explicitly read again but actively feed themselves into the venue details screen as soon a row receives a touch event.

And dummy feeds

Finishing the app before MWC 2013 was pretty much a race against time, both for us and for Time Out’s API folks, who had an entirely different and equally – if not more so – sportive thing to do. Therefore they had very limited time for adding to the (legacy) API that we were building against. For one data feed, this meant that we had to resort to including static JSON files into the app’s manifest and distribution; then use relative, self-referencing URLs as fake API endpoints. The illustrated list of top venues on the app’s main screen was driven this way.

Not exactly nice, but much better than throwing static content into the HTML! Also, it kept the display code already fit for switching to the dynamic data source that eventually materialized later, and compatible with our offline data caching strategy.

As the lack of live data on top venues then extended right to their teaser images, we made the latter physically part of the JSON dummy feed. In Base64 :) But even the low-end reference device did a graceful job of handling this huge load of ASCII garbage.

State preservation

We had a whopping 5M of local storage to spam, and different plans already (as well as much higher needs) for storing the map and application data for offline use. So what to do with this liberal and easily accessed storage location? We thought we could at least preserve the current application state here, so you’d find the app exactly as you left it when you returned to it.

Map

A city guide is the very showcase of an app that’s not only geo aware but geo centric. Maps fit for quick rendering and interaction in both online and offline use were naturally a paramount requirement.

After looking around what was available, we decided to go with Leaflet, a free, easy to integrate, mobile friendly JavaScript library. It proved to be really flexible with respect to both behaviour and map sources.

With its support for pinching, panning and graceful touch handling plus a clean and easy API, Leaflet made us arrive at a well-usable, decent-looking map with moderate effort and little pain:

For a different project, we later rendered the OSM vector data for most of Europe into terabytes of PNG tiles in cloud storage using on-demand cloud power. Which we’d recommend as an approach if there’s a good reason not to rely on 3rd party hosted apps, as long as you don’t try this at home; Moving the tiles may well be slower and more costly than their generation.

But as time was tight before the initial release of this app, we just – legally and cautiously(!) – scraped ready-to use OSM tiles off MapQuest.com.

The packaging of the tiles for offline use was rather easy for Barcelona because about 1000 map tiles are sufficient to cover the whole city area up to street level (zoom level 16). So we could add each tile as a single line into the manifest.appache file. The resulting, fully automatic, browser-based download on first use was only 10M.

This left us with a lot of lines like

/mobile/maps/barcelona/15/16575/12234.png
/mobile/maps/barcelona/15/16575/12235.png
...

in the manifest and wishing for a $GENERATE clause as for DNS zone files.

As convenient as it may seem to throw all your offline dependencies’ locations into a single file and just expect them to be available as a consequence, there are significant drawbacks to this approach. The article Application Cache is a Douchebag by Jake Archibald summarizes them and some help is given at Html5Rocks by Eric Bidleman.

We found at the time that the degree of control over the current download state, and the process of resuming the app cache load in case that the initial time users spent in our app didn’t suffice for that to complete was rather tiresome.

For Barcelona, we resorted to marking the cache state as dirty in Local Storage and clearing that flag only after we received the updateready event of the window.applicationCache object but in the later generalization to more cities, we moved the map away from the app cache altogether.

Offline storage

The first step towards offline-readiness was obviously to know if the device was online or offline, so we’d be able to switch the data source between live and local.

This sounds easier than it was. Even with cross-platform considerations aside, neither the online state property (window.navigator.onLine), the events fired on the <body> element for state changes (“online” and “offline”, again on the <body>), nor the navigator.connection object that was supposed to have the on/offline state plus bandwidth and more, really turned out reliable enough.

Standardization is still ongoing around all of the above, and some implementations are labeled as experimental for a good reason :)

We ultimately ended up writing a NetworkStateService class that uses all of the above as hints, but ultimately and very pragmatically convinces itself with regular HEAD requests to a known live URL that no event went missing and the state is correct.

That settled, we still needed to make the app work in offline mode. In terms of storage opportunities, we were looking at:

Storage Capacity Updates Access Typical use
App / app cache, i.e. everything listed in the file that the value of appcache_path in the app‘s webapp.manifest points to, and which is and therefore downloaded onto the device when the app is installed. <= 50M. On other platforms (e.g. iOS/Safari), user interaction required from 10M+. Recommendation from Moziila was to stay <2M. Hard. Requires user interaction / consent, and only wholesale update of entire app possible. By (relative) path HTML, JS, CSS, static assets such as UI icons
LocalStorage 5M on UTF8-platforms such as FFOS, 2.5M in UTF16, e.g. on Chrome. Details here Anytime from app By name Key-value storage of app status, user input, or entire data of modest apps
Device Storage (often SD card) Limited only by hardware Anytime from app (unless mounted as UDB drive when cionnected to desktop computer) By path, through Device Storage API Big things
FileSystem API Bad idea
Database Unlimited on FFOS. Mileage on other platforms varies Anytime from app Quick and by arbitrary properties Databases :)

Some aspects of where to store the data for offline operation were decided upon easily, others not so much:

  • the app, i.e. the HTML, JS, CSS, and UI images would go into the app cache
  • state would be maintained in Local Storage
  • map tiles again in the app cache. Which was a rather dumb decision, as we learned later. Barcelona up to zoom level 16 was 10M, but later cities were different. London was >200M and even reduced to max. zoom 15 still worth 61M. So we moved that to Device Storage and added an actively managed download process for later releases.
  • The venue information, i.e. all the names, locations, images, reviews, details, showtimes etc. of the places that Time Out shows in Barcelona. Seeing that we needed lots of space, efficient and arbitrary access plus dynamic updates, this had to to go into the Database. But how?

The state of affairs across the different mobile HTML5 platforms was confusing at best, with Firefox OS already supporting IndexedDB, but Safari and Chrome (considering earlier versions up to Android 2.x) still relying on a swamp of similar but different sqlite / WebSQL variations.

So we cried for help and received it, as always when we had reached out to the Mozilla team. This time in the form of a pointer to pouchDB, a JS-based DB layer that at the same time wraps away the different native DB storage engines behind a CouchDB-like interface and adds super easy on-demand synchronization to a remote CouchDB-hosted master DB out there.

Back last year it still was in pre-alpha state but very usable already. There were some drawbacks, such as the need for adding a shim for WebSql based platforms. Which in turn meant we couldn’t rely on storage being 8 bit clean, so that we had to base64 our binaries, most of all the venue images. Not exactly pouchDB’s fault, but still blowing up the size.

Harvesting

The DB platform being chosen, we next had to think how we’d harvest all the venue data from Time Out’s API into the DB. There were a couple of endpoints at our disposal. The most promising for this task was proximity search with no category or other restrictions applied, as we thought it would let us harvest a given city square by square.

Trouble with distance metrics however being that they produce circles rather than squares. So step 1 of our thinking would miss venues in the corners of our theoretical grid

while extending the radius to (half the) the grid’s diagonal, would produce redundant hits and necessitate deduplication.

In the end, we simply searched by proximity to a city center location, paginating through the result indefinitely, so that we could be sure to to encounter every venue, and only once:

Technically, we built the harvester in PHP as an extension to the CORS-enabled, result-reducing API proxy for live operation that was already in place. It fed the venue information in to the master CouchDB co-hosted there.

Time left before MWC 2013 getting tight, we didn’t spend much time on a sophisticated data organization and just pushed the venue information into the DB as one table per category, one row per venue, indexed by location.

This allowed us to support category based and area / proximity based (map and list) browsing. We developed an idea how offline keyword search might be made possible, but it never came to that. So the app simply removes the search icon when it goes offline, and puts it back when it has live connectivity again.

Overall, the app now

  • supported live operation out of box,
  • checked its synchronization state to the remote master DB on startup,
  • asked, if needed, permission to make the big (initial or update) download,
  • supported all use cases but keyword search when offline.

The involved components and their interactions are summarized in this diagram:

Organizing vs. Optimizing the code

For the development of the app, we maintained the code in a well-structured and extensive source tree, with e.g. each JavaScript class residing in a file of its own. Part of the source tree is shown below:

This was, however, not ideal for deployment of the app, especially as a hosted Firefox OS app or mobile web site, where download would be the faster, the fewer and smaller files we had.

Here, Require.js came to our rescue.

It provides a very elegant way of smart and asynchronous requirement handling (AMD), but more importantly for our purpose, comes with an optimizer that minifies and combines the JS and CSS source into one file each:

To enable asynchronous dependency management, modules and their requirements must be made known to the AMD API through declarations, essentially of a function that returns the constructor for the class you’re defining.

Applied to the search result screen of our application, this looks like this:

define
(
  // new class being definied
  'screensSearchResultScreen',

  // its dependencies
  ['screens/abstractResultScreen', 'app/applicationController'],

  // its anonymous constructor
  function (AbstractResultScreen, ApplicationController)
  {
    var SearchResultScreen = $.extend(true, {}, AbstractResultScreen,
    {
      // properties and methods
      dom:
      {
        resultRowTemplate: $('#searchResultRowTemplate'),
        list: $('#search-result-screen-inner-list'),
        ...
      }
      ...
    }
    ...

    return SearchResultScreen;
  }
);

For executing the optimization step in the build & deployment process, we used Rhino, Mozilla’s Java-based JavaScript engine:

java -classpath ./lib/js.jar:./lib/compiler.jar   
  org.mozilla.javascript.tools.shell.Main ./lib/r.js -o /tmp/timeout-webapp/
  $1_config.js

CSS bundling and minification is supported, too, and requires just another call with a different config.

Outcome

Four weeks had been a very tight timeline to start with, and we had completely underestimated the intricacies of taking HTML5 to a mobile and offline-enabled context, and wrapping up the result as a Marketplace-ready Firefox OS app.

Debugging capabilities in Firefox OS, especially on the devices themselves, were still at an early stage (compared to clicking about:app-manager today). So the lights in our Cologne office remained lit until pretty late then.

Having built the app with a clear separation between functionality and presentation also turned out a wise choice when a week before T0 new mock-ups for most of the front end came in :)

But it was great and exciting fun, we learned a lot in the process, and ended up with some very useful shiny new tools in our box. Often based on pointers from the super helpful team at Mozilla.

Truth be told, we had started into the project with mixed expectations as to how close to the native app experience we could get. We came back fully convinced and eager for more.

In the end, we made the deadline and as a fellow hacker you can probably imagine our relief. The app finally even received its 70 seconds of fame, when Jay Sullivan shortly demoed it at Mozilla’s MWC 2013 press conference as a showcase for HTML5?s and Firefox OS’s offline readiness (Time Out piece at 7:50). We were so proud!

If you want to play with it, you can find the app in the marketplace or go ahead try it online (no offline mode then).

Since then, the Time Out Firefox OS app has continued to evolve, and we as a team have used the chance to continue to play with and build apps for FFOS. To some degree, the reusable part of this has become a framework in the meantime, but that’s a story for another day..

We’d like to thank everyone who helped us along the way, especially Taylor Wescoatt, Sophie Lewis and Dave Cook from Time Out, Desigan Chinniah and Harald Kirschner from Mozilla, who were always there when we needed help, and of course Robert Nyman, who patiently coached us through writing this up.

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Edgeconf 3 – just be there next time, trust me

I just got back from Edgeconf 3 in London, England, and I am blown away by how good the event was. If you are looking for a web conference that is incredible value for money, look no further.

edgeconf3

The main difference of Edgeconf is its format. Whilst you had a stellar line-up of experts, the conference is not a series of talks or even several tracks in parallel. Instead, it is a series of panels with curated Q&A in the style of Question Time on BBC. Questions are submitted by the audience before the conference using Google Moderator and expert moderator triage and collate the questions. Members from the audience read out the questions to the panel and the moderator then picks experts to answer them. Audience members also can show their intent to ask a question or offer extra information.

In essence: the whole conference is about getting questions answered, not about presenting. This means that there is a massive amount of information available in a very short amount of time and there is no chance to grand-stand or advocate solutions without proof.

The main workload of the conference is covered by the moderators. It is up to them to not only triage the questions but also keep the discussion lively and keep it entertaining.

All the moderators met the day before the event and spent half a day going through all the submitted questions and whittle them down to seven per panel. Each person answering a question has 30 seconds to a minute to answer and there is strict time-keeping.

The whole event was streamed live on YouTube and the recordings are available on Youtube/Google+.

During the panels, the audience can interact live using the Onslyde system. You can agree or disagree with a topic and request to speak or ask a question. All this information is logged and can be played in sync with the video recording later on. Onslyde also creates analytics reports showing sentiment analysis and more. Other conferences like HTML5DevConf, Velocity and OsCon also started using this system.

Another big thing about Edgeconf is that any of the extra income from tickets and sponsorship (in this case around £10,000) get donated to a good cause. At the end of the conference the organisers showed a full disclosure of expenditure. The cause this time was Codeclub, a charity teaching kids coding.

I am very proud to have been one of the moderators this time and run the accessibility panel (a detailed post on this comes later).

I have to thank the organisers and everyone involved for a great event. I learned a lot during the day and I am happy to be involved again in September.

View full post on Christian Heilmann

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Linklib – lets film lovers and filmmakers send time synced links from videos to phones – a WebFWD project

Have you ever googled films and TV-shows while you watch them? Do you think Youtube’s popup annotations in the middle of a video are distracting?

Having shot a documentary about the Pirate Bay for 4 years I wanted to embed links directly into the film to give the audience more nuances in the complex and bizarre story about the Swedish file-sharing site. I constantly google videos I watch.

What problem is Linklib solving?

Linklib lets filmmakers, film fans, journalists and bloggers send time synched links from a full screen video directly to their audiences’ phones. Instead of googling an actor, fact checking an election video or feverishly trying to find the soundtrack to that TV-series, just pick up the phone and the information is right there.

When I stumbled over popcorn.js in 2011 I realized the amazing potential of embedding time synched links into films, but I was still looking for a way to hide the hyperlinks from the fullscreen video.

So we built Linklib, a system that sends time synced links from streamed video to phones. That way you can read up on that actress, fact check that election video or follow that rapper on twitter while you’re watching the video. Without obtrusive annotations in the frame.

Linklib is a free and open library of time synced video commentary. Film directors, journalists and fan communities can add facts and comments to give films more depth and nuances. The system works just as well for feature films, documentaries, music videos, educational and commercical films. Linklib is an open source project that wants to tell better stories by using the open web.

How it works

The basic components of Linklib’s system are a remote, usually a smartphone or a tablet, and a video viewer, typically a computer. The remote shows synchronized links from the video viewer and can send and receive events such as play, pause, forward and rewind. To sync the phone with the video we show a QR code that you can scan with your phone. At the moment our video viewer can show youtube, vimeo and html5 video streams.

A lobby server handles the communication between the remote and the video. The remote uses socket.io to communicate with the lobby server and is written in JavaScript.

For users to be able to add videos and create link feeds of their own we’ve built a web based authoring tool focused on simplicity. The tool is built using Twitter bootstrap and jQuery. All links and account information are stored on a mysql database on Amazon AWS.

Components

  • Remote – shows synchronized links from the Video Viwer and can send receive events such as play, pause, forward and rewind.
  • Video Viewer – Shows a youtube or vimeo stream.
  • Lobby server – handles communication between Remote and Video Viewer
  • Authoring Tool – Web based system that allows users to add videos and create link flows for them

APIs and Libraries

  • Remote uses socket.io to communicate with Lobby server and is written in JavaScript.
  • Lobby server is based on node.js
  • Video viewer uses popcorn.js to play videos
  • All links and account information are store on a mysql database on Amazon AWS
  • Authoring Tool uses Twitter bootstrap and jQuery

Help us test out Linklib

Are you a filmmaker looking for a way to tie closer bonds to your audience? Or a Game of Thrones-fan looking for a way to fill your favorite episode with geeky references? Maybe you want to throw in a bunch of research that you couldn’t explain in your last conference video? Or you’re a fashion designer that wants to reveal the details of your catwalk? If you’re a film producer you could fill your youtube trailer with your characters’ social media and reviews, like the great documentary Indiegame: The Movie here beneath.

You can also add mashups and remixes to that banging new Outkast music video! And help activists worldwide spread information that doesn’t make the mainstream news! Linklib puts the web into videos without ruining the traditional viewing experience.

We just launched a beta and we’d love your feedback about bugs and features!

View full post on Mozilla Hacks – the Web developer blog

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)