Google Maps – The Bits They Don’t Tell You

I’ve done quite a lot of work with the Google Maps JavaScript API in the last year or so. I think I’ve picked up quite a bit along the way, which you won’t find in the official reference guide.

When I first started working with it, one of my favourite things was the excellent documentation that came with it. Sadly, since the shift to Material Design, it’s now very difficult to navigate and find anything. In fact, I’ve pretty much given up on it. It’s a lot easier to just use Stack Overflow.

Here are some fairly basic things I found, which, depending on your project, might make life easier.

Use a map object
Using an overarching object to hold anything map related – data arrays, functions, etc. really helps when you’re using dynamic data or lots of other JavaScript. It’s basically just a namespace, package or module.

Push overlays into arrays
When you add any overlay, for example a marker or polygon, the normal process is to read the geo data out of an object or array and use it to add the overlays. However, if you then want to interact with those overlays you have no way of selecting them. When you create an overlay push it into an array. That way you can loop through the items or select one by its index.

Add key or id property to get an overlay easily
In addition to adding an overlay to an array you can give it its own custom property like an id or key so that you can select it without knowing its index. The Google Maps overlay objects, which can have properties like fillColor, map, position, etc. are actually just JavaScript objects so you can add your own properties. You can then use filter() to access an individual overlay from the array or you can alias it with a variable.

Use polygons appropriate for zoom range
If you define a polygon it will work at any zoom range. For your map usage it’s worth considering if you need to allow the full zoom range to be used. It might be easier to limit it. Imagine a polygon for the outline of France. If you’re zoomed right out, looking at the world you can get away with just a hexagon shape. If you zoom in close you need to pick out each little twist and turn in the coastline. See what you need and use simplified polygons for speed and performance where possible.

Use dynamic SVGs as icons
You can use your own image files as markers instead of the standard pin. However, these don’t have to be static image files. You can create your own function which takes parameters for colours or values and uses these to return an SVG including these details. You can then set this function as the icon image.

Set bounds and extend them
When you create a map, also create a bounds object. This holds location data for the top right (NE) and bottom left (SW) of a box, which determines the portion of the map shown on screen. It manages the zoom level for you. Whenever you add a new overlay to your map you can extend these bounds so that all of your overlays will always be shown.

What I Learned in 2014: Part 2 – Javascript and Google Maps

This is the second part of a three-part article looking back at what new web things I’ve learned in 2014. This part focuses on JavaScript.

JavaScript and jQuery

This is a big area, probably the area where I have made the most progress in the last year. The main shift for me has been from doing everything in jQuery, which I learned first, to using native JavaScript. Hopefully by learning to do more with native Javascript I can cut down on the jQuery bloat, especially in mobile friendly pages.

In “vanilla JavaScript” I’ve learnt to use a few new built-in functions, which perform very well in modern browsers. One of the things that really slows down a page’s performance in JavaScript is looping through a long list of items and performing various operations within each. I’ve learned four new functions which perform operations very quickly – map, filter, forEach and reduce. I would urge anyone using standard for loops to look into these. One for loop operation I tried on a list of 10,000 items killed Chrome. Switching to using map it worked in under a second. I believe that jQuery’s each and filter functions already leverage these bult-in functions. The other useful thing I’ve discovered when working with loops is to move anything you can outside of the loop, e.g. a function. Don’t declare it every time – just do it once and call it each time.

I’ve finally got the hang of the ternary operator. This just means that I can now write my conditional statements in a much more compact way, things like return (confirmed) ? true : false;. If the variable ‘confirmed’ is truthy, return true, otherwise return false.

A great discovery in the last couple of months has been the hashchange event. The browser can detect changes to the part of the URL that appears after the #. This means that when we use links to change something like filter the data in a table, instead of the link’s href bring empty or set to the meaningless “#”, we can put something meaningful in there. For example our href could be “#female” and the URL will change to reflect this. The hashchange event will listen for this change and we can then grab the part after the hash symbol using window.location.hash and do our filtering. This has the added bonus of appearing in the browser’s history so the user can hit their back button to undo a filter. Much better and feels like this is how it’s supposed to work.

I think I’ve now understood how to properly use functions and objects in JavaScript to set the appropriate scope for variables. Wrapping functionality in functions means that each function is its own self-contained unit, which means no unexpected or conflicting references cropping up and it makes the code easier to maintain and test.

Earlier this year I wrote a jQuery script to handle pagination in a HTML table. I won’t go into the horribly complicated detail here but the learning point for me was to get the logic clear in my mind before getting into the code. I actually went back to pen and paper, sketching out the various scenarios and then finding the patterns to create my code.

JavaScript Frameworks and jQuery Plugins
Thanks to a very patient colleague I’ve now got a much better grip on Angular.js. I can now work with not just binding data in the HTML but can also write directives to create new page components and services to handle commonly required functions.

As part of the Angular work I’ve also learned how to do Unit Testing using the Jasmine framework. Unit testing always felt like a lot of extra work to me but now I see that having a long list of small tests that run is invaluable. It gives you the freedom to write new code knowing that any knock-on effects you create in the process will be picked up. It makes for far more robust and less buggy code.

Recently, I’ve implemented 2 jQuery plugins into a project, tablesorter for automatically sorting the rows of a table by clicking on a column heading, and elevateZoom for adding the capability of zooming in on a thumbnail image, like we often see on clothing details pages. Both are very well written with a lot of options available. Using these has made me realise that I can now go into the code of the plugins and actually follow (more or less) what is going on. I hope to be able to write and share some of my own in the next couple of years.

Google Maps API v.3

I’ve now spent a few months working with this API and have got a good understanding of how it works and how it can be used and extended to do more. I created my own utility library of functions for all the things I need to do regularly – draw markers and polygons with info windows which appear on click, calculating areas, converting area units, adding data layers and heatmaps, encoding/decoding polygon paths, adding new map controls, etc. There was also some more advanced functionality in there too which goes beyond what’s included in the API – calculating the optimal bounds (map viewport) to show a number of polygons, determining the direction or winding (clockwise or anti/counter-clockwise) of a polygon, calculating the centroid (centre from the average coordinates of points) of a polygon.

I’ve also used some third party features to extend the mapping functionality. One of these has allowed me to cluster markers so rather than have a lot of marekrs close together on screen we show a number of markers, much neater. Another has enabled me to place text labels on the map, which isn’t possible out-of-the-box.

The key tricks that I have picked up along the way are to 1) push any markers or polygons into an array so you can access them easily in JavaScript and 2) add your own custom properties to the native objects for markers and polygons, e.g. id or name, so that you can identify them easily in code.