People are getting used to using their devices as their personal assistants. Personally I often rely on my smartphone or my Outlook calendar reminding me of things: birthdays, appointments, meetings and deadlines.

However, typing all the information, appointments, favorite restaurants and airlines is definitely a tedious task. Probably for this reason back in 2011 Apple decided to integrate Siri into iOS. This way users can use their iPhone as their secretary, when they are not concerned of being consider idiots by others staring at them while they’re having a pleasant conversation with their phone.

Recently W3C released a new specification: Web Speech API. This opens the doors for entirely new ways users can interact with web applications. It will be no longer just keyboard and mouse, you’ll be able to talk to the browser, issue commands and dictate text. Developers now have the opportunity to build voice-driven personal assistant applications that work in the browser. The API is currently implemented only in the most recent release of Google Chrome (version 25), and the implementation is incomplete.

Only a few days after my Twitter stream notified me about the Web Speech API becoming available in Chrome, Nokia Berlin was hosting the first HERE Hackathon. We had several developers coming over to play with our location APIs. Web Speech API + maps was a perfect little project for a hackathon.

So there I was, hacking Vocal Search together. Vocal Search is a simple little application that takes the user’s voice input, understands it and search for relevant places around matching the user’s request. A request can be something like: Find me a restaurant and hopefully even something more complex like “I am hungry, find a french restaurant around here”.

Hacking maps at the HERE Winter Hackathon

The first version of Vocal Search I built at the hackathon was very basic. A full screen map centered in the current location, a search box in case the user wants to type the search terms and an icon to enable voice capturing. Users could issue commands like “look for a restaurant” or “find a supermarket” and the application would search for relevant places around the user’s position matching the given search terms using the HERE Places API.

image

The way the Web Speech API works with the current, partial implementation is the following: the browser requests permission of accessing the microphone. When the user accepts audio capturing starts. As audio is being captured, the recorded audio is sent to a server at Google, speech to text is performed and the result is sent back to the browser where the request originated and becomes available as a parameter of a JavaScript callback.

Web Speech API

A simplified version of the speech recognition code for Vocal Search is something like this:

(function(){
    var recognizing = false,
        transcript = '',
        speechRecognitionHandler = new webkitSpeechRecognition();
    //https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#dfn-continuous
    speechRecognitionHandler.continuos = true;
    //https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#dfn-interimresults
    speechRecognitionHandler.interimResults = true;
  
    speechRecognitionHandler.onstart = function(){
        recognizing = true;
    };
    speechRecognitionHandler.onerror = function(e){
        recognizing = false;
        console.log('Something wrong happened', e.error);
    };
    speechRecognitionHandler.onresult = function(e){
        //We've got something here
        var interim_transcript = '';
        for (var i = event.resultIndex; i < event.results.length; ++i) {
            if (event.results[i].isFinal) {
                transcript += event.results[i][0].transcript;
            }
        }
    };
    speechRecognitionHandler.onend = function(e){
        //Ok, done
        recognizing = false;
        //This should be everything the user said:
        console.log(transcript);
        //Do something interesting with transcript
    };
})();

As you can see, at the current status the implementation of Web Speech API is nothing particularly smart: it is only a speech to text service accessible from JavaScript. In the future, however, it will be much more that that. The specification defines (roughly for now) the possibility of defining grammars. This means Web Speech will become a complete NLU (Natural Language Understanding) API directly available on the browser. The diagram above will the become something like this:

Web Speech + Grammars

Unfortunately, for now you’ll have to parse the content of that transcript variable yourself.

During the hackathon, the smartest thing I could think of was a regular-expression-based command parser. If transcript contains search for, look for or find then the user definitely wanted to search for something. Right after the command, transcript probably contains the search terms. Pass the search term to the Places REST API and boom, pins on the map appear.

This worked fine, although it was somehow a big limitation. Sure, you could define thousands of regular expressions, but that is totally not the way to go. However I considered that enough for a day of hacking, and promised to myself I will revisit the code later on, hoping one day the Web Speech API will be completely implemented by all browser vendors.

Just a few days ago I was googling for I-don’t-remember-what, and I stumbled upon something incredibly awesome: a REST API that given a piece of text or a phrase returns a JSON object containing the following:

  • Category: provides a high level identification about the subject of the sentence.
  • Action: a more specific type of category, and provides some information about the intent of the text
  • Entities: important pieces of information from the sentence in a normalized form.

Isn’t that great? It is exactly what I needed to make Vocal Search better and smarter. Have a look at Maluuba’s nAPI, it is a really nice API to play with. They have libraries for Ruby, Python and Java, but in the end it is just a HTTP GET request with the API Key in the query string, so it can be easily done via AJAX in the browser. Unfortunately, they currently don’t have CORS enabled and there is no JSONP support, so you’ll have to proxy the call (for non business critical apps you can use corsproxy).

So here is what my onend callback does now (more or less, the actual code is a little more complex than this):


speechRecognitionHandler.onend = function(e){
    //Ok, done
    recognizing = false;
    //This should be everything the user said:
    console.log(transcript);
    //Do something interesting with transcript
    $.ajax({
        url: 'http://www.corsproxy.com/napi.maluuba.com/v0/interpret',
        data: {
            apikey: 'myapikey',
            phrase: transcript
        }
    }).done(function(data){
        if(data.action === 'BUSINESS_SEARCH') {
            //The user's wants to search for something, cool!
            //data.entities should be now an array of search terms
            firePlacesSearch(data.entities && data.entities.searchTerm.join(' '));
        }
    }).fail(function(){
        alert('Oh no! Something must have gone wrong.')
    });  
};

