<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">/** @preserve OverlappingMarkerSpiderfier
https://github.com/jawj/OverlappingMarkerSpiderfier
Copyright (c) 2011 - 2013 George MacKerron
Released under the MIT licence: http://opensource.org/licenses/mit-license
Note: The Google Maps API v3 must be included *before* this code
 */

(function() {
  var ref,
    hasProp = {}.hasOwnProperty,
    slice = [].slice;

  if (((ref = this['google']) != null ? ref['maps'] : void 0) == null) {
    return;
  }

  this['OverlappingMarkerSpiderfier'] = (function() {
    var ge, gm, j, lcH, lcU, len, mt, p, ref1, twoPi, x;

    p = _Class.prototype;

    ref1 = [_Class, p];
    for (j = 0, len = ref1.length; j &lt; len; j++) {
      x = ref1[j];
      x['VERSION'] = '0.3.3';
    }

    gm = google.maps;

    ge = gm.event;

    mt = gm.MapTypeId;

    twoPi = Math.PI * 2;

    p['keepSpiderfied'] = false;

    p['markersWontHide'] = false;

    p['markersWontMove'] = false;

    p['nearbyDistance'] = 20;

    p['circleSpiralSwitchover'] = 9;

    p['circleFootSeparation'] = 23;

    p['circleStartAngle'] = twoPi / 12;

    p['spiralFootSeparation'] = 26;

    p['spiralLengthStart'] = 11;

    p['spiralLengthFactor'] = 4;

    p['spiderfiedZIndex'] = 1000;

    p['usualLegZIndex'] = 10;

    p['highlightedLegZIndex'] = 20;

    p['legWeight'] = 1.5;

    p['legColors'] = {
      'usual': {},
      'highlighted': {}
    };

    lcU = p['legColors']['usual'];

    lcH = p['legColors']['highlighted'];

    lcU[mt.HYBRID] = lcU[mt.SATELLITE] = '#fff';

    lcH[mt.HYBRID] = lcH[mt.SATELLITE] = '#f00';

    lcU[mt.TERRAIN] = lcU[mt.ROADMAP] = '#444';

    lcH[mt.TERRAIN] = lcH[mt.ROADMAP] = '#f00';

    function _Class(map1, opts) {
      var e, k, l, len1, ref2, v;
      this.map = map1;
      if (opts == null) {
        opts = {};
      }
      for (k in opts) {
        if (!hasProp.call(opts, k)) continue;
        v = opts[k];
        this[k] = v;
      }
      this.projHelper = new this.constructor.ProjHelper(this.map);
      this.initMarkerArrays();
      this.listeners = {};
      ref2 = ['click', 'zoom_changed', 'maptypeid_changed'];
      for (l = 0, len1 = ref2.length; l &lt; len1; l++) {
        e = ref2[l];
        ge.addListener(this.map, e, (function(_this) {
          return function() {
            return _this['unspiderfy']();
          };
        })(this));
      }
    }

    p.initMarkerArrays = function() {
      this.markers = [];
      return this.markerListenerRefs = [];
    };

    p['addMarker'] = function(marker) {
      var listenerRefs;
      if (marker['_oms'] != null) {
        return this;
      }
      marker['_oms'] = true;
      listenerRefs = [
        ge.addListener(marker, 'click', (function(_this) {
          return function(event) {
            return _this.spiderListener(marker, event);
          };
        })(this))
      ];
      if (!this['markersWontHide']) {
        listenerRefs.push(ge.addListener(marker, 'visible_changed', (function(_this) {
          return function() {
            return _this.markerChangeListener(marker, false);
          };
        })(this)));
      }
      if (!this['markersWontMove']) {
        listenerRefs.push(ge.addListener(marker, 'position_changed', (function(_this) {
          return function() {
            return _this.markerChangeListener(marker, true);
          };
        })(this)));
      }
      this.markerListenerRefs.push(listenerRefs);
      this.markers.push(marker);
      return this;
    };

    p.markerChangeListener = function(marker, positionChanged) {
      if ((marker['_omsData'] != null) &amp;&amp; (positionChanged || !marker.getVisible()) &amp;&amp; !((this.spiderfying != null) || (this.unspiderfying != null))) {
        return this['unspiderfy'](positionChanged ? marker : null);
      }
    };

    p['getMarkers'] = function() {
      return this.markers.slice(0);
    };

    p['removeMarker'] = function(marker) {
      var i, l, len1, listenerRef, listenerRefs;
      if (marker['_omsData'] != null) {
        this['unspiderfy']();
      }
      i = this.arrIndexOf(this.markers, marker);
      if (i &lt; 0) {
        return this;
      }
      listenerRefs = this.markerListenerRefs.splice(i, 1)[0];
      for (l = 0, len1 = listenerRefs.length; l &lt; len1; l++) {
        listenerRef = listenerRefs[l];
        ge.removeListener(listenerRef);
      }
      delete marker['_oms'];
      this.markers.splice(i, 1);
      return this;
    };

    p['clearMarkers'] = function() {
      var i, l, len1, len2, listenerRef, listenerRefs, marker, n, ref2;
      this['unspiderfy']();
      ref2 = this.markers;
      for (i = l = 0, len1 = ref2.length; l &lt; len1; i = ++l) {
        marker = ref2[i];
        listenerRefs = this.markerListenerRefs[i];
        for (n = 0, len2 = listenerRefs.length; n &lt; len2; n++) {
          listenerRef = listenerRefs[n];
          ge.removeListener(listenerRef);
        }
        delete marker['_oms'];
      }
      this.initMarkerArrays();
      return this;
    };

    p['addListener'] = function(event, func) {
      var base;
      ((base = this.listeners)[event] != null ? base[event] : base[event] = []).push(func);
      return this;
    };

    p['removeListener'] = function(event, func) {
      var i;
      i = this.arrIndexOf(this.listeners[event], func);
      if (!(i &lt; 0)) {
        this.listeners[event].splice(i, 1);
      }
      return this;
    };

    p['clearListeners'] = function(event) {
      this.listeners[event] = [];
      return this;
    };

    p.trigger = function() {
      var args, event, func, l, len1, ref2, ref3, results;
      event = arguments[0], args = 2 &lt;= arguments.length ? slice.call(arguments, 1) : [];
      ref3 = (ref2 = this.listeners[event]) != null ? ref2 : [];
      results = [];
      for (l = 0, len1 = ref3.length; l &lt; len1; l++) {
        func = ref3[l];
        results.push(func.apply(null, args));
      }
      return results;
    };

    p.generatePtsCircle = function(count, centerPt) {
      var angle, angleStep, circumference, i, l, legLength, ref2, results;
      circumference = this['circleFootSeparation'] * (2 + count);
      legLength = circumference / twoPi;
      angleStep = twoPi / count;
      results = [];
      for (i = l = 0, ref2 = count; 0 &lt;= ref2 ? l &lt; ref2 : l &gt; ref2; i = 0 &lt;= ref2 ? ++l : --l) {
        angle = this['circleStartAngle'] + i * angleStep;
        results.push(new gm.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle)));
      }
      return results;
    };

    p.generatePtsSpiral = function(count, centerPt) {
      var angle, i, l, legLength, pt, ref2, results;
      legLength = this['spiralLengthStart'];
      angle = 0;
      results = [];
      for (i = l = 0, ref2 = count; 0 &lt;= ref2 ? l &lt; ref2 : l &gt; ref2; i = 0 &lt;= ref2 ? ++l : --l) {
        angle += this['spiralFootSeparation'] / legLength + i * 0.0005;
        pt = new gm.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle));
        legLength += twoPi * this['spiralLengthFactor'] / angle;
        results.push(pt);
      }
      return results;
    };

    p.spiderListener = function(marker, event) {
      var l, len1, m, mPt, markerPt, markerSpiderfied, nDist, nearbyMarkerData, nonNearbyMarkers, pxSq, ref2;
      markerSpiderfied = marker['_omsData'] != null;
      if (!(markerSpiderfied &amp;&amp; this['keepSpiderfied'])) {
        this['unspiderfy']();
      }
      if (markerSpiderfied || this.map.getStreetView().getVisible() || this.map.getMapTypeId() === 'GoogleEarthAPI') {
        return this.trigger('click', marker, event);
      } else {
        nearbyMarkerData = [];
        nonNearbyMarkers = [];
        nDist = this['nearbyDistance'];
        pxSq = nDist * nDist;
        markerPt = this.llToPt(marker.position);
        ref2 = this.markers;
        for (l = 0, len1 = ref2.length; l &lt; len1; l++) {
          m = ref2[l];
          if (!((m.map != null) &amp;&amp; m.getVisible())) {
            continue;
          }
          mPt = this.llToPt(m.position);
          if (this.ptDistanceSq(mPt, markerPt) &lt; pxSq) {
            nearbyMarkerData.push({
              marker: m,
              markerPt: mPt
            });
          } else {
            nonNearbyMarkers.push(m);
          }
        }
        if (nearbyMarkerData.length === 1) {
          return this.trigger('click', marker, event);
        } else {
          return this.spiderfy(nearbyMarkerData, nonNearbyMarkers);
        }
      }
    };

    p['markersNearMarker'] = function(marker, firstOnly) {
      var l, len1, m, mPt, markerPt, markers, nDist, pxSq, ref2, ref3, ref4;
      if (firstOnly == null) {
        firstOnly = false;
      }
      if (this.projHelper.getProjection() == null) {
        throw "Must wait for 'idle' event on map before calling markersNearMarker";
      }
      nDist = this['nearbyDistance'];
      pxSq = nDist * nDist;
      markerPt = this.llToPt(marker.position);
      markers = [];
      ref2 = this.markers;
      for (l = 0, len1 = ref2.length; l &lt; len1; l++) {
        m = ref2[l];
        if (m === marker || (m.map == null) || !m.getVisible()) {
          continue;
        }
        mPt = this.llToPt((ref3 = (ref4 = m['_omsData']) != null ? ref4.usualPosition : void 0) != null ? ref3 : m.position);
        if (this.ptDistanceSq(mPt, markerPt) &lt; pxSq) {
          markers.push(m);
          if (firstOnly) {
            break;
          }
        }
      }
      return markers;
    };

    p['markersNearAnyOtherMarker'] = function() {
      var i, i1, i2, l, len1, len2, len3, m, m1, m1Data, m2, m2Data, mData, n, nDist, pxSq, q, ref2, ref3, ref4, results;
      if (this.projHelper.getProjection() == null) {
        throw "Must wait for 'idle' event on map before calling markersNearAnyOtherMarker";
      }
      nDist = this['nearbyDistance'];
      pxSq = nDist * nDist;
      mData = (function() {
        var l, len1, ref2, ref3, ref4, results;
        ref2 = this.markers;
        results = [];
        for (l = 0, len1 = ref2.length; l &lt; len1; l++) {
          m = ref2[l];
          results.push({
            pt: this.llToPt((ref3 = (ref4 = m['_omsData']) != null ? ref4.usualPosition : void 0) != null ? ref3 : m.position),
            willSpiderfy: false
          });
        }
        return results;
      }).call(this);
      ref2 = this.markers;
      for (i1 = l = 0, len1 = ref2.length; l &lt; len1; i1 = ++l) {
        m1 = ref2[i1];
        if (!((m1.map != null) &amp;&amp; m1.getVisible())) {
          continue;
        }
        m1Data = mData[i1];
        if (m1Data.willSpiderfy) {
          continue;
        }
        ref3 = this.markers;
        for (i2 = n = 0, len2 = ref3.length; n &lt; len2; i2 = ++n) {
          m2 = ref3[i2];
          if (i2 === i1) {
            continue;
          }
          if (!((m2.map != null) &amp;&amp; m2.getVisible())) {
            continue;
          }
          m2Data = mData[i2];
          if (i2 &lt; i1 &amp;&amp; !m2Data.willSpiderfy) {
            continue;
          }
          if (this.ptDistanceSq(m1Data.pt, m2Data.pt) &lt; pxSq) {
            m1Data.willSpiderfy = m2Data.willSpiderfy = true;
            break;
          }
        }
      }
      ref4 = this.markers;
      results = [];
      for (i = q = 0, len3 = ref4.length; q &lt; len3; i = ++q) {
        m = ref4[i];
        if (mData[i].willSpiderfy) {
          results.push(m);
        }
      }
      return results;
    };

    p.makeHighlightListenerFuncs = function(marker) {
      return {
        highlight: (function(_this) {
          return function() {
            return marker['_omsData'].leg.setOptions({
              strokeColor: _this['legColors']['highlighted'][_this.map.mapTypeId],
              zIndex: _this['highlightedLegZIndex']
            });
          };
        })(this),
        unhighlight: (function(_this) {
          return function() {
            return marker['_omsData'].leg.setOptions({
              strokeColor: _this['legColors']['usual'][_this.map.mapTypeId],
              zIndex: _this['usualLegZIndex']
            });
          };
        })(this)
      };
    };

    p.spiderfy = function(markerData, nonNearbyMarkers) {
      var bodyPt, footLl, footPt, footPts, highlightListenerFuncs, leg, marker, md, nearestMarkerDatum, numFeet, spiderfiedMarkers;
      this.spiderfying = true;
      numFeet = markerData.length;
      bodyPt = this.ptAverage((function() {
        var l, len1, results;
        results = [];
        for (l = 0, len1 = markerData.length; l &lt; len1; l++) {
          md = markerData[l];
          results.push(md.markerPt);
        }
        return results;
      })());
      footPts = numFeet &gt;= this['circleSpiralSwitchover'] ? this.generatePtsSpiral(numFeet, bodyPt).reverse() : this.generatePtsCircle(numFeet, bodyPt);
      spiderfiedMarkers = (function() {
        var l, len1, results;
        results = [];
        for (l = 0, len1 = footPts.length; l &lt; len1; l++) {
          footPt = footPts[l];
          footLl = this.ptToLl(footPt);
          nearestMarkerDatum = this.minExtract(markerData, (function(_this) {
            return function(md) {
              return _this.ptDistanceSq(md.markerPt, footPt);
            };
          })(this));
          marker = nearestMarkerDatum.marker;
          leg = new gm.Polyline({
            map: this.map,
            path: [marker.position, footLl],
            strokeColor: this['legColors']['usual'][this.map.mapTypeId],
            strokeWeight: this['legWeight'],
            zIndex: this['usualLegZIndex']
          });
          marker['_omsData'] = {
            usualPosition: marker.position,
            leg: leg
          };
          if (this['legColors']['highlighted'][this.map.mapTypeId] !== this['legColors']['usual'][this.map.mapTypeId]) {
            highlightListenerFuncs = this.makeHighlightListenerFuncs(marker);
            marker['_omsData'].hightlightListeners = {
              highlight: ge.addListener(marker, 'mouseover', highlightListenerFuncs.highlight),
              unhighlight: ge.addListener(marker, 'mouseout', highlightListenerFuncs.unhighlight)
            };
          }
          marker.setPosition(footLl);
          marker.setZIndex(Math.round(this['spiderfiedZIndex'] + footPt.y));
          results.push(marker);
        }
        return results;
      }).call(this);
      delete this.spiderfying;
      this.spiderfied = true;
      return this.trigger('spiderfy', spiderfiedMarkers, nonNearbyMarkers);
    };

    p['unspiderfy'] = function(markerNotToMove) {
      var l, len1, listeners, marker, nonNearbyMarkers, ref2, unspiderfiedMarkers;
      if (markerNotToMove == null) {
        markerNotToMove = null;
      }
      if (this.spiderfied == null) {
        return this;
      }
      this.unspiderfying = true;
      unspiderfiedMarkers = [];
      nonNearbyMarkers = [];
      ref2 = this.markers;
      for (l = 0, len1 = ref2.length; l &lt; len1; l++) {
        marker = ref2[l];
        if (marker['_omsData'] != null) {
          marker['_omsData'].leg.setMap(null);
          if (marker !== markerNotToMove) {
            marker.setPosition(marker['_omsData'].usualPosition);
          }
          marker.setZIndex(null);
          listeners = marker['_omsData'].hightlightListeners;
          if (listeners != null) {
            ge.removeListener(listeners.highlight);
            ge.removeListener(listeners.unhighlight);
          }
          delete marker['_omsData'];
          unspiderfiedMarkers.push(marker);
        } else {
          nonNearbyMarkers.push(marker);
        }
      }
      delete this.unspiderfying;
      delete this.spiderfied;
      this.trigger('unspiderfy', unspiderfiedMarkers, nonNearbyMarkers);
      return this;
    };

    p.ptDistanceSq = function(pt1, pt2) {
      var dx, dy;
      dx = pt1.x - pt2.x;
      dy = pt1.y - pt2.y;
      return dx * dx + dy * dy;
    };

    p.ptAverage = function(pts) {
      var l, len1, numPts, pt, sumX, sumY;
      sumX = sumY = 0;
      for (l = 0, len1 = pts.length; l &lt; len1; l++) {
        pt = pts[l];
        sumX += pt.x;
        sumY += pt.y;
      }
      numPts = pts.length;
      return new gm.Point(sumX / numPts, sumY / numPts);
    };

    p.llToPt = function(ll) {
      return this.projHelper.getProjection().fromLatLngToDivPixel(ll);
    };

    p.ptToLl = function(pt) {
      return this.projHelper.getProjection().fromDivPixelToLatLng(pt);
    };

    p.minExtract = function(set, func) {
      var bestIndex, bestVal, index, item, l, len1, val;
      for (index = l = 0, len1 = set.length; l &lt; len1; index = ++l) {
        item = set[index];
        val = func(item);
        if ((typeof bestIndex === "undefined" || bestIndex === null) || val &lt; bestVal) {
          bestVal = val;
          bestIndex = index;
        }
      }
      return set.splice(bestIndex, 1)[0];
    };

    p.arrIndexOf = function(arr, obj) {
      var i, l, len1, o;
      if (arr.indexOf != null) {
        return arr.indexOf(obj);
      }
      for (i = l = 0, len1 = arr.length; l &lt; len1; i = ++l) {
        o = arr[i];
        if (o === obj) {
          return i;
        }
      }
      return -1;
    };

    _Class.ProjHelper = function(map) {
      return this.setMap(map);
    };

    _Class.ProjHelper.prototype = new gm.OverlayView();

    _Class.ProjHelper.prototype['draw'] = function() {};

    return _Class;

  })();

}).call(this);


</pre></body></html>