├── LICENSE ├── README.md ├── index.html └── libs ├── img ├── feed-icon-14x14.png ├── filter-icon.png ├── move-handle.png └── resize-handle.png ├── locationfilter.css └── locationfilter.js /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2013 Martin Raifer 2 | This work is free. You can redistribute it and/or modify it under the 3 | terms of the Do What The Fuck You Want To Public License, Version 2. 4 | See http://www.wtfpl.net/ for more details. 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [osm-qa-feeds](https://tyrasd.github.io/osm-qa-feeds/) 2 | ============ 3 | 4 | A tool to create customized OpenStreetMap quality assurance feeds. 5 | 6 | Currently supported feed providers: 7 | * [OSM notes](http://wiki.openstreetmap.org/wiki/Notes) 8 | * [whodidit](http://wiki.openstreetmap.org/wiki/Quality_assurance#WhoDidIt) 9 | * [newestosm](http://neis-one.org/2012/07/new-contributor-feed/) 10 | * [KeepRight!](http://wiki.openstreetmap.org/wiki/Keepright) 11 | * [Osmose QA](http://wiki.openstreetmap.org/wiki/Osmose) 12 | * [(GB only) OS Locator Musical Chairs](http://wiki.openstreetmap.org/wiki/OS_Locator_Musical_Chairs) 13 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | osm qa feeds 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 69 | 70 | 71 |
72 | 73 |
Get a list of OpenStreetMap quality assurance feeds for an area of your choice.
74 | 75 | 80 | 84 | 90 | 91 | 278 | 279 | 280 | -------------------------------------------------------------------------------- /libs/img/feed-icon-14x14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrasd/osm-qa-feeds/22d71ccf0a0b7df59d5bfedd5b7862e4df6defb1/libs/img/feed-icon-14x14.png -------------------------------------------------------------------------------- /libs/img/filter-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrasd/osm-qa-feeds/22d71ccf0a0b7df59d5bfedd5b7862e4df6defb1/libs/img/filter-icon.png -------------------------------------------------------------------------------- /libs/img/move-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrasd/osm-qa-feeds/22d71ccf0a0b7df59d5bfedd5b7862e4df6defb1/libs/img/move-handle.png -------------------------------------------------------------------------------- /libs/img/resize-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tyrasd/osm-qa-feeds/22d71ccf0a0b7df59d5bfedd5b7862e4df6defb1/libs/img/resize-handle.png -------------------------------------------------------------------------------- /libs/locationfilter.css: -------------------------------------------------------------------------------- 1 | div.leaflet-marker-icon.location-filter.resize-marker { 2 | background: url( img/resize-handle.png ) no-repeat; 3 | cursor: move; 4 | } 5 | div.leaflet-marker-icon.location-filter.move-marker { 6 | background: url( img/move-handle.png ) no-repeat; 7 | cursor: move; 8 | } 9 | 10 | div.location-filter.button-container { 11 | background: #bfbfbf; 12 | background: rgba(0, 0, 0, 0.25); 13 | -moz-border-radius: 7px; 14 | -webkit-border-radius: 7px; 15 | border-radius: 7px; 16 | padding: 5px; 17 | } 18 | .leaflet-container div.location-filter.button-container a { 19 | display: inline-block; 20 | color: #0F2416; 21 | font-size: 11px; 22 | font-weight: normal; 23 | text-shadow: #A1BB9C 0 1px; 24 | padding: 6px 7px; 25 | border: 1px solid #9CC5A4; 26 | -moz-border-radius: 3px; 27 | -webkit-border-radius: 3px; 28 | border-radius: 3px; 29 | -webkit-box-shadow: inset rgba(255,255,255,0.75) 0 1px 1px; 30 | -moz-box-shadow: inset rgba(255,255,255,0.75) 0 1px 1px; 31 | box-shadow: inset rgba(255,255,255,0.75) 0 1px 1px; 32 | background: #c4e3b9; 33 | background: rgba(218, 252, 205, 0.9); 34 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(218, 252, 205, 0.9)), color-stop(100%, rgba(173, 226, 176, 0.9))); 35 | background: -webkit-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); 36 | background: -moz-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); 37 | background: -ms-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); 38 | background: -o-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); 39 | background: linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); 40 | } 41 | .leaflet-container div.location-filter.button-container a:hover { 42 | color: #263F1C; 43 | background: #dde6d8; 44 | background: rgba(245, 255, 240, 0.9); 45 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(245, 255, 240, 0.9)), color-stop(100%, rgba(203, 228, 205, 0.9))); 46 | background: -webkit-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); 47 | background: -moz-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); 48 | background: -ms-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); 49 | background: -o-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); 50 | background: linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); 51 | } 52 | 53 | .leaflet-container div.location-filter.button-container a.enable-button { 54 | padding: 6px 7px 6px 25px; 55 | background-image: url( img/filter-icon.png ), -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(218, 252, 205, 0.9)), color-stop(100%, rgba(173, 226, 176, 0.9))); 56 | background-image: url( img/filter-icon.png ), -webkit-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); 57 | background-image: url( img/filter-icon.png ), -moz-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); 58 | background-image: url( img/filter-icon.png ), -ms-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); 59 | background-image: url( img/filter-icon.png ), -o-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); 60 | background-image: url( img/filter-icon.png ), linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%); 61 | background-repeat: no-repeat; 62 | background-position: left center; 63 | } 64 | .leaflet-container div.location-filter.button-container a.enable-button:hover, 65 | .leaflet-container div.location-filter.button-container.enabled a.enable-button { 66 | background-image: url( img/filter-icon.png ), -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(245, 255, 240, 0.9)), color-stop(100%, rgba(203, 228, 205, 0.9))); 67 | background-image: url( img/filter-icon.png ), -webkit-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); 68 | background-image: url( img/filter-icon.png ), -moz-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); 69 | background-image: url( img/filter-icon.png ), -ms-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); 70 | background-image: url( img/filter-icon.png ), -o-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); 71 | background-image: url( img/filter-icon.png ), linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%); 72 | background-repeat: no-repeat; 73 | background-position: left center; 74 | } 75 | 76 | .leaflet-container div.location-filter.button-container a.adjust-button { 77 | margin-left: 2px; 78 | } 79 | -------------------------------------------------------------------------------- /libs/locationfilter.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Leaflet.locationfilter - leaflet location filter plugin 3 | * Copyright (C) 2012, Tripbirds.com 4 | * http://tripbirds.com 5 | * 6 | * Licensed under the MIT License. 7 | * 8 | * Date: 2012-09-24 9 | * Version: 0.1 10 | */ 11 | L.LatLngBounds.prototype.modify = function(map, amount) { 12 | var sw = this.getSouthWest(), 13 | ne = this.getNorthEast(), 14 | swPoint = map.latLngToLayerPoint(sw), 15 | nePoint = map.latLngToLayerPoint(ne); 16 | 17 | sw = map.layerPointToLatLng(new L.Point(swPoint.x-amount, swPoint.y+amount)); 18 | ne = map.layerPointToLatLng(new L.Point(nePoint.x+amount, nePoint.y-amount)); 19 | 20 | return new L.LatLngBounds(sw, ne); 21 | }; 22 | 23 | L.Control.Button = L.Class.extend({ 24 | initialize: function(options) { 25 | L.Util.setOptions(this, options); 26 | }, 27 | 28 | addTo: function(container) { 29 | container.addButton(this); 30 | return this; 31 | }, 32 | 33 | onAdd: function (buttonContainer) { 34 | this._buttonContainer = buttonContainer; 35 | this._button = L.DomUtil.create('a', this.options.className, this._buttonContainer.getContainer()); 36 | this._button.href = '#'; 37 | this.setText(this.options.text); 38 | 39 | var that = this; 40 | this._onClick = function(event) { 41 | that.options.onClick.call(that, event); 42 | }; 43 | 44 | L.DomEvent 45 | .on(this._button, 'click', L.DomEvent.stopPropagation) 46 | .on(this._button, 'mousedown', L.DomEvent.stopPropagation) 47 | .on(this._button, 'dblclick', L.DomEvent.stopPropagation) 48 | .on(this._button, 'click', L.DomEvent.preventDefault) 49 | .on(this._button, 'click', this._onClick, this); 50 | }, 51 | 52 | remove: function() { 53 | L.DomEvent.off(this._button, "click", this._onClick); 54 | this._buttonContainer.getContainer().removeChild(this._button); 55 | }, 56 | 57 | setText: function(text) { 58 | this._button.title = text; 59 | this._button.innerHTML = text; 60 | } 61 | }); 62 | 63 | L.Control.ButtonContainer = L.Control.extend({ 64 | options: { 65 | position: 'topleft' 66 | }, 67 | 68 | getContainer: function() { 69 | if (!this._container) { 70 | this._container = L.DomUtil.create('div', this.options.className); 71 | } 72 | return this._container; 73 | }, 74 | 75 | onAdd: function (map) { 76 | this._map = map; 77 | return this.getContainer(); 78 | }, 79 | 80 | addButton: function(button) { 81 | button.onAdd(this); 82 | }, 83 | 84 | addClass: function(className) { 85 | L.DomUtil.addClass(this.getContainer(), className); 86 | }, 87 | 88 | removeClass: function(className) { 89 | L.DomUtil.removeClass(this.getContainer(), className); 90 | } 91 | }); 92 | 93 | L.LocationFilter = L.Class.extend({ 94 | includes: L.Mixin.Events, 95 | 96 | options: { 97 | enableButton: { 98 | enableText: "Select area", 99 | disableText: "Remove selection" 100 | }, 101 | adjustButton: { 102 | text: "Select area within current zoom" 103 | } 104 | }, 105 | 106 | initialize: function(options) { 107 | L.Util.setOptions(this, options); 108 | }, 109 | 110 | addTo: function(map) { 111 | map.addLayer(this); 112 | return this; 113 | }, 114 | 115 | onAdd: function(map) { 116 | this._map = map; 117 | this._layer = new L.LayerGroup(); 118 | 119 | if (this.options.enableButton || this.options.adjustButton) { 120 | this._initializeButtonContainer(); 121 | } 122 | 123 | if (this.options.enable) { 124 | this.enable(); 125 | } 126 | }, 127 | 128 | onRemove: function(map) { 129 | this.disable(); 130 | if (this._buttonContainer) { 131 | this._buttonContainer.removeFrom(map); 132 | } 133 | }, 134 | 135 | /* Get the current filter bounds */ 136 | getBounds: function() { 137 | return new L.LatLngBounds(this._sw, this._ne); 138 | }, 139 | 140 | setBounds: function(bounds) { 141 | this._nw = bounds.getNorthWest(); 142 | this._ne = bounds.getNorthEast(); 143 | this._sw = bounds.getSouthWest(); 144 | this._se = bounds.getSouthEast(); 145 | if (this.isEnabled()) { 146 | this._draw(); 147 | this.fire("change", {bounds: bounds}); 148 | } 149 | }, 150 | 151 | isEnabled: function() { 152 | return this._enabled; 153 | }, 154 | 155 | /* Draw a rectangle */ 156 | _drawRectangle: function(bounds, options) { 157 | options = options || {}; 158 | var defaultOptions = { 159 | stroke: false, 160 | fill: true, 161 | fillColor: "black", 162 | fillOpacity: 0.3, 163 | clickable: false 164 | }; 165 | options = L.Util.extend(defaultOptions, options); 166 | var rect = new L.Rectangle(bounds, options); 167 | rect.addTo(this._layer); 168 | return rect; 169 | }, 170 | 171 | /* Draw a draggable marker */ 172 | _drawImageMarker: function(point, options) { 173 | var marker = new L.Marker(point, { 174 | icon: new L.DivIcon({ 175 | iconAnchor: options.anchor, 176 | iconSize: options.size, 177 | className: options.className 178 | }), 179 | draggable: true 180 | }); 181 | marker.addTo(this._layer); 182 | return marker; 183 | }, 184 | 185 | /* Draw a move marker. Sets up drag listener that updates the 186 | filter corners and redraws the filter when the move marker is 187 | moved */ 188 | _drawMoveMarker: function(point) { 189 | var that = this; 190 | this._moveMarker = this._drawImageMarker(point, { 191 | "className": "location-filter move-marker", 192 | "anchor": [-10, -10], 193 | "size": [13,13] 194 | }); 195 | this._moveMarker.on('drag', function(e) { 196 | var markerPos = that._moveMarker.getLatLng(), 197 | latDelta = markerPos.lat-that._nw.lat, 198 | lngDelta = markerPos.lng-that._nw.lng; 199 | that._nw = new L.LatLng(that._nw.lat+latDelta, that._nw.lng+lngDelta, true); 200 | that._ne = new L.LatLng(that._ne.lat+latDelta, that._ne.lng+lngDelta, true); 201 | that._sw = new L.LatLng(that._sw.lat+latDelta, that._sw.lng+lngDelta, true); 202 | that._se = new L.LatLng(that._se.lat+latDelta, that._se.lng+lngDelta, true); 203 | that._draw(); 204 | }); 205 | this._setupDragendListener(this._moveMarker); 206 | return this._moveMarker; 207 | }, 208 | 209 | /* Draw a resize marker */ 210 | _drawResizeMarker: function(point, latFollower, lngFollower, otherPos) { 211 | return this._drawImageMarker(point, { 212 | "className": "location-filter resize-marker", 213 | "anchor": [7, 6], 214 | "size": [13, 12] 215 | }); 216 | }, 217 | 218 | /* Track moving of the given resize marker and update the markers 219 | given in options.moveAlong to match the position of the moved 220 | marker. Update filter corners and redraw the filter */ 221 | _setupResizeMarkerTracking: function(marker, options) { 222 | var that = this; 223 | marker.on('drag', function(e) { 224 | var curPosition = marker.getLatLng(), 225 | latMarker = options.moveAlong.lat, 226 | lngMarker = options.moveAlong.lng; 227 | // Move follower markers when this marker is moved 228 | latMarker.setLatLng(new L.LatLng(curPosition.lat, latMarker.getLatLng().lng, true)); 229 | lngMarker.setLatLng(new L.LatLng(lngMarker.getLatLng().lat, curPosition.lng, true)); 230 | // Sort marker positions in nw, ne, sw, se order 231 | var corners = [that._nwMarker.getLatLng(), 232 | that._neMarker.getLatLng(), 233 | that._swMarker.getLatLng(), 234 | that._seMarker.getLatLng()]; 235 | corners.sort(function(a, b) { 236 | if (a.lat != b.lat) 237 | return b.lat-a.lat; 238 | else 239 | return a.lng-b.lng; 240 | }); 241 | // Update corner points and redraw everything except the resize markers 242 | that._nw = corners[0]; 243 | that._ne = corners[1]; 244 | that._sw = corners[2]; 245 | that._se = corners[3]; 246 | that._draw({repositionResizeMarkers: false}); 247 | }); 248 | this._setupDragendListener(marker); 249 | }, 250 | 251 | /* Emit a change event whenever dragend is triggered on the 252 | given marker */ 253 | _setupDragendListener: function(marker) { 254 | var that = this; 255 | marker.on('dragend', function(e) { 256 | that.fire("change", {bounds: that.getBounds()}); 257 | }); 258 | }, 259 | 260 | /* Create bounds for the mask rectangles and the location 261 | filter rectangle */ 262 | _calculateBounds: function() { 263 | var mapBounds = this._map.getBounds(), 264 | outerBounds = new L.LatLngBounds( 265 | new L.LatLng(mapBounds.getSouthWest().lat-0.1, 266 | mapBounds.getSouthWest().lng-0.1, true), 267 | new L.LatLng(mapBounds.getNorthEast().lat+0.1, 268 | mapBounds.getNorthEast().lng+0.1, true) 269 | ); 270 | 271 | // The south west and north east points of the mask */ 272 | this._osw = outerBounds.getSouthWest(); 273 | this._one = outerBounds.getNorthEast(); 274 | 275 | // Bounds for the mask rectangles 276 | this._northBounds = new L.LatLngBounds(new L.LatLng(this._ne.lat, this._osw.lng, true), this._one); 277 | this._westBounds = new L.LatLngBounds(new L.LatLng(this._sw.lat, this._osw.lng, true), this._nw); 278 | this._eastBounds = new L.LatLngBounds(this._se, new L.LatLng(this._ne.lat, this._one.lng, true)); 279 | this._southBounds = new L.LatLngBounds(this._osw, new L.LatLng(this._sw.lat, this._one.lng, true)); 280 | }, 281 | 282 | /* Initializes rectangles and markers */ 283 | _initialDraw: function() { 284 | if (this._initialDrawCalled) { 285 | return; 286 | } 287 | 288 | // Calculate filter bounds 289 | this._calculateBounds(); 290 | 291 | // Create rectangles 292 | this._northRect = this._drawRectangle(this._northBounds); 293 | this._westRect = this._drawRectangle(this._westBounds); 294 | this._eastRect = this._drawRectangle(this._eastBounds); 295 | this._southRect = this._drawRectangle(this._southBounds); 296 | this._innerRect = this._drawRectangle(this.getBounds(), { 297 | fillOpacity: 0, 298 | stroke: true, 299 | color: "white", 300 | weight: 1, 301 | opacity: 0.9 302 | }); 303 | 304 | // Create resize markers 305 | this._nwMarker = this._drawResizeMarker(this._nw); 306 | this._neMarker = this._drawResizeMarker(this._ne); 307 | this._swMarker = this._drawResizeMarker(this._sw); 308 | this._seMarker = this._drawResizeMarker(this._se); 309 | 310 | // Setup tracking of resize markers. Each marker has pair of 311 | // follower markers that must be moved whenever the marker is 312 | // moved. For example, whenever the north west resize marker 313 | // moves, the south west marker must move along on the x-axis 314 | // and the north east marker must move on the y axis 315 | this._setupResizeMarkerTracking(this._nwMarker, {moveAlong: {lat: this._neMarker, lng: this._swMarker}}); 316 | this._setupResizeMarkerTracking(this._neMarker, {moveAlong: {lat: this._nwMarker, lng: this._seMarker}}); 317 | this._setupResizeMarkerTracking(this._swMarker, {moveAlong: {lat: this._seMarker, lng: this._nwMarker}}); 318 | this._setupResizeMarkerTracking(this._seMarker, {moveAlong: {lat: this._swMarker, lng: this._neMarker}}); 319 | 320 | // Create move marker 321 | this._moveMarker = this._drawMoveMarker(this._nw); 322 | 323 | this._initialDrawCalled = true; 324 | }, 325 | 326 | /* Reposition all rectangles and markers to the current filter bounds. */ 327 | _draw: function(options) { 328 | options = L.Util.extend({repositionResizeMarkers: true}, options); 329 | 330 | // Calculate filter bounds 331 | this._calculateBounds(); 332 | 333 | // Reposition rectangles 334 | this._northRect.setBounds(this._northBounds); 335 | this._westRect.setBounds(this._westBounds); 336 | this._eastRect.setBounds(this._eastBounds); 337 | this._southRect.setBounds(this._southBounds); 338 | this._innerRect.setBounds(this.getBounds()); 339 | 340 | // Reposition resize markers 341 | if (options.repositionResizeMarkers) { 342 | this._nwMarker.setLatLng(this._nw); 343 | this._neMarker.setLatLng(this._ne); 344 | this._swMarker.setLatLng(this._sw); 345 | this._seMarker.setLatLng(this._se); 346 | } 347 | 348 | // Reposition the move marker 349 | this._moveMarker.setLatLng(this._nw); 350 | }, 351 | 352 | /* Adjust the location filter to the current map bounds */ 353 | _adjustToMap: function() { 354 | this.setBounds(this._map.getBounds()); 355 | this._map.zoomOut(); 356 | }, 357 | 358 | /* Enable the location filter */ 359 | enable: function() { 360 | if (this._enabled) { 361 | return; 362 | } 363 | 364 | // Initialize corners 365 | var bounds; 366 | if (this._sw && this._ne) { 367 | bounds = new L.LatLngBounds(this._sw, this._ne); 368 | } else if (this.options.bounds) { 369 | bounds = this.options.bounds; 370 | } else { 371 | bounds = this._map.getBounds(); 372 | } 373 | this._map.invalidateSize(); 374 | this._nw = bounds.getNorthWest(); 375 | this._ne = bounds.getNorthEast(); 376 | this._sw = bounds.getSouthWest(); 377 | this._se = bounds.getSouthEast(); 378 | 379 | 380 | // Update buttons 381 | if (this._buttonContainer) { 382 | this._buttonContainer.addClass("enabled"); 383 | } 384 | 385 | if (this._enableButton) { 386 | this._enableButton.setText(this.options.enableButton.disableText); 387 | } 388 | 389 | if (this.options.adjustButton) { 390 | this._createAdjustButton(); 391 | } 392 | 393 | // Draw filter 394 | this._initialDraw(); 395 | this._draw(); 396 | 397 | // Set up map move event listener 398 | var that = this; 399 | this._moveHandler = function() { 400 | that._draw(); 401 | }; 402 | this._map.on("move", this._moveHandler); 403 | 404 | // Add the filter layer to the map 405 | this._layer.addTo(this._map); 406 | 407 | // Zoom out the map if necessary 408 | var mapBounds = this._map.getBounds(); 409 | bounds = new L.LatLngBounds(this._sw, this._ne).modify(this._map, 10); 410 | if (!mapBounds.contains(bounds.getSouthWest()) || !mapBounds.contains(bounds.getNorthEast())) { 411 | this._map.fitBounds(bounds); 412 | } 413 | 414 | this._enabled = true; 415 | 416 | // Fire the enabled event 417 | this.fire("enabled"); 418 | }, 419 | 420 | /* Disable the location filter */ 421 | disable: function() { 422 | if (!this._enabled) { 423 | return; 424 | } 425 | 426 | // Update buttons 427 | if (this._buttonContainer) { 428 | this._buttonContainer.removeClass("enabled"); 429 | } 430 | 431 | if (this._enableButton) { 432 | this._enableButton.setText(this.options.enableButton.enableText); 433 | } 434 | 435 | if (this._adjustButton) { 436 | this._adjustButton.remove(); 437 | } 438 | 439 | // Remove event listener 440 | this._map.off("move", this._moveHandler); 441 | 442 | // Remove rectangle layer from map 443 | this._map.removeLayer(this._layer); 444 | 445 | this._enabled = false; 446 | 447 | // Fire the disabled event 448 | this.fire("disabled"); 449 | }, 450 | 451 | /* Create a button that allows the user to adjust the location 452 | filter to the current zoom */ 453 | _createAdjustButton: function() { 454 | var that = this; 455 | this._adjustButton = new L.Control.Button({ 456 | className: "adjust-button", 457 | text: this.options.adjustButton.text, 458 | 459 | onClick: function(event) { 460 | that._adjustToMap(); 461 | that.fire("adjustToZoomClick"); 462 | } 463 | }).addTo(this._buttonContainer); 464 | }, 465 | 466 | /* Create the location filter button container and the button that 467 | toggles the location filter */ 468 | _initializeButtonContainer: function() { 469 | var that = this; 470 | this._buttonContainer = new L.Control.ButtonContainer({className: "location-filter button-container"}); 471 | 472 | if (this.options.enableButton) { 473 | this._enableButton = new L.Control.Button({ 474 | className: "enable-button", 475 | text: this.options.enableButton.enableText, 476 | 477 | onClick: function(event) { 478 | if (!that._enabled) { 479 | // Enable the location filter 480 | that.enable(); 481 | that.fire("enableClick"); 482 | } else { 483 | // Disable the location filter 484 | that.disable(); 485 | that.fire("disableClick"); 486 | } 487 | } 488 | }).addTo(this._buttonContainer); 489 | } 490 | 491 | this._buttonContainer.addTo(this._map); 492 | } 493 | }); 494 | --------------------------------------------------------------------------------