Here we go, super easy, works great. Now I can say things like “I feel like having a beer, find me a pub”. I get the transcript back from Google, I send it to Maluubas’s nAPI, I get back a response that tells me it is as business search, and that the search terms are beer and pub. I pass that to the places API and I get pubs highlighted on the map with colorful pins. It is a really nice toy.

Now, demo time. Vocal Search is available at vocalsearch.marcon.me and all the code is on Github. To start recording click the microphone icon or press s when the focus is on the map. Same thing to stop recording. Note that since Vocal Search runs on http:// and not on https:// the browser will ask for permission to record every single time, and the preference cannot be saved.

Should the demo not work, corsproxy is probably down as it is now for me. Please try again later. I am working on setting up my own CORS proxy service.

Update: the supernice guys at Maluuba actually read my feedback email and enabled CORS for their nAPI. This means proxying the AJAX calls to http://napi.maluuba.com/v0/interpret is no longer necessary, everything just works. Good job guys!

2012 is gone, and it is time to summarize what happened during the last year, decide what was good and what was bad and get ready for an awesome 2013.

So, we said 2012 is gone: this means more than 12 years have passed since I was 18. Now I am all grown up, I am an engineer and I make stuff on the web. Who would have thought…

New Year 2013

13 months at Nokia

Looking back, 2012 has been pretty great. Towards the end of 2011 I joined an awesome team at Nokia in Berlin: amazing guys. We spent most of our time making City Pages and Place Pages great products for our users. We made them pretty, and we spent lots of time fighting with performance optimizations. We did pair programming, unit testing, pair swapping, refactoring, aimed for continuos deployment, everything driven by pragmatism and common sense. I had a really great time.

With the whole personal maps team we transformed our periodic research days into research weeks: this was a fantastic choice to push innovation forward. For a week everybody has the possibility to experiment, build new concepts, test new prototypes. Developers can pretend to be designers, designers have the freedom to bring in new concepts everybody can play with, we all have fun together. The results have been astonishing. The Alien, Maps Labs, all these cool little things were only some of the great stuff built during research weeks.

Conferences, Workshops, Hackathons

During 2012 I was lucky enough to be able to attend a conference and to speak at a conference. Conferences are great occasions to hang out with fellow geeks, see what others are doing, learn a lot and why not, visit new places.

In the spring I attended Front-Trends, a pretty good conference in Warsaw, Poland. Awesome speakers, good food, lots of beer.

However, I truly believe the best way to enjoy a conference is being a speaker. Preparing a presentation is often a hard job, takes time to research the topics of your presentation, takes lots of effort to come up with a speech and fancy slides and going on stage, presenting in front of a crowd is really not easy. But in exchange for that you get to meet other great speakers, discuss and share stories. Also you have the opportunity to talk in front of a group of people that are somehow interested in what you do, that are spending time and money just to attend your session. When I presented at Frontendconf.ch I had the chance to experience all this awesomeness, and now I want to do it again.

Being part of Frontendconf.ch was already fantastic, but to make the whole thing even more rewarding I found out that my presentation has been featured among the Talks To Help You Become A Better Front-End Engineer In 2013 by Addy Osmani on Smashing Magazine.

2012 wasn’t only about conferences. I had the chance to attend a great Node.js Workshop organized by The Node Firm where I also met @bdufresne. He is a really nice guy, I am very happy we worked together during the little hackathon that closed the workshop.

Speaking of hackathons, I showed up at a couple of events in Berlin, always with my buddy @thingsinjars. At the HTML5 Apps Hackathon we came up with Soundscape, a little map-based game to explore the world of sound and music. Then at Nodecopter we hacked together a little application that flies a quadcopter and takes 360° panoramas of the surroundings. This I must say wasn’t as successful as we hoped.

jHERE

2012 was also the year of jHERE. In November at Nokia we launched HERE, the new generation of personal mapping experience. While I was working on this huge rebranding during the day, at night I was building jHERE a jQuery plugin web developers can use to simply add maps to their websites. jHERE has been pretty successful so far, the websites gets a few hundreds visits every day and the project has 111 stars on Github.

When people started using jHERE I started collecting some feedback. Mostly developers are happy with what they can achieve with the plugin, but somebody reported some bugs and some other guys suggested new features. This means lots of work for 2013 to improve the quality, the reliably and the number of features offered by jHERE.

New challenges

2012 has been pretty positive, so what am I going to do in 2013?

First of all, after attending several events (hackathons, workshop, conferences) I am now trying to organize one. On January 19th at Nokia Berlin @thingsinjars and I are hosting the first HERE Hackathon, an event where web and maps geeks meet for a day full of geo-hacking with all the HERE APIs. I hope it will be a success, so we can keep doing this kind of community-targeted initiatives.

Next goal is to do more speaking. I have in mind a few conferences where I would like to submit a topic, I hope at least one will accept my proposal.

The last challenge for this year is to learn well a new (and hopefully useful) programming language. I still don’t know what it will be. Python? Objective-C? Or perhaps some .NET stuff to build apps for Windows phone? We shall see.

Well, I guess I summarized everything that happened in 2012 and defined my goals for 2013. Now I better get started!

jHERE was born as a simple jQuery plugin with very few functionalities: add a map to a web page, add markers and events for markers, simple support for KML and heatmaps.

However, as I was using it for my hacks I realized there are other features that are not essentials but still nice to have. The original HERE Maps API has plenty of interesting functionalities, and not exposing them through jHERE would be a shame.

On the other hand I did not want the plugin to grow uncontrollably to a huge mess of code. Not only this would increase a lot the size of jHERE, but also due to size and complexity the codebase would have become hard to maintain.

