I'm almost managing to keep to my intended schedule of one map-based web experiment per week. Unfortunately, I've mostly been working on internal Nokia Maps projects over the weekends recently so I've not had much to post here.

I can share my latest toy, though: CoverMap.me

Using just the public APIs over a couple of hours last Sunday afternoon, I made this to allow you to set a Nokia Map as your Facebook Timeline cover. The whole process is really straightforward so I thought I'd go over the main parts.

The exact aim of CoverMap.me is to allow the user to position a map exactly, choose from any of the available map styles and set the image as their cover image.

Make a Facebook App

Go to developers.facebook.com/apps/ and click 'Create New App', fill in the basic details ā€“ name of the app, URL it will be hosted on, etc ā€“ and you're done.

Facebook login

I've used the Facebook JS SDK extensively over the summer for various projects but I wanted to try out the PHP one for this. Super, super simple. Really. Include the library (available here), set your appId and secret and request the $login_url.

$facebook->getLoginUrl(array('redirect_uri' => "http://example.com/index.php"));

That will give you a link which will take care of logging the user in and giving you basic access permissions and details about them.

Nokia Maps JS API

When I'm hacking together something quick and simple with the Nokia Maps API, I usually use the properly awsm jQuery plugin jOVI written by the equally awsm Max. This makes 90% of the things you would want to do with a map extremely easy and if you're doing stuff advanced enough to want the extra 10%, you're probably not the type who'd want to use a jQuery plugin, anyway. Either way, you need to register on the Nokia developer site to get your Nokia app_id and secret.

To create a map using jOVI, simply include the plugin in your page then run .jOVI on the object you want to contain the map along with starting parameters:

$(window).on('load', function() {
  $('#mapContainer').jOVI({
    center: [38.895111, -77.036667], // Washington D.C.
    zoom: 12,           // zoom level
    behavior: true,     // map interaction
    zoomBar: true,      // zoom bar
    scaleBar: false,    // scale bar at the bottom
    overview: false,    // minimap (bottom-right)
    typeSelector: false,// normal, satellite, terrain
    positioning: true   // geolocation
  }, "APP_ID", "APP_SECRET");
});

This gives us a complete embedded map.

As I mentioned above, part of the idea for CoverMap.me was to allow the to choose from any of the available map styles. This was an interesting oddity because the public JS API gives you the choice of 'Normal', 'Satellite', 'Satellite Plain' (a.k.a. no text), 'Smart' (a.k.a. grey), 'Smart Public Transport', 'Terrain' and 'Traffic' while the RESTful Maps API (the API that provides static, non-interactive map images) supports all of these plus options to choose each of them with big or small text plus a 'Night Time' mode. Because of this, I decided to go for a two-step approach where users were shown the JS-powered map to let them choose their location then they went through to the RESTful static map to allow them to choose from the larger array of static tiles.

RESTful Maps

The RESTful Maps API is relatively new but does provide a nice, quick map solution when you don't need any interactivity. Just set an img src with the query parameters you need and get back an image.

(this should be all on one line)
http://m.nok.it/
    ?app_id=APP_ID
    &token=APP_TOKEN
    &nord       // Don't redirect to maps.nokia.com
    &w=640      // Width
    &h=480      // Height
    &nodot      // Don't put a green dot in the centre
    &c=38.895111, -77.036667 // Where to centre
    &z=12       // Zoom level
    &t=0        // Tile Style

That URL produces this image:

Map of Washington D.C.

Upload to Facebook

Given the above, we've now got an image showing a map positioned exactly where the user wants it in the tile style the user likes. We just need to make the Facebook API call to set it as Timeline Cover Image and we're done.

You'd think.

Facebook doesn't provide an API endpoint to update a user's profile image or timeline cover. It's probably a privacy thing or a security thing or something. Either way, it doesn't exist. Never fear! There's a solution!

With the default permissions given by a Facebook login/OAUTH token exchange/etc... (that thing we did earlier), we are allowed to upload a photo to an album.

The easiest way to do this is to download the map tile using cURL then repost it to Facebook. The clever way to do it would be to pipe the incoming input stream directly back out to Facebook without writing to the local file system but it would be slightly more hassle to set that up and wouldn't really make much of a difference to how it works.

// Download from RESTful Maps
$tileUrl = "http://m.nok.it/?app_id=APP_ID&token=APP_TOKEN&nord&w=640&h=480&nodot&c=38.895111,%20-77.036667&z=12&t=0";
$ch = curl_init( $tileUrl );
$fp = fopen( $filename, 'wb' );
curl_setopt( $ch, CURLOPT_FILE, $fp );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_exec( $ch ); 
curl_close( $ch );
fclose( $fp );

//Upload to Facebook
$full_image_path = realpath($filename);
$args = array('message' => 'Uploaded by CoverMap.me');
$args['image'] = '@' . $full_image_path;
$data = $facebook->api("/{$album_id}/photos", 'post', $args);

The closest thing we can do then is to construct a Facebook link which suggests the user should set the uploaded image as their Timeline Cover:

// $data['id'] is the image's Facebook ID 
$fb_image_link = "http://www.facebook.com/" . $username . "?preview_cover=" . $data['id'];

Done

There we go. Minimal development required to create a web app with very little demand on the user that gives them a Nokia Map on their Facebook profile. Not too bad for a Sunday afternoon.

Go try it out and let me know what you think.