From f97c4b2baedfcd6b8bb4fa7d13738eeb05c2b9b3 Mon Sep 17 00:00:00 2001 From: George MacKerron Date: Sun, 6 May 2012 17:49:22 +0100 Subject: [PATCH 01/22] Fixed repos link in header --- lib/oms.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/oms.coffee b/lib/oms.coffee index 42bedcd..2057515 100755 --- a/lib/oms.coffee +++ b/lib/oms.coffee @@ -1,5 +1,5 @@ ###* @preserve OverlappingMarkerSpiderfier -https://github.com/jawj/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 From 33aa37e7eb084af844133fab5d13f970f8ba20a6 Mon Sep 17 00:00:00 2001 From: George MacKerron Date: Mon, 7 May 2012 13:20:13 +0200 Subject: [PATCH 02/22] Fixed a stray google.maps reference --- README.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.textile b/README.textile index 3e520c2..56c36d9 100755 --- a/README.textile +++ b/README.textile @@ -38,7 +38,7 @@ Create an @OverlappingMarkerSpiderfier@ instance: bc. var oms = new OverlappingMarkerSpiderfier(map); -Instead of adding click listeners to your markers directly via @google.maps.event.addListener@, add a global listener on the @OverlappingMarkerSpiderfier@ instance instead. The listener will be passed the clicked marker as its first argument. +Instead of adding click listeners to your markers directly via @marker.addEventListener@ or @marker.on@, add a global listener on the @OverlappingMarkerSpiderfier@ instance instead. The listener will be passed the clicked marker as its first argument. bc. var popup = new L.Popup(); oms.addListener('click', function(marker) { From c1df66aeb7673250ae3699afcfc2540422543cab Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Mon, 23 Jul 2012 18:04:03 +0300 Subject: [PATCH 03/22] Remove incorrect GMaps references --- README.textile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.textile b/README.textile index 56c36d9..920e530 100755 --- a/README.textile +++ b/README.textile @@ -2,7 +2,7 @@ h1. Overlapping Marker Spiderfier for Leaflet *Ever noticed how, in "Google Earth":http://earth.google.com, marker pins that overlap each other spring apart gracefully when you click them, so you can pick the one you meant?* -*And ever noticed how, when using the "Leaflet API":http://code.google.com/apis/maps/documentation/javascript/, the same thing doesn't happen?* +*And ever noticed how, when using the "Leaflet API":http://leaflet.cloudmade.com, the same thing doesn't happen?* This code makes Leaflet map markers behave in that Google Earth way (minus the animation). Small numbers of markers (yes, up to 8) spiderfy into a circle. Larger numbers fan out into a more space-efficient spiral. @@ -125,7 +125,7 @@ Adds a listener to react to one of three events. @event@ may be @'click'@, @'spiderfy'@ or @'unspiderfy'@. -For @'click'@ events, @listenerFunc@ receives one argument: the clicked marker object. You'll probably want to use this listener to do something like show a @google.maps.InfoWindow@. +For @'click'@ events, @listenerFunc@ receives one argument: the clicked marker object. You'll probably want to use this listener to do something like show a `Popup`. For @'spiderfy'@ or @'unspiderfy'@ events, @listenerFunc@ receives two arguments: first, an @Array@ of the markers that were spiderfied or unspiderfied; second, an @Array@ of the markers that were not. One use for these listeners is to make some distinction between spiderfied and non-spiderfied markers when some markers are spiderfied -- e.g. highlighting those that are spiderfied, or dimming out those that aren't. From 9f42beb2f2e74c19c86f7d428b26c475f0586cb2 Mon Sep 17 00:00:00 2001 From: George MacKerron Date: Tue, 24 Jul 2012 00:21:51 +0300 Subject: [PATCH 04/22] Fix textile syntax for merged change. --- README.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.textile b/README.textile index 920e530..1943010 100755 --- a/README.textile +++ b/README.textile @@ -125,7 +125,7 @@ Adds a listener to react to one of three events. @event@ may be @'click'@, @'spiderfy'@ or @'unspiderfy'@. -For @'click'@ events, @listenerFunc@ receives one argument: the clicked marker object. You'll probably want to use this listener to do something like show a `Popup`. +For @'click'@ events, @listenerFunc@ receives one argument: the clicked marker object. You'll probably want to use this listener to do something like show an @L.Popup@. For @'spiderfy'@ or @'unspiderfy'@ events, @listenerFunc@ receives two arguments: first, an @Array@ of the markers that were spiderfied or unspiderfied; second, an @Array@ of the markers that were not. One use for these listeners is to make some distinction between spiderfied and non-spiderfied markers when some markers are spiderfied -- e.g. highlighting those that are spiderfied, or dimming out those that aren't. From 8cce6a6f5f174cdbb71ad6170e3c8cad3ba13511 Mon Sep 17 00:00:00 2001 From: George MacKerron Date: Mon, 14 Oct 2013 10:55:58 +0100 Subject: [PATCH 05/22] Now checking that marker is added to map when iterating over candidated markers to spiderfy (addresses #10) --- lib/oms.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/oms.coffee b/lib/oms.coffee index 2057515..820ec0c 100755 --- a/lib/oms.coffee +++ b/lib/oms.coffee @@ -11,7 +11,7 @@ return unless this['L']? # return from wrapper func without doing anything class @['OverlappingMarkerSpiderfier'] p = @:: # this saves a lot of repetition of .prototype that isn't optimized away - p['VERSION'] = '0.2.5' + p['VERSION'] = '0.2.6' twoPi = Math.PI * 2 @@ -119,6 +119,7 @@ class @['OverlappingMarkerSpiderfier'] pxSq = @['nearbyDistance'] * @['nearbyDistance'] markerPt = @map.latLngToLayerPoint(marker.getLatLng()) for m in @markers + continue unless @map.hasLayer(m) mPt = @map.latLngToLayerPoint(m.getLatLng()) if @ptDistanceSq(mPt, markerPt) < pxSq nearbyMarkerData.push(marker: m, markerPt: mPt) From cc37374db6de9524d0b83b78c47c703399edb7a4 Mon Sep 17 00:00:00 2001 From: "Ryan J. Hodge" Date: Fri, 26 Feb 2016 19:53:48 -0800 Subject: [PATCH 06/22] Fix demo map source URL --- README.textile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.textile b/README.textile index 1943010..b70539e 100755 --- a/README.textile +++ b/README.textile @@ -26,7 +26,7 @@ Download "the compiled, minified JS source":http://jawj.github.com/OverlappingMa h2. How to use -See the "demo map source":/jawj/OverlappingMarkerSpiderfier-Leaflet/blob/gh-pages/demo.html, or follow along here for a slightly simpler usage with commentary. +See the "demo map source":http://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet/blob/gh-pages/demo.html, or follow along here for a slightly simpler usage with commentary. Create your map like normal (using the beautiful "Stamen watercolour OSM map":http://maps.stamen.com/#watercolor): From 875837250ca6d24c6fc4c14a856601d3400ac43c Mon Sep 17 00:00:00 2001 From: Robert Plummer Date: Fri, 3 Jun 2016 18:17:13 -0400 Subject: [PATCH 07/22] make compatible with other types of markers that don't have available the method 'setZIndexOffset' --- lib/oms.coffee | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/oms.coffee b/lib/oms.coffee index 820ec0c..7c8f5ca 100755 --- a/lib/oms.coffee +++ b/lib/oms.coffee @@ -159,7 +159,8 @@ class @['OverlappingMarkerSpiderfier'] marker.addEventListener('mouseover', mhl.highlight) marker.addEventListener('mouseout', mhl.unhighlight) marker.setLatLng(footLl) - marker.setZIndexOffset(1000000) + if marker.hasOwnProperty('setZIndexOffset') + marker.setZIndexOffset(1000000) marker delete @spiderfying @spiderfied = yes @@ -174,7 +175,8 @@ class @['OverlappingMarkerSpiderfier'] if marker['_omsData']? @map.removeLayer(marker['_omsData'].leg) marker.setLatLng(marker['_omsData'].usualPosition) unless marker is markerNotToMove - marker.setZIndexOffset(0) + if marker.hasOwnProperty('setZIndexOffset') + marker.setZIndexOffset(0) mhl = marker['_omsData'].highlightListeners if mhl? marker.removeEventListener('mouseover', mhl.highlight) From d970eea3c7cba3a1230ec53c1aea55e4617b8541 Mon Sep 17 00:00:00 2001 From: Robert Plummer Date: Fri, 3 Jun 2016 18:41:53 -0400 Subject: [PATCH 08/22] cleanup build process --- bower.json | 28 ++++ build.sh | 2 + build/.gitignore | 1 - build/build.sh | 21 --- oms.js | 389 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 419 insertions(+), 22 deletions(-) create mode 100644 bower.json create mode 100644 build.sh delete mode 100755 build/.gitignore delete mode 100755 build/build.sh create mode 100644 oms.js diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..c6145a8 --- /dev/null +++ b/bower.json @@ -0,0 +1,28 @@ +{ + "name": "spiderfy", + "homepage": "https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet", + "authors": [ + "George MacKerron " + ], + "description": "Overlapping Marker Spiderfier for Leaflet", + "main": "oms.js", + "keywords": [ + "leaflet", + "cluster", + "spider", + "spiderfy", + "group", + "markers" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "dependencies": { + "leaflet": "0.7.3" + } +} diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..2c80fba --- /dev/null +++ b/build.sh @@ -0,0 +1,2 @@ +#!/bin/bash +node bower_components/coffee-script/bin/coffee -c -o . lib/oms.coffee diff --git a/build/.gitignore b/build/.gitignore deleted file mode 100755 index 8986f9d..0000000 --- a/build/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/tmp/ \ No newline at end of file diff --git a/build/build.sh b/build/build.sh deleted file mode 100755 index 69512ef..0000000 --- a/build/build.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -INDIR=../lib/ -INPREFIX=oms - -OUTDIR=./tmp/ -OUTNAME=${INPREFIX}.min.js -OUTFILE=${OUTDIR}${OUTNAME} - -coffee --output $OUTDIR --compile ${INDIR}${INPREFIX}.coffee - -java -jar /usr/local/closure-compiler/compiler.jar \ - --compilation_level SIMPLE_OPTIMIZATIONS \ - --js ${OUTDIR}${INPREFIX}.js \ - --output_wrapper '(function(){%output%}).call(this);' \ -> $OUTFILE - -echo '/*' $(date) '*/' >> $OUTFILE - -cp $OUTFILE ../../gh-pages/bin -cp ${OUTDIR}${INPREFIX}.js ../../gh-pages/bin \ No newline at end of file diff --git a/oms.js b/oms.js new file mode 100644 index 0000000..3b90ef3 --- /dev/null +++ b/oms.js @@ -0,0 +1,389 @@ +// Generated by CoffeeScript 1.10.0 + +/** @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 + */ + +(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, j, k, len, ref, v; + 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 (j = 0, len = ref.length; j < len; j++) { + e = ref[j]; + this.map.addEventListener(e, (function(_this) { + return function() { + return _this['unspiderfy'](); + }; + })(this)); + } + } + + p.initMarkerArrays = function() { + this.markers = []; + return this.markerListeners = []; + }; + + p['addMarker'] = function(marker) { + var markerListener; + if (marker['_oms'] != null) { + return this; + } + marker['_oms'] = true; + markerListener = (function(_this) { + return function() { + return _this.spiderListener(marker); + }; + })(this); + 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, j, len, marker, markerListener, ref; + this['unspiderfy'](); + ref = this.markers; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + 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; + ((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 < 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, j, len, ref, ref1, results; + event = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + ref1 = (ref = this.listeners[event]) != null ? ref : []; + results = []; + for (j = 0, len = ref1.length; j < len; j++) { + func = ref1[j]; + results.push(func.apply(null, args)); + } + return results; + }; + + p.generatePtsCircle = function(count, centerPt) { + var angle, angleStep, circumference, i, j, legLength, ref, results; + circumference = this['circleFootSeparation'] * (2 + count); + legLength = circumference / twoPi; + angleStep = twoPi / count; + results = []; + for (i = j = 0, ref = count; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) { + 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, j, legLength, pt, ref, results; + legLength = this['spiralLengthStart']; + angle = 0; + results = []; + for (i = j = 0, ref = count; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) { + 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 j, len, m, mPt, markerPt, markerSpiderfied, nearbyMarkerData, nonNearbyMarkers, pxSq, 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 (j = 0, len = ref.length; j < len; j++) { + m = ref[j]; + 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) { + return { + highlight: (function(_this) { + return function() { + return marker['_omsData'].leg.setStyle({ + color: _this['legColors']['highlighted'] + }); + }; + })(this), + unhighlight: (function(_this) { + return function() { + return marker['_omsData'].leg.setStyle({ + color: _this['legColors']['usual'] + }); + }; + })(this) + }; + }; + + 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 j, len, results; + results = []; + for (j = 0, len = markerData.length; j < len; j++) { + md = markerData[j]; + results.push(md.markerPt); + } + return results; + })()); + footPts = numFeet >= this['circleSpiralSwitchover'] ? this.generatePtsSpiral(numFeet, bodyPt).reverse() : this.generatePtsCircle(numFeet, bodyPt); + spiderfiedMarkers = (function() { + var j, len, results; + results = []; + for (j = 0, len = footPts.length; j < len; j++) { + footPt = footPts[j]; + footLl = this.map.layerPointToLatLng(footPt); + nearestMarkerDatum = this.minExtract(markerData, (function(_this) { + return function(md) { + return _this.ptDistanceSq(md.markerPt, footPt); + }; + })(this)); + 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); + if (marker.hasOwnProperty('setZIndexOffset')) { + 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 j, len, marker, mhl, nonNearbyMarkers, ref, unspiderfiedMarkers; + if (markerNotToMove == null) { + markerNotToMove = null; + } + if (this.spiderfied == null) { + return this; + } + this.unspiderfying = true; + unspiderfiedMarkers = []; + nonNearbyMarkers = []; + ref = this.markers; + for (j = 0, len = ref.length; j < len; j++) { + marker = ref[j]; + if (marker['_omsData'] != null) { + this.map.removeLayer(marker['_omsData'].leg); + if (marker !== markerNotToMove) { + marker.setLatLng(marker['_omsData'].usualPosition); + } + if (marker.hasOwnProperty('setZIndexOffset')) { + 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 j, len, numPts, pt, sumX, sumY; + sumX = sumY = 0; + for (j = 0, len = pts.length; j < len; j++) { + pt = pts[j]; + 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, j, len, val; + for (index = j = 0, len = set.length; j < len; index = ++j) { + 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, j, len, o; + if (arr.indexOf != null) { + return arr.indexOf(obj); + } + for (i = j = 0, len = arr.length; j < len; i = ++j) { + o = arr[i]; + if (o === obj) { + return i; + } + } + return -1; + }; + + return _Class; + + })(); + +}).call(this); From 255fd037aa87b540fb3ec53c4bc1b9ace4e3004d Mon Sep 17 00:00:00 2001 From: Robert Plummer Date: Sat, 4 Jun 2016 13:32:04 -0400 Subject: [PATCH 09/22] add index.html for demoing --- index.html | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 index.html diff --git a/index.html b/index.html new file mode 100644 index 0000000..c131587 --- /dev/null +++ b/index.html @@ -0,0 +1,85 @@ + + + + + + Overlapping Marker Spiderfier demo + + + + + + + + + +
+ + \ No newline at end of file From ddd4bf891fc24573b4a4aee470496a9cf73a7e66 Mon Sep 17 00:00:00 2001 From: Robert Plummer Date: Sat, 4 Jun 2016 13:37:57 -0400 Subject: [PATCH 10/22] add image and rename map_canvas to map for clarity --- index.html | 10 +++++----- marker-desat.png | Bin 0 -> 3101 bytes 2 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 marker-desat.png diff --git a/index.html b/index.html index c131587..3622a9c 100644 --- a/index.html +++ b/index.html @@ -9,8 +9,8 @@ body { height: auto; margin: 0; padding: 0; font-family: Georgia, serif; font-size: 0.9em; } table { border-collapse: collapse; border-spacing: 0; } p { margin: 0.75em 0; } - #map_canvas { height: auto; position: absolute; bottom: 0; left: 0; right: 0; top: 0; } - @media print { #map_canvas { height: 950px; } } + #map { height: auto; position: absolute; bottom: 0; left: 0; right: 0; top: 0; } + @media print { #map { height: 950px; } } @@ -20,12 +20,12 @@ -
+
- - + +
+ - -
- \ No newline at end of file diff --git a/lib/oms.coffee b/lib/_spiderfy.coffee old mode 100755 new mode 100644 similarity index 53% rename from lib/oms.coffee rename to lib/_spiderfy.coffee index 9f79a65..2565809 --- a/lib/oms.coffee +++ b/lib/_spiderfy.coffee @@ -1,5 +1,5 @@ 'use strict' -###* @preserve OverlappingMarkerSpiderfier +###* @preserve Spiderfy https://github.com/jawj/OverlappingMarkerSpiderfier-Leaflet Copyright (c) 2011 - 2012 George MacKerron Released under the MIT licence: http://opensource.org/licenses/mit-license @@ -8,45 +8,23 @@ Note: The Leaflet maps API must be included *before* this code # NB. string literal properties -- object.key -- are for Closure Compiler ADVANCED_OPTIMIZATION -return unless this.L? # return from wrapper func without doing anything +return unless @L? # return from wrapper func without doing anything -class @OverlappingMarkerSpiderfier - p = @:: # this saves a lot of repetition of .prototype that isn't optimized away - p.VERSION = '0.2.6' +class @Spiderfy twoPi = Math.PI * 2 - defaultOpts = - keepSpiderfied: no # yes -> don't unspiderfy when a marker is selected - nearbyDistance: 20 # spiderfy markers within this range of the one clicked, in px - - circleSpiralSwitchover: 9 # show spiral instead of circle from this marker count upwards - # 0 -> always spiral; Infinity -> always circle - circleFootSeparation: 25 # related to circumference of circle - circleStartAngle: 1 - spiralFootSeparation: 28 # related to size of spiral (experiment!) - spiralLengthStart: 11 # ditto - spiralLengthFactor: 5 # ditto - - legWeight: 1.5 - legColors: - usual: '#222' - highlighted: '#f00' - unspiderfyEvents: ['click', 'zoomend'] - spiderfyMarkerEvent: 'click' - body: - color: '#222' - radius: 3 - opacity: 0.9 - fillOpacity: 0.9 - # Note: it's OK that this constructor comes after the properties, because of function hoisting constructor: (@map, opts = {}) -> - extend(@, defaultOpts, opts) + extend(@, opts, Spiderfy.defaultOpts) + @enabled = yes @initMarkerArrays() @listeners = {} - if @unspiderfyEvents && @unspiderfyEvents.length - @map.addEventListener(e, => @unspiderfy()) for e in @unspiderfyEvents - + if @offEvents && @offEvents.length + for e in @offEvents + @map.addEventListener(e, @deactivate.bind(this)) + + p = @:: # this saves a lot of repetition of .prototype that isn't optimized away + p.VERSION = '0.2.6' p.initMarkerArrays = -> @markers = [] @markerListeners = [] @@ -55,9 +33,10 @@ class @OverlappingMarkerSpiderfier p.addMarker = (marker) -> return @ if marker._oms? marker._oms = yes - markerListener = => @spiderListener(marker) - if @spiderfyMarkerEvent && @spiderfyMarkerEvent.length - marker.addEventListener(@spiderfyMarkerEvent, markerListener) + markerListener = () => @spiderListener(marker) + if @onEvents && @onEvents.length + for e in @onEvents + marker.addEventListener(e, markerListener) @markerListeners.push(markerListener) @markers.push(marker) @ # return self, for chaining @@ -65,27 +44,29 @@ class @OverlappingMarkerSpiderfier p.getMarkers = -> @markers[0..] # returns a copy, so no funny business p.removeMarker = (marker) -> - @unspiderfy() if marker._omsData? # otherwise it'll be stuck there forever! + @deactivate() if marker._spiderfyData? # otherwise it'll be stuck there forever! i = @arrIndexOf(@markers, marker) return @ if i < 0 markerListener = @markerListeners.splice(i, 1)[0] - if @spiderfyMarkerEvent && @spiderfyMarkerEvent.length - marker.removeEventListener(@spiderfyMarkerEvent, markerListener) + if @onEvents && @onEvents.length + for e in @onEvents + marker.removeEventListener(e, markerListener) delete marker._oms @markers.splice(i, 1) @ # return self, for chaining p.clearMarkers = -> - @unspiderfy() + @deactivate() for marker, i in @markers markerListener = @markerListeners[i] - if @spiderfyMarkerEvent && @spiderfyMarkerEvent.length - marker.removeEventListener(@spiderfyMarkerEvent, markerListener) + if @onEvents && @onEvents.length + for e in @onEvents + marker.removeEventListener(e, markerListener) delete marker._oms @initMarkerArrays() @ # return self, for chaining - # available listeners: click(marker), spiderfy(markers), unspiderfy(markers) + # available listeners: click(marker), activate(markers), deactivate(markers) p.addListener = (event, func) -> (@listeners[event] ?= []).push(func) @ # return self, for chaining @@ -123,10 +104,10 @@ class @OverlappingMarkerSpiderfier pt p.spiderListener = (marker) -> - markerSpiderfied = marker._omsData? - if !@keepSpiderfied - @unspiderfy() unless markerSpiderfied - if markerSpiderfied + active = marker._spiderfyData? + if !@keep + @deactivate() unless active + if active @trigger('click', marker) return @ else @@ -144,16 +125,17 @@ class @OverlappingMarkerSpiderfier if nearbyMarkerData.length is 1 # 1 => the one clicked => none nearby @trigger('click', marker) else if (nearbyMarkerData.length > 0 && nonNearbyMarkers.length > 0) - @spiderfy(nearbyMarkerData, nonNearbyMarkers) + @activate(nearbyMarkerData, nonNearbyMarkers) else null p.makeHighlightListeners = (marker) -> - highlight: => marker._omsData.leg.setStyle(color: @legColors.highlighted) - unhighlight: => marker._omsData.leg.setStyle(color: @legColors.usual) + highlight: => marker._spiderfyData.leg.setStyle(color: @legColors.highlighted) + unhighlight: => marker._spiderfyData.leg.setStyle(color: @legColors.usual) - p.spiderfy = (markerData, nonNearbyMarkers) -> - @spiderfying = yes + p.activate = (markerData, nonNearbyMarkers) -> + return unless @enabled + @activating = yes numFeet = markerData.length bodyPt = @ptAverage(md.markerPt for md in markerData) footPts = if numFeet >= @circleSpiralSwitchover @@ -161,7 +143,7 @@ class @OverlappingMarkerSpiderfier else @generatePtsCircle(numFeet, bodyPt) lastMarkerCoords = null - spiderfiedMarkers = for footPt in footPts + activeMarkers = for footPt in footPts footLl = @map.layerPointToLatLng(footPt) nearestMarkerDatum = @minExtract(markerData, (md) => @ptDistanceSq(md.markerPt, footPt)) marker = nearestMarkerDatum.marker @@ -173,50 +155,50 @@ class @OverlappingMarkerSpiderfier clickable: no } @map.addLayer(leg) - marker._omsData = {usualPosition: marker.getLatLng(), leg: leg} + marker._spiderfyData = {usualPosition: marker.getLatLng(), leg: leg} unless @legColors.highlighted is @legColors.usual mhl = @makeHighlightListeners(marker) - marker._omsData.highlightListeners = mhl + marker._spiderfyData.highlightListeners = mhl marker.addEventListener('mouseover', mhl.highlight) marker.addEventListener('mouseout', mhl.unhighlight) marker.setLatLng(footLl) if marker.hasOwnProperty('setZIndexOffset') marker.setZIndexOffset(1000000) marker - delete @spiderfying - @spiderfied = yes + delete @activating + @isActive = yes if @body && lastMarkerCoords != null body = L.circleMarker(lastMarkerCoords, @body) @map.addLayer(body) @bodies.push(body) - @trigger('spiderfy', spiderfiedMarkers, nonNearbyMarkers) + @trigger('activate', activeMarkers, nonNearbyMarkers) - p.unspiderfy = (markerNotToMove = null) -> - return @ unless @spiderfied? - @unspiderfying = yes - unspiderfiedMarkers = [] + p.deactivate = (markerNotToMove = null) -> + return @ unless @isActive? + @deactivating = yes + inactiveMarkers = [] nonNearbyMarkers = [] for marker in @markers - if marker._omsData? - @map.removeLayer(marker._omsData.leg) - marker.setLatLng(marker._omsData.usualPosition) unless marker is markerNotToMove + if marker._spiderfyData? + @map.removeLayer(marker._spiderfyData.leg) + marker.setLatLng(marker._spiderfyData.usualPosition) unless marker is markerNotToMove if marker.hasOwnProperty('setZIndexOffset') marker.setZIndexOffset(0) - mhl = marker._omsData.highlightListeners + mhl = marker._spiderfyData.highlightListeners if mhl? marker.removeEventListener('mouseover', mhl.highlight) marker.removeEventListener('mouseout', mhl.unhighlight) - delete marker._omsData - unspiderfiedMarkers.push(marker) + delete marker._spiderfyData + inactiveMarkers.push(marker) else nonNearbyMarkers.push(marker) for body in @bodies @map.removeLayer(body) - delete @unspiderfying - delete @spiderfied - @trigger('unspiderfy', unspiderfiedMarkers, nonNearbyMarkers) + delete @deactivating + delete @isActive + @trigger('deactivate', inactiveMarkers, nonNearbyMarkers) @ # return self, for chaining p.ptDistanceSq = (pt1, pt2) -> @@ -244,6 +226,52 @@ class @OverlappingMarkerSpiderfier return arr.indexOf(obj) if arr.indexOf? (return i if o is obj) for o, i in arr -1 + p.enable = () -> + @enabled = yes + @ + p.disable = () -> + @enabled = no + @ + +@Spiderfy.defaultOpts = + keep: no # yes -> don't deactivate when a marker is selected + nearbyDistance: 20 # spiderfy markers within this range of the one clicked, in px + + circleSpiralSwitchover: 9 # show spiral instead of circle from this marker count upwards + # 0 -> always spiral; Infinity -> always circle + circleFootSeparation: 25 # related to circumference of circle + circleStartAngle: 1 + spiralFootSeparation: 28 # related to size of spiral (experiment!) + spiralLengthStart: 11 # ditto + spiralLengthFactor: 5 # ditto + + legWeight: 1.5 + legColors: + usual: '#222' + highlighted: '#f00' + offEvents: ['click', 'zoomend'] + onEvents: ['click'] + body: + color: '#222' + radius: 3 + opacity: 0.9 + fillOpacity: 0.9 + msg: + buttonEnabled: 'spiderfy enabled - click to disable' + buttonDisabled: 'spiderfy disabled - click to enable' + icon: ''' + + + + + + + + + + + +''' extend = (out = {}) -> i = 1 @@ -255,4 +283,65 @@ extend = (out = {}) -> if arguments[i].hasOwnProperty(key) out[key] = arguments[i][key] i++ - out \ No newline at end of file + out + +cleanExtend = (it, using) -> + out = {} + for key of using + if using.hasOwnProperty(key) + if it.hasOwnProperty(key) + out[key] = it[key] + else + out[key] = value + out + +L.Spiderfy = L.Control.extend( + options: extend( + position: 'topleft' + markers: [] + click: null + activate: null + deactivate: null + Spiderfy.defaultOpts), + onAdd: (map) -> + _spiderfy = new Spiderfy(map, cleanExtend(@options, Spiderfy.defaultOpts)) + if @options.click + _spiderfy.addListener('click', @options.click) + if @options.activate + _spiderfy.addListener('activate', @options.activate) + if @options.deactivate + _spiderfy.addListener('deactivate', @options.deactivate) + active = yes + buttonEnabled = @options.msg.buttonEnabled + buttonDisabled = @options.msg.buttonDisabled + button = L.DomUtil.create('a', 'leaflet-bar leaflet-control leaflet-control-spiderfy') + button.setAttribute('href', '#') + button.setAttribute('title', buttonEnabled) + button.innerHTML = @options.icon + style = button.style + style.backgroundColor = 'white' + style.width = '30px' + style.height = '30px' + for marker in @options.markers + _spiderfy.addMarker(marker) + button.onclick = () -> + if (active) + active = no + button.setAttribute('title', buttonDisabled) + style.opacity = 0.5 + _spiderfy + .deactivate() + .disable() + else + active = yes + button.setAttribute('title', buttonEnabled) + style.opacity = 1 + _spiderfy + .enable() + button +) + +L.spiderfy = (options) -> + spiderfy = new L.Spiderfy(options) + map.addControl(spiderfy) + spiderfy \ No newline at end of file diff --git a/oms.js b/spiderfy.js similarity index 60% rename from oms.js rename to spiderfy.js index 2b6372c..e49a41f 100644 --- a/oms.js +++ b/spiderfy.js @@ -2,74 +2,47 @@ (function() { 'use strict'; - /** @preserve OverlappingMarkerSpiderfier + /** @preserve Spiderfy 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 */ - var extend, + var cleanExtend, extend, slice = [].slice; if (this.L == null) { return; } - this.OverlappingMarkerSpiderfier = (function() { - var defaultOpts, p, twoPi; - - p = OverlappingMarkerSpiderfier.prototype; - - p.VERSION = '0.2.6'; + this.Spiderfy = (function() { + var p, twoPi; twoPi = Math.PI * 2; - defaultOpts = { - keepSpiderfied: false, - nearbyDistance: 20, - circleSpiralSwitchover: 9, - circleFootSeparation: 25, - circleStartAngle: 1, - spiralFootSeparation: 28, - spiralLengthStart: 11, - spiralLengthFactor: 5, - legWeight: 1.5, - legColors: { - usual: '#222', - highlighted: '#f00' - }, - unspiderfyEvents: ['click', 'zoomend'], - spiderfyMarkerEvent: 'click', - body: { - color: '#222', - radius: 3, - opacity: 0.9, - fillOpacity: 0.9 - } - }; - - function OverlappingMarkerSpiderfier(map, opts) { + function Spiderfy(map1, opts) { var e, j, len, ref; - this.map = map; + this.map = map1; if (opts == null) { opts = {}; } - extend(this, defaultOpts, opts); + extend(this, opts, Spiderfy.defaultOpts); + this.enabled = true; this.initMarkerArrays(); this.listeners = {}; - if (this.unspiderfyEvents && this.unspiderfyEvents.length) { - ref = this.unspiderfyEvents; + if (this.offEvents && this.offEvents.length) { + ref = this.offEvents; for (j = 0, len = ref.length; j < len; j++) { e = ref[j]; - this.map.addEventListener(e, (function(_this) { - return function() { - return _this.unspiderfy(); - }; - })(this)); + this.map.addEventListener(e, this.deactivate.bind(this)); } } } + p = Spiderfy.prototype; + + p.VERSION = '0.2.6'; + p.initMarkerArrays = function() { this.markers = []; this.markerListeners = []; @@ -77,7 +50,7 @@ }; p.addMarker = function(marker) { - var markerListener; + var e, j, len, markerListener, ref; if (marker._oms != null) { return this; } @@ -87,8 +60,12 @@ return _this.spiderListener(marker); }; })(this); - if (this.spiderfyMarkerEvent && this.spiderfyMarkerEvent.length) { - marker.addEventListener(this.spiderfyMarkerEvent, markerListener); + if (this.onEvents && this.onEvents.length) { + ref = this.onEvents; + for (j = 0, len = ref.length; j < len; j++) { + e = ref[j]; + marker.addEventListener(e, markerListener); + } } this.markerListeners.push(markerListener); this.markers.push(marker); @@ -100,17 +77,21 @@ }; p.removeMarker = function(marker) { - var i, markerListener; - if (marker._omsData != null) { - this.unspiderfy(); + var e, i, j, len, markerListener, ref; + if (marker._spiderfyData != null) { + this.deactivate(); } i = this.arrIndexOf(this.markers, marker); if (i < 0) { return this; } markerListener = this.markerListeners.splice(i, 1)[0]; - if (this.spiderfyMarkerEvent && this.spiderfyMarkerEvent.length) { - marker.removeEventListener(this.spiderfyMarkerEvent, markerListener); + if (this.onEvents && this.onEvents.length) { + ref = this.onEvents; + for (j = 0, len = ref.length; j < len; j++) { + e = ref[j]; + marker.removeEventListener(e, markerListener); + } } delete marker._oms; this.markers.splice(i, 1); @@ -118,14 +99,18 @@ }; p.clearMarkers = function() { - var i, j, len, marker, markerListener, ref; - this.unspiderfy(); + var e, i, j, k, len, len1, marker, markerListener, ref, ref1; + this.deactivate(); ref = this.markers; for (i = j = 0, len = ref.length; j < len; i = ++j) { marker = ref[i]; markerListener = this.markerListeners[i]; - if (this.spiderfyMarkerEvent && this.spiderfyMarkerEvent.length) { - marker.removeEventListener(this.spiderfyMarkerEvent, markerListener); + if (this.onEvents && this.onEvents.length) { + ref1 = this.onEvents; + for (k = 0, len1 = ref1.length; k < len1; k++) { + e = ref1[k]; + marker.removeEventListener(e, markerListener); + } } delete marker._oms; } @@ -194,14 +179,14 @@ }; p.spiderListener = function(marker) { - var j, len, m, mPt, markerPt, markerSpiderfied, nearbyMarkerData, nonNearbyMarkers, pxSq, ref; - markerSpiderfied = marker._omsData != null; - if (!this.keepSpiderfied) { - if (!markerSpiderfied) { - this.unspiderfy(); + var active, j, len, m, mPt, markerPt, nearbyMarkerData, nonNearbyMarkers, pxSq, ref; + active = marker._spiderfyData != null; + if (!this.keep) { + if (!active) { + this.deactivate(); } } - if (markerSpiderfied) { + if (active) { this.trigger('click', marker); return this; } else { @@ -228,7 +213,7 @@ if (nearbyMarkerData.length === 1) { return this.trigger('click', marker); } else if (nearbyMarkerData.length > 0 && nonNearbyMarkers.length > 0) { - return this.spiderfy(nearbyMarkerData, nonNearbyMarkers); + return this.activate(nearbyMarkerData, nonNearbyMarkers); } else { return null; } @@ -239,14 +224,14 @@ return { highlight: (function(_this) { return function() { - return marker._omsData.leg.setStyle({ + return marker._spiderfyData.leg.setStyle({ color: _this.legColors.highlighted }); }; })(this), unhighlight: (function(_this) { return function() { - return marker._omsData.leg.setStyle({ + return marker._spiderfyData.leg.setStyle({ color: _this.legColors.usual }); }; @@ -254,9 +239,12 @@ }; }; - p.spiderfy = function(markerData, nonNearbyMarkers) { - var body, bodyPt, footLl, footPt, footPts, lastMarkerCoords, leg, marker, markerCoords, md, mhl, nearestMarkerDatum, numFeet, spiderfiedMarkers; - this.spiderfying = true; + p.activate = function(markerData, nonNearbyMarkers) { + var activeMarkers, body, bodyPt, footLl, footPt, footPts, lastMarkerCoords, leg, marker, markerCoords, md, mhl, nearestMarkerDatum, numFeet; + if (!this.enabled) { + return; + } + this.activating = true; numFeet = markerData.length; bodyPt = this.ptAverage((function() { var j, len, results; @@ -269,7 +257,7 @@ })()); footPts = numFeet >= this.circleSpiralSwitchover ? this.generatePtsSpiral(numFeet, bodyPt).reverse() : this.generatePtsCircle(numFeet, bodyPt); lastMarkerCoords = null; - spiderfiedMarkers = (function() { + activeMarkers = (function() { var j, len, results; results = []; for (j = 0, len = footPts.length; j < len; j++) { @@ -289,13 +277,13 @@ clickable: false }); this.map.addLayer(leg); - marker._omsData = { + marker._spiderfyData = { usualPosition: marker.getLatLng(), leg: leg }; if (this.legColors.highlighted !== this.legColors.usual) { mhl = this.makeHighlightListeners(marker); - marker._omsData.highlightListeners = mhl; + marker._spiderfyData.highlightListeners = mhl; marker.addEventListener('mouseover', mhl.highlight); marker.addEventListener('mouseout', mhl.unhighlight); } @@ -307,45 +295,45 @@ } return results; }).call(this); - delete this.spiderfying; - this.spiderfied = true; + delete this.activating; + this.isActive = true; if (this.body && lastMarkerCoords !== null) { body = L.circleMarker(lastMarkerCoords, this.body); this.map.addLayer(body); this.bodies.push(body); } - return this.trigger('spiderfy', spiderfiedMarkers, nonNearbyMarkers); + return this.trigger('activate', activeMarkers, nonNearbyMarkers); }; - p.unspiderfy = function(markerNotToMove) { - var body, j, k, len, len1, marker, mhl, nonNearbyMarkers, ref, ref1, unspiderfiedMarkers; + p.deactivate = function(markerNotToMove) { + var body, inactiveMarkers, j, k, len, len1, marker, mhl, nonNearbyMarkers, ref, ref1; if (markerNotToMove == null) { markerNotToMove = null; } - if (this.spiderfied == null) { + if (this.isActive == null) { return this; } - this.unspiderfying = true; - unspiderfiedMarkers = []; + this.deactivating = true; + inactiveMarkers = []; nonNearbyMarkers = []; ref = this.markers; for (j = 0, len = ref.length; j < len; j++) { marker = ref[j]; - if (marker._omsData != null) { - this.map.removeLayer(marker._omsData.leg); + if (marker._spiderfyData != null) { + this.map.removeLayer(marker._spiderfyData.leg); if (marker !== markerNotToMove) { - marker.setLatLng(marker._omsData.usualPosition); + marker.setLatLng(marker._spiderfyData.usualPosition); } if (marker.hasOwnProperty('setZIndexOffset')) { marker.setZIndexOffset(0); } - mhl = marker._omsData.highlightListeners; + mhl = marker._spiderfyData.highlightListeners; if (mhl != null) { marker.removeEventListener('mouseover', mhl.highlight); marker.removeEventListener('mouseout', mhl.unhighlight); } - delete marker._omsData; - unspiderfiedMarkers.push(marker); + delete marker._spiderfyData; + inactiveMarkers.push(marker); } else { nonNearbyMarkers.push(marker); } @@ -355,9 +343,9 @@ body = ref1[k]; this.map.removeLayer(body); } - delete this.unspiderfying; - delete this.spiderfied; - this.trigger('unspiderfy', unspiderfiedMarkers, nonNearbyMarkers); + delete this.deactivating; + delete this.isActive; + this.trigger('deactivate', inactiveMarkers, nonNearbyMarkers); return this; }; @@ -408,10 +396,49 @@ return -1; }; - return OverlappingMarkerSpiderfier; + p.enable = function() { + this.enabled = true; + return this; + }; + + p.disable = function() { + this.enabled = false; + return this; + }; + + return Spiderfy; })(); + this.Spiderfy.defaultOpts = { + keep: false, + nearbyDistance: 20, + circleSpiralSwitchover: 9, + circleFootSeparation: 25, + circleStartAngle: 1, + spiralFootSeparation: 28, + spiralLengthStart: 11, + spiralLengthFactor: 5, + legWeight: 1.5, + legColors: { + usual: '#222', + highlighted: '#f00' + }, + offEvents: ['click', 'zoomend'], + onEvents: ['click'], + body: { + color: '#222', + radius: 3, + opacity: 0.9, + fillOpacity: 0.9 + }, + msg: { + buttonEnabled: 'spiderfy enabled - click to disable', + buttonDisabled: 'spiderfy disabled - click to enable' + }, + icon: '\n \n \n \n \n \n \n \n \n \n' + }; + extend = function(out) { var i, key; if (out == null) { @@ -433,4 +460,79 @@ return out; }; + cleanExtend = function(it, using) { + var key, out; + out = {}; + for (key in using) { + if (using.hasOwnProperty(key)) { + if (it.hasOwnProperty(key)) { + out[key] = it[key]; + } else { + out[key] = value; + } + } + } + return out; + }; + + L.Spiderfy = L.Control.extend({ + options: extend({ + position: 'topleft', + markers: [], + click: null, + activate: null, + deactivate: null + }, Spiderfy.defaultOpts), + onAdd: function(map) { + var _spiderfy, active, button, buttonDisabled, buttonEnabled, j, len, marker, ref, style; + _spiderfy = new Spiderfy(map, cleanExtend(this.options, Spiderfy.defaultOpts)); + if (this.options.click) { + _spiderfy.addListener('click', this.options.click); + } + if (this.options.activate) { + _spiderfy.addListener('activate', this.options.activate); + } + if (this.options.deactivate) { + _spiderfy.addListener('deactivate', this.options.deactivate); + } + active = true; + buttonEnabled = this.options.msg.buttonEnabled; + buttonDisabled = this.options.msg.buttonDisabled; + button = L.DomUtil.create('a', 'leaflet-bar leaflet-control leaflet-control-spiderfy'); + button.setAttribute('href', '#'); + button.setAttribute('title', buttonEnabled); + button.innerHTML = this.options.icon; + style = button.style; + style.backgroundColor = 'white'; + style.width = '30px'; + style.height = '30px'; + ref = this.options.markers; + for (j = 0, len = ref.length; j < len; j++) { + marker = ref[j]; + _spiderfy.addMarker(marker); + } + button.onclick = function() { + if (active) { + active = false; + button.setAttribute('title', buttonDisabled); + style.opacity = 0.5; + return _spiderfy.deactivate().disable(); + } else { + active = true; + button.setAttribute('title', buttonEnabled); + style.opacity = 1; + return _spiderfy.enable(); + } + }; + return button; + } + }); + + L.spiderfy = function(options) { + var spiderfy; + spiderfy = new L.Spiderfy(options); + map.addControl(spiderfy); + return spiderfy; + }; + }).call(this); diff --git a/spiderfy.svg b/spiderfy.svg new file mode 100644 index 0000000..9222eb4 --- /dev/null +++ b/spiderfy.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + From 0c0964279db0c3e0fa9ce975f365faefb2da1d7d Mon Sep 17 00:00:00 2001 From: Robert Plummer Date: Sun, 26 Jun 2016 11:17:28 -0400 Subject: [PATCH 22/22] change name --- lib/{_spiderfy.coffee => spiderfy.coffee} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/{_spiderfy.coffee => spiderfy.coffee} (100%) diff --git a/lib/_spiderfy.coffee b/lib/spiderfy.coffee similarity index 100% rename from lib/_spiderfy.coffee rename to lib/spiderfy.coffee