Therefore I chose to make jHERE an extensible plugin. This means exactly what you are thinking. It is possible to make plugins for the plugin. Except I called them extensions. Plugins for plugins: how meta!

Allowing extensions was a great choice. I was able to easily create an autonit extension - that allows inexperienced web developers to add a map to their pages without having to write any JavaScript code - a routing extensions and a geocode/reverse geocode extension.

This leads unfortunately to another problem: all these extensions - plus the adapter for Zepto.JS - ship as separate files that have to be included with different script tags. This is great for development as it makes debugging easy, but once an application that uses jHERE plus one or more extensions reaches the production stage, having multiple script tags means multiple HTTP connections. This is a big performance hit. Therefore these files have to be combined.

That could be done ad build time, before or after the minification step. But again, building a big JS file with plugin and extensions inside is non sense. Why should my users download a bundle with jHERE and perhaps ten extensions when I only need the geocoding one? So that was not a possibility.

Bulding all the possible combinations of jHERE-core and extensions in not an option either, it would be crazy and completely nonsense.

Wouldn’t it be awesome if the users of the plugin could just choose the components that need to be part of the jHERE bundle? In other words, wouldn’t it be cool if developers could build a version of jHERE that is customized to their needs? This seemed definitely the way to go.

The first option I considered was a build script that can be called from the Makefile. This did not sound like a good option for non-advanced users, thus I almost immediately dropped this possibility.

The ideal choice seemed then a web page where one could simply click few checkboxes and download the custom build. And after this long introduction, this is exactly what this post is about: creating a web build tool for a JavaScript library that handles dependency management and returns customized and minified versions of the library ready for production. The result is live at custom.jhere.net.

jHERE Custom

Custom build tool

The tool I built has two components: one on the backend written in Node.js and the frontend that includes a simple static HTML page and some JavaScript. The backend is a pretty simple piece of software: given the url to two or more JavaScript files it downloads them, combines them together and sends the result to the browser. The frontend contains the list of available files, handles dependencies and builds the appropriate request to be passed to the backend. The custom build tool concatenates together plugin and extensions by fetching the minified version straight from Github.

Since this post is already too long I will now focus only on the backend. The frontend part is not very complicated, but I will probably analyze that in a separate post. The code can be found here: custom.jhere.net/main.js, in case you feel like having a look.

Backend

The backend takes care of serving the static files as well as exposing the endpoints for combining the files and flushing the cache. I used Express as the web framework that handles everything: it makes easy to set up routes, serve static files, parse query parameters, set headers and send responses back to the client.

The concatenation API is very simple. It is a GET or POST request to / with query parameter files set to file1+file2+…fileN. For example to download jHERE with the Zepto adapter you would request something like:

http://custom.jhere.net/
?files=https://raw.github.com/mmarcon/jhere/master/dist/zepto.adapter.min.js
+https://raw.github.com/mmarcon/jhere/master/dist/jhere.min.js

The first thing the code does when such a request is received is parsing the files parameter into an array of URLs that is passed to the concatenation function.

app.all('/', function(req, res, next){
    var files = req.query.files && req.query.files.split(' ');
    if (files && files.length) {
        return concatOnTheFly(files, res);
    }
    next();
});

Note that + in a URL are received as spaces: that is why I am splitting on spaces.

concatOnTheFly recursively fetches the remote files using the Request module.

function concatOnTheFly(files, res){
    var data = "", f;

    //Recursively get files until done.
    function fetch(file) {
        var f;
        request.get({url: file}, function(error, request, body){
            if(error){
                return res.send(500, {error: 'error while fetching' + file});
            }
            data += body;
            //Get next file
            f = files.shift();
            //Is there a next file?
            if(f) {
                //Cool then fetch it
                return fetch(f);
            }
            //Looks like I am done. Force the browser to
            //download what I've got.
            res.header('Pragma', 'no-cache');
            res.header('Content-Disposition', 'attachment; filename=jhere-custom.js');
            return res.send(data);
        });
    }

    //Let's start with the first file
    f = files.shift();
    fetch(f);
}

Requests are currently not being executed in parallel, but since files have to be combined one next to the other and in the given order it was just easier to implement it this way. This was a simple first implementation but after I tested it I noticed it was being pretty slow. I realized it was not necessary to download all the files every time and combine them together. To make it faster I added a simple caching mechanism that caches a specific combination of files the first time it is requested, so the next time it can be served from cache. The cache is a simple object where keys are the hashes of the requested files and values are the resulting combination.

function isCacheable(data){
    return data && data.length < 102400;
}

function concatOnTheFly(files, res){
    var data = "", f,
    key = crypto.createHash('md5').update(files.join('-')).digest("hex");

    //Is this already in cache?
    if(cache[key]) {
        //Yep, then serve it from there!
        res.header('Pragma', 'no-cache');
        res.header('Content-Disposition', 'attachment; filename=jhere-custom.js');
        return res.send(cache[key]);
    }
    //Nope, then get the files
    function fetch(file) {
        var f;
        request.get({url: file}, function(error, request, body){
            if(error){
                return res.send(500, {error: 'error while fetching' + file});
            }
            data += body;
            f = files.shift();
            if(f) {
                return fetch(f);
            }
            //Prevents maliciouos requests from
            //saturating memory with lots of different requests.
            if(cachesize >= MAX_CACHE_SIZE) {
                flushCache();
            }
            //Also defend against big files
            if(isCacheable(data)) {
                //OK, everything should be alright now.
                //Cache this stuff.
                cache[key] = data;
                cachesize++;
            }
            //And return it.
            res.header('Pragma', 'no-cache');
            res.header('Content-Disposition', 'attachment; filename=jhere-custom.js');
            return res.send(data);
        });
    }

    f = files.shift();
    fetch(f);
}

