// Generated by CoffeeScript 1.6.2 /** @preserve OverlappingMarkerSpiderfier https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet Copyright (c) 2011 - 2012 George MacKerron Released under the MIT licence: http://opensource.org/licenses/mit-license Note: The Leaflet maps API must be included *before* this code */ console.log("OverlappingMarkerSpiderfier.js loaded.."); (function () { var __hasProp = {}.hasOwnProperty, __slice = [].slice; if (this["L"] == null) { return; } this["OverlappingMarkerSpiderfier"] = (function () { var p, twoPi; p = _Class.prototype; p["VERSION"] = "0.2.6"; twoPi = Math.PI * 2; p["keepSpiderfied"] = false; p["nearbyDistance"] = 20; p["circleSpiralSwitchover"] = 9; p["circleFootSeparation"] = 25; p["circleStartAngle"] = twoPi / 12; p["spiralFootSeparation"] = 28; p["spiralLengthStart"] = 11; p["spiralLengthFactor"] = 5; p["legWeight"] = 1.5; p["legColors"] = { usual: "#222", highlighted: "#f00", }; function _Class(map, opts) { var e, k, v, _i, _len, _ref, _this = this; this.map = map; if (opts == null) { opts = {}; } for (k in opts) { if (!__hasProp.call(opts, k)) continue; v = opts[k]; this[k] = v; } this.initMarkerArrays(); this.listeners = {}; _ref = ["click", "zoomend"]; for (_i = 0, _len = _ref.length; _i < _len; _i++) { e = _ref[_i]; this.map.addEventListener(e, function () { return _this["unspiderfy"](); }); } } p.initMarkerArrays = function () { this.markers = []; return (this.markerListeners = []); }; p["addMarker"] = function (marker) { var markerListener, _this = this; if (marker["_oms"] != null) { return this; } marker["_oms"] = true; markerListener = function () { return _this.spiderListener(marker); }; marker.addEventListener("click", markerListener); this.markerListeners.push(markerListener); this.markers.push(marker); return this; }; p["getMarkers"] = function () { return this.markers.slice(0); }; p["removeMarker"] = function (marker) { var i, markerListener; if (marker["_omsData"] != null) { this["unspiderfy"](); } i = this.arrIndexOf(this.markers, marker); if (i < 0) { return this; } markerListener = this.markerListeners.splice(i, 1)[0]; marker.removeEventListener("click", markerListener); delete marker["_oms"]; this.markers.splice(i, 1); return this; }; p["clearMarkers"] = function () { var i, marker, markerListener, _i, _len, _ref; this["unspiderfy"](); _ref = this.markers; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { marker = _ref[i]; markerListener = this.markerListeners[i]; marker.removeEventListener("click", markerListener); delete marker["_oms"]; } this.initMarkerArrays(); return this; }; p["addListener"] = function (event, func) { var _base, _ref; ((_ref = (_base = this.listeners)[event]) != null ? _ref : (_base[event] = []) ).push(func); return this; }; p["removeListener"] = function (event, func) { var i; i = this.arrIndexOf(this.listeners[event], func); if (!(i < 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, _i, _len, _ref, _ref1, _results; (event = arguments[0]), (args = 2 <= arguments.length ? __slice.call(arguments, 1) : []); _ref1 = (_ref = this.listeners[event]) != null ? _ref : []; _results = []; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { func = _ref1[_i]; _results.push(func.apply(null, args)); } return _results; }; p.generatePtsCircle = function (count, centerPt) { var angle, angleStep, circumference, i, legLength, _i, _results; circumference = this["circleFootSeparation"] * (2 + count); legLength = circumference / twoPi; angleStep = twoPi / count; _results = []; for ( i = _i = 0; 0 <= count ? _i < count : _i > count; i = 0 <= count ? ++_i : --_i ) { angle = this["circleStartAngle"] + i * angleStep; _results.push( new L.Point( centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle) ) ); } return _results; }; p.generatePtsSpiral = function (count, centerPt) { var angle, i, legLength, pt, _i, _results; legLength = this["spiralLengthStart"]; angle = 0; _results = []; for ( i = _i = 0; 0 <= count ? _i < count : _i > count; i = 0 <= count ? ++_i : --_i ) { angle += this["spiralFootSeparation"] / legLength + i * 0.0005; pt = new L.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) { var m, mPt, markerPt, markerSpiderfied, nearbyMarkerData, nonNearbyMarkers, pxSq, _i, _len, _ref; markerSpiderfied = marker["_omsData"] != null; if (!(markerSpiderfied && this["keepSpiderfied"])) { this["unspiderfy"](); } if (markerSpiderfied) { return this.trigger("click", marker); } else { nearbyMarkerData = []; nonNearbyMarkers = []; pxSq = this["nearbyDistance"] * this["nearbyDistance"]; markerPt = this.map.latLngToLayerPoint(marker.getLatLng()); _ref = this.markers; for (_i = 0, _len = _ref.length; _i < _len; _i++) { m = _ref[_i]; if (!this.map.hasLayer(m)) { continue; } mPt = this.map.latLngToLayerPoint(m.getLatLng()); if (this.ptDistanceSq(mPt, markerPt) < pxSq) { nearbyMarkerData.push({ marker: m, markerPt: mPt, }); } else { nonNearbyMarkers.push(m); } } if (nearbyMarkerData.length === 1) { return this.trigger("click", marker); } else { return this.spiderfy(nearbyMarkerData, nonNearbyMarkers); } } }; p.makeHighlightListeners = function (marker) { var _this = this; return { highlight: function () { return marker["_omsData"].leg.setStyle({ color: _this["legColors"]["highlighted"], }); }, unhighlight: function () { return marker["_omsData"].leg.setStyle({ color: _this["legColors"]["usual"], }); }, }; }; p.spiderfy = function (markerData, nonNearbyMarkers) { var bodyPt, footLl, footPt, footPts, leg, marker, md, mhl, nearestMarkerDatum, numFeet, spiderfiedMarkers; this.spiderfying = true; numFeet = markerData.length; bodyPt = this.ptAverage( (function () { var _i, _len, _results; _results = []; for (_i = 0, _len = markerData.length; _i < _len; _i++) { md = markerData[_i]; _results.push(md.markerPt); } return _results; })() ); footPts = numFeet >= this["circleSpiralSwitchover"] ? this.generatePtsSpiral(numFeet, bodyPt).reverse() : this.generatePtsCircle(numFeet, bodyPt); spiderfiedMarkers = function () { var _i, _len, _results, _this = this; _results = []; for (_i = 0, _len = footPts.length; _i < _len; _i++) { footPt = footPts[_i]; footLl = this.map.layerPointToLatLng(footPt); nearestMarkerDatum = this.minExtract(markerData, function (md) { return _this.ptDistanceSq(md.markerPt, footPt); }); marker = nearestMarkerDatum.marker; leg = new L.Polyline([marker.getLatLng(), footLl], { color: this["legColors"]["usual"], weight: this["legWeight"], clickable: false, }); this.map.addLayer(leg); marker["_omsData"] = { usualPosition: marker.getLatLng(), leg: leg, }; if (this["legColors"]["highlighted"] !== this["legColors"]["usual"]) { mhl = this.makeHighlightListeners(marker); marker["_omsData"].highlightListeners = mhl; marker.addEventListener("mouseover", mhl.highlight); marker.addEventListener("mouseout", mhl.unhighlight); } marker.setLatLng(footLl); marker.setZIndexOffset(1000000); _results.push(marker); } return _results; }.call(this); delete this.spiderfying; this.spiderfied = true; return this.trigger("spiderfy", spiderfiedMarkers, nonNearbyMarkers); }; p["unspiderfy"] = function (markerNotToMove) { var marker, mhl, nonNearbyMarkers, unspiderfiedMarkers, _i, _len, _ref; if (markerNotToMove == null) { markerNotToMove = null; } if (this.spiderfied == null) { return this; } this.unspiderfying = true; unspiderfiedMarkers = []; nonNearbyMarkers = []; _ref = this.markers; for (_i = 0, _len = _ref.length; _i < _len; _i++) { marker = _ref[_i]; if (marker["_omsData"] != null) { this.map.removeLayer(marker["_omsData"].leg); if (marker !== markerNotToMove) { marker.setLatLng(marker["_omsData"].usualPosition); } marker.setZIndexOffset(0); mhl = marker["_omsData"].highlightListeners; if (mhl != null) { marker.removeEventListener("mouseover", mhl.highlight); marker.removeEventListener("mouseout", mhl.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 numPts, pt, sumX, sumY, _i, _len; sumX = sumY = 0; for (_i = 0, _len = pts.length; _i < _len; _i++) { pt = pts[_i]; sumX += pt.x; sumY += pt.y; } numPts = pts.length; return new L.Point(sumX / numPts, sumY / numPts); }; p.minExtract = function (set, func) { var bestIndex, bestVal, index, item, val, _i, _len; for (index = _i = 0, _len = set.length; _i < _len; index = ++_i) { item = set[index]; val = func(item); if ( typeof bestIndex === "undefined" || bestIndex === null || val < bestVal ) { bestVal = val; bestIndex = index; } } return set.splice(bestIndex, 1)[0]; }; p.arrIndexOf = function (arr, obj) { var i, o, _i, _len; if (arr.indexOf != null) { return arr.indexOf(obj); } for (i = _i = 0, _len = arr.length; _i < _len; i = ++_i) { o = arr[i]; if (o === obj) { return i; } } return -1; }; return _Class; })(); }).call(this);