Safari and long lines in Google Maps Javascript API Directions Service

11th October, 2012 - Posted by david

I’ve been working on building the mobile version of CarsIreland.ie lately and one of the features we want is to offer directions from a user’s current location to any of our car dealerships, assuming we have their latitude and longitude co-ordinates. Getting the directions and displaying them on a map are ridiculously simple, thanks to Google’s Direction Service API. Going into the detail of getting this working is beyond the scope of this post, but what I hope to show here is how to resolve an issue in mobile (and possibly desktop) Safari, and maybe even some other browsers.

When you have instantiated your new google.maps.DirectionsService() and called it’s route function, passing your source and destination (among other things) as parameters, you’re supposed to give a callback function with response and status parameters. Assuming the call to route was successful, the response parameter should be a big JSON block of at least one route and step by step guides detailing how to get from source to destination. Conveniently, Google also provide a very handy object called a DirectionsRenderer, which has a function called setDirections, which can generate a nicely formatted HTML table of directions. See https://google-developers.appspot.com/maps/documentation/javascript/examples/directions-panel for an example.

The problem I experienced and am aiming to solve here is that some of the directions (in Ireland at least) involve very long motorway/freeway names, where each junction is separated by a ‘/’, but with no spaces. This can lead to very long strings of the format ‘Long/And/Winding/Junction/Name’. Add in the fact that they also include the Irish/Gaelic translation for some words and it gets even longer! When viewing this steps on Android’s Dolphin or even a desktop Firefox, the browser recognizes that it can split the line at the ‘/’ and thus doesn’t widen the page. Safari unfortunately doesn’t do this and forces very wide page widths, which makes the page look awful. So, today I figured a way to resolve this.

What I did was traverse the response object you get back from Google, looking at each instruction step, trying to find one of these long strings, and replacing the ‘/’ with ‘ / ‘, i.e. a space character on either side, so Safari will then break the lines and not force a wide page. Doing a simple string replace wasn’t sufficient, as some of the instructions contain HTML tags, which can have ‘/’ in them that we ideally want to keep.

So first up is the Javascript regular expression to find matching instances of “long/string”. In simple terms, it’s any alpha-numeric character, followed by a ‘/’, followed by another alpha-numeric character. In Javascript I came up with:

var patt = /([a-z0-9]{1})\/([a-z0-9]{1})/gi;

The gi at the end of the pattern means global search (i.e. don’t stop at the first match), case insensitive (hence no ‘A-Z’ is required).

Now, all we have to do is cycle through the response, looking for routes, legs, steps and instructions and replacing as necessary, via a string’s replace function:

// e.g.
var repl = "$1 / $2";
instruction = instruction.replace(patt, repl);

So, to loop through the response and do the replacing, we need a few nested for loops, our pattern and our replace sequence, as follows:

if (typeof response['routes'] != 'undefined') {
  var patt = /([a-z0-9]{1})\/([a-z0-9]{1})/gi;
  var repl = "$1 / $2";
  // cycle through each route
  for (var i=0; i<response['routes'].length; i++) {
    var route = response['routes'][i];
    if (typeof route['legs'] != 'undefined') {
      // cycle through each leg in that route
      for (var j=0; j<route['legs'].length; j++) {
        var leg = route['legs'][j];
        if (typeof leg['steps'] != 'undefined') {
          // cycle through each step in that leg
          for (var k=0; k<leg['steps'].length; k++) {
            var instructions = leg['steps'][k]['instructions'];
            // if we've found an instruction with a matching pattern
            if (instructions.match(patt)) {
              // do the replace
              response['routes'][i]['legs'][j]['steps'][k]['instructions'] = instructions.replace(patt, repl);
            }
          }
        }
      }
    }
  }
}

So, hopefully this well help people experiencing the same problem I was having with the long strings caused by a lack of spaces between ‘/’ characters! As an alternative, one may just wish to only have a space after the ‘/’, in which case, the replace pattern becomes "$1/ $2".

Tags: google maps javascript regex | david | 11th Oct, 2012 at 21:35pm | No Comments

No Comments

Leave a reply

You must be logged in to post a comment.