This simple caching layer improved performance a lot. However adding a cache created a potential issue. If files are already in cache and I push a new version to Github that is not going to be picked up unless I manually flush the cache. Normally I tend to forget to do things like this though, so I needed an automated way to flush the cache after every push. Therefore I added a new endpoint: /flush.

app.all('/flush', function(req, res){
    if(req.query.auth === AUTH_CODE) {
        flushCache();
        var server  = email.server.connect({
           user: MAIL_USER,
           password: MAIL_PASSWORD,
           host: "smtp.gmail.com",
           ssl: true
        });
        server.send({
           text:    "Cache flushed on " + Date(),
           from:    MAIL_SENDER,
           to:      MAIL_RECIPIENT,
           subject: "jHERE Custom - Cache Flushed"
        }, function(err, message) {
            res.send(200, {result: 'OK'});
        });
    } else {
        res.send(401, {result: 'unauthorized'});
    }
});

This enpoint accepts both GET and POST requests and requires an authentication code passed as a query parameter. If the authentication code is valid then the cache is flushed and an email is sent to my email address. This way I can make sure that the cache is flushed when it should be and also be notified in case of malicious activity. To handle emails I am using emailjs.

To complete the automation part I added a webhook from the Github admin panel. This way every time I push a change my custom build server is notified, the cache is flushed and I receive an email.

Github Admin Console

This works very well, and I am pretty satisfied with the result, especially considering that it was not more than three hours of work.

The complete code can be found here. You will notice that AUTH_CODE, MAIL_USER, MAIL_PASSWORD, MAIL_SENDER, and MAIL_RECIPIENT are not hardcoded but rather read as environment variables from process.env. This way the source code can be shared without disclosing passwords or other information that should not be exposed.

Custom.jhere.net is deployed on Appfog. Although I am not a big fan of their command line tool, their service is pretty awesome, and you can get a very good free forever plan.

AppFog web console

Lately I have been pretty quiet, no blog posts since the beginning of October. There is a reason for this silence: both at work as well as at home I have been busy working on big projects.

Just yesterday during an event in San Francisco Nokia announced HERE, the new generation of digital maps. The whole personal maps team here in Berlin was completely focused on preparing for this event to deliver a great product our users can really enjoy.

At the same time I was working on the new version of jOVI, a jQuery plugin that I built more than a year ago as a simple wrapper to Nokia Maps API. In the last few months I have been lazily maintaining jOVI with some help from @thingsinjars, but the codebase was becoming very messy as we added more features that we needed for our hacks.

At Nokia we were going to deliver something great, HERE is something that will make an impact in the field of digital mapping platforms. Therefore, I decided it was time to make “a better jOVI”, so I dropped the current version and built something new from scratch. jHERE was born.

Announcing jHERE

My toolbox

jOVI was just something I put together very quickly, just a little more than a documentation-less hack. This time I wanted to do things the proper way.

My objectives were keeping the plugin small, clean and well documented. As a build tool I am using make, so I have a Makefile with a bunch of targets to lint the source code, minify the plugin ready for distribution and automatically generate the documentation from the comments in the code. I find much easier (and more likely to happen…) to document my API in the source code and then pull the documentation out with an automatic tool rather than keeping a documentation file up to date.

The whole lint, build, document pipeline is based on Node.js. I am using the jshint module for linting purpose (as well as SublimeLinter for Sublime Text 2 to catch the issues early), UglifyJS for minification and the awesome Docco to generate documentation. The cool thing about Docco is that you don’t have to bother with annotations: you just write your documentation inline with the code (Markdown Supported) and you can render the final result the way you want with an Underscore.js-kind-of-template.

Functionalities

jHERE is a pretty small jQuery plugin, it is about 4KB minified and 1.9KB once gzipped. It is however very powerful: when instantiated for the first time it takes the necessary steps do lazy load the HERE JavaScript API with all the necessary components. The functionalities that are exposed through the plugins are:

  • Creating a map
  • Setting map type
  • Setting center
  • Setting zoom level
  • Adding markers (with events)
  • Adding info bubbles
  • Displaying the content of KML files
  • Visualizing data via Heatmaps

For advanced usage via jHERE it is also possible to access the HERE JavaScript API directly, to invoke the native methods and instantiate native objects.

jHERE features

Support for Zepto.JS

I thought it’d be cool if jHERE supported Zepto.JS too. Zepto is a very small library if compared with jQuery (8.4KB vs 32KB with gzip) so developers may want to replace jQuery with Zepto when they don’t need the full jQuery API for their websites and save quite some bytes. Zepto’s API is jQuery compatible, but it is missing two features I am using in jHERE: $.data and $.Deferred.

To support Zepto I had to build a little (~900Bytes uncompressed) adapter containing a minimal implementation of the missing features. I say minimal because in order to keep it small I only implemented the functionalities/methods I needed, and not the complete API included in jQuery. This turned out to be a winning choice: the adapter is small and it works well.

jhere.net

This time I decided to tell more people about my work. It is very rewarding to see developers using stuff you’ve made. And if developers use it I’ll get feedback and I’ll have the chance to improve jHERE and make a good and useful piece of software.

For this reason I made a pretty website with demos, documentation, Twitter and Facebook buttons: it has everything that is needed. Plus it has an awesome playground built by @thingsinjars. He has really done a great job in building this space where devs can play with code and save the results of their exploration as Gists.

Wrapping up

With jHERE it is super easy to add maps to your blog or website. So if you feel like giving it a try just visit the playground and start making beautiful maps. And of course do no hesitate to ask questions, raise issues, and even contribute. Fork jHERE on Github!!

