Using MarkerClusterer and MarkerWithLabel with Google Maps

Both MarkerClusterer and MarkerWithLabel are great libraries, but they do have their quirks;


What is a cluster marker?
MarkerClusterer doesn't use Google Markers or pin styles, it takes an image path and creates HTML on a layer. The resultant markup is given a class of 'cluster' that you can target in your CSS.
Do I have to pass set an image path for the marker?
Yes. You can amend that in the source code*, just check for the image path where the IMG tag is created and only add it if the path is defined.
How do I set the zoom level where clusters become active?
The minimum level at which clusters are visible is set through the maxZoom property. Note: This property also affects the click action of the clusters, if you click on a cluster pin and the zoom level exceeds the maxZoom, the zoom is reset. Again, you can amend this in the source code*, it's not configurable.
On a small screen clicking a cluster doesn't zoom in
When setting Google Maps to show a boundary it tries to maintain spacing between that boundary and the edge of the container. This can be a pain on small screens because we're short on screen space already, to work around this for the cluster markers we again need to go into the source code*, we need to store the maps current zoom level and then test it once the boundary has been set. If the zoom level has not been changed then increase the zoom level manually.
Clicking on a cluster of a single pin zooms in too far
The easiest way to avoid this is to set the maximum zoom level of the Google Map.
Can I set the line-height of a ClusterMarker?
Weirdly, no. The line-height is being used to vertically align the counter so is set to match the height. If you want to change that you have to got into the source. For the other options you can pass in inherit to override defaults.

*Amended source code (GitHub)


Can I set the pin background images / hover states though CSS?
Pin images can be null, this allows us to set the images through CSS and set hover states. When doing this you might want to set a background size property to enforce the pin sizes. Note: IE11 does not render SVG markers correctly.
Why do marker labels show through other markers?
The labels do not exist in the same layer as their Google Markers so do not obey the same z-index values as their partner. If you must enforce the z-index order then apply the pin styling to the marker label using background images.
Setting a markers z-index puts it under other markers
Markers have a zIndex already set, if you want to amend this position you probably should use the original z-index value as the start point using marker.getZIndex().
Why are the pins too big on iOS?
Pins size and scaledSize must be integers, strings will cause hard to debug issues with click regions.

Centering a boundary on a point

As mentioned markerClusterer uses boundaries to show the markers, we need a custom function to center a boundary. I've written a Gist to enable this, it's had limited testing as it didn't go into the production version but you can find it at: Center a boundary on a point.

Using jQuery.ajax rather than jQuery.load

jQuery.load is an incredibly useful method, but if you want to do more with the returned source than put it into a div then you may want to use jQuery.ajax directly with your own callback.

The source code for the load method is a great starting point for writing your own callback, in particular how the 'done' callback selects the items to append;

jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector );

This is most likely what you're looking to amend by using your own callback. The parseHTML method creates an HTML fragment and then appends it to a div (this div is an orphan, it is never inserted into the DOM).

You may, for example want to run two selects;

tempDiv = jQuery("<div>").append(jQuery.parseHTML( responseText )); someResult = tempDiv.find( selector1 ); someOtherResult = tempDiv.find( selector2 );

iOS 7 and 412 precondition failed

With every release of iOS there tend to be some gremlins lurking in Safari, iOS 7 was no different.

When first testing the site I've been building in iOS 7 I was getting a failure when resubmitting an AJAX POST request, the response was 412 (Precondition Failed).

Eventually I found this issue explained related to a MooTools issue.

"Safari responds to etags properly and adds "If-None-Match" and "If-Modified-Since" headers to another request for the same file. This makes Apache respond with a 412 status (Precondition Failed) as it should do for "post" requests (according to RFC 2616)."

"Unfortunately Safari doesn't then deal with the 412 as it does with a 304 (Not Modified). It doesn't grab what it has in the cache and put it in the response, it gives you nothing."

The date on that blog post is 04/12/2009! There is no sign of this issue in iOS6 so maybe it's slipped through the iOS cracks and will be patched

The Fix? Switch to GET and Safari will deal with the request correctly.