mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Leaflet upgrade (#7855)
* Squashed 'lib/Leaflet.markercluster/' changes from e96388d6c..584add242 584add242 Merge pull request #846 from ghybs/spiderfyLegFix e8ca4e8c6 Refactor(Spiderfier): circle spiderfy clockwise like spiral 949d88ae6 Fix(Spiderfier): min leg distance for circle and skip 1st pos for spiral 645e3a8b3 Bump this off ed8e05ab5 1.2.0 e8219ecd3 Merge pull request #838 from lucaswerkmeister/836 17e8cb710 Support DistanceGrid with cell size 0 cc61460fc Make DistanceGrid cells closed sets 00a24788b Merge pull request #832 from ghybs/refactorOptions a256831f2 Refactor(examplePane): assign clusterPane option only if pane is provided 61e06292d Refactor(options): move clusterPane into options field 0a00ec3a6 Merge pull request #831 from adammertel/master 644663697 new subplugin in readme - MarkerCluster.List f175a7cc3 1.1.0 d077f4920 Merge pull request #819 from ckrahe/panes 37bc74004 Default group clusterPane to L.Marker default f80ee8bce Rename option for clarity bd3748a89 Add testing section. 90004e431 Change option name to avoid collision with Leaflet. Document default. Add pane unit tests. e8f27e469 Follow standard and fully-qualify example references. 480c78698 Create pane example. Add second link to custom example. 4fffa0aa5 Support optional pane f1b0d8fe3 Other 1.0.6 80570d1ec Update changelog for 1.0.6 397693fa8 Be a bit more careful with minZoom. refs #789 eab34569c Merge pull request #794 from ghybs/readme-https e2d5201d8 Merge pull request #795 from ghybs/examples-https b5afe4fe8 Refactor(examples/debug): use HTTPS for CDN, Tiles & OSM link 77fbc29d5 Docs(README): use https for demo links e387e1f48 Fix non-integer min/max zoom and add a test. Ref #789 4062f3768 Remove mention of custom build stuff that hasn't existed for a while c56a60d51 Fix addressPoints2 usage in example. Fixes #781 e9cc1e29f Bump for 1.0.5 590cce513 Merge pull request #779 from timkelty/pass-fitBounds-options 4a2399606 README for fitBounds options Pass undefined 97c3bb093 Allow paddling fitBounds options to zoomToBounds d7288c7fe Merge pull request #776 from kent1D/patch-1 fcf9e9dd5 Update CHANGELOG.md 254187999 Remove unnecessary undefined check, this is set to null by default. f01f8b1fe Merge pull request #773 from MrCheeze/master ea9400017 Fixed check to match coding standards (!==) b97aa03af Fixed bug where disableClusteringAtZoom being 0 is treated the same as null 80dad1839 Bump for 1.0.4 ac052696a add subplugin Leaflet.MarkerCluster.PlacementStrategies (#766) 162f15722 Pull minZoom fetching out to fix errors removing a MCG from a map while an animation is going on. 31e413d28 Add a note about the JS files 701591250 bump readme to 1.0.3 (#756) 588765b71 Bump for 1.0.3 c82f34252 Another test and fix for #753 706d6f266 Test and fix for moving a marker while the MCG is off the map. Refs #753 848a172a5 Bump version a44c7c402 Update CHANGELOG for 1.0.2 cf26d0190 Update changelog for 1.0.0 b67410966 If a marker is moved with an open popup on it, re-open the popup after moving it. Fixes #651 16cf328a5 Support layerremove event. fixes #647 2a88279e9 Support layeradd event. refs #647 dbdedb93e Tidy up all these event handlers we now need to add. cbfdb9806 Fix a few more cases where negative minZoom wasn't handled. refs #704 e65cb900c Fix an issue when opening a popup inside of zoomToShowLayer. If there was an existing spiderfied marker with a popup on it, the map would scroll back to the location of that marker. 37d5143a7 Merge pull request #747 from z3ut/fix-zoom-to-show-layer 63c648177 Add support for maps with negative minZoom. Fixes #704 0f8b3d102 Bump version ee69a43f8 Add an example with draggable markers. Fix dragging markers. Fixes #685 f6379783a Bump all examples to leaflet 1.0.3 1e81a9aba Add an ISSUE_TEMPLATE based on the leaflet one 8bb6278e7 Remove zoomToShowLayer moveStart event check 9c5fe783b Add zoomToShowLayer tests 3468278a7 Fixed zoomToShowLayer() markers disappearing bug 7db30166f Merge pull request #746 from marcianoviereck92/patch-1 fa20d91b0 Fixed leaflet 1.0.2 bug where clearLayers would throw an exception ad023e9ef Merge pull request #738 from bertyhell/patch-1 7872b96e8 Update example map link a1d98d65f Add example image of the marker cluster map 7b577c1b6 Add example image to readme 87cd5fd2f Add example image e6a24dc50 Merge pull request #734 from ghybs/patch-3 76f0b0f30 README corrected iconCreateFunction 771b41b3e README improve plugin install instructions d4d93457f README correct TOC order 29972bef5 Add install and build steps with jake (#733) bd8f1369a Revert "npm instructions for 1.0.0 in readme" c0ac83899 npm instructions for 1.0.0 in readme f22d877c1 Should bump leaflet version here too dd55b4bcc Update bower.json for 1.0.0 too 9ac8ee068 Bump package.json 1.0.0 a806d5064 Bump readme for 1.0.0 7da6fb2ad Merge pull request #656 from ghybs/recursively-simplified bbd5dad61 Merge pull request #703 from tyleralves/patch-2 2c4123994 Merge pull request #708 from ghybs/addLayerFreezableCompatibility 4fce18cfe Added missing rounding to map._zoom f87592144 Get zoom from internal _zoom instead of map.getZoom() 0e5c3347f Remove leaflet from peerDependencies (Leaflet/Leaflet#4534) 7c894bf72 Merge pull request #697 from qedsoftware/bulk-icon-performance 53c1f94a1 Refresh icons after bulk action, not during one 7b360f931 Merge pull request #700 from qedsoftware/travis 49a4dc445 Fix travis build 7269ac32a Merge pull request #690 from LukeSwart/patch-1 d4a2d05b9 Update README.md 05e10293d Merge pull request #672 from ghybs/patch-3 cab42e4ee Replaced links to gh-pages by github.io 5171f18bb Update npm install location c0051f0a9 Bump version number to match leaflet 3ab1c69da Merge pull request #665 from hyperknot/rc1 c578c76ed updated peer dep to leaflet rc1 68ca95f79 Update README.md 5bb70eae9 Merge pull request #657 from ghybs/spiderfyCombinedWithDisableClustering 617b8f3f7 Merge pull request #658 from ghybs/patch-2 cc7aea0cc Replaced `dependencies` by `peerDependencies` 6ee9972ab Copied note for `spiderfyOnMaxZoom` option explanation. e4dca376f Merged conditions for zoomOrSpiderfy to avoid no action with disableClusteringAtZoom c78e73987 Created disableClusteringAtZoomSpec 8bdb884c8 Simplified _recursively d91addd7b Add building instructions cb05eb292 Merge pull request #644 from ghybs/master 44963c185 Corrected #529 in master (Leaflet 1.0.0) a4c3bce8b Remove built files, we only ship these in tags now. BYO otherwise. 2d6b625d9 Merge pull request #617 from zverev/unspiderfy f2ea5b5db Merge pull request #624 from ghybs/addNestedLayerGroups 33e5eec4f Clone input array at first group met 088001092 Merge pull request #626 from isedwards/geojson_semicolons 9d7731600 Added a couple of missing semi-colons to improve readability/best practice. 9b451926f Manage nested groups in removeLayer and removeLayers as well 01467aa41 Missing final blank line in AddLayersSpec 7cf8152dd Manage adding nested Layer Groups bfc877c8a Use the new travis infrastructure hopefully 2faaba2cb Add unspiderfy test 37fce91f2 Merge branch 'master' into unspiderfy 54976bf69 fix a typo f61cfafc0 Public unspiderfy method ba3c95b27 Update CHANGELOG 5f88d2428 Update leaflet version in package.json and format 43b094824 Grab leaflet from https always. Fixes #614 57cf04cdc Don't return markers that need to be removed in eachLayer/getLayers. a44af7231 Update readme for 1.0.0 1b68284d8 Add test from calvinmetcalf in #397 e18deb3a2 Add missing tests to spec/index.html runner 9f6125501 Fix spiderfySpec tests 97e27e173 Merge branch 'master' into leaflet-master-merge 8ecc49410 Merge pull request #603 from ghybs/leaflet-master-merge 822131832 Documentation for unspiderfied event de4d3321c Test for unspiderfied event e3017c5e4 Merge remote-tracking branch 'newmanw/master' 6a93ee3a1 Add and fix tests from #421 e5ab67d26 Merge commit 'ac8c7063af5ea8e9cce4ce595c7d8303dc595c17' d9c131036 Merge pull request #609 from OriginalSin/OriginalSin-patch-1 58480310d Merge pull request #607 from ghybs/removeAnimClassOnMapRemovedButSpiderfied ad78e3c02 Merge pull request #610 from ghybs/patch-1 c1b79349e Added sub-plugin MCG.Freezable ed9f02e6a Update MarkerClusterGroup.js fd59fa494 Added missing blank line end of file spiderfySpec e894b31fc Added listener de-binding on remove 4360bf546 Added test in spiderfySpec for class add/remove c4bc5759a Corrected _spiderfierOnRemove to use no animation a0ccbe062 Merge pull request #604 from ghybs/correctUnspiderfyVector 9a212d189 Merge pull request #606 from ghybs/spiderfyOnAllChildrenInBottomMostCluster f18b7f9da Improved methods existence checks 4bb81fda0 Correct smart tab issue cf2f310d2 Added spiderfy test for current zoom 8bb5e64a6 Simplified spiderfy at current zoom trigger 8e2e653ac Improved _zoomOrSpiderfy 6084aa7bb Removed useless comment c338c7777 Removed useless comment a4ec12ceb Replaced instanceof L.Marker by .setOpacity check 088b6ae7d Replaced instanceof L.Marker by .setOpacity check f1ec8c5e0 Correct unspiderfy L.Circle and removeOutsideVisibleBoundsSpec 6328db92f Added magic-string devDependency d37d0ed80 Updated examples script src to v1.0.0-beta.2 (leaflet-src.js) b0e2acf27 Merged new commits and corrected all test suites c69219fa4 Merge pull request #602 from tomchadwin/master 79abfe1bd Formatting typo 1a7d012cd Merge remote-tracking branch 'upstream/leaflet-master-merge' into leaflet-master-merge 5fcd073a8 Merge pull request #600 from ghybs/readmeToc 1226ecb43 Corrected sub-levels indentation 6c7da0549 Added TOC into README b348916ca Merge pull request #599 from ghybs/master d30f3aec8 README new sub-plugins section added links e80c1e0cd README added sub-plugins section 050145c29 Merge pull request #587 from ghybs/maxLatitude eb71a8f84 Merge pull request #588 from ghybs/patch-1 3e21068b3 Merge pull request #585 from ghybs/animationSpiderfyNoSMIL ab451fc3f Added reference to chunked addLayers explanation 183cb4686 Removed no longer needed code d76e9a467 Improved naming of _checkBoundsMaxLat aa1ba5207 Corrected test suite for max latitude check 95dbec9ec Added bounds expansion to Infinity cd4f76dec Merge pull request #584 from ghybs/addLayers-Optimization 71ce1a184 Corrected legOptions class assignment d6d4e7f89 Corrected spiderfy leg anim and leg opacity option 984c632ab Replaced spiderfy legs animation from SMIL to CSS transition bf228d5f7 Removed class extension 1c4a5f62c Replaced bounds reset method extension by cluster private method d55e21919 Merge pull request #583 from ghybs/refreshClusters 8a9f126b5 Added test for refresh singleMarkerMode reject alien markers 54c642c13 Added hasLayer check for singleMarkerMode refresh 127d367c2 Converted singleMarkerMode and animateOption specs d9441c78c Reset bounds rather than re-create 7bbf70e47 Externalized bound and wLatLng computations 0df95323b Merge pull request #579 from ghybs/patch-1 e09833063 Refactored RefreshSpec to use before/afterEach 845f70236 Separated code for singleMarkerMode refresh e6f36e0da Made refreshClusters to re-draw markers in singleMarkerMode 37e923719 Added getChildCount and getAllChildMarkers 3d08cb1a8 Typos f56c4fa56 Typo and re-organized methods 7fd26abea Small punctuation improvements 4b3931f38 Corrected chunk* options description 0aaa590e4 Merge remote-tracking branch 'upstream/master' into patch-1 88233ae36 Merge branch 'patch-1' of https://github.com/ghybs/Leaflet.markercluster into patch-1 c24555196 Parse id to an int, fixes #531 29d7c6e0a Merge pull request #565 from Cyrille37/patch-1 e97134b5e Merge pull request #578 from ghybs/animateOption 739c6f10a Added spiderLegPolylineOptions in section All options d6966aa17 Added description of chunk* options for addLayers 52d238af5 Added animate option 4aeb0dff6 Merge pull request #575 from ghybs/removeOutsideVisibleBounds 134d0a8bd Merge pull request #574 from ghybs/patch-1 60746cc16 Merge pull request #577 from ghybs/refreshClusters 69e142d65 Converted removeOutsideVisibleBoundsSpec test suite e5fabbe0e Improved reliability of RefreshSpec test suite 957151362 Clean remote e7efb8d76 Merge branch 'removeOutsideVisibleBounds' of https://github.com/ghybs/Leaflet.markercluster into removeOutsideVisibleBounds f8a1ff926 Corrected effect of removeOutsideVisibleBounds option feb518cc3 Corrected example for refreshIconOptions cc8de424b Improved example for refreshIconOptions 603b85788 Corrected typo 43dda33b6 Don't need to keep track of the issues this was added for 63ed8842e Merge pull request #564 from ghybs/master 5b4dc71c1 Merge pull request #572 from ghybs/patch-2 50bb1a383 Merge pull request #571 from ghybs/patch-1 60360b13b Improved zoomToShowLayer with callback check d5c7c9460 Replaced constructors by factories 61d24ffdd typo corrected 67fec60ce Added Refresh src in spec/index, newline at end of spec/suites/refresh dea22170d Updated README be3cacca5 Added license in package.json, trying to revert dist files d1b11d9e6 Sync NPM dependencies so test suites are run against Leaflet 1.0.0-beta1 ac71269a4 Merge branch 'leaflet-master' into leaflet-master-merge 306ef6b62 Re-built dist files to include Refresh methods d56061f87 Disabled animation in test suite and added new src file in spec index 3fb556586 Modified method names, added new file to build script, build dist files, added license to package.josn, created test spec suite and added it to spec index. fe8949348 in section "Events" added "clustermouseout" event a12254c67 Corrected compatibility with MCG and added direct refresh of MCG when refreshing Marker a06712053 Additional methods to facilitate marker icons update and propagate to parent clusters in real-time. For issues #561, #555, #535 and #498. 49c92f8f4 placed new file in src b91a135e5 Merge branch 'master' of https://github.com/ghybs/Leaflet.markercluster-1 afc132d21 first commit 10d440ba4 Rough contributing file, stolen from leaflet version 64a2d5711 Merge pull request #556 from Intermaps/remove-layers-fix 879aa2897 corrected explanation text 3c3a9aad9 Moved files to sub-folder and added explanation text and page formatting 2fe03885f first commit of gh-pages for leaflet marker cluster test of hierarchical tree da64e04a1 add spec for removing layers when the group is not on the map a6a897670 remove duplicate _arraySplice 801f6443f fix removeLayers when cluster is not on the map a415818d4 Merge pull request #553 from cyrilchaponeverysens/master cfb91e1c5 Revert "Added "main" property to bower.json to make it compatible with wiredep" (there was already a valid main section) 44bd117de Merge pull request #533 from olive380/patch-2 84da57e41 Update QuickHullSpec.js 3fd3e0d65 Delete showCoverageOnHover-vertically-aligned-markers.html 9a29fd0b6 Delete showCoverageOnHover-horizontally-aligned-markers.html e2be3564b Merge pull request #532 from olive380/patch-1 8d2ae0b73 Create remove-geoJSON-when-spiderfied.html 468241db1 Create showCoverageOnHover-horizontally-aligned-markers.html 368076a14 Create showCoverageOnHover-vertically-aligned-markers.html e6aa0b253 Update MarkerClusterGroup.js 502d8ac2c Update MarkerClusterGroup.js a2f509ce4 Update MarkerCluster.QuickHull.js 0fe481dab Update MarkerCluster.QuickHull.js 79e65560d Update MarkerCluster.QuickHull.js e9889719d Update MarkerCluster.QuickHull.js 59a934408 Update MarkerClusterGroup.js 102f14718 Merge pull request #472 from Eschon/leaflet-master 6e35cf74b rounded zoom to work with fractional zoom levels 53997cd3e Fire unspiderfied event ac8c7063a Fix indention from spaces to tabs 90fbaca19 Provide more detailed context information on the spiderfied event a1e06288d Fix for the latest leaflet master changes. fixes #289 517ba04fc We weren't using the chunked option, fixed. 920c58f09 Small bug still using old variable 530ccaf1a Specifically ignore out setLatLng calls. Should fix using this with Leaflet.Label (which out don't setLatLng hack broke) f86404e84 Revert "Cludge around setLatLng so we don't cause 'move' events when we hack-move markers. This wants doing better." db142ea67 Working animated spiderfying I think... 4e3b8252f Some of animated stuff works. The lines don't animate as we aren't adding the vector layer initially any more and some other bits are broken too 542892d6e get non-animated spiderfying working. 27827b5d6 Rough marker move tracking. refs #57 51014578d Cludge around setLatLng so we don't cause 'move' events when we hack-move markers. This wants doing better. bc463e42c Change event propagation overrides to work with leaflet master code. git-subtree-dir: lib/Leaflet.markercluster git-subtree-split: 584add242e2a190bc30bf86e9d2bae44bd362722 * Squashed 'lib/Leaflet.awesome-markers/' changes from 4dfeef694..734042aef 734042aef Merge pull request #90 from fraulyoner/2.0/develop 23a8efa22 Fix typos in README git-subtree-dir: lib/Leaflet.awesome-markers git-subtree-split: 734042aef260eb3d9b72bbac5db00dfc07dbc602 * webui: Updated leaflet version
This commit is contained in:
+197
-43
@@ -1,16 +1,12 @@
|
||||
/* required styles */
|
||||
|
||||
.leaflet-map-pane,
|
||||
.leaflet-pane,
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-tile-pane,
|
||||
.leaflet-tile-container,
|
||||
.leaflet-overlay-pane,
|
||||
.leaflet-shadow-pane,
|
||||
.leaflet-marker-pane,
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-overlay-pane svg,
|
||||
.leaflet-pane > svg,
|
||||
.leaflet-pane > canvas,
|
||||
.leaflet-zoom-box,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-layer {
|
||||
@@ -20,7 +16,6 @@
|
||||
}
|
||||
.leaflet-container {
|
||||
overflow: hidden;
|
||||
-ms-touch-action: none;
|
||||
}
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
@@ -28,20 +23,49 @@
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
|
||||
.leaflet-safari .leaflet-tile {
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
}
|
||||
/* hack that prevents hw layers "stretching" when loading new tiles */
|
||||
.leaflet-safari .leaflet-tile-container {
|
||||
width: 1600px;
|
||||
height: 1600px;
|
||||
-webkit-transform-origin: 0 0;
|
||||
}
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
display: block;
|
||||
}
|
||||
/* map is broken in FF if you have max-width: 100% on tiles */
|
||||
.leaflet-container img {
|
||||
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
|
||||
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
|
||||
.leaflet-container .leaflet-overlay-pane svg,
|
||||
.leaflet-container .leaflet-marker-pane img,
|
||||
.leaflet-container .leaflet-shadow-pane img,
|
||||
.leaflet-container .leaflet-tile-pane img,
|
||||
.leaflet-container img.leaflet-image-layer {
|
||||
max-width: none !important;
|
||||
}
|
||||
/* stupid Android 2 doesn't understand "max-width: none" properly */
|
||||
.leaflet-container img.leaflet-image-layer {
|
||||
max-width: 15000px !important;
|
||||
|
||||
.leaflet-container.leaflet-touch-zoom {
|
||||
-ms-touch-action: pan-x pan-y;
|
||||
touch-action: pan-x pan-y;
|
||||
}
|
||||
.leaflet-container.leaflet-touch-drag {
|
||||
-ms-touch-action: pinch-zoom;
|
||||
}
|
||||
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.leaflet-container {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.leaflet-container a {
|
||||
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
|
||||
}
|
||||
.leaflet-tile {
|
||||
filter: inherit;
|
||||
visibility: hidden;
|
||||
@@ -52,18 +76,26 @@
|
||||
.leaflet-zoom-box {
|
||||
width: 0;
|
||||
height: 0;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
z-index: 800;
|
||||
}
|
||||
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
|
||||
.leaflet-overlay-pane svg {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.leaflet-tile-pane { z-index: 2; }
|
||||
.leaflet-objects-pane { z-index: 3; }
|
||||
.leaflet-overlay-pane { z-index: 4; }
|
||||
.leaflet-shadow-pane { z-index: 5; }
|
||||
.leaflet-marker-pane { z-index: 6; }
|
||||
.leaflet-popup-pane { z-index: 7; }
|
||||
.leaflet-pane { z-index: 400; }
|
||||
|
||||
.leaflet-tile-pane { z-index: 200; }
|
||||
.leaflet-overlay-pane { z-index: 400; }
|
||||
.leaflet-shadow-pane { z-index: 500; }
|
||||
.leaflet-marker-pane { z-index: 600; }
|
||||
.leaflet-tooltip-pane { z-index: 650; }
|
||||
.leaflet-popup-pane { z-index: 700; }
|
||||
|
||||
.leaflet-map-pane canvas { z-index: 100; }
|
||||
.leaflet-map-pane svg { z-index: 200; }
|
||||
|
||||
.leaflet-vml-shape {
|
||||
width: 1px;
|
||||
@@ -80,7 +112,8 @@
|
||||
|
||||
.leaflet-control {
|
||||
position: relative;
|
||||
z-index: 7;
|
||||
z-index: 800;
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-top,
|
||||
@@ -124,7 +157,9 @@
|
||||
|
||||
/* zoom and fade animations */
|
||||
|
||||
.leaflet-fade-anim .leaflet-tile,
|
||||
.leaflet-fade-anim .leaflet-tile {
|
||||
will-change: opacity;
|
||||
}
|
||||
.leaflet-fade-anim .leaflet-popup {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
@@ -132,11 +167,17 @@
|
||||
-o-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.leaflet-fade-anim .leaflet-tile-loaded,
|
||||
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.leaflet-zoom-animated {
|
||||
-webkit-transform-origin: 0 0;
|
||||
-ms-transform-origin: 0 0;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||
will-change: transform;
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
@@ -144,8 +185,7 @@
|
||||
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-tile,
|
||||
.leaflet-pan-anim .leaflet-tile,
|
||||
.leaflet-touching .leaflet-zoom-animated {
|
||||
.leaflet-pan-anim .leaflet-tile {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
-o-transition: none;
|
||||
@@ -159,24 +199,44 @@
|
||||
|
||||
/* cursors */
|
||||
|
||||
.leaflet-clickable {
|
||||
.leaflet-interactive {
|
||||
cursor: pointer;
|
||||
}
|
||||
.leaflet-container {
|
||||
.leaflet-grab {
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
}
|
||||
.leaflet-crosshair,
|
||||
.leaflet-crosshair .leaflet-interactive {
|
||||
cursor: crosshair;
|
||||
}
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-control {
|
||||
cursor: auto;
|
||||
}
|
||||
.leaflet-dragging .leaflet-container,
|
||||
.leaflet-dragging .leaflet-clickable {
|
||||
.leaflet-dragging .leaflet-grab,
|
||||
.leaflet-dragging .leaflet-grab .leaflet-interactive,
|
||||
.leaflet-dragging .leaflet-marker-draggable {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
}
|
||||
|
||||
/* marker & overlays interactivity */
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-pane > svg path,
|
||||
.leaflet-tile-container {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.leaflet-marker-icon.leaflet-interactive,
|
||||
.leaflet-image-layer.leaflet-interactive,
|
||||
.leaflet-pane > svg path.leaflet-interactive {
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* visual tweaks */
|
||||
|
||||
@@ -249,7 +309,14 @@
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-bar a:first-child {
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:last-child {
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
|
||||
/* zoom control */
|
||||
|
||||
@@ -258,16 +325,10 @@
|
||||
font: bold 18px 'Lucida Console', Monaco, monospace;
|
||||
text-indent: 1px;
|
||||
}
|
||||
.leaflet-control-zoom-out {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-zoom-in {
|
||||
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
|
||||
font-size: 22px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-zoom-out {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
|
||||
/* layers control */
|
||||
@@ -303,6 +364,11 @@
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
.leaflet-control-layers-scrollbar {
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.leaflet-control-layers-selector {
|
||||
margin-top: 2px;
|
||||
position: relative;
|
||||
@@ -317,6 +383,11 @@
|
||||
margin: 5px -10px 5px -6px;
|
||||
}
|
||||
|
||||
/* Default icon URLs */
|
||||
.leaflet-default-icon-path {
|
||||
background-image: url(images/marker-icon.png);
|
||||
}
|
||||
|
||||
|
||||
/* attribution and scale controls */
|
||||
|
||||
@@ -354,8 +425,8 @@
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
@@ -386,6 +457,7 @@
|
||||
.leaflet-popup {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.leaflet-popup-content-wrapper {
|
||||
padding: 1px;
|
||||
@@ -400,11 +472,13 @@
|
||||
margin: 18px 0;
|
||||
}
|
||||
.leaflet-popup-tip-container {
|
||||
margin: 0 auto;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -20px;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-popup-tip {
|
||||
width: 17px;
|
||||
@@ -422,7 +496,7 @@
|
||||
.leaflet-popup-content-wrapper,
|
||||
.leaflet-popup-tip {
|
||||
background: white;
|
||||
|
||||
color: #333;
|
||||
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button {
|
||||
@@ -430,6 +504,7 @@
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 4px 4px 0 0;
|
||||
border: none;
|
||||
text-align: center;
|
||||
width: 18px;
|
||||
height: 14px;
|
||||
@@ -476,3 +551,82 @@
|
||||
background: #fff;
|
||||
border: 1px solid #666;
|
||||
}
|
||||
|
||||
|
||||
/* Tooltip */
|
||||
/* Base styles for the element that has a tooltip */
|
||||
.leaflet-tooltip {
|
||||
position: absolute;
|
||||
padding: 6px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
color: #222;
|
||||
white-space: nowrap;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-tooltip.leaflet-clickable {
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-tooltip-top:before,
|
||||
.leaflet-tooltip-bottom:before,
|
||||
.leaflet-tooltip-left:before,
|
||||
.leaflet-tooltip-right:before {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border: 6px solid transparent;
|
||||
background: transparent;
|
||||
content: "";
|
||||
}
|
||||
|
||||
/* Directions */
|
||||
|
||||
.leaflet-tooltip-bottom {
|
||||
margin-top: 6px;
|
||||
}
|
||||
.leaflet-tooltip-top {
|
||||
margin-top: -6px;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before,
|
||||
.leaflet-tooltip-top:before {
|
||||
left: 50%;
|
||||
margin-left: -6px;
|
||||
}
|
||||
.leaflet-tooltip-top:before {
|
||||
bottom: 0;
|
||||
margin-bottom: -12px;
|
||||
border-top-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before {
|
||||
top: 0;
|
||||
margin-top: -12px;
|
||||
margin-left: -6px;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-left {
|
||||
margin-left: -6px;
|
||||
}
|
||||
.leaflet-tooltip-right {
|
||||
margin-left: 6px;
|
||||
}
|
||||
.leaflet-tooltip-left:before,
|
||||
.leaflet-tooltip-right:before {
|
||||
top: 50%;
|
||||
margin-top: -6px;
|
||||
}
|
||||
.leaflet-tooltip-left:before {
|
||||
right: 0;
|
||||
margin-right: -12px;
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-right:before {
|
||||
left: 0;
|
||||
margin-left: -12px;
|
||||
border-right-color: #fff;
|
||||
}
|
||||
|
||||
+5
-9
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
../../lib/Leaflet.markercluster/dist/leaflet.markercluster-src.js
|
||||
File diff suppressed because it is too large
Load Diff
@@ -71,8 +71,8 @@ Add the ionicon stylesheet from a [CDN](http://code.ionicframework.com/ionicons/
|
||||
| Property | Description | Default Value | Possible values |
|
||||
| --------------- | ---------------------- | ------------- | ---------------------------------------------------- |
|
||||
| icon | Name of the icon | 'home' | See glyphicons or font-awesome |
|
||||
| prefix | Select de icon library | 'glyphicon' | 'fa' for font-awesome or 'glyphicon' for bootstrap 3 |
|
||||
| markerColor | Color of the marker | 'blue' | 'red', 'darkred', 'orange', 'green', 'darkgreen', 'blue', 'purple', 'darkpuple', 'cadetblue' |
|
||||
| prefix | Select the icon library| 'glyphicon' | 'fa' for font-awesome or 'glyphicon' for bootstrap 3 |
|
||||
| markerColor | Color of the marker | 'blue' | 'red', 'darkred', 'orange', 'green', 'darkgreen', 'blue', 'purple', 'darkpurple', 'cadetblue' |
|
||||
| iconColor | Color of the icon | 'white' | 'white', 'black' or css code (hex, rgba etc) |
|
||||
| spin | Make the icon spin | false | true or false. Font-awesome required |
|
||||
| extraClasses | Additional classes in the created <i> tag | '' | 'fa-rotate90 myclass' eller other custom configuration |
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.10
|
||||
- 6
|
||||
cache:
|
||||
directories:
|
||||
- "travis_phantomjs"
|
||||
before_install:
|
||||
- "export PHANTOMJS_VERSION=2.1.1"
|
||||
- "hash -r"
|
||||
- "phantomjs --version"
|
||||
- "export PATH=$PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64/bin:$PATH"
|
||||
- "hash -r"
|
||||
- "phantomjs --version"
|
||||
- "if [ $(phantomjs --version) != \"$PHANTOMJS_VERSION\" ]; then rm -rf $PWD/travis_phantomjs; mkdir -p $PWD/travis_phantomjs; fi"
|
||||
- "hash -r"
|
||||
- "if [ $(phantomjs --version) != \"$PHANTOMJS_VERSION\" ]; then wget https://github.com/Medium/phantomjs/releases/download/v$PHANTOMJS_VERSION/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -O $PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2; fi"
|
||||
- "if [ $(phantomjs --version) != \"$PHANTOMJS_VERSION\" ]; then tar -xvf $PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs; fi"
|
||||
- "hash -r"
|
||||
- "phantomjs --version"
|
||||
@@ -3,9 +3,127 @@ Leaflet.markercluster
|
||||
|
||||
(all changes without author notice are by [@danzel](https://github.com/danzel))
|
||||
|
||||
## Master
|
||||
## 1.2.0 (2017-11-06)
|
||||
|
||||
##0.4 (2013-12-19)
|
||||
### Improvements
|
||||
|
||||
* Move `clusterPane` option in to `options` field (by [@ghybs](https://github.com/ghybs)) [#832](https://github.com/Leaflet/Leaflet.markercluster/pull/832)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix very small `maxClusterRadius` hanging the browser (by [@lucaswerkmeister](https://github.com/lucaswerkmeister)) [#838](https://github.com/Leaflet/Leaflet.markercluster/pull/838)
|
||||
|
||||
## 1.1.0 (2017-08-27)
|
||||
|
||||
### Improvements
|
||||
|
||||
* Add `clusterPane` option to allow putting clusters in a different pane (by [@ckrahe](https://github.com/ckrahe)) [#819](https://github.com/Leaflet/Leaflet.markercluster/issues/819)
|
||||
|
||||
## 1.0.6 (2017-06-19)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix some issues when used with non-integer zoom [#789](https://github.com/Leaflet/Leaflet.markercluster/issues/789)
|
||||
* Change examples to use https (by [@ghybs](https://github.com/ghybs)) [#794](https://github.com/Leaflet/Leaflet.markercluster/pull/794)
|
||||
|
||||
## 1.0.5 (2017-04-26)
|
||||
|
||||
### Improvements
|
||||
|
||||
* Allow passing fitBounds options to zoomToBounds (by [@timkelty](https://github.com/timkelty)) [#779](https://github.com/Leaflet/Leaflet.markercluster/pull/779)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fixed bug where disableClusteringAtZoom being 0 is treated the same as null (by [@MrCheeze](https://github.com/MrCheeze)) [#773](https://github.com/Leaflet/Leaflet.markercluster/pull/773)
|
||||
|
||||
## 1.0.4 (2017-03-14)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix errors removing a MarkerClusterGroup from the map during an animation [#758](https://github.com/Leaflet/Leaflet.markercluster/issues/758)
|
||||
|
||||
## 1.0.3 (2017-02-02)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix moving markers while the MarkerClusterGroup is not on the map [#753](https://github.com/Leaflet/Leaflet.markercluster/issues/753)
|
||||
|
||||
## 1.0.2 (2017-01-27)
|
||||
|
||||
### Improvements
|
||||
|
||||
* Support `layeradd` and `layerremove` events [#647](https://github.com/Leaflet/Leaflet.markercluster/issues/647)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Add support for maps with negative minZoom [#704](https://github.com/Leaflet/Leaflet.markercluster/issues/704)
|
||||
* Fixed zoomToShowLayer() markers disappearing bug (by [@z3ut](https://github.com/z3ut)) [#739](https://github.com/Leaflet/Leaflet.markercluster/issues/739)
|
||||
* Fix an issue when opening a popup inside of zoomToShowLayer
|
||||
* If a marker is moved with an open popup on it, re-open the popup after moving it. [#651](https://github.com/Leaflet/Leaflet.markercluster/issues/651)
|
||||
|
||||
|
||||
## 1.0.1 (2017-01-25)
|
||||
|
||||
### Improvements
|
||||
|
||||
* Add install and build steps with jake (by [@kazes](https://github.com/kazes)) [#733](https://github.com/Leaflet/Leaflet.markercluster/pull/733)
|
||||
* Readme improvements (by [@ghybs](https://github.com/ghybs), [@bertyhell](https://github.com/bertyhell)) [#734](https://github.com/Leaflet/Leaflet.markercluster/pull/738), [#734](https://github.com/Leaflet/Leaflet.markercluster/pull/738
|
||||
* Bump all examples to leaflet 1.0.3
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fixed leaflet 1.0.2 bug where clearLayers would throw an exception (by [@marcianoviereck92](https://github.com/marcianoviereck92)) [#746](https://github.com/Leaflet/Leaflet.markercluster/pull/746)
|
||||
|
||||
|
||||
## 1.0.0 (2016-10-03)
|
||||
|
||||
### Improvements
|
||||
|
||||
* Compatibility with Leaflet 1.0.0 (by [@danzel](https://githum.com/danzel), [@Eschon](https://github.com/Eschon), [@ghybs](https://github.com/ghybs), [@IvanSanchez](https://github.com/IvanSanchez))
|
||||
* Support moving markers [#57](https://github.com/Leaflet/Leaflet.markercluster/issues/57)
|
||||
* chunkedLoading option to keep browser more responsive during larging a load data set [#292](https://github.com/Leaflet/Leaflet.markercluster/issues/292)
|
||||
* maxClusterRadius can be a function (by [@Schwanksta](https://github.com/Schwanksta)) [#298](https://github.com/Leaflet/Leaflet.markercluster/issues/298)
|
||||
* Spiderfy without zooming when all markers at same location (by [@rdenniston](https://github.com/rdenniston), [@ghybs](https://github.com/ghybs)) [#415](https://github.com/Leaflet/Leaflet.markercluster/issues/415), [#606](https://github.com/Leaflet/Leaflet.markercluster/issues/606)
|
||||
* On becoming visible, markers retain their original opacity. (by [@IvanSanchez](https://github.com/IvanSanchez)) [#444](https://github.com/Leaflet/Leaflet.markercluster/issues/444)
|
||||
* Spiderleg Polyline options (by [@mikeatlas](https://github.com/mikeatlas)) [#466](https://github.com/Leaflet/Leaflet.markercluster/issues/466)
|
||||
* Extra methods to allow refreshing cluster icons (by [@ghybs](https://github.com/ghybs)) [#564](https://github.com/Leaflet/Leaflet.markercluster/issues/564)
|
||||
* Ability to disable animations (by [@ghybs](https://github.com/ghybs)) [#578](https://github.com/Leaflet/Leaflet.markercluster/issues/578)
|
||||
* Optimized performance of bulk addLayers and removeLayers (by [@ghybs](https://github.com/ghybs)) [#584](https://github.com/Leaflet/Leaflet.markercluster/issues/584)
|
||||
* Replaced spiderfy legs animation from SMIL to CSS transition (by [@ghybs](https://github.com/ghybs)) [#585](https://github.com/Leaflet/Leaflet.markercluster/issues/585)
|
||||
* Provide more detailed context information on the spiderfied event (by [@evanvosberg](https://github.com/evanvosberg)) [#421](https://github.com/Leaflet/Leaflet.markercluster/issues/421)
|
||||
* Add unspiderfied event
|
||||
* Readme updates (by [@ghybs](https://github.com/ghybs), [@tomchadwin](https://github.com/tomchadwin) [@Cyrille37](https://github.com/Cyrille37) [@franckl](https://github.com/franckl) [@mikeatlas](https://github.com/mikeatlas)
|
||||
[@rdenniston](https://github.com/rdenniston) [@maackle](https://github.com/maackle) [@fureigh](https://github.com/fureigh) [@Wildhoney](https://github.com/Wildhoney) [@Schwanksta](https://github.com/Schwanksta) [@frankrowe](https://github.com/frankrowe))
|
||||
* Improve adding and removing nested LayerGroups (by [@ghybs](https://github.com/ghybs)) [#624](https://github.com/Leaflet/Leaflet.markercluster/pull/624)
|
||||
* Add public unspiderfy method (by [@zverev](https://github.com/zverev)) [#617](https://github.com/Leaflet/Leaflet.markercluster/pull/617)
|
||||
* Optimized performance of bulk add with complex icon create function (by [@mlazowik](https://github.com/mlazowik)) [#697](https://github.com/Leaflet/Leaflet.markercluster/pull/697)
|
||||
* Remove leaflet from peerDependencies (by [@tyleralves](https://github.com/tyleralves)) [#703](https://github.com/Leaflet/Leaflet.markercluster/pull/703)
|
||||
* Simplified _recursively (by [@ghybs](https://github.com/ghybs)) [#656](https://github.com/Leaflet/Leaflet.markercluster/pull/656)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* Fix getBounds when removeOutsideVisibleBounds: false is set. [#321](https://github.com/Leaflet/Leaflet.markercluster/issues/321)
|
||||
* Fix zoomToShowLayer fails after initial spiderfy [#286](https://github.com/Leaflet/Leaflet.markercluster/issues/286)
|
||||
* Fix cluster not disappearing on Android [#344](https://github.com/Leaflet/Leaflet.markercluster/issues/344)
|
||||
* Fix RemoveLayers() when spiderified (by [@Grsmto](https://github.com/Grsmto)) [#358](https://github.com/Leaflet/Leaflet.markercluster/issues/358)
|
||||
* Remove lines from map when removing cluster (by [@olive380](https://github.com/olive380)) [#532](https://github.com/Leaflet/Leaflet.markercluster/issues/532)
|
||||
* Fix getConvexHull when all markers are located at same latitude (by [@olive380](https://github.com/olive380)) [#533](https://github.com/Leaflet/Leaflet.markercluster/issues/533)
|
||||
* Fix removeLayers when cluster is not on the map (by [@eschon](https://github.com/eschon)) [#556](https://github.com/Leaflet/Leaflet.markercluster/issues/556)
|
||||
* Improved zoomToShowLayer with callback check (by [@ghybs](https://github.com/ghybs)) [#572](https://github.com/Leaflet/Leaflet.markercluster/issues/572)
|
||||
* Improved reliability of RefreshSpec test suite for PhantomJS (by [@ghybs](https://github.com/ghybs)) [#577](https://github.com/Leaflet/Leaflet.markercluster/issues/577)
|
||||
* Corrected effect of removeOutsideVisibleBounds option (by [@ghybs](https://github.com/ghybs)) [#575](https://github.com/Leaflet/Leaflet.markercluster/issues/575)
|
||||
* Fix getLayer when provided a string [#531](https://github.com/Leaflet/Leaflet.markercluster/issues/531)
|
||||
* Documentation improvements (by [@ghybs](https://github.com/ghybs)) [#579](https://github.com/Leaflet/Leaflet.markercluster/issues/579)
|
||||
* Correct _getExpandedVisibleBounds for Max Latitude (by [@ghybs](https://github.com/ghybs)) [#587](https://github.com/Leaflet/Leaflet.markercluster/issues/587)
|
||||
* Correct unspiderfy vector (by [@ghybs](https://github.com/ghybs)) [#604](https://github.com/Leaflet/Leaflet.markercluster/issues/604)
|
||||
* Remove "leaflet-cluster-anim" class on map remove while spiderfied (by [@ghybs](https://github.com/ghybs)) [#607](https://github.com/Leaflet/Leaflet.markercluster/issues/607)
|
||||
* Fix disableClusteringAtZoom maxZoom troubles (by [@OriginalSin](https://github.com/OriginalSin)) [#609](https://github.com/Leaflet/Leaflet.markercluster/issues/609)
|
||||
* Fix clusters not disappearing when they were near the edge on mobile (by [@ghybs](https://github.com/ghybs)) [#529](https://github.com/Leaflet/Leaflet.markercluster/issues/529)
|
||||
* Remove leaflet from dependencies (by [@ghybs](https://github.com/ghybs)) [#639](https://github.com/Leaflet/Leaflet.markercluster/issues/639)
|
||||
* Fix interaction between zoomOrSpiderfy and disableClusteringAtZoom (by [@ghybs](https://github.com/ghybs)) [#633](https://github.com/Leaflet/Leaflet.markercluster/issues/633) [#648](https://github.com/Leaflet/Leaflet.markercluster/issues/648)
|
||||
|
||||
|
||||
## 0.4 (2013-12-19)
|
||||
|
||||
### Improvements
|
||||
|
||||
@@ -16,7 +134,8 @@ Leaflet.markercluster
|
||||
|
||||
* Fix some cases zoomToShowLayer wouldn't work (Reported by [@absemetov](https://github.com/absemetov)) [#203](https://github.com/Leaflet/Leaflet.markercluster/issues/203) [#228](https://github.com/Leaflet/Leaflet.markercluster/issues/228) [#286](https://github.com/Leaflet/Leaflet.markercluster/issues/286)
|
||||
|
||||
##0.3 (2013-12-18)
|
||||
|
||||
## 0.3 (2013-12-18)
|
||||
|
||||
### Improvements
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
Contributing to Leaflet.MarkerCluster
|
||||
=====================================
|
||||
|
||||
1. [Reporting Bugs](#reporting-bugs)
|
||||
2. [Contributing Code](#contributing-code)
|
||||
3. [Building](#building)
|
||||
4. [Testing](#testing)
|
||||
|
||||
## Reporting Bugs
|
||||
|
||||
Before reporting a bug on the project's [issues page](https://github.com/Leaflet/Leaflet.markercluster/issues),
|
||||
first make sure that your issue is caused by Leaflet.MarkerCluster, not your application code
|
||||
(e.g. passing incorrect arguments to methods, etc.).
|
||||
Second, search the already reported issues for similar cases,
|
||||
and if it's already reported, just add any additional details in the comments.
|
||||
|
||||
After you've made sure that you've found a new Leaflet.markercluster bug,
|
||||
here are some tips for creating a helpful report that will make fixing it much easier and quicker:
|
||||
|
||||
* Write a **descriptive, specific title**. Bad: *Problem with polylines*. Good: *Doing X in IE9 causes Z*.
|
||||
* Include **browser, OS and Leaflet version** info in the description.
|
||||
* Create a **simple test case** that demonstrates the bug (e.g. using [JSFiddle](http://jsfiddle.net/) or [JS Bin](http://jsbin.com/)).
|
||||
* Check whether the bug can be reproduced in **other browsers**.
|
||||
* Check if the bug occurs in the stable version, master, or both.
|
||||
* *Bonus tip:* if the bug only appears in the master version but the stable version is fine,
|
||||
use `git bisect` to find the exact commit that introduced the bug.
|
||||
|
||||
If you just want some help with your project,
|
||||
try asking [on the Leaflet forum](https://groups.google.com/forum/#!forum/leaflet-js) instead.
|
||||
|
||||
## Contributing Code
|
||||
|
||||
### Considerations for Accepting Patches
|
||||
|
||||
While we happily accept patches, we're also committed to keeping Leaflet simple, lightweight and blazingly fast.
|
||||
So bugfixes, performance optimizations and small improvements that don't add a lot of code
|
||||
are much more likely to get accepted quickly.
|
||||
|
||||
Before sending a pull request with a new feature, check if it's been discussed before already
|
||||
(either on [GitHub issues](https://github.com/Leaflet/Leaflet/issues)
|
||||
or [Leaflet UserVoice](http://leaflet.uservoice.com/)),
|
||||
and ask yourself two questions:
|
||||
|
||||
1. Are you sure that this new feature is important enough to justify its presence in the Leaflet core?
|
||||
Or will it look better as a plugin in a separate repository?
|
||||
2. Is it written in a simple, concise way that doesn't add bulk to the codebase?
|
||||
|
||||
If your feature or API improvement did get merged into master,
|
||||
please consider submitting another pull request with the corresponding [documentation update](#improving-documentation).
|
||||
|
||||
## Building
|
||||
|
||||
Install the dependencies:
|
||||
```
|
||||
npm install -g jake
|
||||
npm install
|
||||
```
|
||||
|
||||
Then to build:
|
||||
```
|
||||
jake
|
||||
```
|
||||
Output will be in the ```dist/``` directory
|
||||
|
||||
## Testing
|
||||
|
||||
To run unit tests:
|
||||
```
|
||||
jake test
|
||||
```
|
||||
@@ -0,0 +1,23 @@
|
||||
- [ ] I'm reporting a bug, not asking for help
|
||||
- [ ] I'm sure this is a Leaflet.MarkerCluster code issue, not an issue with my own code nor with the framework I'm using (Cordova, Ionic, Angular, React…)
|
||||
- [ ] I've searched through the issues to make sure it's not yet reported
|
||||
|
||||
----
|
||||
|
||||
## How to reproduce
|
||||
|
||||
- Leaflet version I'm using:
|
||||
- Leaflet.MarkerCluster version I'm using:
|
||||
- Browser (with version) I'm using:
|
||||
- OS/Platform (with version) I'm using:
|
||||
- step 1
|
||||
- step 2
|
||||
|
||||
## What behaviour I'm expecting and which behaviour I'm seeing
|
||||
|
||||
## Minimal example reproducing the issue
|
||||
|
||||
- [ ] this example is as simple as possible
|
||||
- [ ] this example does not rely on any third party code
|
||||
|
||||
Using http://playground-leaflet.rhcloud.com/beg/1/edit?html,output or any other jsfiddle like site.
|
||||
@@ -3,77 +3,148 @@ Leaflet.markercluster
|
||||
|
||||
Provides Beautiful Animated Marker Clustering functionality for [Leaflet](http://leafletjs.com), a JS library for interactive maps.
|
||||
|
||||
*Requires Leaflet 0.7.0 or newer.*
|
||||
*Requires Leaflet 1.0.0*
|
||||
|
||||

|
||||
|
||||
For a Leaflet 0.7 compatible version, [use the leaflet-0.7 branch](https://github.com/Leaflet/Leaflet.markercluster/tree/leaflet-0.7)<br>
|
||||
For a Leaflet 0.5 compatible version, [Download b128e950](https://github.com/Leaflet/Leaflet.markercluster/archive/b128e950d8f5d7da5b60bd0aa9a88f6d3dd17c98.zip)<br>
|
||||
For a Leaflet 0.4 compatible version, [Download the 0.2 release](https://github.com/Leaflet/Leaflet.markercluster/archive/0.2.zip)
|
||||
|
||||
<!---
|
||||
TOC created with gh-md-toc
|
||||
https://github.com/ekalinin/github-markdown-toc
|
||||
removed link to h1 and indented back 2 spaces all links.
|
||||
-->
|
||||
## Table of Contents
|
||||
* [Using the plugin](#using-the-plugin)
|
||||
* [Building, testing and linting scripts](#building-testing-and-linting-scripts)
|
||||
* [Examples](#examples)
|
||||
* [Usage](#usage)
|
||||
* [Options](#options)
|
||||
* [Defaults](#defaults)
|
||||
* [Customising the Clustered Markers](#customising-the-clustered-markers)
|
||||
* [All Options](#all-options)
|
||||
* [Enabled by default (boolean options)](#enabled-by-default-boolean-options)
|
||||
* [Other options](#other-options)
|
||||
* [Chunked addLayers options](#chunked-addlayers-options)
|
||||
* [Events](#events)
|
||||
* [Additional MarkerClusterGroup Events](#additional-markerclustergroup-events)
|
||||
* [Methods](#methods)
|
||||
* [Group methods](#group-methods)
|
||||
* [Adding and removing Markers](#adding-and-removing-markers)
|
||||
* [Bulk adding and removing Markers](#bulk-adding-and-removing-markers)
|
||||
* [Getting the visible parent of a marker](#getting-the-visible-parent-of-a-marker)
|
||||
* [Refreshing the clusters icon](#refreshing-the-clusters-icon)
|
||||
* [Other Group Methods](#other-group-methods)
|
||||
* [Clusters methods](#clusters-methods)
|
||||
* [Getting the bounds of a cluster](#getting-the-bounds-of-a-cluster)
|
||||
* [Zooming to the bounds of a cluster](#zooming-to-the-bounds-of-a-cluster)
|
||||
* [Other clusters methods](#other-clusters-methods)
|
||||
* [Handling LOTS of markers](#handling-lots-of-markers)
|
||||
* [License](#license)
|
||||
* [Sub-plugins](#sub-plugins)
|
||||
|
||||
|
||||
## Using the plugin
|
||||
Include the plugin CSS and JS files on your page after Leaflet files, using your method of choice:
|
||||
* [Download the `v1.2.0` release](https://github.com/Leaflet/Leaflet.markercluster/archive/v1.2.0.zip)
|
||||
* Use unpkg CDN: `https://unpkg.com/[email protected]/dist/`
|
||||
* Install with npm: `npm install leaflet.markercluster`
|
||||
|
||||
Install with Bower: `bower install leaflet.markercluster`
|
||||
In each case, use files in the `dist` folder:
|
||||
* `MarkerCluster.css`
|
||||
* `MarkerCluster.Default.css` (not needed if you use your own `iconCreateFunction` instead of the default one)
|
||||
* `leaflet.markercluster.js` (or `leaflet.markercluster-src.js` for the non-minified version)
|
||||
|
||||
### Building, testing and linting scripts
|
||||
Install jake `npm install -g jake` then run `npm install`
|
||||
* To check the code for errors and build Leaflet from source, run `jake`.
|
||||
* To run the tests, run `jake test`.
|
||||
|
||||
### Examples
|
||||
See the included examples for usage.
|
||||
|
||||
The [realworld example](http://leaflet.github.com/Leaflet.markercluster/example/marker-clustering-realworld.388.html) is a good place to start, it uses all of the defaults of the clusterer.
|
||||
Or check out the [custom example](http://leaflet.github.com/Leaflet.markercluster/example/marker-clustering-custom.html) for how to customise the behaviour and appearance of the clusterer
|
||||
The [realworld example](https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld.388.html) is a good place to start, it uses all of the defaults of the clusterer.
|
||||
Or check out the [custom example](https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-custom.html) for how to customise the behaviour and appearance of the clusterer
|
||||
|
||||
### Usage
|
||||
Create a new MarkerClusterGroup, add your markers to it, then add it to the map
|
||||
|
||||
```javascript
|
||||
var markers = new L.MarkerClusterGroup();
|
||||
markers.addLayer(new L.Marker(getRandomLatLng(map)));
|
||||
var markers = L.markerClusterGroup();
|
||||
markers.addLayer(L.marker(getRandomLatLng(map)));
|
||||
... Add more layers ...
|
||||
map.addLayer(markers);
|
||||
```
|
||||
|
||||
## Options
|
||||
### Defaults
|
||||
By default the Clusterer enables some nice defaults for you:
|
||||
* **showCoverageOnHover**: When you mouse over a cluster it shows the bounds of its markers.
|
||||
* **zoomToBoundsOnClick**: When you click a cluster we zoom to its bounds.
|
||||
* **spiderfyOnMaxZoom**: When you click a cluster at the bottom zoom level we spiderfy it so you can see all of its markers. (*Note: the spiderfy occurs at the current zoom level if all items within the cluster are physically located at the same latitude and longitude.*)
|
||||
* **spiderfyOnMaxZoom**: When you click a cluster at the bottom zoom level we spiderfy it so you can see all of its markers. (*Note: the spiderfy occurs at the current zoom level if all items within the cluster are still clustered at the maximum zoom level or at zoom specified by `disableClusteringAtZoom` option*)
|
||||
* **removeOutsideVisibleBounds**: Clusters and markers too far from the viewport are removed from the map for performance.
|
||||
* **spiderLegPolylineOptions**: Allows you to specify [PolylineOptions](http://leafletjs.com/reference.html#polyline-options) to style spider legs. By default, they are `{ weight: 1.5, color: '#222' }`.
|
||||
* **spiderLegPolylineOptions**: Allows you to specify [PolylineOptions](http://leafletjs.com/reference.html#polyline-options) to style spider legs. By default, they are `{ weight: 1.5, color: '#222', opacity: 0.5 }`.
|
||||
|
||||
You can disable any of these as you want in the options when you create the MarkerClusterGroup:
|
||||
```javascript
|
||||
var markers = new L.MarkerClusterGroup({ spiderfyOnMaxZoom: false, showCoverageOnHover: false, zoomToBoundsOnClick: false });
|
||||
var markers = L.markerClusterGroup({
|
||||
spiderfyOnMaxZoom: false,
|
||||
showCoverageOnHover: false,
|
||||
zoomToBoundsOnClick: false
|
||||
});
|
||||
```
|
||||
|
||||
### Customising the Clustered Markers
|
||||
As an option to MarkerClusterGroup you can provide your own function for creating the Icon for the clustered markers.
|
||||
The default implementation changes color at bounds of 10 and 100, but more advanced uses may require customising this.
|
||||
You do not need to include the .Default css if you go this way.
|
||||
You are passed a MarkerCluster object, you'll probably want to use getChildCount() or getAllChildMarkers() to work out the icon to show
|
||||
You are passed a MarkerCluster object, you'll probably want to use `getChildCount()` or `getAllChildMarkers()` to work out the icon to show.
|
||||
|
||||
```javascript
|
||||
var markers = new L.MarkerClusterGroup({
|
||||
var markers = L.markerClusterGroup({
|
||||
iconCreateFunction: function(cluster) {
|
||||
return new L.DivIcon({ html: '<b>' + cluster.getChildCount() + '</b>' });
|
||||
return L.divIcon({ html: '<b>' + cluster.getChildCount() + '</b>' });
|
||||
}
|
||||
});
|
||||
```
|
||||
Check out the [custom example](http://leaflet.github.com/Leaflet.markercluster/example/marker-clustering-custom.html) for an example of this.
|
||||
Check out the [custom example](https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-custom.html) for an example of this.
|
||||
|
||||
If you need to update the clusters icon (e.g. they are based on markers real-time data), use the method [refreshClusters()](#refreshing-the-clusters-icon).
|
||||
|
||||
### All Options
|
||||
Enabled by default (boolean options):
|
||||
#### Enabled by default (boolean options)
|
||||
* **showCoverageOnHover**: When you mouse over a cluster it shows the bounds of its markers.
|
||||
* **zoomToBoundsOnClick**: When you click a cluster we zoom to its bounds.
|
||||
* **spiderfyOnMaxZoom**: When you click a cluster at the bottom zoom level we spiderfy it so you can see all of its markers. (*Note: the spiderfy occurs at the current zoom level if all items within the cluster are physically located at the same latitude and longitude.*)
|
||||
* **spiderfyOnMaxZoom**: When you click a cluster at the bottom zoom level we spiderfy it so you can see all of its markers. (*Note: the spiderfy occurs at the current zoom level if all items within the cluster are still clustered at the maximum zoom level or at zoom specified by `disableClusteringAtZoom` option*).
|
||||
* **removeOutsideVisibleBounds**: Clusters and markers too far from the viewport are removed from the map for performance.
|
||||
* **animate**: Smoothly split / merge cluster children when zooming and spiderfying. If `L.DomUtil.TRANSITION` is false, this option has no effect (no animation is possible).
|
||||
|
||||
Other options
|
||||
* **animateAddingMarkers**: If set to true then adding individual markers to the MarkerClusterGroup after it has been added to the map will add the marker and animate it in to the cluster. Defaults to false as this gives better performance when bulk adding markers. addLayers does not support this, only addLayer with individual Markers.
|
||||
* **disableClusteringAtZoom**: If set, at this zoom level and below markers will not be clustered. This defaults to disabled. [See Example](http://leaflet.github.com/Leaflet.markercluster/example/marker-clustering-realworld-maxzoom.388.html)
|
||||
#### Other options
|
||||
* **animateAddingMarkers**: If set to true (and `animate` option is also true) then adding individual markers to the MarkerClusterGroup after it has been added to the map will add the marker and animate it into the cluster. Defaults to false as this gives better performance when bulk adding markers. addLayers does not support this, only addLayer with individual Markers.
|
||||
* **disableClusteringAtZoom**: If set, at this zoom level and below, markers will not be clustered. This defaults to disabled. [See Example](https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld-maxzoom.388.html). Note: you may be interested in disabling `spiderfyOnMaxZoom` option when using `disableClusteringAtZoom`.
|
||||
* **maxClusterRadius**: The maximum radius that a cluster will cover from the central marker (in pixels). Default 80. Decreasing will make more, smaller clusters. You can also use a function that accepts the current map zoom and returns the maximum cluster radius in pixels.
|
||||
* **polygonOptions**: Options to pass when creating the L.Polygon(points, options) to show the bounds of a cluster
|
||||
* **singleMarkerMode**: If set to true, overrides the icon for all added markers to make them appear as a 1 size cluster
|
||||
* **spiderfyDistanceMultiplier**: Increase from 1 to increase the distance away from the center that spiderfied markers are placed. Use if you are using big marker icons (Default:1)
|
||||
* **iconCreateFunction**: Function used to create the cluster icon [See default as example](https://github.com/Leaflet/Leaflet.markercluster/blob/15ed12654acdc54a4521789c498e4603fe4bf781/src/MarkerClusterGroup.js#L542).
|
||||
* **polygonOptions**: Options to pass when creating the L.Polygon(points, options) to show the bounds of a cluster. Defaults to empty, which lets Leaflet use the [default Path options](http://leafletjs.com/reference.html#path-options).
|
||||
* **singleMarkerMode**: If set to true, overrides the icon for all added markers to make them appear as a 1 size cluster. Note: the markers are not replaced by cluster objects, only their icon is replaced. Hence they still react to normal events, and option `disableClusteringAtZoom` does not restore their previous icon (see [#391](https://github.com/Leaflet/Leaflet.markercluster/issues/391)).
|
||||
* **spiderLegPolylineOptions**: Allows you to specify [PolylineOptions](http://leafletjs.com/reference.html#polyline-options) to style spider legs. By default, they are `{ weight: 1.5, color: '#222', opacity: 0.5 }`.
|
||||
* **spiderfyDistanceMultiplier**: Increase from 1 to increase the distance away from the center that spiderfied markers are placed. Use if you are using big marker icons (Default: 1).
|
||||
* **iconCreateFunction**: Function used to create the cluster icon. See [the default implementation](https://github.com/Leaflet/Leaflet.markercluster/blob/15ed12654acdc54a4521789c498e4603fe4bf781/src/MarkerClusterGroup.js#L542) or the [custom example](https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-custom.html).
|
||||
* **clusterPane**: Map pane where the cluster icons will be added. Defaults to L.Marker's default (currently 'markerPane'). [See the pane example](https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-pane.html).
|
||||
|
||||
#### Chunked addLayers options
|
||||
Options for the [addLayers](#bulk-adding-and-removing-markers) method. See [#357](https://github.com/Leaflet/Leaflet.markercluster/issues/357) for explanation on how the chunking works.
|
||||
* **chunkedLoading**: Boolean to split the addLayer**s** processing in to small intervals so that the page does not freeze.
|
||||
* **chunkInterval**: Time interval (in ms) during which addLayers works before pausing to let the rest of the page process. In particular, this prevents the page from freezing while adding a lot of markers. Defaults to 200ms.
|
||||
* **chunkDelay**: Time delay (in ms) between consecutive periods of processing for addLayers. Default to 50ms.
|
||||
* **chunkProgress**: Callback function that is called at the end of each chunkInterval. Typically used to implement a progress indicator, e.g. [code in RealWorld 50k](https://github.com/Leaflet/Leaflet.markercluster/blob/master/example/marker-clustering-realworld.50000.html#L33-L49). Defaults to null. Arguments:
|
||||
1. Number of processed markers
|
||||
2. Total number of markers being added
|
||||
3. Elapsed time (in ms)
|
||||
|
||||
## Events
|
||||
If you register for click, mouseover, etc events are just related to Markers in the cluster.
|
||||
To receive events for clusters listen to 'cluster' + 'eventIWant', ex: 'clusterclick', 'clustermouseover'.
|
||||
Leaflet events like `click`, `mouseover`, etc. are just related to _Markers_ in the cluster.
|
||||
To receive events for clusters, listen to `'cluster' + '<eventName>'`, ex: `clusterclick`, `clustermouseover`, `clustermouseout`.
|
||||
|
||||
Set your callback up as follows to handle both cases:
|
||||
|
||||
@@ -83,68 +154,139 @@ markers.on('click', function (a) {
|
||||
});
|
||||
|
||||
markers.on('clusterclick', function (a) {
|
||||
// a.layer is actually a cluster
|
||||
console.log('cluster ' + a.layer.getAllChildMarkers().length);
|
||||
});
|
||||
```
|
||||
|
||||
#### Additional MarkerClusterGroup Events
|
||||
### Additional MarkerClusterGroup Events
|
||||
|
||||
- **animationend**: Fires when marker clustering/unclustering animation has completed
|
||||
- **spiderfied**: Fires when overlapping markers get spiderified
|
||||
- **spiderfied**: Fires when overlapping markers get spiderified (Contains ```cluster``` and ```markers``` attributes)
|
||||
- **unspiderfied**: Fires when overlapping markers get unspiderified (Contains ```cluster``` and ```markers``` attributes)
|
||||
|
||||
## Methods
|
||||
|
||||
### Getting the bounds of a cluster
|
||||
When you receive an event from a cluster you can query it for the bounds.
|
||||
See [example/marker-clustering-convexhull.html](http://leaflet.github.com/Leaflet.markercluster/example/marker-clustering-convexhull.html) for a working example.
|
||||
```javascript
|
||||
markers.on('clusterclick', function (a) {
|
||||
map.addLayer(new L.Polygon(a.layer.getConvexHull()));
|
||||
});
|
||||
```
|
||||
### Group methods
|
||||
|
||||
### Zooming to the bounds of a cluster
|
||||
When you receive an event from a cluster you can zoom to its bounds in one easy step.
|
||||
If all of the markers will appear at a higher zoom level, that zoom level is zoomed to instead.
|
||||
See [marker-clustering-zoomtobounds.html](http://leaflet.github.com/Leaflet.markercluster/example/marker-clustering-zoomtobounds.html) for a working example.
|
||||
```javascript
|
||||
markers.on('clusterclick', function (a) {
|
||||
a.layer.zoomToBounds();
|
||||
});
|
||||
```
|
||||
#### Adding and removing Markers
|
||||
`addLayer`, `removeLayer` and `clearLayers` are supported and they should work for most uses.
|
||||
|
||||
### Getting the visible parent of a marker
|
||||
#### Bulk adding and removing Markers
|
||||
`addLayers` and `removeLayers` are bulk methods for adding and removing markers and should be favoured over the single versions when doing bulk addition/removal of markers. Each takes an array of markers. You can use [dedicated options](#chunked-addlayers-options) to fine-tune the behaviour of `addLayers`.
|
||||
|
||||
These methods extract non-group layer children from Layer Group types, even deeply nested. _However_, be noted that:
|
||||
- `chunkProgress` jumps backward when `addLayers` finds a group (since appending its children to the input array makes the total increase).
|
||||
- Groups are not actually added into the MarkerClusterGroup, only their non-group child layers. Therfore, `hasLayer` method will return `true` for non-group child layers, but `false` on any (possibly parent) Layer Group types.
|
||||
|
||||
If you are removing a lot of markers it will almost definitely be better to call `clearLayers` then call `addLayers` to add the markers you don't want to remove back in. See [#59](https://github.com/Leaflet/Leaflet.markercluster/issues/59#issuecomment-9320628) for details.
|
||||
|
||||
#### Getting the visible parent of a marker
|
||||
If you have a marker in your MarkerClusterGroup and you want to get the visible parent of it (Either itself or a cluster it is contained in that is currently visible on the map).
|
||||
This will return null if the marker and its parent clusters are not visible currently (they are not near the visible viewpoint)
|
||||
```
|
||||
```javascript
|
||||
var visibleOne = markerClusterGroup.getVisibleParent(myMarker);
|
||||
console.log(visibleOne.getLatLng());
|
||||
```
|
||||
|
||||
### Adding and removing Markers
|
||||
addLayer, removeLayer and clearLayers are supported and they should work for most uses.
|
||||
#### Refreshing the clusters icon
|
||||
If you have [customized](#customising-the-clustered-markers) the clusters icon to use some data from the contained markers, and later that data changes, use this method to force a refresh of the cluster icons.
|
||||
You can use the method:
|
||||
- without arguments to force all cluster icons in the Marker Cluster Group to be re-drawn.
|
||||
- with an array or a mapping of markers to force only their parent clusters to be re-drawn.
|
||||
- with an L.LayerGroup. The method will look for all markers in it. Make sure it contains only markers which are also within this Marker Cluster Group.
|
||||
- with a single marker.
|
||||
```javascript
|
||||
markers.refreshClusters();
|
||||
markers.refreshClusters([myMarker0, myMarker33]);
|
||||
markers.refreshClusters({id_0: myMarker0, id_any: myMarker33});
|
||||
markers.refreshClusters(myLayerGroup);
|
||||
markers.refreshClusters(myMarker);
|
||||
```
|
||||
|
||||
### Bulk adding and removing Markers
|
||||
addLayers and removeLayers are bulk methods for adding and removing markers and should be favoured over the single versions when doing bulk addition/removal of markers. Each takes an array of markers
|
||||
The plugin also adds a method on L.Marker to easily update the underlying icon options and refresh the icon.
|
||||
If passing a second argument that evaluates to `true`, the method will also trigger a `refreshCluster` on the parent MarkerClusterGroup for that single marker.
|
||||
```javascript
|
||||
// Use as many times as required to update markers,
|
||||
// then call refreshClusters once finished.
|
||||
for (i in markersSubArray) {
|
||||
markersSubArray[i].refreshIconOptions(newOptionsMappingArray[i]);
|
||||
}
|
||||
markers.refreshClusters(markersSubArray);
|
||||
|
||||
If you are removing a lot of markers it will almost definitely be better to call clearLayers then call addLayers to add the markers you don't want to remove back in. See [#59](https://github.com/Leaflet/Leaflet.markercluster/issues/59#issuecomment-9320628) for details.
|
||||
// If updating only one marker, pass true to
|
||||
// refresh this marker's parent clusters right away.
|
||||
myMarker.refreshIconOptions(optionsMap, true);
|
||||
```
|
||||
|
||||
### Other Methods
|
||||
````
|
||||
hasLayer(layer): Returns true if the given layer (marker) is in the MarkerClusterGroup
|
||||
zoomToShowLayer(layer, callback): Zooms to show the given marker (spidifying if required), calls the callback when the marker is visible on the map
|
||||
addLayers(layerArray): Adds the markers in the given array from the MarkerClusterGroup in an efficent bulk method.
|
||||
removeLayers(layerArray): Removes the markers in the given array from the MarkerClusterGroup in an efficent bulk method.
|
||||
````
|
||||
#### Other Group Methods
|
||||
* **hasLayer**(layer): Returns true if the given layer (marker) is in the MarkerClusterGroup.
|
||||
* **zoomToShowLayer**(layer, callback): Zooms to show the given marker (spiderfying if required), calls the callback when the marker is visible on the map.
|
||||
|
||||
### Clusters methods
|
||||
The following methods can be used with clusters (not the group). They are typically used for event handling.
|
||||
|
||||
#### Getting the bounds of a cluster
|
||||
When you receive an event from a cluster you can query it for the bounds.
|
||||
```javascript
|
||||
markers.on('clusterclick', function (a) {
|
||||
var latLngBounds = a.layer.getBounds();
|
||||
});
|
||||
```
|
||||
|
||||
You can also query for the bounding convex polygon.
|
||||
See [example/marker-clustering-convexhull.html](https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-convexhull.html) for a working example.
|
||||
```javascript
|
||||
markers.on('clusterclick', function (a) {
|
||||
map.addLayer(L.polygon(a.layer.getConvexHull()));
|
||||
});
|
||||
```
|
||||
|
||||
#### Zooming to the bounds of a cluster
|
||||
When you receive an event from a cluster you can zoom to its bounds in one easy step.
|
||||
If all of the markers will appear at a higher zoom level, that zoom level is zoomed to instead.
|
||||
`zoomToBounds` takes an optional argument to pass [options to the resulting `fitBounds` call](http://leafletjs.com/reference.html#map-fitboundsoptions).
|
||||
|
||||
See [marker-clustering-zoomtobounds.html](https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-zoomtobounds.html) for a working example.
|
||||
```javascript
|
||||
markers.on('clusterclick', function (a) {
|
||||
a.layer.zoomToBounds({padding: [20, 20]});
|
||||
});
|
||||
```
|
||||
|
||||
#### Other clusters methods
|
||||
* **getChildCount**: Returns the total number of markers contained within that cluster.
|
||||
* **getAllChildMarkers**: Returns the array of total markers contained within that cluster.
|
||||
* **spiderfy**: Spiderfies the child markers of this cluster
|
||||
* **unspiderfy**: Unspiderfies a cluster (opposite of spiderfy)
|
||||
|
||||
## Handling LOTS of markers
|
||||
The Clusterer can handle 10000 or even 50000 markers (in chrome). IE9 has some issues with 50000.
|
||||
[realworld 10000 example](http://leaflet.github.com/Leaflet.markercluster/example/marker-clustering-realworld.10000.html)
|
||||
[realworld 50000 example](http://leaflet.github.com/Leaflet.markercluster/example/marker-clustering-realworld.50000.html)
|
||||
Performance optimizations could be done so these are handled more gracefully (Running the initial clustering over multiple JS calls rather than locking the browser for a long time)
|
||||
The Clusterer can handle 10,000 or even 50,000 markers (in chrome). IE9 has some issues with 50,000.
|
||||
- [realworld 10,000 example](https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld.10000.html)
|
||||
- [realworld 50,000 example](https://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld.50000.html)
|
||||
|
||||
### License
|
||||
Note: these two examples use the `chunkedLoading` option set to true in order to avoid locking the browser for a long time.
|
||||
|
||||
## License
|
||||
|
||||
Leaflet.markercluster is free software, and may be redistributed under the MIT-LICENSE.
|
||||
|
||||
[](https://travis-ci.org/Leaflet/Leaflet.markercluster)
|
||||
|
||||
## Sub-plugins
|
||||
Leaflet.markercluster plugin is very popular and as such it generates high and
|
||||
diverse expectations for increased functionalities.
|
||||
|
||||
If you are in that case, be sure to have a look first at the repository
|
||||
[issues](https://github.com/Leaflet/Leaflet.markercluster/issues) in case what
|
||||
you are looking for would already be discussed, and some workarounds would be proposed.
|
||||
|
||||
Check also the below sub-plugins:
|
||||
|
||||
| Plugin | Description | Maintainer |
|
||||
| :----- | :---------- | :--------- |
|
||||
| [Leaflet.FeatureGroup.SubGroup](https://github.com/ghybs/Leaflet.FeatureGroup.SubGroup) | Creates a Feature Group that adds its child layers into a parent group when added to a map (e.g. through L.Control.Layers). Typical usage is to dynamically add/remove groups of markers from Marker Cluster. | [ghybs](https://github.com/ghybs) |
|
||||
| [Leaflet.MarkerCluster.LayerSupport](https://github.com/ghybs/Leaflet.MarkerCluster.LayerSupport) | Brings compatibility with L.Control.Layers and other Leaflet plugins. I.e. everything that uses direct calls to map.addLayer and map.removeLayer. | [ghybs](https://github.com/ghybs) |
|
||||
| [Leaflet.MarkerCluster.Freezable](https://github.com/ghybs/Leaflet.MarkerCluster.Freezable) | Adds the ability to freeze clusters at a specified zoom. E.g. freezing at maxZoom + 1 makes as if clustering was programmatically disabled. | [ghybs](https://github.com/ghybs) |
|
||||
| [Leaflet.MarkerCluster.PlacementStrategies](https://github.com/adammertel/Leaflet.MarkerCluster.PlacementStrategies) | Implements new strategies to position clustered markers (eg: clock, concentric circles, ...). Recommended to use with circleMarkers. [Demo](https://adammertel.github.io/Leaflet.MarkerCluster.PlacementStrategies/demo/demo1.html) | [adammertel](https://github.com/adammertel) / [UNIVIE](http://carto.univie.ac.at/) |
|
||||
| [Leaflet.MarkerCluster.List](https://github.com/adammertel/Leaflet.MarkerCluster.List) | Displays child elements in a list. Suitable for mobile devices. [Demo](https://adammertel.github.io/Leaflet.MarkerCluster.List/demo/demo1.html) | [adammertel](https://github.com/adammertel) / [UNIVIE](http://carto.univie.ac.at/) |
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"name": "leaflet.markercluster",
|
||||
"version": "0.4.0",
|
||||
"main": "dist/leaflet.markercluster-src.js",
|
||||
"version": "1.2.0",
|
||||
"homepage": "https://github.com/Leaflet/Leaflet.markercluster",
|
||||
"authors": [
|
||||
"Dave Leaver <[email protected]>"
|
||||
@@ -23,6 +22,6 @@
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"leaflet": ">= 0.7.0"
|
||||
"leaflet": ">= 1.0.3"
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,12 @@ var deps = {
|
||||
src: ['MarkerCluster.Spiderfier.js'],
|
||||
desc: 'Provides the ability to show all of the child markers of a cluster.',
|
||||
heading: 'Spiderfier'
|
||||
},
|
||||
|
||||
Refresh: {
|
||||
src: ['MarkerClusterGroup.Refresh.js'],
|
||||
desc: 'Method to request refreshing of clusters icon to reflect changes in markers data.',
|
||||
heading: 'Refresh'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+9
-1
@@ -3,4 +3,12 @@
|
||||
-moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
-o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
transition: transform 0.3s ease-out, opacity 0.3s ease-in;
|
||||
}
|
||||
}
|
||||
|
||||
.leaflet-cluster-spider-leg {
|
||||
/* stroke-dashoffset (duration and function) should match with leaflet-marker-icon transform in order to track it exactly */
|
||||
-webkit-transition: -webkit-stroke-dashoffset 0.3s ease-out, -webkit-stroke-opacity 0.3s ease-in;
|
||||
-moz-transition: -moz-stroke-dashoffset 0.3s ease-out, -moz-stroke-opacity 0.3s ease-in;
|
||||
-o-transition: -o-stroke-dashoffset 0.3s ease-out, -o-stroke-opacity 0.3s ease-in;
|
||||
transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
We don't ship the .js files in the git master branch.
|
||||
They are only present in version tags and in npm.
|
||||
|
||||
See how to get the JS files here: https://github.com/Leaflet/Leaflet.markercluster#using-the-plugin
|
||||
Or how to build them: https://github.com/Leaflet/Leaflet.markercluster#building-testing-and-linting-scripts
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
]
|
||||
};
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
});
|
||||
|
||||
var map = L.map('map')
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 381 KiB |
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = L.latLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = L.latLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
<link rel="stylesheet" href="../dist/MarkerCluster.css" />
|
||||
<link rel="stylesheet" href="../dist/MarkerCluster.Default.css" />
|
||||
<script src="../dist/leaflet.markercluster-src.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="map"></div>
|
||||
<button id="moveone">Move a random marker</button>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
var map = new L.Map('map', {center: latlng, zoom: 15, layers: [tiles]});
|
||||
|
||||
var markers = new L.MarkerClusterGroup();
|
||||
var markersList = [];
|
||||
|
||||
function populate() {
|
||||
for (var i = 0; i < 100; i++) {
|
||||
var m = new L.Marker(getRandomLatLng(map), { draggable: true });
|
||||
markersList.push(m);
|
||||
markers.addLayer(m);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function populateRandomVector() {
|
||||
for (var i = 0, latlngs = [], len = 20; i < len; i++) {
|
||||
latlngs.push(getRandomLatLng(map));
|
||||
}
|
||||
var path = new L.Polyline(latlngs);
|
||||
map.addLayer(path);
|
||||
}
|
||||
function getRandomLatLng(map) {
|
||||
var bounds = map.getBounds(),
|
||||
southWest = bounds.getSouthWest(),
|
||||
northEast = bounds.getNorthEast(),
|
||||
lngSpan = northEast.lng - southWest.lng,
|
||||
latSpan = northEast.lat - southWest.lat;
|
||||
|
||||
return new L.LatLng(
|
||||
southWest.lat + latSpan * Math.random(),
|
||||
southWest.lng + lngSpan * Math.random());
|
||||
}
|
||||
|
||||
markers.on('clusterclick', function (a) {
|
||||
alert('cluster ' + a.layer.getAllChildMarkers().length);
|
||||
});
|
||||
markers.on('click', function (a) {
|
||||
alert('marker ' + a.layer);
|
||||
});
|
||||
|
||||
populate();
|
||||
map.addLayer(markers);
|
||||
|
||||
L.DomUtil.get('moveone').onclick = function () {
|
||||
var m = markersList[Math.floor(Math.random() * markersList.length)];
|
||||
var bounds = map.getBounds(),
|
||||
southWest = bounds.getSouthWest(),
|
||||
northEast = bounds.getNorthEast(),
|
||||
lngSpan = northEast.lng - southWest.lng,
|
||||
latSpan = northEast.lat - southWest.lat;
|
||||
m.setLatLng(new L.LatLng(
|
||||
southWest.lat + latSpan * 0.5,
|
||||
southWest.lng + lngSpan * 0.5));
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
<span>Mouse over a cluster to see the bounds of its children and click a cluster to zoom to those bounds</span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = L.latLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
<span>Mouse over a cluster to see the bounds of its children and click a cluster to zoom to those bounds</span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = L.latLng(0.78, 102.37);
|
||||
|
||||
@@ -39,14 +39,14 @@
|
||||
var popupText = 'geometry type: ' + feature.geometry.type;
|
||||
|
||||
if (feature.properties.color) {
|
||||
popupText += '<br/>color: ' + feature.properties.color
|
||||
popupText += '<br/>color: ' + feature.properties.color;
|
||||
}
|
||||
|
||||
layer.bindPopup(popupText);
|
||||
}
|
||||
});
|
||||
|
||||
geojson.addLayer(new L.Marker(new L.LatLng(2.745530718801952, 105.194091796875)))
|
||||
geojson.addLayer(new L.Marker(new L.LatLng(2.745530718801952, 105.194091796875)));
|
||||
|
||||
var eye1 = new L.Marker(new L.LatLng(-0.7250783020332547, 101.8212890625));
|
||||
var eye2 = new L.Marker(new L.LatLng(-0.7360637370492077, 103.2275390625));
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
<link rel="stylesheet" href="../dist/MarkerCluster.css" />
|
||||
<script src="../dist/leaflet.markercluster-src.js"></script>
|
||||
|
||||
<style>
|
||||
.myclusterA {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: greenyellow;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
}
|
||||
.myclusterB {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: red;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="map"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = L.latLng(50.5, 30.51);
|
||||
|
||||
var map = L.map('map', {center: latlng, zoom: 15, layers: [tiles]});
|
||||
|
||||
//Define a pane above the default markerPane
|
||||
map.createPane('paneB').style.zIndex = 610;
|
||||
|
||||
//Create two markerClusterGroups, one in the default markerPane, one in our custom pane
|
||||
var markersA = createMarkerClusterGroup('myclusterA');
|
||||
var markersB = createMarkerClusterGroup('myclusterB', 'paneB');
|
||||
|
||||
function createMarkerClusterGroup(className, pane) {
|
||||
var options = {
|
||||
maxClusterRadius: 120,
|
||||
iconCreateFunction: function (cluster) {
|
||||
var markers = cluster.getAllChildMarkers();
|
||||
var n = 0;
|
||||
for (var i = 0; i < markers.length; i++) {
|
||||
n += markers[i].number;
|
||||
}
|
||||
return L.divIcon({ html: n, className: className, iconSize: L.point(40, 40) });
|
||||
},
|
||||
//Disable all of the defaults & specify the pane:
|
||||
spiderfyOnMaxZoom: false,
|
||||
showCoverageOnHover: false,
|
||||
zoomToBoundsOnClick: false
|
||||
};
|
||||
if (pane) {
|
||||
options.clusterPane = pane;
|
||||
}
|
||||
var mcg = L.markerClusterGroup(options);
|
||||
return(mcg);
|
||||
}
|
||||
|
||||
function populate(markers) {
|
||||
for (var i = 0; i < 100; i++) {
|
||||
var m = L.marker(getRandomLatLng(map), { title: i });
|
||||
m.number = i;
|
||||
markers.addLayer(m);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getRandomLatLng(map) {
|
||||
var bounds = map.getBounds(),
|
||||
southWest = bounds.getSouthWest(),
|
||||
northEast = bounds.getNorthEast(),
|
||||
lngSpan = northEast.lng - southWest.lng,
|
||||
latSpan = northEast.lat - southWest.lat;
|
||||
|
||||
return L.latLng(
|
||||
southWest.lat + latSpan * Math.random(),
|
||||
southWest.lng + lngSpan * Math.random());
|
||||
}
|
||||
|
||||
populate(markersA);
|
||||
populate(markersB);
|
||||
map.addLayer(markersA);
|
||||
map.addLayer(markersB);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
<span>Markers will show on the bottom 2 zoom levels even though the markers would normally cluster.</span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, Points © 2012 LINZ'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Points © 2012 LINZ'
|
||||
}),
|
||||
latlng = L.latLng(-37.82, 175.24);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<link rel="stylesheet" href="mobile.css" />
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, Points © 2012 LINZ'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Points © 2012 LINZ'
|
||||
}),
|
||||
latlng = L.latLng(-37.821, 175.22);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
<span>Mouse over a cluster to see the bounds of its children and click a cluster to zoom to those bounds</span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, Points © 2012 LINZ'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Points © 2012 LINZ'
|
||||
}),
|
||||
latlng = L.latLng(-37.89, 175.46);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
<span>Mouse over a cluster to see the bounds of its children and click a cluster to zoom to those bounds</span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, Points © 2012 LINZ'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Points © 2012 LINZ'
|
||||
}),
|
||||
latlng = L.latLng(-37.82, 175.24);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
<div id="map"></div>
|
||||
<span>Mouse over a cluster to see the bounds of its children and click a cluster to zoom to those bounds</span>
|
||||
<script type="text/javascript">
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, Points © 2012 LINZ'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Points © 2012 LINZ'
|
||||
}),
|
||||
latlng = L.latLng(-37.79, 175.27);
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
markerList.push(marker);
|
||||
}
|
||||
for (var i = 0; i < addressPoints2.length; i++) {
|
||||
var a = addressPoints[i];
|
||||
var a = addressPoints2[i];
|
||||
var title = a[2];
|
||||
var marker = L.marker(L.latLng(a[0], a[1]), { title: title });
|
||||
marker.bindPopup(title);
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = L.latLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = L.latLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = L.latLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
<span>When clicked we will zoom down to a marker, spiderfying if required to show it and then open its popup</span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = L.latLng(-37.82, 175.24);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
<span id="time"></span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
<span>Bug <a href="https://github.com/danzel/Leaflet.markercluster/issues/69">#69</a>. Click the button 2+ times. Zoom out. Should just be a single cluster but instead one of the child markers is still visible.</span><br/>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
<span id="time"></span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
<span id="time"></span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(-37.36142550190516, 174.254150390625);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
return new L.DivIcon({ html: '<div><span>' + childCount + '</span></div>', className: 'marker-cluster' + c, iconSize: new L.Point(270, 270) });
|
||||
};
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(54.18815548107151, 6.1083984375);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -51,9 +51,9 @@
|
||||
var trainPosition = 0,
|
||||
trainDirection = 'up';
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
map = new L.Map('map', {zoom: 15, layers: [tiles]}),
|
||||
markers = new L.MarkerClusterGroup({ spiderfyOnMaxZoom: false, showCoverageOnHover: false, zoomToBoundsOnClick: false });
|
||||
|
||||
+4
-4
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(40.782982, -73.969452);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
|
||||
var map = new L.Map('map');
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
});
|
||||
map.addLayer(tiles);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
//Mobile does different bounds to desktop, makes the bug easier to reproduce
|
||||
L.Browser.mobile = true;
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
<span id="time"></span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
|
||||
+4
-4
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css" />
|
||||
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet-src.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="../screen.css" />
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
<span id="time"></span>
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ==" crossorigin="" />
|
||||
<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js" integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA==" crossorigin=""></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="screen.css" />
|
||||
|
||||
<link rel="stylesheet" href="../dist/MarkerCluster.css" />
|
||||
<link rel="stylesheet" href="../dist/MarkerCluster.Default.css" />
|
||||
<script src="../dist/leaflet.markercluster-src.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="map"></div>
|
||||
<button id="doit">Remove marker #1</button><button id="doit2">Remove marker #2</button><br/>
|
||||
<span>New Bug. Spiderfy the cluster then click the button #1. All markers disapear, but it should remain marker #2.</span><br/>
|
||||
<span>New Bug. Spiderfy the cluster then click the button #2. All markers disapear, but it should remain marker #1.</span><br/>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}),
|
||||
latlng = new L.LatLng(50.5, 30.51);
|
||||
|
||||
var map = new L.Map('map', {center: latlng, zoom: 15, layers: [tiles]});
|
||||
|
||||
var markers = new L.MarkerClusterGroup({ disableClusteringAtZoom: 19});
|
||||
var markersList = [];
|
||||
var m;
|
||||
|
||||
geoJsonFeature = { "type": "FeatureCollection",
|
||||
"features": [ { "type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [30.51, 50.5]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
m = L.geoJson(geoJsonFeature, {
|
||||
pointToLayer: function (feature, latlng) {
|
||||
return L.marker(latlng);
|
||||
}
|
||||
});
|
||||
markersList.push(m);
|
||||
markers.addLayer(m);
|
||||
|
||||
|
||||
geoJsonFeature = { "type": "FeatureCollection",
|
||||
"features": [ { "type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [30.5101, 50.5]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
m = L.geoJson(geoJsonFeature, {
|
||||
pointToLayer: function (feature, latlng) {
|
||||
return L.marker(latlng);
|
||||
}
|
||||
});
|
||||
markersList.push(m);
|
||||
markers.addLayer(m);
|
||||
|
||||
map.addLayer(markers);
|
||||
|
||||
L.DomUtil.get('doit').onclick = function () {
|
||||
markers.removeLayer(markersList[0]);
|
||||
};
|
||||
|
||||
L.DomUtil.get('doit2').onclick = function () {
|
||||
markers.removeLayer(markersList[1]);
|
||||
};
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"name": "leaflet.markercluster",
|
||||
"repository": "https://github.com/Leaflet/Leaflet.markercluster",
|
||||
"version": "0.4.0",
|
||||
"version": "1.2.0",
|
||||
"description": "Provides Beautiful Animated Marker Clustering functionality for Leaflet",
|
||||
"dependencies": {
|
||||
"leaflet": "~0.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jshint": "~2.1.3",
|
||||
"mocha": "~1.10.0",
|
||||
"karma": "~0.8.5",
|
||||
"uglify-js": "~2.3.6",
|
||||
"jake": "~0.5.16"
|
||||
"jake": "~0.5.16",
|
||||
"magic-string": "^0.7.0",
|
||||
"leaflet": "~1.0.3"
|
||||
},
|
||||
"main": "dist/leaflet.markercluster.js",
|
||||
"scripts": {
|
||||
"test": "jake test",
|
||||
"prepublish": "jake"
|
||||
},
|
||||
"keywords": ["gis", "map"]
|
||||
"keywords": ["gis", "map"],
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<script type="text/javascript" src="../src/MarkerCluster.QuickHull.js"></script>
|
||||
<script type="text/javascript" src="../src/MarkerCluster.Spiderfier.js"></script>
|
||||
<script type="text/javascript" src="../src/MarkerOpacity.js"></script>
|
||||
<script type="text/javascript" src="../src/MarkerClusterGroup.Refresh.js"></script>
|
||||
|
||||
<script>
|
||||
mocha.setup('bdd');
|
||||
@@ -32,11 +33,17 @@
|
||||
|
||||
<script type="text/javascript" src="suites/LeafletSpec.js"></script>
|
||||
|
||||
<script type="text/javascript" src="suites/DistanceGridSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/QuickHullSpec.js"></script>
|
||||
|
||||
<script type="text/javascript" src="suites/AddLayer.MultipleSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/AddLayer.SingleSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/AddLayersSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/animateOptionSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/singleMarkerModeSpec.js"></script>
|
||||
|
||||
<script type="text/javascript" src="suites/ChildChangingIconSupportSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/markerMoveSupportSpec.js"></script>
|
||||
|
||||
<script type="text/javascript" src="suites/CircleMarkerSupportSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/CircleSupportSpec.js"></script>
|
||||
@@ -55,9 +62,15 @@
|
||||
<script type="text/javascript" src="suites/RemoveLayerSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/removeLayersSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/spiderfySpec.js"></script>
|
||||
<script type="text/javascript" src="suites/unspiderfySpec.js"></script>
|
||||
<script type="text/javascript" src="suites/zoomAnimationSpec.js"></script>
|
||||
|
||||
<script type="text/javascript" src="suites/RememberOpacity.js"></script>
|
||||
<script type="text/javascript" src="suites/supportNegativeZoomSpec.js"></script>
|
||||
|
||||
<script type="text/javascript" src="suites/RefreshSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/removeOutsideVisibleBoundsSpec.js"></script>
|
||||
<script type="text/javascript" src="suites/nonIntegerZoomSpec.js"></script>
|
||||
|
||||
<script>
|
||||
(window.mochaPhantomJS || window.mocha).run();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Karma configuration
|
||||
var libSources = require(__dirname+'/../build/build.js').getFiles();
|
||||
var leafletSources = require(__dirname+'/../node_modules/leaflet/build/build.js').getFiles();
|
||||
var leafletSources = require(__dirname+'/../node_modules/leaflet/build/build.js').getFiles(); // Caution Leaflet 1.0.0-beta.2 build needs magic-string
|
||||
|
||||
// base path, that will be used to resolve files and exclude
|
||||
basePath = '';
|
||||
|
||||
@@ -1,26 +1,70 @@
|
||||
describe('addLayer adding a single marker', function () {
|
||||
var map, div;
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
// Nothing for this test suite.
|
||||
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
document.body.removeChild(div);
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.clearLayers();
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// Throw away group as it can be assigned with different configurations between tests.
|
||||
group = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('appears when added to the group before the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
@@ -29,9 +73,11 @@
|
||||
expect(marker._icon).to.not.be(undefined);
|
||||
expect(marker._icon.parentNode).to.be(map._panes.markerPane);
|
||||
});
|
||||
|
||||
it('appears when added to the group after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
|
||||
map.addLayer(group);
|
||||
@@ -40,9 +86,11 @@
|
||||
expect(marker._icon).to.not.be(undefined);
|
||||
expect(marker._icon.parentNode).to.be(map._panes.markerPane);
|
||||
});
|
||||
|
||||
it('appears (using animations) when added after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup({ animateAddingMarkers: true });
|
||||
group = new L.MarkerClusterGroup({ animateAddingMarkers: true });
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
|
||||
map.addLayer(group);
|
||||
@@ -52,10 +100,10 @@
|
||||
expect(marker._icon.parentNode).to.be(map._panes.markerPane);
|
||||
});
|
||||
|
||||
|
||||
it('does not appear when too far away when added before the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([3.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
@@ -63,9 +111,11 @@
|
||||
|
||||
expect(marker._icon).to.be(undefined);
|
||||
});
|
||||
|
||||
it('does not appear when too far away when added after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([3.5, 1.5]);
|
||||
|
||||
map.addLayer(group);
|
||||
@@ -74,5 +124,31 @@
|
||||
expect(marker._icon).to.be(undefined);
|
||||
});
|
||||
|
||||
it('passes control to addLayers when marker is a Layer Group', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker1 = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
var layerGroup = new L.LayerGroup([marker1, marker2]);
|
||||
|
||||
map.addLayer(group);
|
||||
group.addLayer(layerGroup);
|
||||
|
||||
expect(group._topClusterLevel.getChildCount()).to.equal(2);
|
||||
|
||||
expect(marker1._icon).to.be(undefined);
|
||||
expect(marker2._icon).to.be(undefined);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(1);
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
|
||||
@@ -1,25 +1,70 @@
|
||||
describe('addLayers adding multiple markers', function () {
|
||||
var map, div;
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
// Nothing for this test suite.
|
||||
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
document.body.removeChild(div);
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.clearLayers();
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// Throw away group as it can be assigned with different configurations between tests.
|
||||
group = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('creates a cluster when 2 overlapping markers are added before the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
@@ -34,7 +79,8 @@
|
||||
|
||||
it('creates a cluster when 2 overlapping markers are added after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
@@ -47,11 +93,10 @@
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(1);
|
||||
});
|
||||
|
||||
|
||||
|
||||
it('creates a cluster and marker when 2 overlapping markers and one non-overlapping are added before the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
var marker3 = new L.Marker([3.0, 1.5]);
|
||||
@@ -65,9 +110,11 @@
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(2);
|
||||
});
|
||||
|
||||
it('creates a cluster and marker when 2 overlapping markers and one non-overlapping are added after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
var marker3 = new L.Marker([3.0, 1.5]);
|
||||
@@ -82,4 +129,31 @@
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(2);
|
||||
});
|
||||
|
||||
});
|
||||
it('handles nested Layer Groups', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker1 = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
var marker3 = new L.Marker([3.0, 1.5]);
|
||||
var layerGroup = new L.LayerGroup([marker1, new L.LayerGroup([marker2])]);
|
||||
|
||||
map.addLayer(group);
|
||||
group.addLayers([layerGroup, marker3]);
|
||||
|
||||
expect(marker1._icon).to.be(undefined);
|
||||
expect(marker2._icon).to.be(undefined);
|
||||
expect(marker3._icon.parentNode).to.be(map._panes.markerPane);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(2);
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
|
||||
@@ -1,54 +1,106 @@
|
||||
describe('support for CircleMarker elements', function () {
|
||||
var map, div, clock;
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.removeLayers(group.getLayers());
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// group must be thrown away since we are testing it with a potentially
|
||||
// different configuration at each test.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
document.body.removeChild(div);
|
||||
clock = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('appears when added to the group before the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.CircleMarker([1.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker._container).to.not.be(undefined);
|
||||
expect(marker._container.parentNode).to.be(map._pathRoot);
|
||||
// Leaflet 1.0.0 now uses an intermediate L.Renderer.
|
||||
// marker > _path > _rootGroup (g) > _container (svg) > pane (div)
|
||||
expect(marker._path.parentNode.parentNode).to.not.be(undefined);
|
||||
expect(marker._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
|
||||
clock.tick(1000);
|
||||
});
|
||||
|
||||
it('appears when added to the group after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.CircleMarker([1.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker._container).to.not.be(undefined);
|
||||
expect(marker._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker._path.parentNode.parentNode).to.not.be(undefined);
|
||||
expect(marker._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
|
||||
clock.tick(1000);
|
||||
});
|
||||
|
||||
it('appears animated when added to the group after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup({ animateAddingMarkers: true });
|
||||
group = new L.MarkerClusterGroup({ animateAddingMarkers: true });
|
||||
|
||||
var marker = new L.CircleMarker([1.5, 1.5]);
|
||||
var marker2 = new L.CircleMarker([1.5, 1.5]);
|
||||
|
||||
@@ -56,35 +108,37 @@
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
|
||||
expect(marker._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker2._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
expect(marker2._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
expect(marker._container.parentNode).to.be(null);
|
||||
expect(marker2._container.parentNode).to.be(null);
|
||||
expect(marker._path.parentNode).to.be(null);
|
||||
expect(marker2._path.parentNode).to.be(null);
|
||||
});
|
||||
|
||||
|
||||
it('creates a cluster when 2 overlapping markers are added before the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.CircleMarker([1.5, 1.5]);
|
||||
var marker2 = new L.CircleMarker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker._container).to.be(undefined);
|
||||
expect(marker2._container).to.be(undefined);
|
||||
expect(marker._path).to.be(undefined);
|
||||
expect(marker2._path).to.be(undefined);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(1);
|
||||
|
||||
clock.tick(1000);
|
||||
});
|
||||
|
||||
it('creates a cluster when 2 overlapping markers are added after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.CircleMarker([1.5, 1.5]);
|
||||
var marker2 = new L.CircleMarker([1.5, 1.5]);
|
||||
|
||||
@@ -92,8 +146,8 @@
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
|
||||
expect(marker._container.parentNode).to.be(null); //Removed then re-added, so null
|
||||
expect(marker2._container).to.be(undefined);
|
||||
expect(marker._path.parentNode).to.be(null); //Removed then re-added, so null
|
||||
expect(marker2._path).to.be(undefined);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(1);
|
||||
|
||||
@@ -102,20 +156,29 @@
|
||||
|
||||
it('disappears when removed from the group', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.CircleMarker([1.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker._container).to.not.be(undefined);
|
||||
expect(marker._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker._path.parentNode).to.not.be(undefined);
|
||||
expect(marker._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
|
||||
group.removeLayer(marker);
|
||||
|
||||
expect(marker._container.parentNode).to.be(null);
|
||||
expect(marker._path.parentNode).to.be(null);
|
||||
|
||||
clock.tick(1000);
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -1,54 +1,106 @@
|
||||
describe('support for Circle elements', function () {
|
||||
var map, div, clock;
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.removeLayers(group.getLayers());
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// group must be thrown away since we are testing it with a potentially
|
||||
// different configuration at each test.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
document.body.removeChild(div);
|
||||
clock = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('appears when added to the group before the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Circle([1.5, 1.5], 200);
|
||||
|
||||
group.addLayer(marker);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker._container).to.not.be(undefined);
|
||||
expect(marker._container.parentNode).to.be(map._pathRoot);
|
||||
// Leaflet 1.0.0 now uses an intermediate L.Renderer.
|
||||
// marker > _path > _rootGroup (g) > _container (svg) > pane (div)
|
||||
expect(marker._path.parentNode).to.not.be(undefined);
|
||||
expect(marker._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
|
||||
clock.tick(1000);
|
||||
});
|
||||
|
||||
it('appears when added to the group after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Circle([1.5, 1.5], 200);
|
||||
|
||||
group.addLayer(marker);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker._container).to.not.be(undefined);
|
||||
expect(marker._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker._path.parentNode).to.not.be(undefined);
|
||||
expect(marker._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
|
||||
clock.tick(1000);
|
||||
});
|
||||
|
||||
it('appears animated when added to the group after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup({ animateAddingMarkers: true });
|
||||
group = new L.MarkerClusterGroup({ animateAddingMarkers: true });
|
||||
|
||||
var marker = new L.Circle([1.5, 1.5], 200);
|
||||
var marker2 = new L.Circle([1.5, 1.5], 200);
|
||||
|
||||
@@ -56,32 +108,34 @@
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
|
||||
expect(marker._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker2._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
expect(marker2._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
|
||||
clock.tick(1000);
|
||||
});
|
||||
|
||||
|
||||
it('creates a cluster when 2 overlapping markers are added before the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Circle([1.5, 1.5], 200);
|
||||
var marker2 = new L.Circle([1.5, 1.5], 200);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker._container).to.be(undefined);
|
||||
expect(marker2._container).to.be(undefined);
|
||||
expect(marker._path).to.be(undefined);
|
||||
expect(marker2._path).to.be(undefined);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(1);
|
||||
|
||||
clock.tick(1000);
|
||||
});
|
||||
|
||||
it('creates a cluster when 2 overlapping markers are added after the group is added to the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Circle([1.5, 1.5], 200);
|
||||
var marker2 = new L.Circle([1.5, 1.5], 200);
|
||||
|
||||
@@ -89,8 +143,8 @@
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
|
||||
expect(marker._container.parentNode).to.be(null); //Removed then re-added, so null
|
||||
expect(marker2._container).to.be(undefined);
|
||||
expect(marker._path.parentNode).to.be(null); //Removed then re-added, so null
|
||||
expect(marker2._path).to.be(undefined);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(1);
|
||||
|
||||
@@ -99,20 +153,29 @@
|
||||
|
||||
it('disappears when removed from the group', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Circle([1.5, 1.5], 200);
|
||||
|
||||
group.addLayer(marker);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker._container).to.not.be(undefined);
|
||||
expect(marker._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker._path.parentNode).to.not.be(undefined);
|
||||
expect(marker._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
|
||||
group.removeLayer(marker);
|
||||
|
||||
expect(marker._container.parentNode).to.be(null);
|
||||
expect(marker._path.parentNode).to.be(null);
|
||||
|
||||
clock.tick(1000);
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -18,4 +18,24 @@
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('getNearObject', function () {
|
||||
var grid = new L.DistanceGrid(100),
|
||||
obj = {};
|
||||
|
||||
grid.addObject(obj, { x: 0, y: 0 });
|
||||
|
||||
expect(grid.getNearObject({ x: 50, y: 50 })).to.equal(obj);
|
||||
expect(grid.getNearObject({ x: 100, y: 0 })).to.equal(obj);
|
||||
});
|
||||
|
||||
it('getNearObject with cellSize 0', function () {
|
||||
var grid = new L.DistanceGrid(0),
|
||||
obj = {};
|
||||
|
||||
grid.addObject(obj, { x: 0, y: 0 });
|
||||
|
||||
expect(grid.getNearObject({ x: 50, y: 50 })).to.equal(null);
|
||||
expect(grid.getNearObject({ x: 0, y: 0 })).to.equal(obj);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,63 +1,115 @@
|
||||
describe('adding non point data works', function () {
|
||||
var map, div;
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
// Nothing for this test suite.
|
||||
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
document.body.removeChild(div);
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.removeLayers(group.getLayers());
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// group must be thrown away since we are testing it with a potentially
|
||||
// different configuration at each test.
|
||||
group = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('Allows adding a polygon before via addLayer', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0,2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayer(polygon);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(polygon._container).to.not.be(undefined);
|
||||
expect(polygon._container.parentNode).to.be(map._pathRoot);
|
||||
// Leaflet 1.0.0 now uses an intermediate L.Renderer.
|
||||
// polygon > _path > _rootGroup (g) > _container (svg) > pane (div)
|
||||
expect(polygon._path).to.not.be(undefined);
|
||||
expect(polygon._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
|
||||
expect(group.hasLayer(polygon));
|
||||
});
|
||||
|
||||
it('Allows adding a polygon before via addLayers([])', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayers([polygon]);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(polygon._container).to.not.be(undefined);
|
||||
expect(polygon._container.parentNode).to.be(map._pathRoot);
|
||||
expect(polygon._path).to.not.be(undefined);
|
||||
expect(polygon._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
});
|
||||
|
||||
it('Removes polygons from map when removed', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayer(polygon);
|
||||
map.addLayer(group);
|
||||
map.removeLayer(group);
|
||||
|
||||
expect(polygon._container.parentNode).to.be(null);
|
||||
expect(polygon._path.parentNode).to.be(null);
|
||||
});
|
||||
|
||||
describe('hasLayer', function () {
|
||||
|
||||
it('returns false when not added', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
expect(group.hasLayer(polygon)).to.be(false);
|
||||
@@ -72,7 +124,8 @@
|
||||
});
|
||||
|
||||
it('returns true before adding to map', function() {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayers([polygon]);
|
||||
@@ -81,7 +134,8 @@
|
||||
});
|
||||
|
||||
it('returns true after adding to map after adding polygon', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayer(polygon);
|
||||
@@ -91,7 +145,8 @@
|
||||
});
|
||||
|
||||
it('returns true after adding to map before adding polygon', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
map.addLayer(group);
|
||||
@@ -99,11 +154,14 @@
|
||||
|
||||
expect(group.hasLayer(polygon)).to.be(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('removeLayer', function() {
|
||||
|
||||
it('removes before adding to map', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayer(polygon);
|
||||
@@ -114,7 +172,8 @@
|
||||
});
|
||||
|
||||
it('removes before adding to map', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayers([polygon]);
|
||||
@@ -125,7 +184,8 @@
|
||||
});
|
||||
|
||||
it('removes after adding to map after adding polygon', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayer(polygon);
|
||||
@@ -137,7 +197,8 @@
|
||||
});
|
||||
|
||||
it('removes after adding to map before adding polygon', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
map.addLayer(group);
|
||||
@@ -147,11 +208,14 @@
|
||||
group.removeLayer(polygon);
|
||||
expect(group.hasLayer(polygon)).to.be(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('removeLayers', function () {
|
||||
|
||||
it('removes before adding to map', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayer(polygon);
|
||||
@@ -162,7 +226,8 @@
|
||||
});
|
||||
|
||||
it('removes before adding to map', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayers([polygon]);
|
||||
@@ -173,7 +238,8 @@
|
||||
});
|
||||
|
||||
it('removes after adding to map after adding polygon', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
group.addLayer(polygon);
|
||||
@@ -185,7 +251,8 @@
|
||||
});
|
||||
|
||||
it('removes after adding to map before adding polygon', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
map.addLayer(group);
|
||||
@@ -195,5 +262,15 @@
|
||||
group.removeLayers([polygon]);
|
||||
expect(group.hasLayer(polygon)).to.be(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
describe('Map pane selection', function() {
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
// Nothing for this test suite.
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.clearLayers();
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// Throw away group as it can be assigned with different configurations between tests.
|
||||
group = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Create map pane
|
||||
map.createPane('testPane');
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('recognizes and applies option', function() {
|
||||
group = new L.MarkerClusterGroup({clusterPane: 'testPane'});
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(map._panes.testPane.childNodes.length).to.be(1);
|
||||
});
|
||||
|
||||
it('defaults to default marker pane', function() {
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(map._panes[L.Marker.prototype.options.pane].childNodes.length).to.be(1);
|
||||
});
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -17,19 +17,36 @@ describe('quickhull', function () {
|
||||
});
|
||||
|
||||
describe('getConvexHull', function () {
|
||||
it('creates a hull', function () {
|
||||
expect(L.QuickHull.getConvexHull([
|
||||
{ lat: 0, lng: 0 },
|
||||
{ lat: 10, lng: 0 },
|
||||
{ lat: 10, lng: 10 },
|
||||
{ lat: 0, lng: 10 },
|
||||
{ lat: 5, lng: 5 },
|
||||
])).to.eql([
|
||||
{ lat: 0, lng: 10 },
|
||||
{ lat: 10, lng: 10 },
|
||||
{ lat: 10, lng: 0 },
|
||||
{ lat: 0, lng: 0 },
|
||||
]);
|
||||
});
|
||||
});
|
||||
it('creates a hull', function () {
|
||||
expect(L.QuickHull.getConvexHull([ { lat: 0, lng: 0 },
|
||||
{ lat: 10, lng: 0 },
|
||||
{ lat: 10, lng: 10 },
|
||||
{ lat: 0, lng: 10 },
|
||||
{ lat: 5, lng: 5 }
|
||||
])).to.eql([
|
||||
{ lat: 0, lng: 10 },
|
||||
{ lat: 10, lng: 10 },
|
||||
{ lat: 10, lng: 0 },
|
||||
{ lat: 0, lng: 0 }
|
||||
]);
|
||||
});
|
||||
it('creates a hull for vertically-aligned objects', function () {
|
||||
expect(L.QuickHull.getConvexHull([ { lat: 0, lng: 0 },
|
||||
{ lat: 5, lng: 0 },
|
||||
{ lat: 10, lng: 0 }
|
||||
])).to.eql([
|
||||
{ lat: 0, lng: 0 },
|
||||
{ lat: 10, lng: 0 }
|
||||
]);
|
||||
});
|
||||
it('creates a hull for horizontally-aligned objects', function () {
|
||||
expect(L.QuickHull.getConvexHull([ { lat: 0, lng: 0 },
|
||||
{ lat: 0, lng: 5 },
|
||||
{ lat: 0, lng: 10 }
|
||||
])).to.eql([
|
||||
{ lat: 0, lng: 0 },
|
||||
{ lat: 0, lng: 10 }
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
describe('refreshClusters', function () {
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
|
||||
// Look away to avoid refreshing the display while adding markers.
|
||||
// By adding markers one by one (instead of using addLayers) we make
|
||||
// sure we never start an async process.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[-11, -11],
|
||||
[-10, -10]
|
||||
]))
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.removeLayers(group.getLayers());
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// group must be thrown away since we are testing it with a potentially
|
||||
// different configuration at each test.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
clock = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
|
||||
var div, map, group, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
function getClusterAtZoom(marker, zoom) {
|
||||
var parent = marker.__parent;
|
||||
|
||||
while (parent && parent._zoom !== zoom) {
|
||||
parent = parent.__parent;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
function setMapView() {
|
||||
// Now look at the markers to force cluster icons drawing.
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('flags all non-visible parent clusters of a given marker', function () {
|
||||
|
||||
group = L.markerClusterGroup().addTo(map);
|
||||
|
||||
var marker1 = L.marker([1.5, 1.5]).addTo(group),
|
||||
marker2 = L.marker([1.5, 1.5]).addTo(group); // Needed to force a cluster.
|
||||
|
||||
setMapView();
|
||||
|
||||
var marker1cluster10 = getClusterAtZoom(marker1, 10),
|
||||
marker1cluster2 = getClusterAtZoom(marker1, 2),
|
||||
marker1cluster5 = getClusterAtZoom(marker1, 5);
|
||||
|
||||
// First go to some zoom levels so that Leaflet initializes clusters icons.
|
||||
expect(marker1cluster10._iconNeedsUpdate).to.be.ok();
|
||||
map.setZoom(10, {animate: false});
|
||||
expect(marker1cluster10._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
expect(marker1cluster2._iconNeedsUpdate).to.be.ok();
|
||||
map.setZoom(2, {animate: false});
|
||||
expect(marker1cluster2._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
// Finish on an intermediate zoom level.
|
||||
expect(marker1cluster5._iconNeedsUpdate).to.be.ok();
|
||||
map.setZoom(5, {animate: false});
|
||||
expect(marker1cluster5._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
// Run any animation.
|
||||
clock.tick(1000);
|
||||
|
||||
// Then request clusters refresh.
|
||||
// No need to actually modify the marker.
|
||||
group.refreshClusters(marker1);
|
||||
|
||||
// Now check that non-visible clusters are flagged as "dirty".
|
||||
expect(marker1cluster10._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker1cluster2._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
// Also check that visible clusters are "un-flagged" since they should be re-drawn.
|
||||
expect(marker1cluster5._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
});
|
||||
|
||||
it('re-draws visible clusters', function () {
|
||||
|
||||
group = L.markerClusterGroup({
|
||||
iconCreateFunction: function (cluster) {
|
||||
var markers = cluster.getAllChildMarkers();
|
||||
|
||||
for(var i in markers) {
|
||||
if (markers[i].changed) {
|
||||
return new L.DivIcon({
|
||||
className: "changed"
|
||||
});
|
||||
}
|
||||
}
|
||||
return new L.DivIcon({
|
||||
className: "original"
|
||||
});
|
||||
}
|
||||
}).addTo(map);
|
||||
|
||||
var marker1 = L.marker([1.5, 1.5]).addTo(group),
|
||||
marker2 = L.marker([1.5, 1.5]).addTo(group); // Needed to force a cluster.
|
||||
|
||||
setMapView();
|
||||
|
||||
var marker1cluster9 = getClusterAtZoom(marker1, 9);
|
||||
|
||||
// First go to some zoom levels so that Leaflet initializes clusters icons.
|
||||
expect(marker1cluster9._iconNeedsUpdate).to.be.ok();
|
||||
map.setZoom(9, {animate: false});
|
||||
expect(marker1cluster9._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
expect(marker1cluster9._icon.className).to.contain("original");
|
||||
expect(marker1cluster9._icon.className).to.not.contain("changed");
|
||||
|
||||
// Run any animation.
|
||||
clock.tick(1000);
|
||||
|
||||
// Alter the marker.
|
||||
marker1.changed = true;
|
||||
|
||||
// Then request clusters refresh.
|
||||
group.refreshClusters(marker1);
|
||||
|
||||
// Now check that visible clusters icon is re-drawn.
|
||||
expect(marker1cluster9._icon.className).to.contain("changed");
|
||||
expect(marker1cluster9._icon.className).to.not.contain("original");
|
||||
|
||||
});
|
||||
|
||||
// Shared code for the 2 below tests
|
||||
function iconCreateFunction(cluster) {
|
||||
var markers = cluster.getAllChildMarkers();
|
||||
|
||||
for(var i in markers) {
|
||||
if (markers[i].changed) {
|
||||
return new L.DivIcon({
|
||||
className: "changed"
|
||||
});
|
||||
}
|
||||
}
|
||||
return new L.DivIcon({
|
||||
className: "original"
|
||||
});
|
||||
}
|
||||
|
||||
it('re-draws markers in singleMarkerMode', function () {
|
||||
|
||||
group = L.markerClusterGroup({
|
||||
singleMarkerMode: true,
|
||||
iconCreateFunction: iconCreateFunction
|
||||
}).addTo(map);
|
||||
|
||||
var marker1 = L.marker([1.5, 1.5]).addTo(group);
|
||||
|
||||
setMapView();
|
||||
|
||||
expect(marker1._icon.className).to.contain("original");
|
||||
|
||||
// Alter the marker.
|
||||
marker1.changed = true;
|
||||
|
||||
// Then request clusters refresh.
|
||||
group.refreshClusters(marker1);
|
||||
|
||||
expect(marker1._icon.className).to.contain("changed");
|
||||
expect(marker1._icon.className).to.not.contain("original");
|
||||
|
||||
});
|
||||
|
||||
it('does not modify markers that do not belong to the current group (in singleMarkerMode)', function () {
|
||||
|
||||
group = L.markerClusterGroup({
|
||||
singleMarkerMode: true,
|
||||
iconCreateFunction: iconCreateFunction
|
||||
}).addTo(map);
|
||||
|
||||
var marker1 = L.marker([1.5, 1.5]).addTo(group),
|
||||
marker2 = L.marker([1.5, 1.5], {
|
||||
icon: iconCreateFunction({
|
||||
getAllChildMarkers: function () {
|
||||
return marker2;
|
||||
}
|
||||
})
|
||||
}).addTo(map);
|
||||
|
||||
setMapView();
|
||||
|
||||
expect(marker1._icon.className).to.contain("original");
|
||||
expect(marker2._icon.className).to.contain("original");
|
||||
|
||||
// Alter the markers.
|
||||
marker1.changed = true;
|
||||
marker2.changed = true;
|
||||
|
||||
// Then request clusters refresh.
|
||||
group.refreshClusters([marker1, marker2]);
|
||||
|
||||
expect(marker1._icon.className).to.contain("changed");
|
||||
expect(marker1._icon.className).to.not.contain("original");
|
||||
|
||||
expect(marker2._icon.className).to.contain("original");
|
||||
expect(marker2._icon.className).to.not.contain("changed");
|
||||
|
||||
});
|
||||
|
||||
|
||||
// Shared code for below tests.
|
||||
var marker1 = L.marker([1.5, 1.5]),
|
||||
marker2 = L.marker([1.5, 1.5]), // Needed to force a cluster.
|
||||
marker3 = L.marker([1.1, 1.1]),
|
||||
marker4 = L.marker([1.1, 1.1]), // Needed to force a cluster.
|
||||
marker5 = L.marker([1.9, 1.9]),
|
||||
marker6 = L.marker([1.9, 1.9]), // Needed to force a cluster.
|
||||
marker1cluster8,
|
||||
marker1cluster3,
|
||||
marker1cluster5,
|
||||
marker3cluster8,
|
||||
marker3cluster3,
|
||||
marker3cluster5,
|
||||
marker5cluster8,
|
||||
marker5cluster3,
|
||||
marker5cluster5;
|
||||
|
||||
function init3clusterBranches() {
|
||||
|
||||
group = L.markerClusterGroup({
|
||||
maxClusterRadius: 2 // Make sure we keep distinct clusters.
|
||||
}).addTo(map);
|
||||
|
||||
// Populate Marker Cluster Group.
|
||||
marker1.addTo(group);
|
||||
marker2.addTo(group);
|
||||
marker3.addTo(group);
|
||||
marker4.addTo(group);
|
||||
marker5.addTo(group);
|
||||
marker6.addTo(group);
|
||||
|
||||
setMapView();
|
||||
|
||||
marker1cluster8 = getClusterAtZoom(marker1, 8);
|
||||
marker1cluster3 = getClusterAtZoom(marker1, 3);
|
||||
marker1cluster5 = getClusterAtZoom(marker1, 5);
|
||||
marker3cluster8 = getClusterAtZoom(marker3, 8);
|
||||
marker3cluster3 = getClusterAtZoom(marker3, 3);
|
||||
marker3cluster5 = getClusterAtZoom(marker3, 5);
|
||||
marker5cluster8 = getClusterAtZoom(marker5, 8);
|
||||
marker5cluster3 = getClusterAtZoom(marker5, 3);
|
||||
marker5cluster5 = getClusterAtZoom(marker5, 5);
|
||||
|
||||
// Make sure we have 3 distinct clusters up to zoom level Z (let's choose Z = 3)
|
||||
expect(marker1cluster3._childCount).to.equal(2);
|
||||
expect(marker3cluster3._childCount).to.equal(2);
|
||||
expect(marker5cluster3._childCount).to.equal(2);
|
||||
|
||||
// First go to some zoom levels so that Leaflet initializes clusters icons.
|
||||
expect(marker1cluster8._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker5cluster8._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
expect(marker1cluster3._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker3cluster3._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker5cluster3._iconNeedsUpdate).to.be.ok();
|
||||
map.setZoom(3, {animate: false});
|
||||
expect(marker1cluster3._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker5cluster3._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
// Finish on an intermediate zoom level.
|
||||
expect(marker1cluster5._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker3cluster5._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker5cluster5._iconNeedsUpdate).to.be.ok();
|
||||
map.setZoom(5, {animate: false});
|
||||
expect(marker1cluster5._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker3cluster5._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker5cluster5._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
// Run any animation.
|
||||
clock.tick(1000);
|
||||
|
||||
// Ready to refresh clusters with method of choice and assess result.
|
||||
}
|
||||
|
||||
it('does not flag clusters of other markers', function () {
|
||||
|
||||
init3clusterBranches();
|
||||
|
||||
// Then request clusters refresh.
|
||||
// No need to actually modify the marker.
|
||||
group.refreshClusters(marker1);
|
||||
|
||||
// Now check that non-visible clusters are flagged as "dirty".
|
||||
expect(marker1cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker1cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
// Finally check that non-involved clusters are not "dirty".
|
||||
expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
expect(marker5cluster8._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker5cluster3._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
});
|
||||
|
||||
it('processes itself when no argument is passed', function () {
|
||||
|
||||
init3clusterBranches();
|
||||
|
||||
// Then request clusters refresh.
|
||||
// No need to actually modify the marker.
|
||||
group.refreshClusters();
|
||||
|
||||
// Now check that non-visible clusters are flagged as "dirty".
|
||||
expect(marker1cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker1cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
expect(marker3cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker3cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
expect(marker5cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker5cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
});
|
||||
|
||||
it('accepts an array of markers', function () {
|
||||
|
||||
init3clusterBranches();
|
||||
|
||||
// Then request clusters refresh.
|
||||
// No need to actually modify the markers.
|
||||
group.refreshClusters([marker1, marker5]);
|
||||
// Clusters of marker3 and 4 shall not be flagged.
|
||||
|
||||
// Now check that non-visible clusters are flagged as "dirty".
|
||||
expect(marker1cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker1cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
expect(marker5cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker5cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
// Clusters of marker3 and 4 shall not be flagged.
|
||||
expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
});
|
||||
|
||||
it('accepts a mapping of markers', function () {
|
||||
|
||||
init3clusterBranches();
|
||||
|
||||
// Then request clusters refresh.
|
||||
// No need to actually modify the markers.
|
||||
group.refreshClusters({
|
||||
id1: marker1,
|
||||
id2: marker5
|
||||
}); // Clusters of marker3 and 4 shall not be flagged.
|
||||
|
||||
// Now check that non-visible clusters are flagged as "dirty".
|
||||
expect(marker1cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker1cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
expect(marker5cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker5cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
// Clusters of marker3 and 4 shall not be flagged.
|
||||
expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
});
|
||||
|
||||
it('accepts an L.LayerGroup', function () {
|
||||
|
||||
init3clusterBranches();
|
||||
|
||||
// Then request clusters refresh.
|
||||
// No need to actually modify the markers.
|
||||
var layerGroup = new L.LayerGroup([marker1, marker5]);
|
||||
group.refreshClusters(layerGroup);
|
||||
// Clusters of marker3 and 4 shall not be flagged.
|
||||
|
||||
// Now check that non-visible clusters are flagged as "dirty".
|
||||
expect(marker1cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker1cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
expect(marker5cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker5cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
// Clusters of marker3 and 4 shall not be flagged.
|
||||
expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
});
|
||||
|
||||
it('accepts an L.MarkerCluster', function () {
|
||||
|
||||
init3clusterBranches();
|
||||
|
||||
// Then request clusters refresh.
|
||||
// No need to actually modify the markers.
|
||||
group.refreshClusters(marker1cluster8);
|
||||
// Clusters of marker3, 4, 5 and 6 shall not be flagged.
|
||||
|
||||
// Now check that non-visible clusters are flagged as "dirty".
|
||||
expect(marker1cluster8._iconNeedsUpdate).to.be.ok();
|
||||
expect(marker1cluster3._iconNeedsUpdate).to.be.ok();
|
||||
|
||||
// Clusters of marker3 and 4 shall not be flagged.
|
||||
expect(marker3cluster8._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker3cluster3._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
expect(marker5cluster8._iconNeedsUpdate).to.not.be.ok();
|
||||
expect(marker5cluster3._iconNeedsUpdate).to.not.be.ok();
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -27,7 +27,7 @@ describe('Remember opacity', function () {
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
markers = [];
|
||||
for (var i=0; i<markerDefs.length; i++) {
|
||||
for (var i = 0; i < markerDefs.length; i++) {
|
||||
markers.push( L.marker(markerDefs[i].latLng, markerDefs[i].opts ) );
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,27 +1,72 @@
|
||||
describe('removeLayer', function () {
|
||||
var map, div, clock;
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.clearLayers();
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// Throw away group as it can be assigned with different configurations between tests.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('removes a layer that was added to it', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
|
||||
map.addLayer(group);
|
||||
@@ -37,7 +82,8 @@
|
||||
|
||||
it('doesnt remove a layer not added to it', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
|
||||
map.addLayer(group);
|
||||
@@ -53,7 +99,8 @@
|
||||
|
||||
it('removes a layer that was added to it (before being on the map) that is shown in a cluster', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
@@ -68,7 +115,8 @@
|
||||
|
||||
it('removes a layer that was added to it (after being on the map) that is shown in a cluster', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
@@ -84,7 +132,8 @@
|
||||
|
||||
it('removes a layer that was added to it (before being on the map) that is individually', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1, 1.5]);
|
||||
var marker2 = new L.Marker([3, 1.5]);
|
||||
|
||||
@@ -103,7 +152,8 @@
|
||||
|
||||
it('removes a layer (with animation) that was added to it (after being on the map) that is shown in a cluster', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup({ animateAddingMarkers: true });
|
||||
group = new L.MarkerClusterGroup({ animateAddingMarkers: true });
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
@@ -128,7 +178,8 @@
|
||||
|
||||
it('removes the layers that are in the given LayerGroup', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
@@ -145,7 +196,8 @@
|
||||
|
||||
it('removes the layers that are in the given LayerGroup when not on the map', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
@@ -158,4 +210,30 @@
|
||||
expect(group.hasLayer(marker)).to.be(true);
|
||||
expect(group.hasLayer(marker2)).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('passes control to removeLayers when marker is a Layer Group', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker1 = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker1, marker2]);
|
||||
|
||||
var layer = L.layerGroup();
|
||||
layer.addLayer(marker2);
|
||||
group.removeLayer(new L.LayerGroup([layer]));
|
||||
|
||||
expect(group.hasLayer(marker1)).to.be(true);
|
||||
expect(group.hasLayer(marker2)).to.be(false);
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
describe('animate option', function () {
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
previousTransitionSetting = L.DomUtil.TRANSITION;
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
// Restore previous setting so that next tests are unaffected.
|
||||
L.DomUtil.TRANSITION = previousTransitionSetting;
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.removeLayers(group.getLayers());
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// Throw away group as it can be assigned with different configurations between tests.
|
||||
group = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group, previousTransitionSetting;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('hooks animated methods version by default', function () {
|
||||
|
||||
// Need to add to map so that we have the top cluster level created.
|
||||
group = L.markerClusterGroup().addTo(map);
|
||||
|
||||
var withAnimation = L.MarkerClusterGroup.prototype._withAnimation;
|
||||
|
||||
// MCG animated methods.
|
||||
expect(group._animationStart).to.be(withAnimation._animationStart);
|
||||
expect(group._animationZoomIn).to.be(withAnimation._animationZoomIn);
|
||||
expect(group._animationZoomOut).to.be(withAnimation._animationZoomOut);
|
||||
expect(group._animationAddLayer).to.be(withAnimation._animationAddLayer);
|
||||
|
||||
// MarkerCluster spiderfy animated methods
|
||||
var cluster = group._topClusterLevel;
|
||||
|
||||
withAnimation = L.MarkerCluster.prototype;
|
||||
|
||||
expect(cluster._animationSpiderfy).to.be(withAnimation._animationSpiderfy);
|
||||
expect(cluster._animationUnspiderfy).to.be(withAnimation._animationUnspiderfy);
|
||||
|
||||
});
|
||||
|
||||
it('hooks non-animated methods version when set to false', function () {
|
||||
|
||||
// Need to add to map so that we have the top cluster level created.
|
||||
group = L.markerClusterGroup({animate: false}).addTo(map);
|
||||
|
||||
var noAnimation = L.MarkerClusterGroup.prototype._noAnimation;
|
||||
|
||||
// MCG non-animated methods.
|
||||
expect(group._animationStart).to.be(noAnimation._animationStart);
|
||||
expect(group._animationZoomIn).to.be(noAnimation._animationZoomIn);
|
||||
expect(group._animationZoomOut).to.be(noAnimation._animationZoomOut);
|
||||
expect(group._animationAddLayer).to.be(noAnimation._animationAddLayer);
|
||||
|
||||
// MarkerCluster spiderfy non-animated methods
|
||||
var cluster = group._topClusterLevel;
|
||||
|
||||
noAnimation = L.MarkerClusterNonAnimated.prototype;
|
||||
|
||||
expect(cluster._animationSpiderfy).to.be(noAnimation._animationSpiderfy);
|
||||
expect(cluster._animationUnspiderfy).to.be(noAnimation._animationUnspiderfy);
|
||||
|
||||
});
|
||||
|
||||
it('always hooks non-animated methods version when L.DomUtil.TRANSITION is false', function () {
|
||||
|
||||
// Fool Leaflet, make it think the browser does not support transitions.
|
||||
L.DomUtil.TRANSITION = false;
|
||||
|
||||
// Need to add to map so that we have the top cluster level created.
|
||||
group = L.markerClusterGroup({animate: true}).addTo(map);
|
||||
|
||||
var noAnimation = L.MarkerClusterGroup.prototype._noAnimation;
|
||||
|
||||
// MCG non-animated methods.
|
||||
expect(group._animationStart).to.be(noAnimation._animationStart);
|
||||
expect(group._animationZoomIn).to.be(noAnimation._animationZoomIn);
|
||||
expect(group._animationZoomOut).to.be(noAnimation._animationZoomOut);
|
||||
expect(group._animationAddLayer).to.be(noAnimation._animationAddLayer);
|
||||
|
||||
// MarkerCluster spiderfy non-animated methods
|
||||
var cluster = group._topClusterLevel;
|
||||
|
||||
noAnimation = L.MarkerClusterNonAnimated.prototype;
|
||||
|
||||
expect(cluster._animationSpiderfy).to.be(noAnimation._animationSpiderfy);
|
||||
expect(cluster._animationUnspiderfy).to.be(noAnimation._animationUnspiderfy);
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
describe('disableClusteringAtZoom option', function () {
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.clearLayers();
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// group must be thrown away since we are testing it with a potentially
|
||||
// different configuration at each test.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
clock = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('unclusters at zoom level equal or higher', function () {
|
||||
|
||||
var maxZoom = 15;
|
||||
|
||||
group = new L.MarkerClusterGroup({
|
||||
disableClusteringAtZoom: maxZoom
|
||||
});
|
||||
|
||||
group.addLayers([
|
||||
new L.Marker([1.5, 1.5]),
|
||||
new L.Marker([1.5, 1.5])
|
||||
]);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(group._maxZoom).to.equal(maxZoom - 1);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.equal(1); // 1 cluster.
|
||||
|
||||
map.setZoom(14);
|
||||
clock.tick(1000);
|
||||
expect(map._panes.markerPane.childNodes.length).to.equal(1); // 1 cluster.
|
||||
|
||||
map.setZoom(15);
|
||||
clock.tick(1000);
|
||||
expect(map._panes.markerPane.childNodes.length).to.equal(2); // 2 markers.
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -1,25 +1,71 @@
|
||||
describe('events', function() {
|
||||
var map, div;
|
||||
beforeEach(function() {
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
//
|
||||
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
});
|
||||
afterEach(function() {
|
||||
document.body.removeChild(div);
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.removeLayers(group.getLayers());
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// group must be thrown away since we are testing it with a potentially
|
||||
// different configuration at each test.
|
||||
group = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('is fired for a single child marker', function () {
|
||||
var callback = sinon.spy();
|
||||
var group = new L.MarkerClusterGroup();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
|
||||
@@ -27,14 +73,16 @@
|
||||
group.addLayer(marker);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.fire('click');
|
||||
// In Leaflet 1.0.0, event propagation must be explicitly set by 3rd argument.
|
||||
marker.fire('click', null, true);
|
||||
|
||||
expect(callback.called).to.be(true);
|
||||
});
|
||||
|
||||
it('is fired for a child polygon', function () {
|
||||
var callback = sinon.spy();
|
||||
var group = new L.MarkerClusterGroup();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
@@ -42,14 +90,15 @@
|
||||
group.addLayer(polygon);
|
||||
map.addLayer(group);
|
||||
|
||||
polygon.fire('click');
|
||||
polygon.fire('click', null, true);
|
||||
|
||||
expect(callback.called).to.be(true);
|
||||
});
|
||||
|
||||
it('is fired for a cluster click', function () {
|
||||
var callback = sinon.spy();
|
||||
var group = new L.MarkerClusterGroup();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
@@ -61,15 +110,17 @@
|
||||
var cluster = group.getVisibleParent(marker);
|
||||
expect(cluster instanceof L.MarkerCluster).to.be(true);
|
||||
|
||||
cluster.fire('click');
|
||||
cluster.fire('click', null, true);
|
||||
|
||||
expect(callback.called).to.be(true);
|
||||
});
|
||||
|
||||
describe('after being added, removed, re-added from the map', function() {
|
||||
|
||||
it('still fires events for nonpoint data', function() {
|
||||
var callback = sinon.spy();
|
||||
var group = new L.MarkerClusterGroup();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
|
||||
@@ -79,14 +130,15 @@
|
||||
map.removeLayer(group);
|
||||
map.addLayer(group);
|
||||
|
||||
polygon.fire('click');
|
||||
polygon.fire('click', null, true);
|
||||
|
||||
expect(callback.called).to.be(true);
|
||||
});
|
||||
|
||||
it('still fires events for point data', function() {
|
||||
var callback = sinon.spy();
|
||||
var group = new L.MarkerClusterGroup();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
|
||||
@@ -96,14 +148,15 @@
|
||||
map.removeLayer(group);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.fire('click');
|
||||
marker.fire('click', null, true);
|
||||
|
||||
expect(callback.called).to.be(true);
|
||||
});
|
||||
|
||||
it('still fires cluster events', function() {
|
||||
var callback = sinon.spy();
|
||||
var group = new L.MarkerClusterGroup();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
@@ -118,14 +171,15 @@
|
||||
var cluster = group.getVisibleParent(marker);
|
||||
expect(cluster instanceof L.MarkerCluster).to.be(true);
|
||||
|
||||
cluster.fire('click');
|
||||
cluster.fire('click', null, true);
|
||||
|
||||
expect(callback.called).to.be(true);
|
||||
});
|
||||
|
||||
it('doesnt break map events', function () {
|
||||
it('does not break map events', function () {
|
||||
var callback = sinon.spy();
|
||||
var group = new L.MarkerClusterGroup();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
map.on('zoomend', callback);
|
||||
map.addLayer(group);
|
||||
@@ -137,12 +191,200 @@
|
||||
|
||||
expect(callback.called).to.be(true);
|
||||
});
|
||||
|
||||
//layeradd
|
||||
it('fires layeradd when markers are added while not on the map', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
group.on('layeradd', callback);
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
group.addLayer(marker);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layeradd when vectors are added while not on the map', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
group.on('layeradd', callback);
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
group.addLayer(polygon);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layeradd when markers are added while on the map', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
group.on('layeradd', callback);
|
||||
map.addLayer(group);
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
group.addLayer(marker);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layeradd when vectors are added while on the map', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
group.on('layeradd', callback);
|
||||
map.addLayer(group);
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
group.addLayer(polygon);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layeradd when markers are added using addLayers while on the map with chunked loading', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup({ chunkedLoading: true });
|
||||
group.on('layeradd', callback);
|
||||
map.addLayer(group);
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
group.addLayers([marker]);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layeradd when vectors are added using addLayers while on the map with chunked loading', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup({ chunkedLoading: true });
|
||||
group.on('layeradd', callback);
|
||||
map.addLayer(group);
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
group.addLayers([polygon]);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
//layerremove
|
||||
it('fires layerremove when a marker is removed while not on the map', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
group.on('layerremove', callback);
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
group.addLayer(marker);
|
||||
group.removeLayer(marker);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layerremove when a vector is removed while not on the map', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
group.on('layerremove', callback);
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
group.addLayer(polygon);
|
||||
group.removeLayer(polygon);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layerremove when a marker is removed while on the map', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
group.on('layerremove', callback);
|
||||
map.addLayer(group);
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
group.addLayer(marker);
|
||||
group.removeLayer(marker);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layerremove when a vector is removed while on the map', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
group.on('layerremove', callback);
|
||||
map.addLayer(group);
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
group.addLayer(polygon);
|
||||
group.removeLayer(polygon);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layerremove when a marker is removed using removeLayers while on the map with chunked loading', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup({ chunkedLoading: true });
|
||||
group.on('layerremove', callback);
|
||||
map.addLayer(group);
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
group.addLayers([marker]);
|
||||
group.removeLayers([marker]);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layerremove when a vector is removed using removeLayers while on the map with chunked loading', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup({ chunkedLoading: true });
|
||||
group.on('layerremove', callback);
|
||||
map.addLayer(group);
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
group.addLayers([polygon]);
|
||||
group.removeLayers([polygon]);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layerremove when a marker is removed using removeLayers while not on the map with chunked loading', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup({ chunkedLoading: true });
|
||||
group.on('layerremove', callback);
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
group.addLayers([marker]);
|
||||
group.removeLayers([marker]);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('fires layerremove when a vector is removed using removeLayers while not on the map with chunked loading', function() {
|
||||
var callback = sinon.spy();
|
||||
|
||||
group = new L.MarkerClusterGroup({ chunkedLoading: true });
|
||||
group.on('layerremove', callback);
|
||||
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
group.addLayers([polygon]);
|
||||
group.removeLayers([polygon]);
|
||||
|
||||
expect(callback.callCount).to.be(1);
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
//No normal events can be fired by a clustered marker, so probably don't need this.
|
||||
it('is fired for a clustered child marker', function() {
|
||||
var callback = sinon.spy();
|
||||
var group = new L.MarkerClusterGroup();
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
@@ -156,4 +398,12 @@
|
||||
expect(callback.called).to.be(true);
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
});
|
||||
@@ -45,4 +45,21 @@
|
||||
expect(layers).to.contain(marker);
|
||||
expect(layers).to.contain(polygon);
|
||||
});
|
||||
|
||||
it('skips markers and polygons removed while not on the map', function () {
|
||||
var group = new L.MarkerClusterGroup();
|
||||
var polygon = new L.Polygon([[1.5, 1.5], [2.0, 1.5], [2.0, 2.0], [1.5, 2.0]]);
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([polygon, marker]);
|
||||
|
||||
map.addLayer(group);
|
||||
map.removeLayer(group);
|
||||
|
||||
group.removeLayers([polygon, marker]);
|
||||
|
||||
var layers = group.getLayers();
|
||||
|
||||
expect(layers.length).to.be(0);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,111 @@
|
||||
describe('moving markers', function () {
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.clearLayers();
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// Throw away group as it can be assigned with different configurations between tests.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('moves a marker that was moved while off the map', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([10, 10]);
|
||||
map.addLayer(group);
|
||||
group.addLayer(marker);
|
||||
|
||||
map.removeLayer(group);
|
||||
marker.setLatLng([1.5, 1.5]);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(group.getLayers().length).to.be(1);
|
||||
});
|
||||
|
||||
it('moves multiple markers that were moved while off the map', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
map.addLayer(group);
|
||||
|
||||
var markers = [];
|
||||
for (var i = 0; i < 10; i++) {
|
||||
var marker = new L.Marker([10, 10]);
|
||||
group.addLayer(marker);
|
||||
markers.push(marker);
|
||||
}
|
||||
|
||||
map.removeLayer(group);
|
||||
for (var i = 0; i < 10; i++) {
|
||||
var marker = markers[i];
|
||||
marker.setLatLng([1.5, 1.5]);
|
||||
}
|
||||
map.addLayer(group);
|
||||
|
||||
expect(group.getLayers().length).to.be(10);
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
describe('non-integer min/max zoom', function () {
|
||||
var map, div, clock;
|
||||
beforeEach(function () {
|
||||
clock = sinon.useFakeTimers();
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { minZoom: 0.5, maxZoom: 18.5 });
|
||||
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
});
|
||||
afterEach(function () {
|
||||
clock.restore();
|
||||
document.body.removeChild(div);
|
||||
});
|
||||
|
||||
it('dont break adding and removing markers', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
var marker3 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
map.addLayer(group);
|
||||
|
||||
group.addLayer(marker3);
|
||||
|
||||
expect(marker._icon).to.be(undefined);
|
||||
expect(marker2._icon).to.be(undefined);
|
||||
expect(marker3._icon).to.be(undefined);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(1);
|
||||
|
||||
group.removeLayer(marker2);
|
||||
});
|
||||
});
|
||||
@@ -1,27 +1,72 @@
|
||||
describe('removeLayers', function () {
|
||||
var map, div, clock;
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.clearLayers();
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// Throw away group as it can be assigned with different configurations between tests.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('removes all the layer given to it', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var markers = [
|
||||
new L.Marker([1.5, 1.5]),
|
||||
new L.Marker([1.5, 1.5]),
|
||||
@@ -41,10 +86,58 @@
|
||||
expect(group.getLayers().length).to.be(0);
|
||||
});
|
||||
|
||||
it('removes all the layer given to it even though they move', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var markers = [
|
||||
new L.Marker([10, 10]),
|
||||
new L.Marker([20, 20]),
|
||||
new L.Marker([30, 30])
|
||||
];
|
||||
var len = markers.length;
|
||||
map.addLayer(group);
|
||||
|
||||
group.addLayers(markers);
|
||||
|
||||
markers.forEach(function (marker) {
|
||||
marker.setLatLng([1.5, 1.5]);
|
||||
group.removeLayer(marker);
|
||||
expect(group.getLayers().length).to.be(len - 1);
|
||||
group.addLayer(marker);
|
||||
expect(group.getLayers().length).to.be(len);
|
||||
});
|
||||
|
||||
expect(group.getLayers().length).to.be(len);
|
||||
});
|
||||
|
||||
it('removes all the layer given to it even if the group is not on the map', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var markers = [
|
||||
new L.Marker([1.5, 1.5]),
|
||||
new L.Marker([1.5, 1.5]),
|
||||
new L.Marker([1.5, 1.5])
|
||||
];
|
||||
|
||||
map.addLayer(group);
|
||||
group.addLayers(markers);
|
||||
map.removeLayer(group);
|
||||
group.removeLayers(markers);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(group.hasLayer(markers[0])).to.be(false);
|
||||
expect(group.hasLayer(markers[1])).to.be(false);
|
||||
expect(group.hasLayer(markers[2])).to.be(false);
|
||||
|
||||
expect(group.getLayers().length).to.be(0);
|
||||
});
|
||||
|
||||
it('doesnt break if we are spiderfied', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var markers = [
|
||||
new L.Marker([1.5, 1.5]),
|
||||
new L.Marker([1.5, 1.5]),
|
||||
@@ -72,4 +165,45 @@
|
||||
expect(group._spiderfied).to.be(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('handles nested Layer Groups', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker1 = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
var marker3 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
map.addLayer(group);
|
||||
|
||||
group.addLayers([marker1, marker2, marker3]);
|
||||
|
||||
expect(group.hasLayer(marker1)).to.be(true);
|
||||
expect(group.hasLayer(marker2)).to.be(true);
|
||||
expect(group.hasLayer(marker3)).to.be(true);
|
||||
|
||||
group.removeLayers([
|
||||
marker1,
|
||||
new L.LayerGroup([
|
||||
marker2, new L.LayerGroup([
|
||||
marker3
|
||||
])
|
||||
])
|
||||
]);
|
||||
|
||||
expect(group.hasLayer(marker1)).to.be(false);
|
||||
expect(group.hasLayer(marker2)).to.be(false);
|
||||
expect(group.hasLayer(marker3)).to.be(false);
|
||||
|
||||
expect(group.getLayers().length).to.be(0);
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
describe('Option removeOutsideVisibleBounds', function () {
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
// Nothing for this test suite.
|
||||
clock = sinon.useFakeTimers();
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
// Restore the previous setting, so that even in case of test failure, next tests are not affected.
|
||||
L.Browser.mobile = previousMobileSetting;
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
//group.removeLayers(group.getLayers());
|
||||
group.clearLayers();
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// group must be thrown away since we are testing it with a potentially
|
||||
// different configuration at each test.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
clock = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var marker1 = L.marker([1.5, -0.4]), // 2 screens width away.
|
||||
marker2 = L.marker([1.5, 0.6]), // 1 screen width away.
|
||||
marker3 = L.marker([1.5, 1.5]), // In view port.
|
||||
marker4 = L.marker([1.5, 2.4]), // 1 screen width away.
|
||||
marker5 = L.marker([1.5, 3.4]), // 2 screens width away.
|
||||
markers = [marker1, marker2, marker3, marker4, marker5],
|
||||
previousMobileSetting = L.Browser.mobile,
|
||||
div, map, group, i, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
// Add all markers once to map then remove them immediately so that their icon is null (instead of undefined).
|
||||
for (i = 0; i < markers.length; i++) {
|
||||
map.removeLayer(markers[i].addTo(map));
|
||||
}
|
||||
|
||||
|
||||
function prepareGroup() {
|
||||
|
||||
// "group" should be assigned with a Marker Cluster Group before calling this function.
|
||||
group.addTo(map);
|
||||
|
||||
group.addLayers(markers);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('removes objects more than 1 screen away from view port by default', function () {
|
||||
|
||||
group = L.markerClusterGroup();
|
||||
|
||||
prepareGroup();
|
||||
|
||||
expect(marker1._icon).to.be(null);
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(3); // markers 2, 3 and 4.
|
||||
expect(marker5._icon).to.be(null);
|
||||
|
||||
});
|
||||
|
||||
it('removes objects out of view port by default for mobile device', function () {
|
||||
|
||||
// Fool Leaflet, make it thinks it runs on a mobile device.
|
||||
L.Browser.mobile = true;
|
||||
|
||||
group = L.markerClusterGroup();
|
||||
|
||||
prepareGroup();
|
||||
|
||||
expect(marker1._icon).to.be(null);
|
||||
expect(marker2._icon).to.be(null);
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(1); // marker 3 only.
|
||||
expect(marker4._icon).to.be(null);
|
||||
expect(marker5._icon).to.be(null);
|
||||
|
||||
});
|
||||
|
||||
it('leaves all objects on map when set to false', function () {
|
||||
|
||||
group = L.markerClusterGroup({
|
||||
removeOutsideVisibleBounds: false
|
||||
});
|
||||
|
||||
prepareGroup();
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(5); // All 5 markers.
|
||||
|
||||
});
|
||||
|
||||
|
||||
// Following tests need markers at very high latitude.
|
||||
// They test the _checkBoundsMaxLat method against the default Web/Spherical Mercator projection maximum latitude (85.0511287798).
|
||||
// The actual map view should be '-1.0986328125,84.92929204957956,1.0986328125,85.11983467698401'
|
||||
// The expanded bounds without correction should be '-3.2958984375,84.7387494221751,3.2958984375,85.31037730438847'
|
||||
var latLngsMaxLatDefault = [
|
||||
[100, 3], // Impossible in real world, but nothing prevents the user from entering such latitude, and Web/Spherical Mercator projection will still display it at 85.0511287798
|
||||
[85.2, 1.5], // 1 "screen" heights away.
|
||||
[85, 0], // In center of view.
|
||||
[84.8, -1.5], // 1 "screen" height away.
|
||||
[84.6, -3] // 2 "screens" height away.
|
||||
];
|
||||
|
||||
function moveMarkersAndMapToMaxLat(latLngs, isSouth) {
|
||||
for (i = 0; i < markers.length; i++) {
|
||||
if (isSouth) {
|
||||
markers[i].setLatLng([-latLngs[i][0], latLngs[i][1]]);
|
||||
} else {
|
||||
markers[i].setLatLng(latLngs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
map.fitBounds([
|
||||
[isSouth ? -86 : 85, -1],
|
||||
[isSouth ? -85 : 86, 1] // The actual map view longitude span will be wider. '-1.0986328125,84.92929204957956,1.0986328125,85.11983467698401'
|
||||
]);
|
||||
}
|
||||
|
||||
function checkProjection(latLngs) {
|
||||
expect(map.options.crs).to.equal(L.CRS.EPSG3857);
|
||||
expect(L.CRS.EPSG3857.projection).to.equal(L.Projection.SphericalMercator);
|
||||
expect(L.Projection.SphericalMercator.MAX_LATITUDE).to.be.a('number');
|
||||
|
||||
var mapZoom = map.getZoom();
|
||||
|
||||
for (i = 0; i < markers.length; i++) {
|
||||
try {
|
||||
expect(markers[i].__parent._zoom).to.be.below(mapZoom);
|
||||
} catch (e) {
|
||||
console.log("Failed marker: " + (i + 1));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it('includes objects above the Web Mercator projection maximum limit by default', function () {
|
||||
|
||||
moveMarkersAndMapToMaxLat(latLngsMaxLatDefault);
|
||||
|
||||
group = L.markerClusterGroup();
|
||||
|
||||
prepareGroup();
|
||||
|
||||
checkProjection(latLngsMaxLatDefault);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(4); // Markers 1, 2, 3 and 4.
|
||||
expect(marker5._icon).to.be(null);
|
||||
|
||||
});
|
||||
|
||||
it('includes objects below the Web Mercator projection minimum limit by default', function () {
|
||||
|
||||
moveMarkersAndMapToMaxLat(latLngsMaxLatDefault, true);
|
||||
|
||||
// Make sure we are really in Southern hemisphere.
|
||||
expect(map.getBounds().getNorth()).to.be.below(-80);
|
||||
|
||||
group = L.markerClusterGroup();
|
||||
|
||||
prepareGroup();
|
||||
|
||||
checkProjection(latLngsMaxLatDefault);
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(4); // Markers 1, 2, 3 and 4.
|
||||
expect(marker5._icon).to.be(null);
|
||||
|
||||
});
|
||||
|
||||
|
||||
// The actual map view should be '-1.0986328125,84.92929204957956,1.0986328125,85.11983467698401'
|
||||
var latLngsMaxLatMobile = [
|
||||
[100, 1], // Impossible in real world, but nothing prevents the user from entering such latitude, and Web/Spherical Mercator projection will still display it at 85.0511287798
|
||||
[85.2, 0.5], // 1 "screen" heights away, but should be included by the correction.
|
||||
[85, 0], // In center of view.
|
||||
[84.9, -1], // 1 "screen" height away.
|
||||
[84.8, -1.5] // 2 "screens" height away.
|
||||
];
|
||||
|
||||
it('includes objects above the Web Mercator projection maximum limit for mobile device', function () {
|
||||
|
||||
// Fool Leaflet, make it thinks it runs on a mobile device.
|
||||
L.Browser.mobile = true;
|
||||
|
||||
moveMarkersAndMapToMaxLat(latLngsMaxLatMobile);
|
||||
|
||||
group = L.markerClusterGroup({
|
||||
maxClusterRadius: 10
|
||||
});
|
||||
|
||||
prepareGroup();
|
||||
|
||||
checkProjection(latLngsMaxLatMobile);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(3); // Markers 1, 2 and 3.
|
||||
expect(marker4._icon).to.be(null);
|
||||
expect(marker5._icon).to.be(null);
|
||||
|
||||
});
|
||||
|
||||
it('includes objects below the Web Mercator projection minimum limit for mobile device', function () {
|
||||
|
||||
// Fool Leaflet, make it thinks it runs on a mobile device.
|
||||
L.Browser.mobile = true;
|
||||
|
||||
moveMarkersAndMapToMaxLat(latLngsMaxLatMobile, true);
|
||||
|
||||
// Make sure we are really in Southern hemisphere.
|
||||
expect(map.getBounds().getNorth()).to.be.below(-80);
|
||||
|
||||
group = L.markerClusterGroup({
|
||||
maxClusterRadius: 10
|
||||
});
|
||||
|
||||
prepareGroup();
|
||||
|
||||
checkProjection(latLngsMaxLatMobile);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(3); // Markers 1, 2 and 3.
|
||||
expect(marker4._icon).to.be(null);
|
||||
expect(marker5._icon).to.be(null);
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -0,0 +1,110 @@
|
||||
describe('singleMarkerMode option', function () {
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
// Reset the marker icon.
|
||||
marker.setIcon(defaultIcon);
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.removeLayers(group.getLayers());
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// Throw away group as it can be assigned with different configurations between tests.
|
||||
group = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group;
|
||||
|
||||
var defaultIcon = new L.Icon.Default(),
|
||||
clusterIcon = new L.Icon.Default(),
|
||||
marker = L.marker([1.5, 1.5]);
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('overrides marker icons when set to true', function () {
|
||||
|
||||
group = L.markerClusterGroup({
|
||||
singleMarkerMode: true,
|
||||
iconCreateFunction: function (layer) {
|
||||
return clusterIcon;
|
||||
}
|
||||
}).addTo(map);
|
||||
|
||||
expect(marker.options.icon).to.equal(defaultIcon);
|
||||
|
||||
marker.addTo(group);
|
||||
|
||||
expect(marker.options.icon).to.equal(clusterIcon);
|
||||
|
||||
});
|
||||
|
||||
it('does not modify marker icons by default (or set to false)', function () {
|
||||
|
||||
group = L.markerClusterGroup({
|
||||
iconCreateFunction: function (layer) {
|
||||
return clusterIcon;
|
||||
}
|
||||
}).addTo(map);
|
||||
|
||||
expect(marker.options.icon).to.equal(defaultIcon);
|
||||
|
||||
marker.addTo(group);
|
||||
|
||||
expect(marker.options.icon).to.equal(defaultIcon);
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -1,28 +1,74 @@
|
||||
describe('spiderfy', function () {
|
||||
var map, div, clock;
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.removeLayers(group.getLayers());
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// group must be thrown away since we are testing it with a potentially
|
||||
// different configuration at each test.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
document.body.removeChild(div);
|
||||
clock = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('Spiderfies 2 Markers', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
@@ -38,7 +84,8 @@
|
||||
|
||||
it('Spiderfies 2 CircleMarkers', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.CircleMarker([1.5, 1.5]);
|
||||
var marker2 = new L.CircleMarker([1.5, 1.5]);
|
||||
|
||||
@@ -48,13 +95,16 @@
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
expect(marker._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker2._container.parentNode).to.be(map._pathRoot);
|
||||
// Leaflet 1.0.0 now uses an intermediate L.Renderer.
|
||||
// marker > _path > _rootGroup (g) > _container (svg) > pane (div)
|
||||
expect(marker._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
expect(marker2._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
});
|
||||
|
||||
it('Spiderfies 2 Circles', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Circle([1.5, 1.5], 10);
|
||||
var marker2 = new L.Circle([1.5, 1.5], 10);
|
||||
|
||||
@@ -64,14 +114,191 @@
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
expect(marker._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker2._container.parentNode).to.be(map._pathRoot);
|
||||
expect(marker._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
expect(marker2._path.parentNode.parentNode.parentNode).to.be(map.getPane('overlayPane'));
|
||||
});
|
||||
|
||||
it('Spiderfies at current zoom if all child markers are at the exact same position', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
// Get the appropriate cluster.
|
||||
var cluster = marker.__parent,
|
||||
zoom = map.getZoom();
|
||||
|
||||
while (cluster._zoom !== zoom) {
|
||||
cluster = cluster.__parent;
|
||||
}
|
||||
|
||||
expect(zoom).to.be.lessThan(10);
|
||||
|
||||
cluster.fireEvent('click', null, true);
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
expect(map.getZoom()).to.equal(zoom);
|
||||
|
||||
expect(marker._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(marker2._icon.parentNode).to.be(map._panes.markerPane);
|
||||
|
||||
});
|
||||
|
||||
it('Spiderfies at current zoom if all child markers are still within a single cluster at map maxZoom', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.50001]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker.__parent._zoom).to.equal(18);
|
||||
|
||||
// Get the appropriate cluster.
|
||||
var cluster = marker.__parent,
|
||||
zoom = map.getZoom();
|
||||
|
||||
while (cluster._zoom !== zoom) {
|
||||
cluster = cluster.__parent;
|
||||
}
|
||||
|
||||
expect(zoom).to.be.lessThan(10);
|
||||
|
||||
cluster.fireEvent('click', null, true);
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
expect(map.getZoom()).to.equal(zoom);
|
||||
|
||||
expect(marker._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(marker2._icon.parentNode).to.be(map._panes.markerPane);
|
||||
|
||||
});
|
||||
|
||||
it('removes all markers and spider legs when group is removed from map', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(3); // The 2 markers + semi-transparent cluster.
|
||||
expect(map.getPane('overlayPane').firstChild.firstChild.childNodes.length).to.be(2); // The 2 spider legs.
|
||||
|
||||
});
|
||||
|
||||
it('adds then removes class "leaflet-cluster-anim" from mapPane on spiderfy', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
expect(map._panes.mapPane.className).to.contain('leaflet-cluster-anim');
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
expect(map._panes.mapPane.className).to.not.contain('leaflet-cluster-anim');
|
||||
|
||||
});
|
||||
|
||||
it('adds then removes class "leaflet-cluster-anim" from mapPane on unspiderfy', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
marker.__parent.unspiderfy();
|
||||
|
||||
expect(map._panes.mapPane.className).to.contain('leaflet-cluster-anim');
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
expect(map._panes.mapPane.className).to.not.contain('leaflet-cluster-anim');
|
||||
|
||||
});
|
||||
|
||||
it('fires unspiderfied event on unspiderfy', function (done) {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
// Add event listener
|
||||
group.on('unspiderfied', function (event) {
|
||||
expect(event.target).to.be(group);
|
||||
expect(event.cluster).to.be.a(L.Marker);
|
||||
expect(event.markers[1]).to.be(marker);
|
||||
expect(event.markers[0]).to.be(marker2);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
marker.__parent.unspiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
});
|
||||
|
||||
it('does not leave class "leaflet-cluster-anim" on mapPane when group is removed while spiderfied', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
map.removeLayer(group);
|
||||
|
||||
expect(map._panes.mapPane.className).to.not.contain('leaflet-cluster-anim');
|
||||
|
||||
});
|
||||
|
||||
describe('zoomend event listener', function () {
|
||||
|
||||
it('unspiderfies correctly', function () {
|
||||
|
||||
var group = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Circle([1.5, 1.5], 10);
|
||||
var marker2 = new L.Circle([1.5, 1.5], 10);
|
||||
|
||||
@@ -88,5 +315,67 @@
|
||||
//We should unspiderfy with no animation, so this should be null
|
||||
expect(group._spiderfied).to.be(null);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('spiderfied event listener', function () {
|
||||
it('Spiderfies 2 Markers', function (done) {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
map.addLayer(group);
|
||||
|
||||
// Add event listener
|
||||
group.on('spiderfied', function (event) {
|
||||
expect(event.target).to.be(group);
|
||||
expect(event.cluster).to.be.a(L.Marker);
|
||||
expect(event.markers[1]).to.be(marker);
|
||||
expect(event.markers[0]).to.be(marker2);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
clock.tick(200);
|
||||
});
|
||||
|
||||
it('Spiderfies 2 Circles', function (done) {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
var marker = new L.Circle([1.5, 1.5], 10);
|
||||
var marker2 = new L.Circle([1.5, 1.5], 10);
|
||||
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
map.addLayer(group);
|
||||
|
||||
// Add event listener
|
||||
group.on('spiderfied', function (event) {
|
||||
expect(event.target).to.be(group);
|
||||
expect(event.cluster).to.be.a(L.Marker);
|
||||
expect(event.markers[1]).to.be(marker);
|
||||
expect(event.markers[0]).to.be(marker2);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
clock.tick(200);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
describe('things behave correctly with negative minZoom', function () {
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
// Nothing for this test suite.
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.clearLayers();
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// Throw away group as it can be assigned with different configurations between tests.
|
||||
group = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { minZoom: -3, maxZoom: 18 });
|
||||
|
||||
map.setView(L.latLng(0, 0), -3);
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('shows a single marker added to the group before the group is added to the map', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker._icon).to.not.be(undefined);
|
||||
expect(marker._icon.parentNode).to.be(map._panes.markerPane);
|
||||
});
|
||||
|
||||
it('shows a single marker added to the group after the group is added to the map', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
|
||||
map.addLayer(group);
|
||||
group.addLayer(marker);
|
||||
|
||||
expect(marker._icon).to.not.be(undefined);
|
||||
expect(marker._icon.parentNode).to.be(map._panes.markerPane);
|
||||
});
|
||||
|
||||
it('creates a cluster when 2 overlapping markers are added before the group is added to the map', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
map.addLayer(group);
|
||||
|
||||
expect(marker._icon).to.be(undefined);
|
||||
expect(marker2._icon).to.be(undefined);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(1);
|
||||
});
|
||||
it('creates a cluster when 2 overlapping markers are added after the group is added to the map', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
map.addLayer(group);
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
|
||||
expect(marker._icon).to.be(null); //Null as was added and then removed
|
||||
expect(marker2._icon).to.be(undefined);
|
||||
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(1);
|
||||
});
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
@@ -0,0 +1,169 @@
|
||||
describe('unspiderfy', function () {
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.removeLayers(group.getLayers());
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// group must be thrown away since we are testing it with a potentially
|
||||
// different configuration at each test.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
clock = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var div, map, group, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, {
|
||||
maxZoom: 18
|
||||
});
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('Unspiderfies 2 Markers', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
group.unspiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
expect(map.hasLayer(marker)).to.be(false);
|
||||
expect(map.hasLayer(marker2)).to.be(false);
|
||||
});
|
||||
|
||||
it('Unspiderfies 2 CircleMarkers', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.CircleMarker([1.5, 1.5]);
|
||||
var marker2 = new L.CircleMarker([1.5, 1.5]);
|
||||
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
group.unspiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
expect(map.hasLayer(marker)).to.be(false);
|
||||
expect(map.hasLayer(marker2)).to.be(false);
|
||||
});
|
||||
|
||||
it('Unspiderfies 2 Circles', function () {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Circle([1.5, 1.5], 10);
|
||||
var marker2 = new L.Circle([1.5, 1.5], 10);
|
||||
|
||||
group.addLayer(marker);
|
||||
group.addLayer(marker2);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
group.unspiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
expect(map.hasLayer(marker)).to.be(false);
|
||||
expect(map.hasLayer(marker2)).to.be(false);
|
||||
});
|
||||
|
||||
it('fires unspiderfied event on unspiderfy', function (done) {
|
||||
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([1.5, 1.5]);
|
||||
var marker2 = new L.Marker([1.5, 1.5]);
|
||||
|
||||
group.addLayers([marker, marker2]);
|
||||
map.addLayer(group);
|
||||
|
||||
marker.__parent.spiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
// Add event listener
|
||||
group.on('unspiderfied', function (event) {
|
||||
expect(event.target).to.be(group);
|
||||
expect(event.cluster).to.be.a(L.Marker);
|
||||
expect(event.markers[1]).to.be(marker);
|
||||
expect(event.markers[0]).to.be(marker2);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
group.unspiderfy();
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,33 +1,86 @@
|
||||
describe('zoomAnimation', function () {
|
||||
var map, div, clock;
|
||||
|
||||
/**
|
||||
* Avoid as much as possible creating and destroying objects for each test.
|
||||
* Instead, try re-using them, except for the ones under test of course.
|
||||
* PhantomJS does not perform garbage collection for the life of the page,
|
||||
* i.e. during the entire test process (Karma runs all tests in a single page).
|
||||
* http://stackoverflow.com/questions/27239708/how-to-get-around-memory-error-with-karma-phantomjs
|
||||
*
|
||||
* The `beforeEach` and `afterEach do not seem to cause much issue.
|
||||
* => they can still be used to initialize some setup between each test.
|
||||
* Using them keeps a readable spec/index.
|
||||
*
|
||||
* But refrain from re-creating div and map every time. Re-use those objects.
|
||||
*/
|
||||
|
||||
/////////////////////////////
|
||||
// SETUP FOR EACH TEST
|
||||
/////////////////////////////
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
clock = sinon.useFakeTimers();
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
clock.restore();
|
||||
|
||||
document.body.removeChild(div);
|
||||
// Restore the previous setting, so that even in case of test failure, next tests are not affected.
|
||||
L.Browser.mobile = previousMobileSetting;
|
||||
|
||||
if (group instanceof L.MarkerClusterGroup) {
|
||||
group.clearLayers();
|
||||
map.removeLayer(group);
|
||||
}
|
||||
|
||||
// group must be thrown away since we are testing it with a potentially
|
||||
// different configuration at each test.
|
||||
group = null;
|
||||
|
||||
clock.restore();
|
||||
clock = null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// PREPARATION CODE
|
||||
/////////////////////////////
|
||||
|
||||
var previousMobileSetting = L.Browser.mobile,
|
||||
div, map, group, clock;
|
||||
|
||||
div = document.createElement('div');
|
||||
div.style.width = '200px';
|
||||
div.style.height = '200px';
|
||||
document.body.appendChild(div);
|
||||
|
||||
map = L.map(div, { maxZoom: 18 });
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// TESTS
|
||||
/////////////////////////////
|
||||
|
||||
it('adds the visible marker to the map when zooming in', function () {
|
||||
map.setView(new L.LatLng(-37.36142550190516, 174.254150390625), 7);
|
||||
|
||||
var markers = new L.MarkerClusterGroup({
|
||||
group = new L.MarkerClusterGroup({
|
||||
showCoverageOnHover: true,
|
||||
maxClusterRadius: 20,
|
||||
disableClusteringAtZoom: 15
|
||||
});
|
||||
var marker = new L.Marker([-37.77852090603777, 175.3103667497635]);
|
||||
markers.addLayer(marker); //The one we zoom in on
|
||||
markers.addLayer(new L.Marker([-37.711800591811055, 174.50034790039062])); //Marker that we cluster with at the top zoom level, but not 1 level down
|
||||
map.addLayer(markers);
|
||||
group.addLayer(marker); //The one we zoom in on
|
||||
group.addLayer(new L.Marker([-37.711800591811055, 174.50034790039062])); //Marker that we cluster with at the top zoom level, but not 1 level down
|
||||
map.addLayer(group);
|
||||
|
||||
clock.tick(1000);
|
||||
map.setView([-37.77852090603777, 175.3103667497635], 15);
|
||||
@@ -41,12 +94,12 @@
|
||||
|
||||
it('adds the visible marker to the map when jumping around', function () {
|
||||
|
||||
var markers = new L.MarkerClusterGroup();
|
||||
group = new L.MarkerClusterGroup();
|
||||
var marker1 = new L.Marker([48.858280181884766, 2.2945759296417236]);
|
||||
var marker2 = new L.Marker([16.02359962463379, -61.70280075073242]);
|
||||
markers.addLayer(marker1); //The one we zoom in on first
|
||||
markers.addLayer(marker2); //Marker that we cluster with at the top zoom level, but not 1 level down
|
||||
map.addLayer(markers);
|
||||
group.addLayer(marker1); //The one we zoom in on first
|
||||
group.addLayer(marker2); //Marker that we cluster with at the top zoom level, but not 1 level down
|
||||
map.addLayer(group);
|
||||
|
||||
//show the first
|
||||
map.fitBounds(new L.LatLngBounds(new L.LatLng(41.371582, -5.142222), new L.LatLng(51.092804, 9.561556)));
|
||||
@@ -65,15 +118,16 @@
|
||||
|
||||
it('adds the visible markers to the map, but not parent clusters when jumping around', function () {
|
||||
|
||||
var markers = new L.MarkerClusterGroup(),
|
||||
marker1 = new L.Marker([59.9520, 30.3307]),
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker1 = new L.Marker([59.9520, 30.3307]),
|
||||
marker2 = new L.Marker([59.9516, 30.3308]),
|
||||
marker3 = new L.Marker([59.9513, 30.3312]);
|
||||
|
||||
markers.addLayer(marker1);
|
||||
markers.addLayer(marker2);
|
||||
markers.addLayer(marker3);
|
||||
map.addLayer(markers);
|
||||
group.addLayer(marker1);
|
||||
group.addLayer(marker2);
|
||||
group.addLayer(marker3);
|
||||
map.addLayer(group);
|
||||
|
||||
//Show none of them
|
||||
map.setView([53.0676, 170.6835], 16);
|
||||
@@ -92,4 +146,265 @@
|
||||
expect(marker3._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(3);
|
||||
});
|
||||
});
|
||||
|
||||
it('removes clicked clusters on the edge of a mobile screen', function () {
|
||||
|
||||
L.Browser.mobile = true;
|
||||
|
||||
// Corresponds to zoom level 8 for the above div dimensions.
|
||||
map.fitBounds(new L.LatLngBounds([
|
||||
[1, 1],
|
||||
[2, 2]
|
||||
]));
|
||||
|
||||
group = new L.MarkerClusterGroup({
|
||||
maxClusterRadius: 80
|
||||
}).addTo(map);
|
||||
|
||||
// Add a marker 1 pixel below the initial screen bottom edge.
|
||||
var bottomPoint = map.getPixelBounds().max.add([0, 1]),
|
||||
bottomLatLng = map.unproject(bottomPoint),
|
||||
centerLng = map.getCenter().lng,
|
||||
bottomPosition = new L.LatLng(
|
||||
bottomLatLng.lat,
|
||||
centerLng
|
||||
),
|
||||
bottomMarker = new L.Marker(bottomPosition).addTo(group),
|
||||
initialZoom = map.getZoom();
|
||||
|
||||
expect(bottomMarker._icon).to.be(undefined);
|
||||
|
||||
// Add many markers 79 pixels above the first one, so they cluster with it.
|
||||
var newPoint = bottomPoint.add([0, -79]),
|
||||
newLatLng = L.latLng(
|
||||
map.unproject(newPoint).lat,
|
||||
centerLng
|
||||
);
|
||||
|
||||
for (var i = 0; i < 10; i += 1) {
|
||||
group.addLayer(new L.Marker(newLatLng));
|
||||
}
|
||||
|
||||
var parentCluster = bottomMarker.__parent;
|
||||
|
||||
expect(parentCluster._icon.parentNode).to.be(map._panes.markerPane);
|
||||
|
||||
parentCluster.fireEvent('click', null, true);
|
||||
|
||||
//Run the the animation
|
||||
clock.tick(1000);
|
||||
|
||||
expect(map.getZoom()).to.equal(initialZoom + 1); // The fitBounds with 200px height should result in zooming 1 level in.
|
||||
|
||||
// Finally make sure that the cluster has been removed from map.
|
||||
expect(parentCluster._icon).to.be(null);
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(2); // The bottomMarker + cluster for the 10 above markers.
|
||||
|
||||
});
|
||||
|
||||
describe('zoomToShowLayer', function () {
|
||||
|
||||
it('zoom to single marker inside map view', function () {
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([59.9520, 30.3307]);
|
||||
|
||||
group.addLayer(marker);
|
||||
map.addLayer(group);
|
||||
|
||||
var zoomCallbackSpy = sinon.spy();
|
||||
|
||||
map.setView(marker.getLatLng(), 10);
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
var initialCenter = map.getCenter();
|
||||
var initialZoom = map.getZoom();
|
||||
|
||||
group.zoomToShowLayer(marker, zoomCallbackSpy);
|
||||
|
||||
//Run the the animation
|
||||
clock.tick(1000);
|
||||
|
||||
//Marker should be visible, map center and zoom level should stay the same, callback called once
|
||||
expect(marker._icon).to.not.be(undefined);
|
||||
expect(marker._icon).to.not.be(null);
|
||||
expect(map.getBounds().contains(marker.getLatLng())).to.be.true;
|
||||
expect(map.getCenter()).to.eql(initialCenter);
|
||||
expect(map.getZoom()).to.equal(initialZoom);
|
||||
sinon.assert.calledOnce(zoomCallbackSpy);
|
||||
});
|
||||
|
||||
it('pan map to single marker outside map view', function () {
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker = new L.Marker([59.9520, 30.3307]);
|
||||
|
||||
group.addLayer(marker);
|
||||
map.addLayer(group);
|
||||
|
||||
var zoomCallbackSpy = sinon.spy();
|
||||
|
||||
//Show none of them
|
||||
map.setView([53.0676, 170.6835], 16);
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
var initialZoom = map.getZoom();
|
||||
|
||||
group.zoomToShowLayer(marker, zoomCallbackSpy);
|
||||
|
||||
//Run the the animation
|
||||
clock.tick(1000);
|
||||
|
||||
//Marker should be visible, map center should be equal to marker center,
|
||||
//zoom level should stay the same, callback called once
|
||||
expect(marker._icon).to.not.be(undefined);
|
||||
expect(marker._icon).to.not.be(null);
|
||||
expect(map.getBounds().contains(marker.getLatLng())).to.be.true;
|
||||
expect(map.getCenter()).to.eql(marker.getLatLng());
|
||||
expect(map.getZoom()).to.equal(initialZoom);
|
||||
sinon.assert.calledOnce(zoomCallbackSpy);
|
||||
});
|
||||
|
||||
it('change view and zoom to marker in cluster inside map view', function () {
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker1 = new L.Marker([59.9520, 30.3307]);
|
||||
var marker2 = new L.Marker([59.9516, 30.3308]);
|
||||
var marker3 = new L.Marker([59.9513, 30.3312]);
|
||||
|
||||
group.addLayer(marker1);
|
||||
group.addLayer(marker2);
|
||||
group.addLayer(marker3);
|
||||
map.addLayer(group);
|
||||
|
||||
var zoomCallbackSpy = sinon.spy();
|
||||
|
||||
map.setView(marker1.getLatLng(), 16);
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
group.zoomToShowLayer(marker1, zoomCallbackSpy);
|
||||
|
||||
//Run the the animation
|
||||
clock.tick(1000);
|
||||
|
||||
//Now the markers should all be visible, there should be no visible clusters, and callback called once
|
||||
expect(marker1._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(marker2._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(marker3._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(3);
|
||||
expect(map.getBounds().contains(marker1.getLatLng())).to.be.true;
|
||||
sinon.assert.calledOnce(zoomCallbackSpy);
|
||||
});
|
||||
|
||||
it('change view and zoom to marker in cluster outside map view', function () {
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker1 = new L.Marker([59.9520, 30.3307]);
|
||||
var marker2 = new L.Marker([59.9516, 30.3308]);
|
||||
var marker3 = new L.Marker([59.9513, 30.3312]);
|
||||
|
||||
group.addLayer(marker1);
|
||||
group.addLayer(marker2);
|
||||
group.addLayer(marker3);
|
||||
map.addLayer(group);
|
||||
|
||||
var zoomCallbackSpy = sinon.spy();
|
||||
|
||||
//Show none of them
|
||||
map.setView([53.0676, 170.6835], 16);
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
group.zoomToShowLayer(marker1, zoomCallbackSpy);
|
||||
|
||||
//Run the the animation
|
||||
clock.tick(1000);
|
||||
|
||||
//Now the markers should all be visible, there should be no visible clusters, and callback called once
|
||||
expect(marker1._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(marker2._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(marker3._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(3);
|
||||
expect(map.getBounds().contains(marker1.getLatLng())).to.be.true;
|
||||
sinon.assert.calledOnce(zoomCallbackSpy);
|
||||
});
|
||||
|
||||
it('spiderfy overlapping markers', function () {
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker1 = new L.Marker([59.9520, 30.3307]);
|
||||
var marker2 = new L.Marker([59.9520, 30.3307]);
|
||||
var marker3 = new L.Marker([59.9520, 30.3307]);
|
||||
|
||||
group.addLayer(marker1);
|
||||
group.addLayer(marker2);
|
||||
group.addLayer(marker3);
|
||||
map.addLayer(group);
|
||||
|
||||
var zoomCallbackSpy = sinon.spy();
|
||||
|
||||
//Show none of them
|
||||
map.setView([53.0676, 170.6835], 16);
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
group.zoomToShowLayer(marker1, zoomCallbackSpy);
|
||||
|
||||
//Run the the animation
|
||||
clock.tick(1000);
|
||||
|
||||
//Now the markers should all be visible, parent cluster should be spiderfied, and callback called once
|
||||
expect(marker1._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(marker2._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(marker3._icon.parentNode).to.be(map._panes.markerPane);
|
||||
expect(map._panes.markerPane.childNodes.length).to.be(4);//3 markers + spiderfied parent cluster
|
||||
sinon.assert.calledOnce(zoomCallbackSpy);
|
||||
});
|
||||
|
||||
it('zoom or spiderfy markers if they visible on next level of zoom', function () {
|
||||
group = new L.MarkerClusterGroup();
|
||||
|
||||
var marker1 = new L.Marker([59.9520, 30.3307]);
|
||||
var marker2 = new L.Marker([59.9516, 30.3308]);
|
||||
var marker3 = new L.Marker([59.9513, 30.3312]);
|
||||
|
||||
group.addLayer(marker1);
|
||||
group.addLayer(marker2);
|
||||
group.addLayer(marker3);
|
||||
map.addLayer(group);
|
||||
|
||||
var zoomCallbackSpy = sinon.spy();
|
||||
|
||||
//Markers will be visible on zoom 18
|
||||
map.setView([59.9520, 30.3307], 17);
|
||||
|
||||
clock.tick(1000);
|
||||
|
||||
group.zoomToShowLayer(marker1, zoomCallbackSpy);
|
||||
|
||||
//Run the the animation
|
||||
clock.tick(1000);
|
||||
|
||||
//Now the markers should all be visible (zoomed or spiderfied), and callback called once
|
||||
expect(marker1._icon).to.not.be(undefined);
|
||||
expect(marker1._icon).to.not.be(null);
|
||||
expect(marker2._icon).to.not.be(undefined);
|
||||
expect(marker2._icon).to.not.be(null);
|
||||
expect(marker3._icon).to.not.be(undefined);
|
||||
expect(marker3._icon).to.not.be(null);
|
||||
sinon.assert.calledOnce(zoomCallbackSpy);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// CLEAN UP CODE
|
||||
/////////////////////////////
|
||||
|
||||
map.remove();
|
||||
document.body.removeChild(div);
|
||||
|
||||
});
|
||||
|
||||
@@ -92,7 +92,8 @@ L.DistanceGrid.prototype = {
|
||||
for (k = 0, len = cell.length; k < len; k++) {
|
||||
obj = cell[k];
|
||||
dist = this._sqDist(objectPoint[L.Util.stamp(obj)], point);
|
||||
if (dist < closestDistSq) {
|
||||
if (dist < closestDistSq ||
|
||||
dist <= closestDistSq && closest === null) {
|
||||
closestDistSq = dist;
|
||||
closest = obj;
|
||||
}
|
||||
@@ -105,7 +106,8 @@ L.DistanceGrid.prototype = {
|
||||
},
|
||||
|
||||
_getCoord: function (x) {
|
||||
return Math.floor(x / this._cellSize);
|
||||
var coord = Math.floor(x / this._cellSize);
|
||||
return isFinite(coord) ? coord : x;
|
||||
},
|
||||
|
||||
_sqDist: function (p, p2) {
|
||||
|
||||
@@ -108,20 +108,40 @@ Retrieved from: http://en.literateprograms.org/Quickhull_(Javascript)?oldid=1843
|
||||
getConvexHull: function (latLngs) {
|
||||
// find first baseline
|
||||
var maxLat = false, minLat = false,
|
||||
maxLng = false, minLng = false,
|
||||
maxLatPt = null, minLatPt = null,
|
||||
maxLngPt = null, minLngPt = null,
|
||||
maxPt = null, minPt = null,
|
||||
i;
|
||||
|
||||
for (i = latLngs.length - 1; i >= 0; i--) {
|
||||
var pt = latLngs[i];
|
||||
if (maxLat === false || pt.lat > maxLat) {
|
||||
maxPt = pt;
|
||||
maxLatPt = pt;
|
||||
maxLat = pt.lat;
|
||||
}
|
||||
if (minLat === false || pt.lat < minLat) {
|
||||
minPt = pt;
|
||||
minLatPt = pt;
|
||||
minLat = pt.lat;
|
||||
}
|
||||
if (maxLng === false || pt.lng > maxLng) {
|
||||
maxLngPt = pt;
|
||||
maxLng = pt.lng;
|
||||
}
|
||||
if (minLng === false || pt.lng < minLng) {
|
||||
minLngPt = pt;
|
||||
minLng = pt.lng;
|
||||
}
|
||||
}
|
||||
|
||||
if (minLat !== maxLat) {
|
||||
minPt = minLatPt;
|
||||
maxPt = maxLatPt;
|
||||
} else {
|
||||
minPt = minLngPt;
|
||||
maxPt = maxLngPt;
|
||||
}
|
||||
|
||||
var ch = [].concat(this.buildConvexHull([minPt, maxPt], latLngs),
|
||||
this.buildConvexHull([maxPt, minPt], latLngs));
|
||||
return ch;
|
||||
|
||||
@@ -5,7 +5,7 @@ L.MarkerCluster.include({
|
||||
|
||||
_2PI: Math.PI * 2,
|
||||
_circleFootSeparation: 25, //related to circumference of circle
|
||||
_circleStartAngle: Math.PI / 6,
|
||||
_circleStartAngle: 0,
|
||||
|
||||
_spiralFootSeparation: 28, //related to size of spiral (experiment!)
|
||||
_spiralLengthStart: 11,
|
||||
@@ -33,7 +33,7 @@ L.MarkerCluster.include({
|
||||
if (childMarkers.length >= this._circleSpiralSwitchover) {
|
||||
positions = this._generatePointsSpiral(childMarkers.length, center);
|
||||
} else {
|
||||
center.y += 10; //Otherwise circles look wrong
|
||||
center.y += 10; // Otherwise circles look wrong => hack for standard blue icon, renders differently for other icons.
|
||||
positions = this._generatePointsCircle(childMarkers.length, center);
|
||||
}
|
||||
|
||||
@@ -57,9 +57,11 @@ L.MarkerCluster.include({
|
||||
res = [],
|
||||
i, angle;
|
||||
|
||||
legLength = Math.max(legLength, 35); // Minimum distance to get outside the cluster icon.
|
||||
|
||||
res.length = count;
|
||||
|
||||
for (i = count - 1; i >= 0; i--) {
|
||||
for (i = 0; i < count; i++) { // Clockwise, like spiral.
|
||||
angle = this._circleStartAngle + i * angleStep;
|
||||
res[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round();
|
||||
}
|
||||
@@ -68,19 +70,25 @@ L.MarkerCluster.include({
|
||||
},
|
||||
|
||||
_generatePointsSpiral: function (count, centerPt) {
|
||||
var legLength = this._group.options.spiderfyDistanceMultiplier * this._spiralLengthStart,
|
||||
separation = this._group.options.spiderfyDistanceMultiplier * this._spiralFootSeparation,
|
||||
lengthFactor = this._group.options.spiderfyDistanceMultiplier * this._spiralLengthFactor,
|
||||
var spiderfyDistanceMultiplier = this._group.options.spiderfyDistanceMultiplier,
|
||||
legLength = spiderfyDistanceMultiplier * this._spiralLengthStart,
|
||||
separation = spiderfyDistanceMultiplier * this._spiralFootSeparation,
|
||||
lengthFactor = spiderfyDistanceMultiplier * this._spiralLengthFactor * this._2PI,
|
||||
angle = 0,
|
||||
res = [],
|
||||
i;
|
||||
|
||||
res.length = count;
|
||||
|
||||
for (i = count - 1; i >= 0; i--) {
|
||||
// Higher index, closer position to cluster center.
|
||||
for (i = count; i >= 0; i--) {
|
||||
// Skip the first position, so that we are already farther from center and we avoid
|
||||
// being under the default cluster icon (especially important for Circle Markers).
|
||||
if (i < count) {
|
||||
res[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round();
|
||||
}
|
||||
angle += separation / legLength + i * 0.0005;
|
||||
res[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round();
|
||||
legLength += this._2PI * lengthFactor / angle;
|
||||
legLength += lengthFactor / angle;
|
||||
}
|
||||
return res;
|
||||
},
|
||||
@@ -92,6 +100,8 @@ L.MarkerCluster.include({
|
||||
childMarkers = this.getAllChildMarkers(),
|
||||
m, i;
|
||||
|
||||
group._ignoreMove = true;
|
||||
|
||||
this.setOpacity(1);
|
||||
for (i = childMarkers.length - 1; i >= 0; i--) {
|
||||
m = childMarkers[i];
|
||||
@@ -112,22 +122,38 @@ L.MarkerCluster.include({
|
||||
}
|
||||
}
|
||||
|
||||
group.fire('unspiderfied', {
|
||||
cluster: this,
|
||||
markers: childMarkers
|
||||
});
|
||||
group._ignoreMove = false;
|
||||
group._spiderfied = null;
|
||||
}
|
||||
});
|
||||
|
||||
L.MarkerCluster.include(!L.DomUtil.TRANSITION ? {
|
||||
//Non Animated versions of everything
|
||||
//Non Animated versions of everything
|
||||
L.MarkerClusterNonAnimated = L.MarkerCluster.extend({
|
||||
_animationSpiderfy: function (childMarkers, positions) {
|
||||
var group = this._group,
|
||||
map = group._map,
|
||||
fg = group._featureGroup,
|
||||
legOptions = this._group.options.spiderLegPolylineOptions,
|
||||
i, m, leg, newPos;
|
||||
|
||||
for (i = childMarkers.length - 1; i >= 0; i--) {
|
||||
group._ignoreMove = true;
|
||||
|
||||
// Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition.
|
||||
// The reverse order trick no longer improves performance on modern browsers.
|
||||
for (i = 0; i < childMarkers.length; i++) {
|
||||
newPos = map.layerPointToLatLng(positions[i]);
|
||||
m = childMarkers[i];
|
||||
|
||||
// Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it.
|
||||
leg = new L.Polyline([this._latlng, newPos], legOptions);
|
||||
map.addLayer(leg);
|
||||
m._spiderLeg = leg;
|
||||
|
||||
// Now add the marker.
|
||||
m._preSpiderfyLatlng = m._latlng;
|
||||
m.setLatLng(newPos);
|
||||
if (m.setZIndexOffset) {
|
||||
@@ -135,58 +161,95 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? {
|
||||
}
|
||||
|
||||
fg.addLayer(m);
|
||||
|
||||
var legOptions = this._group.options.spiderLegPolylineOptions;
|
||||
leg = new L.Polyline([this._latlng, newPos], legOptions);
|
||||
map.addLayer(leg);
|
||||
m._spiderLeg = leg;
|
||||
}
|
||||
this.setOpacity(0.3);
|
||||
group.fire('spiderfied');
|
||||
|
||||
group._ignoreMove = false;
|
||||
group.fire('spiderfied', {
|
||||
cluster: this,
|
||||
markers: childMarkers
|
||||
});
|
||||
},
|
||||
|
||||
_animationUnspiderfy: function () {
|
||||
this._noanimationUnspiderfy();
|
||||
}
|
||||
} : {
|
||||
//Animated versions here
|
||||
SVG_ANIMATION: (function () {
|
||||
return document.createElementNS('http://www.w3.org/2000/svg', 'animate').toString().indexOf('SVGAnimate') > -1;
|
||||
}()),
|
||||
});
|
||||
|
||||
//Animated versions here
|
||||
L.MarkerCluster.include({
|
||||
|
||||
_animationSpiderfy: function (childMarkers, positions) {
|
||||
var me = this,
|
||||
group = this._group,
|
||||
map = group._map,
|
||||
fg = group._featureGroup,
|
||||
thisLayerPos = map.latLngToLayerPoint(this._latlng),
|
||||
i, m, leg, newPos;
|
||||
thisLayerLatLng = this._latlng,
|
||||
thisLayerPos = map.latLngToLayerPoint(thisLayerLatLng),
|
||||
svg = L.Path.SVG,
|
||||
legOptions = L.extend({}, this._group.options.spiderLegPolylineOptions), // Copy the options so that we can modify them for animation.
|
||||
finalLegOpacity = legOptions.opacity,
|
||||
i, m, leg, legPath, legLength, newPos;
|
||||
|
||||
//Add markers to map hidden at our center point
|
||||
for (i = childMarkers.length - 1; i >= 0; i--) {
|
||||
if (finalLegOpacity === undefined) {
|
||||
finalLegOpacity = L.MarkerClusterGroup.prototype.options.spiderLegPolylineOptions.opacity;
|
||||
}
|
||||
|
||||
if (svg) {
|
||||
// If the initial opacity of the spider leg is not 0 then it appears before the animation starts.
|
||||
legOptions.opacity = 0;
|
||||
|
||||
// Add the class for CSS transitions.
|
||||
legOptions.className = (legOptions.className || '') + ' leaflet-cluster-spider-leg';
|
||||
} else {
|
||||
// Make sure we have a defined opacity.
|
||||
legOptions.opacity = finalLegOpacity;
|
||||
}
|
||||
|
||||
group._ignoreMove = true;
|
||||
|
||||
// Add markers and spider legs to map, hidden at our center point.
|
||||
// Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition.
|
||||
// The reverse order trick no longer improves performance on modern browsers.
|
||||
for (i = 0; i < childMarkers.length; i++) {
|
||||
m = childMarkers[i];
|
||||
|
||||
//If it is a marker, add it now and we'll animate it out
|
||||
if (m.setOpacity) {
|
||||
m.setZIndexOffset(1000000); //Make these appear on top of EVERYTHING
|
||||
m.clusterHide();
|
||||
|
||||
fg.addLayer(m);
|
||||
newPos = map.layerPointToLatLng(positions[i]);
|
||||
|
||||
// Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it.
|
||||
leg = new L.Polyline([thisLayerLatLng, newPos], legOptions);
|
||||
map.addLayer(leg);
|
||||
m._spiderLeg = leg;
|
||||
|
||||
// Explanations: https://jakearchibald.com/2013/animated-line-drawing-svg/
|
||||
// In our case the transition property is declared in the CSS file.
|
||||
if (svg) {
|
||||
legPath = leg._path;
|
||||
legLength = legPath.getTotalLength() + 0.1; // Need a small extra length to avoid remaining dot in Firefox.
|
||||
legPath.style.strokeDasharray = legLength; // Just 1 length is enough, it will be duplicated.
|
||||
legPath.style.strokeDashoffset = legLength;
|
||||
}
|
||||
|
||||
// If it is a marker, add it now and we'll animate it out
|
||||
if (m.setZIndexOffset) {
|
||||
m.setZIndexOffset(1000000); // Make normal markers appear on top of EVERYTHING
|
||||
}
|
||||
if (m.clusterHide) {
|
||||
m.clusterHide();
|
||||
}
|
||||
|
||||
// Vectors just get immediately added
|
||||
fg.addLayer(m);
|
||||
|
||||
if (m._setPos) {
|
||||
m._setPos(thisLayerPos);
|
||||
} else {
|
||||
//Vectors just get immediately added
|
||||
fg.addLayer(m);
|
||||
}
|
||||
}
|
||||
|
||||
group._forceLayout();
|
||||
group._animationStart();
|
||||
|
||||
var initialLegOpacity = L.Path.SVG ? 0 : 0.3,
|
||||
xmlns = L.Path.SVG_NS;
|
||||
|
||||
|
||||
// Reveal markers and spider legs.
|
||||
for (i = childMarkers.length - 1; i >= 0; i--) {
|
||||
newPos = map.layerPointToLatLng(positions[i]);
|
||||
m = childMarkers[i];
|
||||
@@ -195,84 +258,43 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? {
|
||||
m._preSpiderfyLatlng = m._latlng;
|
||||
m.setLatLng(newPos);
|
||||
|
||||
if (m.setOpacity) {
|
||||
if (m.clusterShow) {
|
||||
m.clusterShow();
|
||||
}
|
||||
|
||||
|
||||
//Add Legs.
|
||||
var legOptions = this._group.options.spiderLegPolylineOptions;
|
||||
if (legOptions.opacity === undefined) {
|
||||
legOptions.opacity = initialLegOpacity;
|
||||
}
|
||||
leg = new L.Polyline([me._latlng, newPos], legOptions);
|
||||
map.addLayer(leg);
|
||||
m._spiderLeg = leg;
|
||||
|
||||
//Following animations don't work for canvas
|
||||
if (!L.Path.SVG || !this.SVG_ANIMATION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//How this works:
|
||||
//http://stackoverflow.com/questions/5924238/how-do-you-animate-an-svg-path-in-ios
|
||||
//http://dev.opera.com/articles/view/advanced-svg-animation-techniques/
|
||||
|
||||
//Animate length
|
||||
var length = leg._path.getTotalLength();
|
||||
leg._path.setAttribute("stroke-dasharray", length + "," + length);
|
||||
|
||||
var anim = document.createElementNS(xmlns, "animate");
|
||||
anim.setAttribute("attributeName", "stroke-dashoffset");
|
||||
anim.setAttribute("begin", "indefinite");
|
||||
anim.setAttribute("from", length);
|
||||
anim.setAttribute("to", 0);
|
||||
anim.setAttribute("dur", 0.25);
|
||||
leg._path.appendChild(anim);
|
||||
anim.beginElement();
|
||||
|
||||
//Animate opacity
|
||||
anim = document.createElementNS(xmlns, "animate");
|
||||
anim.setAttribute("attributeName", "stroke-opacity");
|
||||
anim.setAttribute("attributeName", "stroke-opacity");
|
||||
anim.setAttribute("begin", "indefinite");
|
||||
anim.setAttribute("from", 0);
|
||||
anim.setAttribute("to", 0.5);
|
||||
anim.setAttribute("dur", 0.25);
|
||||
leg._path.appendChild(anim);
|
||||
anim.beginElement();
|
||||
}
|
||||
me.setOpacity(0.3);
|
||||
|
||||
//Set the opacity of the spiderLegs back to their correct value
|
||||
// The animations above override this until they complete.
|
||||
// If the initial opacity of the spiderlegs isn't 0 then they appear before the animation starts.
|
||||
if (L.Path.SVG) {
|
||||
this._group._forceLayout();
|
||||
|
||||
for (i = childMarkers.length - 1; i >= 0; i--) {
|
||||
m = childMarkers[i]._spiderLeg;
|
||||
|
||||
m.options.opacity = 0.5;
|
||||
m._path.setAttribute('stroke-opacity', 0.5);
|
||||
// Animate leg (animation is actually delegated to CSS transition).
|
||||
if (svg) {
|
||||
leg = m._spiderLeg;
|
||||
legPath = leg._path;
|
||||
legPath.style.strokeDashoffset = 0;
|
||||
//legPath.style.strokeOpacity = finalLegOpacity;
|
||||
leg.setStyle({opacity: finalLegOpacity});
|
||||
}
|
||||
}
|
||||
this.setOpacity(0.3);
|
||||
|
||||
group._ignoreMove = false;
|
||||
|
||||
setTimeout(function () {
|
||||
group._animationEnd();
|
||||
group.fire('spiderfied');
|
||||
group.fire('spiderfied', {
|
||||
cluster: me,
|
||||
markers: childMarkers
|
||||
});
|
||||
}, 200);
|
||||
},
|
||||
|
||||
_animationUnspiderfy: function (zoomDetails) {
|
||||
var group = this._group,
|
||||
var me = this,
|
||||
group = this._group,
|
||||
map = group._map,
|
||||
fg = group._featureGroup,
|
||||
thisLayerPos = zoomDetails ? map._latLngToNewLayerPoint(this._latlng, zoomDetails.zoom, zoomDetails.center) : map.latLngToLayerPoint(this._latlng),
|
||||
childMarkers = this.getAllChildMarkers(),
|
||||
svg = L.Path.SVG && this.SVG_ANIMATION,
|
||||
m, i, a;
|
||||
svg = L.Path.SVG,
|
||||
m, i, leg, legPath, legLength, nonAnimatable;
|
||||
|
||||
group._ignoreMove = true;
|
||||
group._animationStart();
|
||||
|
||||
//Make us visible and bring the child markers back in
|
||||
@@ -280,39 +302,44 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? {
|
||||
for (i = childMarkers.length - 1; i >= 0; i--) {
|
||||
m = childMarkers[i];
|
||||
|
||||
//Marker was added to us after we were spidified
|
||||
//Marker was added to us after we were spiderfied
|
||||
if (!m._preSpiderfyLatlng) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//Close any popup on the marker first, otherwise setting the location of the marker will make the map scroll
|
||||
m.closePopup();
|
||||
|
||||
//Fix up the location to the real one
|
||||
m.setLatLng(m._preSpiderfyLatlng);
|
||||
delete m._preSpiderfyLatlng;
|
||||
|
||||
//Hack override the location to be our center
|
||||
if (m.setOpacity) {
|
||||
nonAnimatable = true;
|
||||
if (m._setPos) {
|
||||
m._setPos(thisLayerPos);
|
||||
nonAnimatable = false;
|
||||
}
|
||||
if (m.clusterHide) {
|
||||
m.clusterHide();
|
||||
} else {
|
||||
nonAnimatable = false;
|
||||
}
|
||||
if (nonAnimatable) {
|
||||
fg.removeLayer(m);
|
||||
}
|
||||
|
||||
//Animate the spider legs back in
|
||||
// Animate the spider leg back in (animation is actually delegated to CSS transition).
|
||||
if (svg) {
|
||||
a = m._spiderLeg._path.childNodes[0];
|
||||
a.setAttribute('to', a.getAttribute('from'));
|
||||
a.setAttribute('from', 0);
|
||||
a.beginElement();
|
||||
|
||||
a = m._spiderLeg._path.childNodes[1];
|
||||
a.setAttribute('from', 0.5);
|
||||
a.setAttribute('to', 0);
|
||||
a.setAttribute('stroke-opacity', 0);
|
||||
a.beginElement();
|
||||
|
||||
m._spiderLeg._path.setAttribute('stroke-opacity', 0);
|
||||
leg = m._spiderLeg;
|
||||
legPath = leg._path;
|
||||
legLength = legPath.getTotalLength() + 0.1;
|
||||
legPath.style.strokeDashoffset = legLength;
|
||||
leg.setStyle({opacity: 0});
|
||||
}
|
||||
}
|
||||
|
||||
group._ignoreMove = false;
|
||||
|
||||
setTimeout(function () {
|
||||
//If we have only <= one child left then that marker will be shown on the map so don't remove it!
|
||||
var stillThereChildCount = 0;
|
||||
@@ -331,9 +358,10 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (m.setOpacity) {
|
||||
if (m.clusterShow) {
|
||||
m.clusterShow();
|
||||
}
|
||||
if (m.setZIndexOffset) {
|
||||
m.setZIndexOffset(0);
|
||||
}
|
||||
|
||||
@@ -345,6 +373,10 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? {
|
||||
delete m._spiderLeg;
|
||||
}
|
||||
group._animationEnd();
|
||||
group.fire('unspiderfied', {
|
||||
cluster: me,
|
||||
markers: childMarkers
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
@@ -354,6 +386,10 @@ L.MarkerClusterGroup.include({
|
||||
//The MarkerCluster currently spiderfied (if any)
|
||||
_spiderfied: null,
|
||||
|
||||
unspiderfy: function () {
|
||||
this._unspiderfy.apply(this, arguments);
|
||||
},
|
||||
|
||||
_spiderfierOnAdd: function () {
|
||||
this._map.on('click', this._unspiderfyWrapper, this);
|
||||
|
||||
@@ -363,8 +399,8 @@ L.MarkerClusterGroup.include({
|
||||
//Browsers without zoomAnimation or a big zoom don't fire zoomstart
|
||||
this._map.on('zoomend', this._noanimationUnspiderfy, this);
|
||||
|
||||
if (L.Path.SVG && !L.Browser.touch) {
|
||||
this._map._initPathRoot();
|
||||
if (!L.Browser.touch) {
|
||||
this._map.getRenderer(this);
|
||||
//Needs to happen in the pageload, not after, or animations don't work in webkit
|
||||
// http://stackoverflow.com/questions/8455200/svg-animate-with-dynamically-added-elements
|
||||
//Disable on touch browsers as the animation messes up on a touch zoom and isn't very noticable
|
||||
@@ -375,11 +411,13 @@ L.MarkerClusterGroup.include({
|
||||
this._map.off('click', this._unspiderfyWrapper, this);
|
||||
this._map.off('zoomstart', this._unspiderfyZoomStart, this);
|
||||
this._map.off('zoomanim', this._unspiderfyZoomAnim, this);
|
||||
this._map.off('zoomend', this._noanimationUnspiderfy, this);
|
||||
|
||||
this._unspiderfy(); //Ensure that markers are back where they should be
|
||||
//Ensure that markers are back where they should be
|
||||
// Use no animation to avoid a sticky leaflet-cluster-anim class on mapPane
|
||||
this._noanimationUnspiderfy();
|
||||
},
|
||||
|
||||
|
||||
//On zoom start we add a zoomanim handler so that we are guaranteed to be last (after markers are animated)
|
||||
//This means we can define the animation they do rather than Markers doing an animation to their actual location
|
||||
_unspiderfyZoomStart: function () {
|
||||
@@ -389,6 +427,7 @@ L.MarkerClusterGroup.include({
|
||||
|
||||
this._map.on('zoomanim', this._unspiderfyZoomAnim, this);
|
||||
},
|
||||
|
||||
_unspiderfyZoomAnim: function (zoomDetails) {
|
||||
//Wait until the first zoomanim after the user has finished touch-zooming before running the animation
|
||||
if (L.DomUtil.hasClass(this._map._mapPane, 'leaflet-touching')) {
|
||||
@@ -399,7 +438,6 @@ L.MarkerClusterGroup.include({
|
||||
this._unspiderfy(zoomDetails);
|
||||
},
|
||||
|
||||
|
||||
_unspiderfyWrapper: function () {
|
||||
/// <summary>_unspiderfy but passes no arguments</summary>
|
||||
this._unspiderfy();
|
||||
@@ -422,9 +460,13 @@ L.MarkerClusterGroup.include({
|
||||
if (layer._spiderLeg) {
|
||||
this._featureGroup.removeLayer(layer);
|
||||
|
||||
layer.setOpacity(1);
|
||||
//Position will be fixed up immediately in _animationUnspiderfy
|
||||
layer.setZIndexOffset(0);
|
||||
if (layer.clusterShow) {
|
||||
layer.clusterShow();
|
||||
}
|
||||
//Position will be fixed up immediately in _animationUnspiderfy
|
||||
if (layer.setZIndexOffset) {
|
||||
layer.setZIndexOffset(0);
|
||||
}
|
||||
|
||||
this._map.removeLayer(layer._spiderLeg);
|
||||
delete layer._spiderLeg;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
L.MarkerCluster = L.Marker.extend({
|
||||
initialize: function (group, zoom, a, b) {
|
||||
|
||||
L.Marker.prototype.initialize.call(this, a ? (a._cLatLng || a.getLatLng()) : new L.LatLng(0, 0), { icon: this });
|
||||
|
||||
L.Marker.prototype.initialize.call(this, a ? (a._cLatLng || a.getLatLng()) : new L.LatLng(0, 0),
|
||||
{ icon: this, pane: group.options.clusterPane });
|
||||
|
||||
this._group = group;
|
||||
this._zoom = zoom;
|
||||
@@ -11,6 +11,7 @@ L.MarkerCluster = L.Marker.extend({
|
||||
this._childClusters = [];
|
||||
this._childCount = 0;
|
||||
this._iconNeedsUpdate = true;
|
||||
this._boundsNeedUpdate = true;
|
||||
|
||||
this._bounds = new L.LatLngBounds();
|
||||
|
||||
@@ -43,7 +44,7 @@ L.MarkerCluster = L.Marker.extend({
|
||||
},
|
||||
|
||||
//Zoom to the minimum of showing all of the child markers, or the extents of this cluster
|
||||
zoomToBounds: function () {
|
||||
zoomToBounds: function (fitBoundsOptions) {
|
||||
var childClusters = this._childClusters.slice(),
|
||||
map = this._group._map,
|
||||
boundsZoom = map.getBoundsZoom(this._bounds),
|
||||
@@ -66,7 +67,7 @@ L.MarkerCluster = L.Marker.extend({
|
||||
} else if (boundsZoom <= mapZoom) { //If fitBounds wouldn't zoom us down, zoom us down instead
|
||||
this._group._map.setView(this._latlng, mapZoom + 1);
|
||||
} else {
|
||||
this._group._map.fitBounds(this._bounds);
|
||||
this._group._map.fitBounds(this._bounds, fitBoundsOptions);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -99,7 +100,9 @@ L.MarkerCluster = L.Marker.extend({
|
||||
_addChild: function (new1, isNotificationFromChild) {
|
||||
|
||||
this._iconNeedsUpdate = true;
|
||||
this._expandBounds(new1);
|
||||
|
||||
this._boundsNeedUpdate = true;
|
||||
this._setClusterCenter(new1);
|
||||
|
||||
if (new1 instanceof L.MarkerCluster) {
|
||||
if (!isNotificationFromChild) {
|
||||
@@ -119,34 +122,85 @@ L.MarkerCluster = L.Marker.extend({
|
||||
}
|
||||
},
|
||||
|
||||
//Expand our bounds and tell our parent to
|
||||
_expandBounds: function (marker) {
|
||||
var addedCount,
|
||||
addedLatLng = marker._wLatLng || marker._latlng;
|
||||
|
||||
if (marker instanceof L.MarkerCluster) {
|
||||
this._bounds.extend(marker._bounds);
|
||||
addedCount = marker._childCount;
|
||||
} else {
|
||||
this._bounds.extend(addedLatLng);
|
||||
addedCount = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the cluster center is set. If not, uses the child center if it is a cluster, or the marker position.
|
||||
* @param child L.MarkerCluster|L.Marker that will be used as cluster center if not defined yet.
|
||||
* @private
|
||||
*/
|
||||
_setClusterCenter: function (child) {
|
||||
if (!this._cLatLng) {
|
||||
// when clustering, take position of the first point as the cluster center
|
||||
this._cLatLng = marker._cLatLng || addedLatLng;
|
||||
this._cLatLng = child._cLatLng || child._latlng;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Assigns impossible bounding values so that the next extend entirely determines the new bounds.
|
||||
* This method avoids having to trash the previous L.LatLngBounds object and to create a new one, which is much slower for this class.
|
||||
* As long as the bounds are not extended, most other methods would probably fail, as they would with bounds initialized but not extended.
|
||||
* @private
|
||||
*/
|
||||
_resetBounds: function () {
|
||||
var bounds = this._bounds;
|
||||
|
||||
if (bounds._southWest) {
|
||||
bounds._southWest.lat = Infinity;
|
||||
bounds._southWest.lng = Infinity;
|
||||
}
|
||||
if (bounds._northEast) {
|
||||
bounds._northEast.lat = -Infinity;
|
||||
bounds._northEast.lng = -Infinity;
|
||||
}
|
||||
},
|
||||
|
||||
_recalculateBounds: function () {
|
||||
var markers = this._markers,
|
||||
childClusters = this._childClusters,
|
||||
latSum = 0,
|
||||
lngSum = 0,
|
||||
totalCount = this._childCount,
|
||||
i, child, childLatLng, childCount;
|
||||
|
||||
// Case where all markers are removed from the map and we are left with just an empty _topClusterLevel.
|
||||
if (totalCount === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// when showing clusters, take weighted average of all points as cluster center
|
||||
var totalCount = this._childCount + addedCount;
|
||||
// Reset rather than creating a new object, for performance.
|
||||
this._resetBounds();
|
||||
|
||||
//Calculate weighted latlng for display
|
||||
if (!this._wLatLng) {
|
||||
this._latlng = this._wLatLng = new L.LatLng(addedLatLng.lat, addedLatLng.lng);
|
||||
} else {
|
||||
this._wLatLng.lat = (addedLatLng.lat * addedCount + this._wLatLng.lat * this._childCount) / totalCount;
|
||||
this._wLatLng.lng = (addedLatLng.lng * addedCount + this._wLatLng.lng * this._childCount) / totalCount;
|
||||
// Child markers.
|
||||
for (i = 0; i < markers.length; i++) {
|
||||
childLatLng = markers[i]._latlng;
|
||||
|
||||
this._bounds.extend(childLatLng);
|
||||
|
||||
latSum += childLatLng.lat;
|
||||
lngSum += childLatLng.lng;
|
||||
}
|
||||
|
||||
// Child clusters.
|
||||
for (i = 0; i < childClusters.length; i++) {
|
||||
child = childClusters[i];
|
||||
|
||||
// Re-compute child bounds and weighted position first if necessary.
|
||||
if (child._boundsNeedUpdate) {
|
||||
child._recalculateBounds();
|
||||
}
|
||||
|
||||
this._bounds.extend(child._bounds);
|
||||
|
||||
childLatLng = child._wLatLng;
|
||||
childCount = child._childCount;
|
||||
|
||||
latSum += childLatLng.lat * childCount;
|
||||
lngSum += childLatLng.lng * childCount;
|
||||
}
|
||||
|
||||
this._latlng = this._wLatLng = new L.LatLng(latSum / totalCount, lngSum / totalCount);
|
||||
|
||||
// Reset dirty flag.
|
||||
this._boundsNeedUpdate = false;
|
||||
},
|
||||
|
||||
//Set our markers position as given and add it to the map
|
||||
@@ -159,7 +213,7 @@ L.MarkerCluster = L.Marker.extend({
|
||||
},
|
||||
|
||||
_recursivelyAnimateChildrenIn: function (bounds, center, maxZoom) {
|
||||
this._recursively(bounds, 0, maxZoom - 1,
|
||||
this._recursively(bounds, this._group._map.getMinZoom(), maxZoom - 1,
|
||||
function (c) {
|
||||
var markers = c._markers,
|
||||
i, m;
|
||||
@@ -187,8 +241,8 @@ L.MarkerCluster = L.Marker.extend({
|
||||
);
|
||||
},
|
||||
|
||||
_recursivelyAnimateChildrenInAndAddSelfToMap: function (bounds, previousZoomLevel, newZoomLevel) {
|
||||
this._recursively(bounds, newZoomLevel, 0,
|
||||
_recursivelyAnimateChildrenInAndAddSelfToMap: function (bounds, mapMinZoom, previousZoomLevel, newZoomLevel) {
|
||||
this._recursively(bounds, newZoomLevel, mapMinZoom,
|
||||
function (c) {
|
||||
c._recursivelyAnimateChildrenIn(bounds, c._group._map.latLngToLayerPoint(c.getLatLng()).round(), previousZoomLevel);
|
||||
|
||||
@@ -196,7 +250,7 @@ L.MarkerCluster = L.Marker.extend({
|
||||
//As a hack we only do a animation free zoom on a single level zoom, if someone does multiple levels then we always animate
|
||||
if (c._isSingleParent() && previousZoomLevel - 1 === newZoomLevel) {
|
||||
c.clusterShow();
|
||||
c._recursivelyRemoveChildrenFromMap(bounds, previousZoomLevel); //Immediately remove our children as we are replacing them. TODO previousBounds not bounds
|
||||
c._recursivelyRemoveChildrenFromMap(bounds, mapMinZoom, previousZoomLevel); //Immediately remove our children as we are replacing them. TODO previousBounds not bounds
|
||||
} else {
|
||||
c.clusterHide();
|
||||
}
|
||||
@@ -207,13 +261,13 @@ L.MarkerCluster = L.Marker.extend({
|
||||
},
|
||||
|
||||
_recursivelyBecomeVisible: function (bounds, zoomLevel) {
|
||||
this._recursively(bounds, 0, zoomLevel, null, function (c) {
|
||||
this._recursively(bounds, this._group._map.getMinZoom(), zoomLevel, null, function (c) {
|
||||
c.clusterShow();
|
||||
});
|
||||
},
|
||||
|
||||
_recursivelyAddChildrenToMap: function (startPos, zoomLevel, bounds) {
|
||||
this._recursively(bounds, -1, zoomLevel,
|
||||
this._recursively(bounds, this._group._map.getMinZoom() - 1, zoomLevel,
|
||||
function (c) {
|
||||
if (zoomLevel === c._zoom) {
|
||||
return;
|
||||
@@ -275,9 +329,9 @@ L.MarkerCluster = L.Marker.extend({
|
||||
},
|
||||
|
||||
//exceptBounds: If set, don't remove any markers/clusters in it
|
||||
_recursivelyRemoveChildrenFromMap: function (previousBounds, zoomLevel, exceptBounds) {
|
||||
_recursivelyRemoveChildrenFromMap: function (previousBounds, mapMinZoom, zoomLevel, exceptBounds) {
|
||||
var m, i;
|
||||
this._recursively(previousBounds, -1, zoomLevel - 1,
|
||||
this._recursively(previousBounds, mapMinZoom - 1, zoomLevel - 1,
|
||||
function (c) {
|
||||
//Remove markers at every level
|
||||
for (i = c._markers.length - 1; i >= 0; i--) {
|
||||
@@ -316,51 +370,25 @@ L.MarkerCluster = L.Marker.extend({
|
||||
zoom = this._zoom,
|
||||
i, c;
|
||||
|
||||
if (zoomLevelToStart > zoom) { //Still going down to required depth, just recurse to child clusters
|
||||
if (zoomLevelToStart <= zoom) {
|
||||
if (runAtEveryLevel) {
|
||||
runAtEveryLevel(this);
|
||||
}
|
||||
if (runAtBottomLevel && zoom === zoomLevelToStop) {
|
||||
runAtBottomLevel(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (zoom < zoomLevelToStart || zoom < zoomLevelToStop) {
|
||||
for (i = childClusters.length - 1; i >= 0; i--) {
|
||||
c = childClusters[i];
|
||||
if (boundsToApplyTo.intersects(c._bounds)) {
|
||||
c._recursively(boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel);
|
||||
}
|
||||
}
|
||||
} else { //In required depth
|
||||
|
||||
if (runAtEveryLevel) {
|
||||
runAtEveryLevel(this);
|
||||
}
|
||||
if (runAtBottomLevel && this._zoom === zoomLevelToStop) {
|
||||
runAtBottomLevel(this);
|
||||
}
|
||||
|
||||
//TODO: This loop is almost the same as above
|
||||
if (zoomLevelToStop > zoom) {
|
||||
for (i = childClusters.length - 1; i >= 0; i--) {
|
||||
c = childClusters[i];
|
||||
if (boundsToApplyTo.intersects(c._bounds)) {
|
||||
c._recursively(boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_recalculateBounds: function () {
|
||||
var markers = this._markers,
|
||||
childClusters = this._childClusters,
|
||||
i;
|
||||
|
||||
this._bounds = new L.LatLngBounds();
|
||||
delete this._wLatLng;
|
||||
|
||||
for (i = markers.length - 1; i >= 0; i--) {
|
||||
this._expandBounds(markers[i]);
|
||||
}
|
||||
for (i = childClusters.length - 1; i >= 0; i--) {
|
||||
this._expandBounds(childClusters[i]);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
//Returns true if we are the parent of only one cluster and that cluster is the same as us
|
||||
_isSingleParent: function () {
|
||||
//Don't need to check this._markers as the rest won't work if there are any
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Adds 1 public method to MCG and 1 to L.Marker to facilitate changing
|
||||
* markers' icon options and refreshing their icon and their parent clusters
|
||||
* accordingly (case where their iconCreateFunction uses data of childMarkers
|
||||
* to make up the cluster icon).
|
||||
*/
|
||||
|
||||
|
||||
L.MarkerClusterGroup.include({
|
||||
/**
|
||||
* Updates the icon of all clusters which are parents of the given marker(s).
|
||||
* In singleMarkerMode, also updates the given marker(s) icon.
|
||||
* @param layers L.MarkerClusterGroup|L.LayerGroup|Array(L.Marker)|Map(L.Marker)|
|
||||
* L.MarkerCluster|L.Marker (optional) list of markers (or single marker) whose parent
|
||||
* clusters need to be updated. If not provided, retrieves all child markers of this.
|
||||
* @returns {L.MarkerClusterGroup}
|
||||
*/
|
||||
refreshClusters: function (layers) {
|
||||
if (!layers) {
|
||||
layers = this._topClusterLevel.getAllChildMarkers();
|
||||
} else if (layers instanceof L.MarkerClusterGroup) {
|
||||
layers = layers._topClusterLevel.getAllChildMarkers();
|
||||
} else if (layers instanceof L.LayerGroup) {
|
||||
layers = layers._layers;
|
||||
} else if (layers instanceof L.MarkerCluster) {
|
||||
layers = layers.getAllChildMarkers();
|
||||
} else if (layers instanceof L.Marker) {
|
||||
layers = [layers];
|
||||
} // else: must be an Array(L.Marker)|Map(L.Marker)
|
||||
this._flagParentsIconsNeedUpdate(layers);
|
||||
this._refreshClustersIcons();
|
||||
|
||||
// In case of singleMarkerMode, also re-draw the markers.
|
||||
if (this.options.singleMarkerMode) {
|
||||
this._refreshSingleMarkerModeMarkers(layers);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Simply flags all parent clusters of the given markers as having a "dirty" icon.
|
||||
* @param layers Array(L.Marker)|Map(L.Marker) list of markers.
|
||||
* @private
|
||||
*/
|
||||
_flagParentsIconsNeedUpdate: function (layers) {
|
||||
var id, parent;
|
||||
|
||||
// Assumes layers is an Array or an Object whose prototype is non-enumerable.
|
||||
for (id in layers) {
|
||||
// Flag parent clusters' icon as "dirty", all the way up.
|
||||
// Dumb process that flags multiple times upper parents, but still
|
||||
// much more efficient than trying to be smart and make short lists,
|
||||
// at least in the case of a hierarchy following a power law:
|
||||
// http://jsperf.com/flag-nodes-in-power-hierarchy/2
|
||||
parent = layers[id].__parent;
|
||||
while (parent) {
|
||||
parent._iconNeedsUpdate = true;
|
||||
parent = parent.__parent;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Re-draws the icon of the supplied markers.
|
||||
* To be used in singleMarkerMode only.
|
||||
* @param layers Array(L.Marker)|Map(L.Marker) list of markers.
|
||||
* @private
|
||||
*/
|
||||
_refreshSingleMarkerModeMarkers: function (layers) {
|
||||
var id, layer;
|
||||
|
||||
for (id in layers) {
|
||||
layer = layers[id];
|
||||
|
||||
// Make sure we do not override markers that do not belong to THIS group.
|
||||
if (this.hasLayer(layer)) {
|
||||
// Need to re-create the icon first, then re-draw the marker.
|
||||
layer.setIcon(this._overrideMarkerIcon(layer));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
L.Marker.include({
|
||||
/**
|
||||
* Updates the given options in the marker's icon and refreshes the marker.
|
||||
* @param options map object of icon options.
|
||||
* @param directlyRefreshClusters boolean (optional) true to trigger
|
||||
* MCG.refreshClustersOf() right away with this single marker.
|
||||
* @returns {L.Marker}
|
||||
*/
|
||||
refreshIconOptions: function (options, directlyRefreshClusters) {
|
||||
var icon = this.options.icon;
|
||||
|
||||
L.setOptions(icon, options);
|
||||
|
||||
this.setIcon(icon);
|
||||
|
||||
// Shortcut to refresh the associated MCG clusters right away.
|
||||
// To be used when refreshing a single marker.
|
||||
// Otherwise, better use MCG.refreshClusters() once at the end with
|
||||
// the list of modified markers.
|
||||
if (directlyRefreshClusters && this.__parent) {
|
||||
this.__parent._group.refreshClusters(this);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Leaflet.markercluster, Provides Beautiful Animated Marker Clustering functionality for Leaflet, a JS library for interactive maps.
|
||||
https://github.com/Leaflet/Leaflet.markercluster
|
||||
(c) 2012-2013, Dave Leaver, smartrak
|
||||
(c) 2012-2017, Dave Leaver
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user