As I mentioned in a previous post, September Mozilla Dev Derby was focused on geolocation. I submitted two demos for the derby, that I used as a chance to experiment a little bit more than I do at work with Nokia Maps APIs.

The second demo I submitted that I called Neighborhood Hangouts is what I am going to talk about in this post. Neighborhood Hangouts is a simple little application that uses heat maps to nicely display on a map where people hang out in a neighborhood, and what are the places that are liked the most.

The application is pretty simple, therefore I think it is well suited to be used for a step by step tutorial on using Geolocation in the browser.

First of all I have to mention that Geolocation is not part of the HTML5 specification. It is instead a separate specification that is now a W3C Proposed Recommendation. There is lots of confusion about what is and what is not HTML5: Geolocation is not.

Building location aware applications in the browser

As specified by the W3C Recommendation:

The Geolocation API defines a high-level interface to location information associated only with the device hosting the implementation, such as latitude and longitude. The API itself is agnostic of the underlying location information sources. Common sources of location information include Global Positioning System (GPS) and location inferred from network signals such as IP address, RFID, WiFi and Bluetooth MAC addresses, and GSM/CDMA cell IDs, as well as user input. No guarantee is given that the API returns the device’s actual location.

This means that browsers expose at a high level a standard way to retrieve the user’s position, hiding from the developer the way in which the position is actually retrieved. Geolocation is well supported in all modern browsers. It is not supported by Internet Explorer 7 and 8.

If your application targets only very recent browsers you may just assume Geolocation is supported. However doing feature detection is very easy and it is one line of code. Therefore it is probably worth to just do it, so we’ll start from there.

if('geolocation' in navigator) {
    //cool, we've got Geolocation support
} else {
    //never mind, our app won't be location aware.
}

Once support is verified, we can then use Geolocation and get the user’s position. Note that the Geolocation is an asynchronous API, therefore we need to provide callbacks for when the position has been determined or an error condition has been detected.

function doFancyThingsWithPosition(position){
    var latitude = position.coords.latitude,
        longitude = position.coords.longitude;
}

function errorOrPositionNotAvailable(error){
    //error.code =  1 => PERMISSION_DENIED
    //error.code =  2 => POSITION_UNAVAILABLE
    //error.code =  3 => TIMEOUT
    //error.code = -1 => not supported by this browser
}

if('geolocation' in navigator) {
    //cool, we've got Geolocation support
    navigator.geolocation.getCurrentPosition(doFancyThingsWithPosition,
                                             errorOrPositionNotAvailable)
} else {
    //never mind, our app won't be location aware.
    errorOrPositionNotAvailable({code: -1});
}

Here we go, this is a skeleton for a very basic location aware application. As you can see from the code, when everything goes as expected there is nothing complicated. The callback argument is simply an object, that among other often less relevant properties contains a coords object with latitude and longitude values. The error callback receives an error object as the only parameter. One interesting property of this object is code. The standard specifies three possible error conditions:

  • PERMISSION_DENIED: the location acquisition process failed because the document does not have permission to use the Geolocation API, which means the user denied to the browser the permission to detect the current location.
  • POSITION_UNAVAILABLE: the position could not be determined by the device.
  • TIMEOUT: a timeout has expired before the location could be determined.

In addition to these standard error conditions I find convenient to use the same callback to notify the user when the browser does not support Geolocation. In order to do this I manually call the error callback passing an error object with error code set to -1.

It is worth to mention that navigator.geolocation.getCurrentPosition accepts also a third parameter, called PositionOptions. PositionOptions is an object that contains the following properties: enableHighAccuracy, timeout, maximumAge. The name of the properties is probably self explaining, but detailed information can be found on the W3C website.

Fancy things you can do with location information

Having the user’s location is quite nice. When an application is location aware it is able to provide content based on the user’s location: this really creates great value for the user. It is possible for instance to display events or interesting places in the area where the user is located.

There is plenty of public APIs that provide geotagged data of any sort to developers. Photos on Flickr are often geotagged, tweets may contain some geolocation information, Facebook events contain the location of the place where the events are happening, and both from Facebook as well as from Foursquare it is possible to retrieve geotagged checkins from you social graph.

A very basic location aware application can be as simple as grabbing the user’s location as explained in the previous section, doing a search around that location using one of the many APIs that support geotagged data and show to the user relevant data generated around her position. Data can be visualized in many ways, but the first one that comes to mind given the geographical nature of the information is of course a map. Nokia Maps has a pretty good Maps API that can help making beautiful map-based visualizations. In addition to that for the simple things, e.g. displaying geotagged tweets, I wrote jOVI, a nice jQuery plugin that wraps Nokia’s API providing a very intuitive jQuery-style interface for creating maps, handling basic events, displaying pins and bubbles. Feel free to use it, give me feedback and submit pull requests.

Neighborhood Hangouts

One thing that I have been exploring lately is visualizing geotagged information that doesn’t come from my social graph, but rather from people in my neighborhood.

While I do think that my preferences in terms of restaurants, bars and clubs possibly match my friends’ preferences, I think that all this “we look at your social graph to show you the places you like” is mostly nonsense: out of my 218 Facebook friends, only 10% are located in the country where I live. Therefore the places my friends like are likely to be thousands of kilometers away, and I am not going to fly to America to get a drink in a nice place.

So I built Neighborhood Hangouts. This application uses Foursquare’s public data about checkins around a given location (the user’s detected position) to display on a map what are the areas in the neighborhood where people like to hang out (based on the density of the checkins) and what are the popular places (based on the number of checkins). To make the data more meaningful I chose to display it adding heat map layers on top of a map generated with Nokia Maps API. It turned out to be a great choice. I believe heat maps are awesome to show this kind of information in a clear and beautiful way.

Neighborhood Hangouts Screenshot

The well commented JavaScript code for Neighborhood Hangouts can be found here.

If you read up to this point - long post, I know - you should have all the ingredients you need to build a great location aware application in the browser.

It is the middle of September already. This month the Mozilla Dev Derby is focused on geolocation, and I decided to participate again after the not-so-exiting result with the Websockets derby.

mozilla dev derby

This time I wanted to come up with something simple but at the same time nice and effective. I thought a game experience build with HTML5 and the geolocation support would have been a nice idea. After thinking for a while about what I could implement I came up with this Find your Tile idea. In Find you Tile users are shown 3 map tiles - in satellite view. One is centered on their current location (detected via the geolocation API) and the other two are centered on a random city picked from a static list of more than 600 cities around the world.

find your tile

The goal for players is to pick the right map tile for their location. Nothing super exiting but still a demonstration of the cool stuff you can do by using a couple of interesting APIs together. If the player gets the answer wrong, along with the you picked the wrong one message a link to the Wikipedia page corresponding to the city where the wrongly picked tile is centered is provided. This way, in addition to being a game experience it is also a learning experience, as the player has the possibility to discover new cities and read all about them in the best encyclopedia in the world.

In this project I decided not to use jQuery or any other libraries. Instead I wrote everything in pure JavaScript, and since the demo only targets modern browsers I could use stuff like document.querySelector and document.querySelectorAll (IE >= 8), or array.forEach (IE >= 9) and of course navigator.geolocation (IE >= 8) since that was the point of the demo. I also added some nice animation effects with CSS3. I have to say it was fun. jQuery is very very convenient, it always makes our life easy. But it is not always appropriate for the use case (it should always be avoided on mobile for instance), so it is good to learn how to live without it. And this was the perfect excuse to prove I could do it.

The implementation is very simple, and does not require much explanation. The code is open source and available on Github.

To retrieve map tiles corresponding to the desired location I used the RESTful Maps API by Nokia. It is pretty nicely done and it has many customization options. Register your API key and play with this and the other APIs. Making things with maps can be fun. Like when thingsinjars and I built Soundscape.

To generate random tiles instead I had to Google for a while until I found a list of cities with their coordinates. I luckily found one that also includes the Wikipedia handle, so I could add the link to the Wikipedia page as well. Initially I thought I would just randomly generate a coordinate pair and center the two random tiles in there. But since there are approximately 70% chances of generating tiles that are just shades of blue, as 71% of the planet’s surface is covered by oceans and smaller seas I decided to go for the static list. Which I had to manually parse and go through all the cities to geocode them, as most of the coordinates initially in the list were for some reason wrong. Nothing that a simple Node.js script can’t do though.

One thing that I like a lot is the flipping animation of the map tiles. The HTML elements are initially rotated 180 degrees around the Y axes, so the white back is shown. Once the image.onload event is fired on each of the images, JavaScript adds the back CSS class to the element. At that point a CSS transition happens and the card smoothly flips. Awesome. Here is how you do it:

/*The element containing the tile*/
ol li {
    border: 15px solid #fff;
    box-shadow: 0 0 8px #ddd;
    width: 200px;
    height: 200px;
    display: inline-block;
    margin: 5px 20px;
    cursor: pointer;
    opacity: 0.9;
    position: relative;
    z-index: 95;

    /*The transform-style CSS property determines if the children
    of the element are positioned in the 3D-space or are
    flattened in the plane of the element.*/

    -webkit-transform-style: preserve-3d;
    -moz-transform-style: preserve-3d;
    -ms-transform-style: preserve-3d;
    transform-style: preserve-3d;

    /*Configure the transition*/
    -webkit-transition: all 1.0s ease;
    -moz-transition: all 1.0s ease;
    -ms-transition: all 1.0s ease;
    transition: all 1.0s ease;

    /*Initially flipped so the visible part is the back*/
    -webkit-transform: rotateY(180deg);
    -moz-transform: rotateY(180deg);
    -ms-transform: rotateY(180deg);
    transform: rotateY(180deg);

    /*Determines whether or not the back face of the element is visible
    when facing the user. The back face of an element always is
    a transparent background, letting, when visible,
    a mirror image of the front face be displayed.*/
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -ms-backface-visibility: hidden;
    backface-visibility: hidden;

    /*The rotation axis will be 30% from the left*/
    -webkit-transform-origin: 30%;
    -moz-transform-origin: 30%;
    -ms-transform-origin: 30%;
    transform-origin: 30%;
}

/*When back class is applied do the rotation*/
ol li.back {
    -webkit-transform: rotateY(0deg);
    -moz-transform: rotateY(0deg);
    -ms-transform: rotateY(0deg);
    transform: rotateY(0deg);
}

Lots of CSS, but mostly because of the prefixed rules. But in general pretty simple to understand.

//el is an img element
el.onload = function(){
    this.style.display = 'block';
    //Add the back class to trigger CSS transition
    this.parentNode.classList.add('back');
};

Here we go. With some simple JavaScript and CSS code and Nokia Maps API I built my demo for the Mozilla Dev Derby of this month. Enjoy it!

Note: I just realized the demo does not work in IE, not even IE9. Unfortunately the element.classList property (documented here) is not supported by IE. Oh well.

This week I was in Zurich to talk at Frontend Conf, a small but awesome swiss web conference. Since I was in Zurich I had the chance to attend a great Node.js workshop organized by Karolina Szczur and The Node Firm. The workshop was held by Paolo Fragomeni, co-founder and CTO at Nodejitsu.

The workshop had only a few attendants, and this was great because we had the chance to discuss about things that we thought are interesting for us rather than just stare at a guy going through his slide deck. If I had to give a rate to the workshop I would with no doubts say excellent and inspiring. Therefore if these guys organize a workshop near you and you are even only a bit interested in Node I encourage you to attend.

One of the things I loved about the workshop was the little hackathon we had at the end. 15-20 minutes to add a feature to a simple chat application built with Node and Socket.io.

I was pairing with Bertrand Dufresne and I suggested we could add the possibility of posting images in the chat. He initially looked at me as if I was crazy, but I was confident it was easy to do. Which turned out to be true. The next section explains how we did it, analyzing both the frontend as well as the backend code.

Reading the image on the frontend

The first part of the problem is reading the image on the client side. We don’t want to just have an upload form, instead it would be awesome if the image was read by the browser, streamed it through the web socket and then rebroadcasted by the Node server to all the other chat clients.

In terms of user interface, the user will be able to select a file from the filesystem or drag&drop a file do the Send Image button and at that point the file will be sent to the server. The image below shows the user interface and what happens when users post images.

To accomplish this we used a hidden input of type file and the FileReader object to read the selected file and convert it to a base64 string that is sent through the web socket. This technique is supported only by modern browsers, but in this case we didn’t really care about cross browser support.

The code is very very simple, and I believe not much explanation is needed.

//Bind the onchange event for the file input
//using jQuery.
$('#imagefile').on('change', function(e){
    //Get the first (and only one) file element
    //that is included in the original event
    var file = e.originalEvent.target.files[0],
        reader = new FileReader();
    //When the file has been read...
    reader.onload = function(evt){
        //Because of how the file was read,
        //evt.target.result contains the image in base64 format
        //Nothing special, just creates an img element
        //and appends it to the DOM so my UI shows
        //that I posted an image.
        //send the image via Socket.io
        socket.emit('user image', evt.target.result);
    };
    //And now, read the image and base64
    reader.readAsDataURL(file);  
});

Broadcasting to all clients on the backend

At this point the image as a base64 string made all the way to the server, and now we have to broadcast it to all the clients.

I am only going to include some extracts of the code here, the rest can be found in my fork of the original Git repository.

//...
//Require socket.io
var sio = require('socket.io');
//...   
//Create HTTP server
var app = require('http').createServer(handler);
app.listen(8000);
//...   
//Add socket.io
var io = sio.listen(app);
//...   
//And bind events
io.sockets.on('connection', function (socket) {
    socket.on('user image', function (msg) {
        //Received an image: broadcast to all
        socket.broadcast.emit('user image', socket.nickname, msg);
    });

    socket.on('user message', function (msg) {/*See source code*/});
    socket.on('nickname', function (msg) {/*See source code*/});
    socket.on('disconnect', function () function (msg) {/*See source code*/});
});

Note that when calling the broadcast function on a socket object the message is broadcasted to all the sockets connected but the one it was received from.

Receiving and displaying the image on the frontend

Still super-easy. The src attribute of an img element can be set to a base64 string instead of to a URL, and the browser will just display the image.

Therefore when the image is received it is just a matter of adding an img element to the DOM with the src attribute set to the content of the message received via Socket.io.

socket.on('user image', image);

function image (from, base64Image) {
    $('#lines').append($('<p>').append($('<b>').text(from),
        '<img src="' + base64Image + '"/>'));
}

As you can see from the code snippets posted here and by reading the code on Github it is very easy to build simple websocket-based web applications using Node and Socket.io. With the FileReader support it is also simple to read a file, in this case an image, from the filesystem and do cool things with it.

During my research week at Nokia Maps I decided to work on some new, experimental features that required to store some user preferences and that allow users to upload files.

However I really did not feel like writing lots of backend code, running up and down to the system engineers offices and go through all the required steps to obtain a server for storage for a project that may never be deployed in production.

Therefore I decided to use the cloud. I did some research, hoping to find a service that would allow me to use a remote database or any other kind of storage in the cloud via a simple REST API.

Firebase

The closest and most simple API I could find was Firebase. These guys created an amazing service that provides to developers the capability of reading and writing data into a scalable database hosted in the cloud with no need for any kind of backend code. Really really awesome! Unfortunately I received my beta code only at the end of the week, so I really did not have enough time to experiment with this API. But I will play with this nice service soon and give some feedback to the super nice guys at Firebase.

Filepicker.io

A couple of days ago I was reading through my news stream, and I discovered another new service, that turned out to be exactly what I needed. Filepicker.io offers an incredibly easy to use API to enable web applications to take advantage of well known services such as Box, Dropbox, Flickr, Google Drive for storage.

Normally, when a web application allows users to upload files, the only solution is the well known file input.

This is somehow a limitation: first of all it requires some backend code to handle the upload, disk space is required to store all the users’ files and there may be some legal requirements to handle sensitive data. Even more importantly, many users store their photos, documents and files in the cloud rather than on their computer, and it would be really useful if the file input could go beyond just allowing users to pick a file from the local filesystem.

Well, this is exactly what Filepicker.io does. It provides an alternative to the file input, enabling users to upload files from the local filesystem, or from any of the many services on the Internet where you may store data, photos, movies, code, etc., no backend code required. Wow!

image

The documentation is pretty well done, and in no time I was able to build my first application that takes advantage of cloud storage.

My Trails is a simple little application that uses Nokia Maps API to display a KML file on the map. I find it very useful to plan a hiking trip for instance. I have some of my favorites trails stored into a folder on Google Drive, and via Filepicker.io I can easily select one and display it on the map (Filepicker.io API is CORS enabled).

Additionally, using drag&drop I can view KMLs from my local filesystem. In case you want to try this feature here are some KML files you can play with.

And here some pretty screenshots of My Trails.

imageimage

I think Filepicker.io is a great project, the API is simple and it allows developers to build applications that interact with user data without the need of storing it. So users (or, unfortunately Google) still own their data that they keep in the cloud but have the possibility to make it available for any web application via Filepicker.io. Probably browser vendors should consider including a native solution to pick files from the cloud in their browsers.

But until then, good job Filepicker.io guys!

Last week I was working on a feature that requires a rating widget. Along with reviews users can submit a rate, that is later on displayed with stars. It would have been nice if users could use a nice widget that allows them to vote instead of using an ugly radio input. Additionally I wanted the widget to look exactly the same as the UI element that we then use to show the final ratings, which meant using the same CSS sprite we use for everything else.

The final result was quite nice, so I decided to write a little tutorial on how to obtain the same result. I will walk you through the creation of a beautiful beer rating widget, which only uses semantic markup and CSS for styling. No JavaScript here at all. Note however that to have the widget actually do something useful a little bit of JavaScript is required, for instance to set the value of a hidden input field or to post the rating to the backend.

The rating widget I am going to describe handles mouse hover as well as clicks via the :target pseudo selector. To display the beer mugs I am using a sprite that can be downloaded from here and looks like this:

image

The user can beer-rate something from 1 beer to 3 beers, and depending on the rate the sprite is moved left and right to show in color the given rate.

The markup is very simple and pretty sematic. I am only using an helper div inside each of the list elements to display the sprite in the right position.

<ul class="rating-widget">
    <li class="rating-0-beers beer checked" id="rating-0-beers">
        <a>Not voted</a><div></div>
    </li>
    <li class="rating-1-beers beer" id="rating-1-beers">
        <a href="#rating-1-beers">Mee</a><div></div>
    </li>
    <li class="rating-2-beers beer" id="rating-2-beers">
        <a href="#rating-2-beers">Ok Beer</a><div></div>
    </li>
    <li class="rating-3-beers beer" id="rating-3-beers">
        <a href="#rating-3-beers">Awesome beer</a><div></div>
    </li>
</ul>

The CSS code is probably a little bit obscure, but we’ll go through it bit by bit.

First styling of the ul element. Nothing special here:

.rating-widget {
    margin:0;
    padding:0;
    height: 64px;
    list-style-type: none;
}

I am just resetting margin and padding (you may have a CSS reset or normalize.ccs already), setting the height to the height of the sprite and removing any list-style-type.

Then the links. The link is ideally as big as the li elements. So I will position it absolutely to use all the space and worry about size later on.

.rating-widget a {
    background: transparent;
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    text-indent: -100px;
    overflow: hidden;
}

Since the a elements contain text to be more semantic and to be accessible by screen-readers we set overflow: hidden and a pretty big negative text-indent to make sure the text is always hidden.

Then the helper divs. These elements have no semantic value, but are the keys to make the widget good looking by displaying the appropriate number of highlighted beer mugs. They are set to be the size of 1 by 3 mugs in the sprite. Also their z-index is set to -2 so make them always be in the lower “layer” and their display property is set to none, so only the appropriate one can be set to be visible at any given time.

.beer div {
    background: transparent url(http://marcon.me/blog/code-resources/css-rating/beer-sprite.png) 0 0 no-repeat;
    height: 64px;
    width: 201px;
    display: none;
    position: relative;
    z-index: -2;
}

The position property is set to relative because these elements are then moved left and right to show them in the right place. divs are always positioned to be spread on top of the whole widget, as follows.

.rating-0-beers div {background-position: -203px 0; left: 2px;}
.rating-1-beers div {background-position: -137px 0; left: -1px;}
.rating-2-beers div {background-position: -70px 0; left: -69px;}
.rating-3-beers div {background-position: -3px 0; left: -137px;}

These values in px may seem completely random, especially the left positioning. Well, they are a bit. I really suck at Photoshop, so my sprite was a little off and I had to tweak these rules to make it work properly.

With the 3D Inspector that comes with the recent releases of Mozilla Firefox it is possible to better understand the positioning of this div (on top, in light blue) in relation with the position of the other elements.

image

An additional rule makes sure the appropriate div that contains the sprite in the right position is displayed when the list item is hovered, targeted or marked with the checked class (useful for interaction with JavaScript for instance).

.beer:target div,
.beer.checked div,
.beer:hover div {
    display: block;
}

The following trick moves the div inside the li that is hovered up one level. Still in the negative range so the links and lis stay on top and can be selected but on top of all the other helper divs. This way even when a rate is selected it is still possible to hover another rate and the corresponding sprite will be shown on top.

.beer:hover div{
    z-index: -1;
}

The li are style as follows:

.beer {
    display: inline-block;
    width: 64px;
    height: 64px;
    margin: 0;
    padding: 0;
    overflow: visible;
    position: relative;
}

They are inline-block so they are displayed in the same line. They have width and height set to the size of a beer mug icon, have overflow: visible so the helper div which is bigger can be displayed entirely and have position: relative so the link can be correctly positioned absolutely.

Last but not least:

.rating-0-beers{
    width: 0;
}

For the unrated state, which is also the one checked by default, the width is set to 0 as it is not a clickable state, so once a rating is selected it is no longer possible to unset it, but only to select a different one.

And now the final result. Here is the beer rating widget:

@thingsinjars giving an overview of the Web Audio API and covering the basic concepts and then my presentation that shows how we used it in SoundScape - a mashup to position audio samples on a map to make a 3D audio experience.

(Source: vimeo.com)