Replace leaflet.draw with leaflet-locationfilter
This commit is contained in:
parent
babefbba6c
commit
fe6e837cfe
15 changed files with 618 additions and 1173 deletions
BIN
vendor/assets/leaflet/img/filter-icon.png
vendored
Normal file
BIN
vendor/assets/leaflet/img/filter-icon.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
vendor/assets/leaflet/img/move-handle.png
vendored
Normal file
BIN
vendor/assets/leaflet/img/move-handle.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
vendor/assets/leaflet/img/resize-handle.png
vendored
Normal file
BIN
vendor/assets/leaflet/img/resize-handle.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1,017 B |
130
vendor/assets/leaflet/leaflet.draw.css
vendored
130
vendor/assets/leaflet/leaflet.draw.css
vendored
|
@ -1,130 +0,0 @@
|
|||
/* Leaflet controls */
|
||||
|
||||
.leaflet-control-draw {
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
-webkit-border-radius: 7px;
|
||||
-moz-border-radius: 7px;
|
||||
border-radius: 7px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.leaflet-control-draw a {
|
||||
background-color: rgba(255, 255, 255, 0.75);
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
|
||||
.leaflet-control-draw a:first-child{
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.leaflet-control-draw a:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-draw a {
|
||||
width: 27px;
|
||||
height: 27px;
|
||||
}
|
||||
|
||||
.leaflet-control-draw-polyline {
|
||||
background-image: url(images/draw-polyline.png);
|
||||
}
|
||||
|
||||
.leaflet-control-draw-polygon {
|
||||
background-image: url(images/draw-polygon.png);
|
||||
}
|
||||
|
||||
.leaflet-control-draw-rectangle {
|
||||
background-image: url(images/draw-rectangle.png);
|
||||
}
|
||||
|
||||
.leaflet-control-draw-circle {
|
||||
background-image: url(images/draw-circle.png);
|
||||
}
|
||||
|
||||
.leaflet-control-draw-marker {
|
||||
background-image: url(images/draw-marker-icon.png);
|
||||
}
|
||||
|
||||
.leaflet-mouse-marker {
|
||||
background-color: #fff;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.leaflet-draw-label {
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
color: #222;
|
||||
font: 12px/18px "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
margin-left: 20px;
|
||||
margin-top: -21px;
|
||||
padding: 2px 4px;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
.leaflet-error-draw-label {
|
||||
background-color: #F2DEDE;
|
||||
border-color: #E6B6BD;
|
||||
color: #B94A48;
|
||||
}
|
||||
|
||||
.leaflet-draw-label-single {
|
||||
margin-top: -12px
|
||||
}
|
||||
|
||||
.leaflet-draw-label-subtext {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.leaflet-draw-guide-dash {
|
||||
font-size: 1%;
|
||||
opacity: 0.6;
|
||||
position: absolute;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
.leaflet-flash-anim {
|
||||
-webkit-animation-duration: 0.66s;
|
||||
-moz-animation-duration: 0.66s;
|
||||
-o-animation-duration: 0.66s;
|
||||
animation-duration: 0.66s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
-moz-animation-fill-mode: both;
|
||||
-o-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
-webkit-animation-name: leaflet-flash;
|
||||
-moz-animation-name: leaflet-flash;
|
||||
-o-animation-name: leaflet-flash;
|
||||
animation-name: leaflet-flash;
|
||||
}
|
||||
|
||||
@-webkit-keyframes leaflet-flash {
|
||||
0%, 50%, 100% { opacity: 1; }
|
||||
25%, 75% { opacity: 0.3; }
|
||||
}
|
||||
|
||||
@-moz-keyframes leaflet-flash {
|
||||
0%, 50%, 100% { opacity: 1; }
|
||||
25%, 75% { opacity: 0.3; }
|
||||
}
|
||||
|
||||
@-o-keyframes leaflet-flash {
|
||||
0%, 50%, 100% { opacity: 1; }
|
||||
25%, 75% { opacity: 0.3; }
|
||||
}
|
||||
|
||||
@keyframes leaflet-flash {
|
||||
0%, 50%, 100% { opacity: 1; }
|
||||
25%, 75% { opacity: 0; }
|
||||
}
|
10
vendor/assets/leaflet/leaflet.draw.ie.css
vendored
10
vendor/assets/leaflet/leaflet.draw.ie.css
vendored
|
@ -1,10 +0,0 @@
|
|||
/* Conditional stylesheet for IE. */
|
||||
|
||||
.leaflet-control-draw {
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#3F000000', EndColorStr='#3F000000');
|
||||
}
|
||||
|
||||
.leaflet-control-draw a {
|
||||
background-color: #eee;
|
||||
filter: alpha(opacity=90);
|
||||
}
|
931
vendor/assets/leaflet/leaflet.draw.js
vendored
931
vendor/assets/leaflet/leaflet.draw.js
vendored
|
@ -1,931 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2012, Smartrak, Jacob Toye
|
||||
Leaflet.draw is an open-source JavaScript library for drawing shapes/markers on leaflet powered maps.
|
||||
https://github.com/jacobtoye/Leaflet.draw
|
||||
*/
|
||||
(function (window, undefined) {
|
||||
|
||||
L.drawVersion = '0.1.4';
|
||||
|
||||
L.Util.extend(L.LineUtil, {
|
||||
// Checks to see if two line segments intersect. Does not handle degenerate cases.
|
||||
// http://compgeom.cs.uiuc.edu/~jeffe/teaching/373/notes/x06-sweepline.pdf
|
||||
segmentsIntersect: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2, /*Point*/ p3) {
|
||||
return this._checkCounterclockwise(p, p2, p3) !==
|
||||
this._checkCounterclockwise(p1, p2, p3) &&
|
||||
this._checkCounterclockwise(p, p1, p2) !==
|
||||
this._checkCounterclockwise(p, p1, p3);
|
||||
},
|
||||
|
||||
// check to see if points are in counterclockwise order
|
||||
_checkCounterclockwise: function (/*Point*/ p, /*Point*/ p1, /*Point*/ p2) {
|
||||
return (p2.y - p.y) * (p1.x - p.x) > (p1.y - p.y) * (p2.x - p.x);
|
||||
}
|
||||
});
|
||||
|
||||
L.Polyline.include({
|
||||
// Check to see if this polyline has any linesegments that intersect.
|
||||
// NOTE: does not support detecting intersection for degenerate cases.
|
||||
intersects: function () {
|
||||
var points = this._originalPoints,
|
||||
len = points ? points.length : 0,
|
||||
i, j, p, p1, p2, p3;
|
||||
|
||||
if (this._tooFewPointsForIntersection()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = len - 1; i >= 3; i--) {
|
||||
p = points[i - 1];
|
||||
p1 = points[i];
|
||||
|
||||
|
||||
if (this._lineSegmentsIntersectsRange(p, p1, i - 2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
// Check for intersection if new latlng was added to this polyline.
|
||||
// NOTE: does not support detecting intersection for degenerate cases.
|
||||
newLatLngIntersects: function (latlng, skipFirst) {
|
||||
// Cannot check a polyline for intersecting lats/lngs when not added to the map
|
||||
if (!this._map) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.newPointIntersects(this._map.latLngToLayerPoint(latlng), skipFirst);
|
||||
},
|
||||
|
||||
// Check for intersection if new point was added to this polyline.
|
||||
// newPoint must be a layer point.
|
||||
// NOTE: does not support detecting intersection for degenerate cases.
|
||||
newPointIntersects: function (newPoint, skipFirst) {
|
||||
var points = this._originalPoints,
|
||||
len = points ? points.length : 0,
|
||||
lastPoint = points ? points[len - 1] : null,
|
||||
// The previous previous line segment. Previous line segement doesn't need testing.
|
||||
maxIndex = len - 2;
|
||||
|
||||
if (this._tooFewPointsForIntersection(1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this._lineSegmentsIntersectsRange(lastPoint, newPoint, maxIndex, skipFirst ? 1 : 0);
|
||||
},
|
||||
|
||||
// Polylines with 2 sides can only intersect in cases where points are collinear (we don't support detecting these).
|
||||
// Cannot have intersection when < 3 line segments (< 4 points)
|
||||
_tooFewPointsForIntersection: function (extraPoints) {
|
||||
var points = this._originalPoints,
|
||||
len = points ? points.length : 0;
|
||||
// Increment length by extraPoints if present
|
||||
len += extraPoints || 0;
|
||||
|
||||
return !this._originalPoints || len <= 3;
|
||||
},
|
||||
|
||||
// Checks a line segment intersections with any line segements before its predecessor.
|
||||
// Don't need to check the predecessor as will never intersect.
|
||||
_lineSegmentsIntersectsRange: function (p, p1, maxIndex, minIndex) {
|
||||
var points = this._originalPoints,
|
||||
p2, p3;
|
||||
|
||||
minIndex = minIndex || 0;
|
||||
|
||||
// Check all previous line segments (beside the immediately previous) for intersections
|
||||
for (var j = maxIndex; j > minIndex; j--) {
|
||||
p2 = points[j - 1];
|
||||
p3 = points[j];
|
||||
|
||||
if (L.LineUtil.segmentsIntersect(p, p1, p2, p3)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
L.Polygon.include({
|
||||
// Checks a polygon for any intersecting line segments. Ignores holes.
|
||||
intersects: function () {
|
||||
var polylineIntersects,
|
||||
points = this._originalPoints,
|
||||
len, firstPoint, lastPoint, maxIndex;
|
||||
|
||||
if (this._tooFewPointsForIntersection()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
polylineIntersects = L.Polyline.prototype.intersects.call(this);
|
||||
|
||||
// If already found an intersection don't need to check for any more.
|
||||
if (polylineIntersects) {
|
||||
return true;
|
||||
}
|
||||
|
||||
len = points.length;
|
||||
firstPoint = points[0];
|
||||
lastPoint = points[len - 1];
|
||||
maxIndex = len - 2;
|
||||
|
||||
// Check the line segment between last and first point. Don't need to check the first line segment (minIndex = 1)
|
||||
return this._lineSegmentsIntersectsRange(lastPoint, firstPoint, maxIndex, 1);
|
||||
}
|
||||
});
|
||||
|
||||
L.Handler.Draw = L.Handler.extend({
|
||||
includes: L.Mixin.Events,
|
||||
|
||||
initialize: function (map, options) {
|
||||
this._map = map;
|
||||
this._container = map._container;
|
||||
this._overlayPane = map._panes.overlayPane;
|
||||
this._popupPane = map._panes.popupPane;
|
||||
|
||||
// Merge default shapeOptions options with custom shapeOptions
|
||||
if (options && options.shapeOptions) {
|
||||
options.shapeOptions = L.Util.extend({}, this.options.shapeOptions, options.shapeOptions);
|
||||
}
|
||||
L.Util.extend(this.options, options);
|
||||
},
|
||||
|
||||
enable: function () {
|
||||
this.fire('activated');
|
||||
L.Handler.prototype.enable.call(this);
|
||||
},
|
||||
|
||||
addHooks: function () {
|
||||
if (this._map) {
|
||||
L.DomUtil.disableTextSelection();
|
||||
|
||||
this._label = L.DomUtil.create('div', 'leaflet-draw-label', this._popupPane);
|
||||
this._singleLineLabel = false;
|
||||
|
||||
L.DomEvent.addListener(this._container, 'keyup', this._cancelDrawing, this);
|
||||
}
|
||||
},
|
||||
|
||||
removeHooks: function () {
|
||||
if (this._map) {
|
||||
L.DomUtil.enableTextSelection();
|
||||
|
||||
this._popupPane.removeChild(this._label);
|
||||
delete this._label;
|
||||
|
||||
L.DomEvent.removeListener(this._container, 'keyup', this._cancelDrawing);
|
||||
}
|
||||
},
|
||||
|
||||
_updateLabelText: function (labelText) {
|
||||
labelText.subtext = labelText.subtext || '';
|
||||
|
||||
// update the vertical position (only if changed)
|
||||
if (labelText.subtext.length === 0 && !this._singleLineLabel) {
|
||||
L.DomUtil.addClass(this._label, 'leaflet-draw-label-single');
|
||||
this._singleLineLabel = true;
|
||||
}
|
||||
else if (labelText.subtext.length > 0 && this._singleLineLabel) {
|
||||
L.DomUtil.removeClass(this._label, 'leaflet-draw-label-single');
|
||||
this._singleLineLabel = false;
|
||||
}
|
||||
|
||||
this._label.innerHTML =
|
||||
(labelText.subtext.length > 0 ? '<span class="leaflet-draw-label-subtext">' + labelText.subtext + '</span>' + '<br />' : '') +
|
||||
'<span>' + labelText.text + '</span>';
|
||||
},
|
||||
|
||||
_updateLabelPosition: function (pos) {
|
||||
L.DomUtil.setPosition(this._label, pos);
|
||||
},
|
||||
|
||||
// Cancel drawing when the escape key is pressed
|
||||
_cancelDrawing: function (e) {
|
||||
if (e.keyCode === 27) {
|
||||
this.disable();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
L.Polyline.Draw = L.Handler.Draw.extend({
|
||||
Poly: L.Polyline,
|
||||
|
||||
options: {
|
||||
allowIntersection: true,
|
||||
drawError: {
|
||||
color: '#b00b00',
|
||||
message: '<strong>Error:</strong> shape edges cannot cross!',
|
||||
timeout: 2500
|
||||
},
|
||||
icon: new L.DivIcon({
|
||||
iconSize: new L.Point(8, 8),
|
||||
className: 'leaflet-div-icon leaflet-editing-icon'
|
||||
}),
|
||||
guidelineDistance: 20,
|
||||
shapeOptions: {
|
||||
stroke: true,
|
||||
color: '#f06eaa',
|
||||
weight: 4,
|
||||
opacity: 0.5,
|
||||
fill: false,
|
||||
clickable: true
|
||||
},
|
||||
zIndexOffset: 2000 // This should be > than the highest z-index any map layers
|
||||
},
|
||||
|
||||
initialize: function (map, options) {
|
||||
// Merge default drawError options with custom options
|
||||
if (options && options.drawError) {
|
||||
options.drawError = L.Util.extend({}, this.options.drawError, options.drawError);
|
||||
}
|
||||
L.Handler.Draw.prototype.initialize.call(this, map, options);
|
||||
},
|
||||
|
||||
addHooks: function () {
|
||||
L.Handler.Draw.prototype.addHooks.call(this);
|
||||
if (this._map) {
|
||||
this._markers = [];
|
||||
|
||||
this._markerGroup = new L.LayerGroup();
|
||||
this._map.addLayer(this._markerGroup);
|
||||
|
||||
this._poly = new L.Polyline([], this.options.shapeOptions);
|
||||
|
||||
this._updateLabelText(this._getLabelText());
|
||||
|
||||
// Make a transparent marker that will used to catch click events. These click
|
||||
// events will create the vertices. We need to do this so we can ensure that
|
||||
// we can create vertices over other map layers (markers, vector layers). We
|
||||
// also do not want to trigger any click handlers of objects we are clicking on
|
||||
// while drawing.
|
||||
if (!this._mouseMarker) {
|
||||
this._mouseMarker = L.marker(this._map.getCenter(), {
|
||||
icon: L.divIcon({
|
||||
className: 'leaflet-mouse-marker',
|
||||
iconAnchor: [20, 20],
|
||||
iconSize: [40, 40]
|
||||
}),
|
||||
opacity: 0,
|
||||
zIndexOffset: this.options.zIndexOffset
|
||||
});
|
||||
}
|
||||
|
||||
this._mouseMarker
|
||||
.on('click', this._onClick, this)
|
||||
.addTo(this._map);
|
||||
|
||||
this._map.on('mousemove', this._onMouseMove, this);
|
||||
}
|
||||
},
|
||||
|
||||
removeHooks: function () {
|
||||
L.Handler.Draw.prototype.removeHooks.call(this);
|
||||
|
||||
this._clearHideErrorTimeout();
|
||||
|
||||
this._cleanUpShape();
|
||||
|
||||
// remove markers from map
|
||||
this._map.removeLayer(this._markerGroup);
|
||||
delete this._markerGroup;
|
||||
delete this._markers;
|
||||
|
||||
this._map.removeLayer(this._poly);
|
||||
delete this._poly;
|
||||
|
||||
this._mouseMarker.off('click', this._onClick);
|
||||
this._map.removeLayer(this._mouseMarker);
|
||||
delete this._mouseMarker;
|
||||
|
||||
// clean up DOM
|
||||
this._clearGuides();
|
||||
|
||||
this._map.off('mousemove', this._onMouseMove);
|
||||
},
|
||||
|
||||
_finishShape: function () {
|
||||
if (!this.options.allowIntersection && this._poly.newLatLngIntersects(this._poly.getLatLngs()[0], true)) {
|
||||
this._showErrorLabel();
|
||||
return;
|
||||
}
|
||||
if (!this._shapeIsValid()) {
|
||||
this._showErrorLabel();
|
||||
return;
|
||||
}
|
||||
|
||||
this._map.fire(
|
||||
'draw:poly-created',
|
||||
{ poly: new this.Poly(this._poly.getLatLngs(), this.options.shapeOptions) }
|
||||
);
|
||||
this.disable();
|
||||
},
|
||||
|
||||
//Called to verify the shape is valid when the user tries to finish it
|
||||
//Return false if the shape is not valid
|
||||
_shapeIsValid: function () {
|
||||
return true;
|
||||
},
|
||||
|
||||
_onMouseMove: function (e) {
|
||||
var newPos = e.layerPoint,
|
||||
latlng = e.latlng,
|
||||
markerCount = this._markers.length;
|
||||
|
||||
// Save latlng
|
||||
this._currentLatLng = latlng;
|
||||
|
||||
// update the label
|
||||
this._updateLabelPosition(newPos);
|
||||
|
||||
if (markerCount > 0) {
|
||||
this._updateLabelText(this._getLabelText());
|
||||
// draw the guide line
|
||||
this._clearGuides();
|
||||
this._drawGuide(
|
||||
this._map.latLngToLayerPoint(this._markers[markerCount - 1].getLatLng()),
|
||||
newPos
|
||||
);
|
||||
}
|
||||
|
||||
// Update the mouse marker position
|
||||
this._mouseMarker.setLatLng(latlng);
|
||||
|
||||
L.DomEvent.preventDefault(e.originalEvent);
|
||||
},
|
||||
|
||||
_onClick: function (e) {
|
||||
var latlng = e.target.getLatLng(),
|
||||
markerCount = this._markers.length;
|
||||
|
||||
if (markerCount > 0 && !this.options.allowIntersection && this._poly.newLatLngIntersects(latlng)) {
|
||||
this._showErrorLabel();
|
||||
return;
|
||||
}
|
||||
else if (this._errorShown) {
|
||||
this._hideErrorLabel();
|
||||
}
|
||||
|
||||
this._markers.push(this._createMarker(latlng));
|
||||
|
||||
this._poly.addLatLng(latlng);
|
||||
|
||||
if (this._poly.getLatLngs().length === 2) {
|
||||
this._map.addLayer(this._poly);
|
||||
}
|
||||
|
||||
this._updateMarkerHandler();
|
||||
|
||||
this._vertexAdded(latlng);
|
||||
},
|
||||
|
||||
_updateMarkerHandler: function () {
|
||||
// The last marker shold have a click handler to close the polyline
|
||||
if (this._markers.length > 1) {
|
||||
this._markers[this._markers.length - 1].on('click', this._finishShape, this);
|
||||
}
|
||||
|
||||
// Remove the old marker click handler (as only the last point should close the polyline)
|
||||
if (this._markers.length > 2) {
|
||||
this._markers[this._markers.length - 2].off('click', this._finishShape);
|
||||
}
|
||||
},
|
||||
|
||||
_createMarker: function (latlng) {
|
||||
var marker = new L.Marker(latlng, {
|
||||
icon: this.options.icon,
|
||||
zIndexOffset: this.options.zIndexOffset * 2
|
||||
});
|
||||
|
||||
this._markerGroup.addLayer(marker);
|
||||
|
||||
return marker;
|
||||
},
|
||||
|
||||
_drawGuide: function (pointA, pointB) {
|
||||
var length = Math.floor(Math.sqrt(Math.pow((pointB.x - pointA.x), 2) + Math.pow((pointB.y - pointA.y), 2))),
|
||||
i,
|
||||
fraction,
|
||||
dashPoint,
|
||||
dash;
|
||||
|
||||
//create the guides container if we haven't yet (TODO: probaly shouldn't do this every time the user starts to draw?)
|
||||
if (!this._guidesContainer) {
|
||||
this._guidesContainer = L.DomUtil.create('div', 'leaflet-draw-guides', this._overlayPane);
|
||||
}
|
||||
|
||||
//draw a dash every GuildeLineDistance
|
||||
for (i = this.options.guidelineDistance; i < length; i += this.options.guidelineDistance) {
|
||||
//work out fraction along line we are
|
||||
fraction = i / length;
|
||||
|
||||
//calculate new x,y point
|
||||
dashPoint = {
|
||||
x: Math.floor((pointA.x * (1 - fraction)) + (fraction * pointB.x)),
|
||||
y: Math.floor((pointA.y * (1 - fraction)) + (fraction * pointB.y))
|
||||
};
|
||||
|
||||
//add guide dash to guide container
|
||||
dash = L.DomUtil.create('div', 'leaflet-draw-guide-dash', this._guidesContainer);
|
||||
dash.style.backgroundColor =
|
||||
!this._errorShown ? this.options.shapeOptions.color : this.options.drawError.color;
|
||||
|
||||
L.DomUtil.setPosition(dash, dashPoint);
|
||||
}
|
||||
},
|
||||
|
||||
_updateGuideColor: function (color) {
|
||||
if (this._guidesContainer) {
|
||||
for (var i = 0, l = this._guidesContainer.childNodes.length; i < l; i++) {
|
||||
this._guidesContainer.childNodes[i].style.backgroundColor = color;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// removes all child elements (guide dashes) from the guides container
|
||||
_clearGuides: function () {
|
||||
if (this._guidesContainer) {
|
||||
while (this._guidesContainer.firstChild) {
|
||||
this._guidesContainer.removeChild(this._guidesContainer.firstChild);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_updateLabelText: function (labelText) {
|
||||
if (!this._errorShown) {
|
||||
L.Handler.Draw.prototype._updateLabelText.call(this, labelText);
|
||||
}
|
||||
},
|
||||
|
||||
_getLabelText: function () {
|
||||
var labelText,
|
||||
distance,
|
||||
distanceStr;
|
||||
|
||||
if (this._markers.length === 0) {
|
||||
labelText = {
|
||||
text: 'Click to start drawing line.'
|
||||
};
|
||||
} else {
|
||||
// calculate the distance from the last fixed point to the mouse position
|
||||
distance = this._measurementRunningTotal + this._currentLatLng.distanceTo(this._markers[this._markers.length - 1].getLatLng());
|
||||
// show metres when distance is < 1km, then show km
|
||||
distanceStr = distance > 1000 ? (distance / 1000).toFixed(2) + ' km' : Math.ceil(distance) + ' m';
|
||||
|
||||
if (this._markers.length === 1) {
|
||||
labelText = {
|
||||
text: 'Click to continue drawing line.',
|
||||
subtext: distanceStr
|
||||
};
|
||||
} else {
|
||||
labelText = {
|
||||
text: 'Click last point to finish line.',
|
||||
subtext: distanceStr
|
||||
};
|
||||
}
|
||||
}
|
||||
return labelText;
|
||||
},
|
||||
|
||||
_showErrorLabel: function () {
|
||||
this._errorShown = true;
|
||||
|
||||
// Update label
|
||||
L.DomUtil.addClass(this._label, 'leaflet-error-draw-label');
|
||||
L.DomUtil.addClass(this._label, 'leaflet-flash-anim');
|
||||
L.Handler.Draw.prototype._updateLabelText.call(this, { text: this.options.drawError.message });
|
||||
|
||||
// Update shape
|
||||
this._updateGuideColor(this.options.drawError.color);
|
||||
this._poly.setStyle({ color: this.options.drawError.color });
|
||||
|
||||
// Hide the error after 2 seconds
|
||||
this._clearHideErrorTimeout();
|
||||
this._hideErrorTimeout = setTimeout(L.Util.bind(this._hideErrorLabel, this), this.options.drawError.timeout);
|
||||
},
|
||||
|
||||
_hideErrorLabel: function () {
|
||||
this._errorShown = false;
|
||||
|
||||
this._clearHideErrorTimeout();
|
||||
|
||||
// Revert label
|
||||
L.DomUtil.removeClass(this._label, 'leaflet-error-draw-label');
|
||||
L.DomUtil.removeClass(this._label, 'leaflet-flash-anim');
|
||||
this._updateLabelText(this._getLabelText());
|
||||
|
||||
// Revert shape
|
||||
this._updateGuideColor(this.options.shapeOptions.color);
|
||||
this._poly.setStyle({ color: this.options.shapeOptions.color });
|
||||
},
|
||||
|
||||
_clearHideErrorTimeout: function () {
|
||||
if (this._hideErrorTimeout) {
|
||||
clearTimeout(this._hideErrorTimeout);
|
||||
this._hideErrorTimeout = null;
|
||||
}
|
||||
},
|
||||
|
||||
_vertexAdded: function (latlng) {
|
||||
if (this._markers.length === 1) {
|
||||
this._measurementRunningTotal = 0;
|
||||
}
|
||||
else {
|
||||
this._measurementRunningTotal +=
|
||||
latlng.distanceTo(this._markers[this._markers.length - 2].getLatLng());
|
||||
}
|
||||
},
|
||||
|
||||
_cleanUpShape: function () {
|
||||
if (this._markers.length > 0) {
|
||||
this._markers[this._markers.length - 1].off('click', this._finishShape);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
L.Polygon.Draw = L.Polyline.Draw.extend({
|
||||
Poly: L.Polygon,
|
||||
|
||||
options: {
|
||||
shapeOptions: {
|
||||
stroke: true,
|
||||
color: '#f06eaa',
|
||||
weight: 4,
|
||||
opacity: 0.5,
|
||||
fill: true,
|
||||
fillColor: null, //same as color by default
|
||||
fillOpacity: 0.2,
|
||||
clickable: false
|
||||
}
|
||||
},
|
||||
|
||||
_updateMarkerHandler: function () {
|
||||
// The first marker shold have a click handler to close the polygon
|
||||
if (this._markers.length === 1) {
|
||||
this._markers[0].on('click', this._finishShape, this);
|
||||
}
|
||||
},
|
||||
|
||||
_getLabelText: function () {
|
||||
var text;
|
||||
if (this._markers.length === 0) {
|
||||
text = 'Click to start drawing shape.';
|
||||
} else if (this._markers.length < 3) {
|
||||
text = 'Click to continue drawing shape.';
|
||||
} else {
|
||||
text = 'Click first point to close this shape.';
|
||||
}
|
||||
return {
|
||||
text: text
|
||||
};
|
||||
},
|
||||
|
||||
_shapeIsValid: function () {
|
||||
return this._markers.length >= 3;
|
||||
},
|
||||
|
||||
_vertexAdded: function (latlng) {
|
||||
//calc area here
|
||||
},
|
||||
|
||||
_cleanUpShape: function () {
|
||||
if (this._markers.length > 0) {
|
||||
this._markers[0].off('click', this._finishShape);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
L.SimpleShape = {};
|
||||
|
||||
L.SimpleShape.Draw = L.Handler.Draw.extend({
|
||||
addHooks: function () {
|
||||
L.Handler.Draw.prototype.addHooks.call(this);
|
||||
if (this._map) {
|
||||
this._map.dragging.disable();
|
||||
//TODO refactor: move cursor to styles
|
||||
this._container.style.cursor = 'crosshair';
|
||||
|
||||
this._updateLabelText({ text: this._initialLabelText });
|
||||
|
||||
this._map
|
||||
.on('mousedown', this._onMouseDown, this)
|
||||
.on('mousemove', this._onMouseMove, this);
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
removeHooks: function () {
|
||||
L.Handler.Draw.prototype.removeHooks.call(this);
|
||||
if (this._map) {
|
||||
this._map.dragging.enable();
|
||||
//TODO refactor: move cursor to styles
|
||||
this._container.style.cursor = '';
|
||||
|
||||
this._map
|
||||
.off('mousedown', this._onMouseDown, this)
|
||||
.off('mousemove', this._onMouseMove, this);
|
||||
|
||||
L.DomEvent.off(document, 'mouseup', this._onMouseUp);
|
||||
|
||||
// If the box element doesn't exist they must not have moved the mouse, so don't need to destroy/return
|
||||
if (this._shape) {
|
||||
this._map.removeLayer(this._shape);
|
||||
delete this._shape;
|
||||
}
|
||||
}
|
||||
this._isDrawing = false;
|
||||
},
|
||||
|
||||
_onMouseDown: function (e) {
|
||||
this._isDrawing = true;
|
||||
this._startLatLng = e.latlng;
|
||||
|
||||
L.DomEvent
|
||||
.on(document, 'mouseup', this._onMouseUp, this)
|
||||
.preventDefault(e.originalEvent);
|
||||
},
|
||||
|
||||
_onMouseMove: function (e) {
|
||||
var layerPoint = e.layerPoint,
|
||||
latlng = e.latlng;
|
||||
|
||||
this._updateLabelPosition(layerPoint);
|
||||
if (this._isDrawing) {
|
||||
this._updateLabelText({ text: 'Release mouse to finish drawing.' });
|
||||
this._drawShape(latlng);
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseUp: function (e) {
|
||||
if (this._shape) {
|
||||
this._fireCreatedEvent();
|
||||
}
|
||||
|
||||
this.disable();
|
||||
}
|
||||
});
|
||||
|
||||
L.Circle.Draw = L.SimpleShape.Draw.extend({
|
||||
options: {
|
||||
shapeOptions: {
|
||||
stroke: true,
|
||||
color: '#f06eaa',
|
||||
weight: 4,
|
||||
opacity: 0.5,
|
||||
fill: true,
|
||||
fillColor: null, //same as color by default
|
||||
fillOpacity: 0.2,
|
||||
clickable: true
|
||||
}
|
||||
},
|
||||
|
||||
_initialLabelText: 'Click and drag to draw circle.',
|
||||
|
||||
_drawShape: function (latlng) {
|
||||
if (!this._shape) {
|
||||
this._shape = new L.Circle(this._startLatLng, this._startLatLng.distanceTo(latlng), this.options.shapeOptions);
|
||||
this._map.addLayer(this._shape);
|
||||
} else {
|
||||
this._shape.setRadius(this._startLatLng.distanceTo(latlng));
|
||||
}
|
||||
},
|
||||
|
||||
_fireCreatedEvent: function () {
|
||||
this._map.fire(
|
||||
'draw:circle-created',
|
||||
{ circ: new L.Circle(this._startLatLng, this._shape.getRadius(), this.options.shapeOptions) }
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
L.Rectangle.Draw = L.SimpleShape.Draw.extend({
|
||||
options: {
|
||||
shapeOptions: {
|
||||
stroke: true,
|
||||
color: '#f06eaa',
|
||||
weight: 4,
|
||||
opacity: 0.5,
|
||||
fill: true,
|
||||
fillColor: null, //same as color by default
|
||||
fillOpacity: 0.2,
|
||||
clickable: true
|
||||
}
|
||||
},
|
||||
|
||||
_initialLabelText: 'Click and drag to draw rectangle.',
|
||||
|
||||
_drawShape: function (latlng) {
|
||||
if (!this._shape) {
|
||||
this._shape = new L.Rectangle(new L.LatLngBounds(this._startLatLng, latlng), this.options.shapeOptions);
|
||||
this._map.addLayer(this._shape);
|
||||
} else {
|
||||
this._shape.setBounds(new L.LatLngBounds(this._startLatLng, latlng));
|
||||
}
|
||||
},
|
||||
|
||||
_fireCreatedEvent: function () {
|
||||
this._map.fire(
|
||||
'draw:rectangle-created',
|
||||
{ rect: new L.Rectangle(this._shape.getBounds(), this.options.shapeOptions) }
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
L.Marker.Draw = L.Handler.Draw.extend({
|
||||
options: {
|
||||
icon: new L.Icon.Default(),
|
||||
zIndexOffset: 2000 // This should be > than the highest z-index any markers
|
||||
},
|
||||
|
||||
addHooks: function () {
|
||||
L.Handler.Draw.prototype.addHooks.call(this);
|
||||
|
||||
if (this._map) {
|
||||
this._updateLabelText({ text: 'Click map to place marker.' });
|
||||
this._map.on('mousemove', this._onMouseMove, this);
|
||||
}
|
||||
},
|
||||
|
||||
removeHooks: function () {
|
||||
L.Handler.Draw.prototype.removeHooks.call(this);
|
||||
|
||||
if (this._map) {
|
||||
if (this._marker) {
|
||||
this._marker.off('click', this._onClick);
|
||||
this._map
|
||||
.off('click', this._onClick)
|
||||
.removeLayer(this._marker);
|
||||
delete this._marker;
|
||||
}
|
||||
|
||||
this._map.off('mousemove', this._onMouseMove);
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseMove: function (e) {
|
||||
var newPos = e.layerPoint,
|
||||
latlng = e.latlng;
|
||||
|
||||
this._updateLabelPosition(newPos);
|
||||
|
||||
if (!this._marker) {
|
||||
this._marker = new L.Marker(latlng, {
|
||||
icon: this.options.icon,
|
||||
zIndexOffset: this.options.zIndexOffset
|
||||
});
|
||||
// Bind to both marker and map to make sure we get the click event.
|
||||
this._marker.on('click', this._onClick, this);
|
||||
this._map
|
||||
.on('click', this._onClick, this)
|
||||
.addLayer(this._marker);
|
||||
}
|
||||
else {
|
||||
this._marker.setLatLng(latlng);
|
||||
}
|
||||
},
|
||||
|
||||
_onClick: function (e) {
|
||||
this._map.fire(
|
||||
'draw:marker-created',
|
||||
{ marker: new L.Marker(this._marker.getLatLng(), { icon: this.options.icon }) }
|
||||
);
|
||||
this.disable();
|
||||
}
|
||||
});
|
||||
|
||||
L.Map.mergeOptions({
|
||||
drawControl: false
|
||||
});
|
||||
|
||||
L.Control.Draw = L.Control.extend({
|
||||
|
||||
options: {
|
||||
position: 'topleft',
|
||||
polyline: {
|
||||
title: 'Draw a polyline'
|
||||
},
|
||||
polygon: {
|
||||
title: 'Draw a polygon'
|
||||
},
|
||||
rectangle: {
|
||||
title: 'Draw a rectangle'
|
||||
},
|
||||
circle: {
|
||||
title: 'Draw a circle'
|
||||
},
|
||||
marker: {
|
||||
title: 'Add a marker'
|
||||
}
|
||||
},
|
||||
|
||||
handlers: {},
|
||||
|
||||
initialize: function (options) {
|
||||
L.Util.extend(this.options, options);
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
var className = 'leaflet-control-draw',
|
||||
container = L.DomUtil.create('div', className);
|
||||
|
||||
if (this.options.polyline) {
|
||||
this.handlers.polyline = new L.Polyline.Draw(map, this.options.polyline);
|
||||
this._createButton(
|
||||
this.options.polyline.title,
|
||||
className + '-polyline',
|
||||
container,
|
||||
this.handlers.polyline.enable,
|
||||
this.handlers.polyline
|
||||
);
|
||||
this.handlers.polyline.on('activated', this._disableInactiveModes, this);
|
||||
}
|
||||
|
||||
if (this.options.polygon) {
|
||||
this.handlers.polygon = new L.Polygon.Draw(map, this.options.polygon);
|
||||
this._createButton(
|
||||
this.options.polygon.title,
|
||||
className + '-polygon',
|
||||
container,
|
||||
this.handlers.polygon.enable,
|
||||
this.handlers.polygon
|
||||
);
|
||||
this.handlers.polygon.on('activated', this._disableInactiveModes, this);
|
||||
}
|
||||
|
||||
if (this.options.rectangle) {
|
||||
this.handlers.rectangle = new L.Rectangle.Draw(map, this.options.rectangle);
|
||||
this._createButton(
|
||||
this.options.rectangle.title,
|
||||
className + '-rectangle',
|
||||
container,
|
||||
this.handlers.rectangle.enable,
|
||||
this.handlers.rectangle
|
||||
);
|
||||
this.handlers.rectangle.on('activated', this._disableInactiveModes, this);
|
||||
}
|
||||
|
||||
if (this.options.circle) {
|
||||
this.handlers.circle = new L.Circle.Draw(map, this.options.circle);
|
||||
this._createButton(
|
||||
this.options.circle.title,
|
||||
className + '-circle',
|
||||
container,
|
||||
this.handlers.circle.enable,
|
||||
this.handlers.circle
|
||||
);
|
||||
this.handlers.circle.on('activated', this._disableInactiveModes, this);
|
||||
}
|
||||
|
||||
if (this.options.marker) {
|
||||
this.handlers.marker = new L.Marker.Draw(map, this.options.marker);
|
||||
this._createButton(
|
||||
this.options.marker.title,
|
||||
className + '-marker',
|
||||
container,
|
||||
this.handlers.marker.enable,
|
||||
this.handlers.marker
|
||||
);
|
||||
this.handlers.marker.on('activated', this._disableInactiveModes, this);
|
||||
}
|
||||
|
||||
return container;
|
||||
},
|
||||
|
||||
_createButton: function (title, className, container, fn, context) {
|
||||
var link = L.DomUtil.create('a', className, container);
|
||||
link.href = '#';
|
||||
link.title = title;
|
||||
|
||||
L.DomEvent
|
||||
.on(link, 'click', L.DomEvent.stopPropagation)
|
||||
.on(link, 'mousedown', L.DomEvent.stopPropagation)
|
||||
.on(link, 'dblclick', L.DomEvent.stopPropagation)
|
||||
.on(link, 'click', L.DomEvent.preventDefault)
|
||||
.on(link, 'click', fn, context);
|
||||
|
||||
return link;
|
||||
},
|
||||
|
||||
// Need to disable the drawing modes if user clicks on another without disabling the current mode
|
||||
_disableInactiveModes: function () {
|
||||
for (var i in this.handlers) {
|
||||
// Check if is a property of this object and is enabled
|
||||
if (this.handlers.hasOwnProperty(i) && this.handlers[i].enabled()) {
|
||||
this.handlers[i].disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
L.Map.addInitHook(function () {
|
||||
if (this.options.drawControl) {
|
||||
this.drawControl = new L.Control.Draw();
|
||||
this.addControl(this.drawControl);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
}(this));
|
78
vendor/assets/leaflet/leaflet.locationfilter.css
vendored
Normal file
78
vendor/assets/leaflet/leaflet.locationfilter.css
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
div.leaflet-marker-icon.location-filter.resize-marker {
|
||||
background: url( img/resize-handle.png ) no-repeat;
|
||||
cursor: move;
|
||||
}
|
||||
div.leaflet-marker-icon.location-filter.move-marker {
|
||||
background: url( img/move-handle.png ) no-repeat;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
div.location-filter.button-container {
|
||||
background: #bfbfbf;
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
-moz-border-radius: 7px;
|
||||
-webkit-border-radius: 7px;
|
||||
border-radius: 7px;
|
||||
padding: 5px;
|
||||
}
|
||||
.leaflet-container div.location-filter.button-container a {
|
||||
display: inline-block;
|
||||
color: #0F2416;
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
text-shadow: #A1BB9C 0 1px;
|
||||
padding: 6px 7px;
|
||||
border: 1px solid #9CC5A4;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-webkit-box-shadow: inset rgba(255,255,255,0.75) 0 1px 1px;
|
||||
-moz-box-shadow: inset rgba(255,255,255,0.75) 0 1px 1px;
|
||||
box-shadow: inset rgba(255,255,255,0.75) 0 1px 1px;
|
||||
background: #c4e3b9;
|
||||
background: rgba(218, 252, 205, 0.9);
|
||||
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)));
|
||||
background: -webkit-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%);
|
||||
background: -moz-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%);
|
||||
background: -ms-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%);
|
||||
background: -o-linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%);
|
||||
background: linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%);
|
||||
}
|
||||
.leaflet-container div.location-filter.button-container a:hover {
|
||||
color: #263F1C;
|
||||
background: #dde6d8;
|
||||
background: rgba(245, 255, 240, 0.9);
|
||||
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)));
|
||||
background: -webkit-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%);
|
||||
background: -moz-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%);
|
||||
background: -ms-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%);
|
||||
background: -o-linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%);
|
||||
background: linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%);
|
||||
}
|
||||
|
||||
.leaflet-container div.location-filter.button-container a.enable-button {
|
||||
padding: 6px 7px 6px 25px;
|
||||
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)));
|
||||
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%);
|
||||
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%);
|
||||
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%);
|
||||
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%);
|
||||
background-image: url( img/filter-icon.png ), linear-gradient(top, rgba(218, 252, 205, 0.9) 0%, rgba(173, 226, 176, 0.9) 100%);
|
||||
background-repeat: no-repeat;
|
||||
background-position: left center;
|
||||
}
|
||||
.leaflet-container div.location-filter.button-container a.enable-button:hover,
|
||||
.leaflet-container div.location-filter.button-container.enabled a.enable-button {
|
||||
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)));
|
||||
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%);
|
||||
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%);
|
||||
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%);
|
||||
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%);
|
||||
background-image: url( img/filter-icon.png ), linear-gradient(top, rgba(245, 255, 240, 0.9) 0%, rgba(203, 228, 205, 0.9) 100%);
|
||||
background-repeat: no-repeat;
|
||||
background-position: left center;
|
||||
}
|
||||
|
||||
.leaflet-container div.location-filter.button-container a.adjust-button {
|
||||
margin-left: 2px;
|
||||
}
|
489
vendor/assets/leaflet/leaflet.locationfilter.js
vendored
Normal file
489
vendor/assets/leaflet/leaflet.locationfilter.js
vendored
Normal file
|
@ -0,0 +1,489 @@
|
|||
/*
|
||||
* Leaflet.locationfilter - leaflet location filter plugin
|
||||
* Copyright (C) 2012, Tripbirds.com
|
||||
* http://tripbirds.com
|
||||
*
|
||||
* Licensed under the MIT License.
|
||||
*
|
||||
* Date: 2012-09-24
|
||||
* Version: 0.1
|
||||
*/
|
||||
L.LatLngBounds.prototype.modify = function(map, amount) {
|
||||
var sw = this.getSouthWest(),
|
||||
ne = this.getNorthEast(),
|
||||
swPoint = map.latLngToLayerPoint(sw),
|
||||
nePoint = map.latLngToLayerPoint(ne);
|
||||
|
||||
sw = map.layerPointToLatLng(new L.Point(swPoint.x-amount, swPoint.y+amount));
|
||||
ne = map.layerPointToLatLng(new L.Point(nePoint.x+amount, nePoint.y-amount));
|
||||
|
||||
return new L.LatLngBounds(sw, ne);
|
||||
};
|
||||
|
||||
L.Control.Button = L.Class.extend({
|
||||
initialize: function(options) {
|
||||
L.Util.setOptions(this, options);
|
||||
},
|
||||
|
||||
addTo: function(container) {
|
||||
container.addButton(this);
|
||||
return this;
|
||||
},
|
||||
|
||||
onAdd: function (buttonContainer) {
|
||||
this._buttonContainer = buttonContainer;
|
||||
this._button = L.DomUtil.create('a', this.options.className, this._buttonContainer.getContainer());
|
||||
this._button.href = '#';
|
||||
this.setText(this.options.text);
|
||||
|
||||
var that = this;
|
||||
this._onClick = function(event) {
|
||||
that.options.onClick.call(that, event);
|
||||
};
|
||||
|
||||
L.DomEvent
|
||||
.on(this._button, 'click', L.DomEvent.stopPropagation)
|
||||
.on(this._button, 'mousedown', L.DomEvent.stopPropagation)
|
||||
.on(this._button, 'dblclick', L.DomEvent.stopPropagation)
|
||||
.on(this._button, 'click', L.DomEvent.preventDefault)
|
||||
.on(this._button, 'click', this._onClick, this);
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
L.DomEvent.off(this._button, "click", this._onClick);
|
||||
this._buttonContainer.getContainer().removeChild(this._button);
|
||||
},
|
||||
|
||||
setText: function(text) {
|
||||
this._button.title = text;
|
||||
this._button.innerHTML = text;
|
||||
}
|
||||
});
|
||||
|
||||
L.Control.ButtonContainer = L.Control.extend({
|
||||
options: {
|
||||
position: 'topleft'
|
||||
},
|
||||
|
||||
getContainer: function() {
|
||||
if (!this._container) {
|
||||
this._container = L.DomUtil.create('div', this.options.className);
|
||||
}
|
||||
return this._container;
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
this._map = map;
|
||||
return this.getContainer();
|
||||
},
|
||||
|
||||
addButton: function(button) {
|
||||
button.onAdd(this);
|
||||
},
|
||||
|
||||
addClass: function(className) {
|
||||
L.DomUtil.addClass(this.getContainer(), className);
|
||||
},
|
||||
|
||||
removeClass: function(className) {
|
||||
L.DomUtil.removeClass(this.getContainer(), className);
|
||||
}
|
||||
});
|
||||
|
||||
L.LocationFilter = L.Class.extend({
|
||||
options: {
|
||||
enableButton: {
|
||||
enableText: "Select area",
|
||||
disableText: "Remove selection"
|
||||
},
|
||||
adjustButton: {
|
||||
text: "Select area within current zoom"
|
||||
}
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
L.Util.setOptions(this, options);
|
||||
},
|
||||
|
||||
addTo: function(map) {
|
||||
map.addLayer(this);
|
||||
return this;
|
||||
},
|
||||
|
||||
onAdd: function(map) {
|
||||
this._map = map;
|
||||
this._layer = new L.LayerGroup();
|
||||
this._initializeButtonContainer();
|
||||
|
||||
if (this.options.enable) {
|
||||
this.enable();
|
||||
}
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
this.disable();
|
||||
this._buttonContainer.removeFrom(map);
|
||||
},
|
||||
|
||||
/* Get the current filter bounds */
|
||||
getBounds: function() {
|
||||
return new L.LatLngBounds(this._sw, this._ne);
|
||||
},
|
||||
|
||||
setBounds: function(bounds) {
|
||||
this._nw = bounds.getNorthWest();
|
||||
this._ne = bounds.getNorthEast();
|
||||
this._sw = bounds.getSouthWest();
|
||||
this._se = bounds.getSouthEast();
|
||||
this._draw();
|
||||
this._callCallback("onChange");
|
||||
},
|
||||
|
||||
isEnabled: function() {
|
||||
return this._enabled;
|
||||
},
|
||||
|
||||
/* Draw a rectangle */
|
||||
_drawRectangle: function(bounds, options) {
|
||||
options = options || {};
|
||||
var defaultOptions = {
|
||||
stroke: false,
|
||||
fill: true,
|
||||
fillColor: "black",
|
||||
fillOpacity: 0.3,
|
||||
clickable: false
|
||||
};
|
||||
options = L.Util.extend(defaultOptions, options);
|
||||
var rect = new L.Rectangle(bounds, options);
|
||||
rect.addTo(this._layer);
|
||||
return rect;
|
||||
},
|
||||
|
||||
/* Draw a draggable marker */
|
||||
_drawImageMarker: function(point, options) {
|
||||
var marker = new L.Marker(point, {
|
||||
icon: new L.DivIcon({
|
||||
iconAnchor: options.anchor,
|
||||
iconSize: options.size,
|
||||
className: options.className
|
||||
}),
|
||||
draggable: true
|
||||
});
|
||||
marker.addTo(this._layer);
|
||||
return marker;
|
||||
},
|
||||
|
||||
/* Draw a move marker. Sets up drag listener that updates the
|
||||
filter corners and redraws the filter when the move marker is
|
||||
moved */
|
||||
_drawMoveMarker: function(point) {
|
||||
var that = this;
|
||||
this._moveMarker = this._drawImageMarker(point, {
|
||||
"className": "location-filter move-marker",
|
||||
"anchor": [-10, -10],
|
||||
"size": [13,13]
|
||||
});
|
||||
this._moveMarker.on('drag', function(e) {
|
||||
var markerPos = that._moveMarker.getLatLng(),
|
||||
latDelta = markerPos.lat-that._nw.lat,
|
||||
lngDelta = markerPos.lng-that._nw.lng;
|
||||
that._nw = new L.LatLng(that._nw.lat+latDelta, that._nw.lng+lngDelta);
|
||||
that._ne = new L.LatLng(that._ne.lat+latDelta, that._ne.lng+lngDelta);
|
||||
that._sw = new L.LatLng(that._sw.lat+latDelta, that._sw.lng+lngDelta);
|
||||
that._se = new L.LatLng(that._se.lat+latDelta, that._se.lng+lngDelta);
|
||||
that._draw();
|
||||
});
|
||||
this._setupDragendListener(this._moveMarker);
|
||||
return this._moveMarker;
|
||||
},
|
||||
|
||||
/* Draw a resize marker */
|
||||
_drawResizeMarker: function(point, latFollower, lngFollower, otherPos) {
|
||||
return this._drawImageMarker(point, {
|
||||
"className": "location-filter resize-marker",
|
||||
"anchor": [7, 6],
|
||||
"size": [13, 12]
|
||||
});
|
||||
},
|
||||
|
||||
/* Track moving of the given resize marker and update the markers
|
||||
given in options.moveAlong to match the position of the moved
|
||||
marker. Update filter corners and redraw the filter */
|
||||
_setupResizeMarkerTracking: function(marker, options) {
|
||||
var that = this;
|
||||
marker.on('drag', function(e) {
|
||||
var curPosition = marker.getLatLng(),
|
||||
latMarker = options.moveAlong.lat,
|
||||
lngMarker = options.moveAlong.lng;
|
||||
// Move follower markers when this marker is moved
|
||||
latMarker.setLatLng(new L.LatLng(curPosition.lat, latMarker.getLatLng().lng));
|
||||
lngMarker.setLatLng(new L.LatLng(lngMarker.getLatLng().lat, curPosition.lng));
|
||||
// Sort marker positions in nw, ne, sw, se order
|
||||
var corners = [that._nwMarker.getLatLng(),
|
||||
that._neMarker.getLatLng(),
|
||||
that._swMarker.getLatLng(),
|
||||
that._seMarker.getLatLng()];
|
||||
corners.sort(function(a, b) {
|
||||
if (a.lat != b.lat)
|
||||
return b.lat-a.lat;
|
||||
else
|
||||
return a.lng-b.lng;
|
||||
});
|
||||
// Update corner points and redraw everything except the resize markers
|
||||
that._nw = corners[0];
|
||||
that._ne = corners[1];
|
||||
that._sw = corners[2];
|
||||
that._se = corners[3];
|
||||
that._draw({repositionResizeMarkers: false});
|
||||
});
|
||||
this._setupDragendListener(marker);
|
||||
},
|
||||
|
||||
/* Call the callback (given by name) if it was supplied in options */
|
||||
_callCallback: function(callbackName) {
|
||||
if (this.options[callbackName]) {
|
||||
this.options[callbackName](this.getBounds());
|
||||
}
|
||||
},
|
||||
|
||||
/* Call the onChange callback whenever dragend is triggered on the
|
||||
given marker */
|
||||
_setupDragendListener: function(marker) {
|
||||
if (this.options.onChange) {
|
||||
var that = this;
|
||||
marker.on('dragend', function(e) {
|
||||
that._callCallback("onChange");
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/* Create bounds for the mask rectangles and the location
|
||||
filter rectangle */
|
||||
_calculateBounds: function() {
|
||||
var mapBounds = this._map.getBounds(),
|
||||
outerBounds = new L.LatLngBounds(
|
||||
new L.LatLng(mapBounds.getSouthWest().lat-0.1,
|
||||
mapBounds.getSouthWest().lng-0.1),
|
||||
new L.LatLng(mapBounds.getNorthEast().lat+0.1,
|
||||
mapBounds.getNorthEast().lng+0.1)
|
||||
);
|
||||
|
||||
// The south west and north east points of the mask */
|
||||
this._osw = outerBounds.getSouthWest();
|
||||
this._one = outerBounds.getNorthEast();
|
||||
|
||||
// Bounds for the mask rectangles
|
||||
this._northBounds = new L.LatLngBounds(new L.LatLng(this._ne.lat, this._osw.lng), this._one),
|
||||
this._westBounds = new L.LatLngBounds(new L.LatLng(this._sw.lat, this._osw.lng), this._nw),
|
||||
this._eastBounds = new L.LatLngBounds(this._se, new L.LatLng(this._ne.lat, this._one.lng)),
|
||||
this._southBounds = new L.LatLngBounds(this._osw, new L.LatLng(this._sw.lat, this._one.lng));
|
||||
},
|
||||
|
||||
/* Initializes rectangles and markers */
|
||||
_initialDraw: function() {
|
||||
if (this._initialDrawCalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate filter bounds
|
||||
this._calculateBounds();
|
||||
|
||||
// Create rectangles
|
||||
this._northRect = this._drawRectangle(this._northBounds);
|
||||
this._westRect = this._drawRectangle(this._westBounds);
|
||||
this._eastRect = this._drawRectangle(this._eastBounds);
|
||||
this._southRect = this._drawRectangle(this._southBounds);
|
||||
this._innerRect = this._drawRectangle(this.getBounds(), {
|
||||
fillColor: "transparent",
|
||||
stroke: true,
|
||||
color: "white",
|
||||
weight: 1,
|
||||
opacity: 0.9
|
||||
});
|
||||
|
||||
// Create resize markers
|
||||
this._nwMarker = this._drawResizeMarker(this._nw);
|
||||
this._neMarker = this._drawResizeMarker(this._ne);
|
||||
this._swMarker = this._drawResizeMarker(this._sw);
|
||||
this._seMarker = this._drawResizeMarker(this._se);
|
||||
|
||||
// Setup tracking of resize markers. Each marker has pair of
|
||||
// follower markers that must be moved whenever the marker is
|
||||
// moved. For example, whenever the north west resize marker
|
||||
// moves, the south west marker must move along on the x-axis
|
||||
// and the north east marker must move on the y axis
|
||||
this._setupResizeMarkerTracking(this._nwMarker, {moveAlong: {lat: this._neMarker, lng: this._swMarker}});
|
||||
this._setupResizeMarkerTracking(this._neMarker, {moveAlong: {lat: this._nwMarker, lng: this._seMarker}});
|
||||
this._setupResizeMarkerTracking(this._swMarker, {moveAlong: {lat: this._seMarker, lng: this._nwMarker}});
|
||||
this._setupResizeMarkerTracking(this._seMarker, {moveAlong: {lat: this._swMarker, lng: this._neMarker}});
|
||||
|
||||
// Create move marker
|
||||
this._moveMarker = this._drawMoveMarker(this._nw);
|
||||
|
||||
this._initialDrawCalled = true;
|
||||
},
|
||||
|
||||
/* Reposition all rectangles and markers to the current filter bounds. */
|
||||
_draw: function(options) {
|
||||
options = L.Util.extend({repositionResizeMarkers: true}, options);
|
||||
|
||||
// Calculate filter bounds
|
||||
this._calculateBounds();
|
||||
|
||||
// Reposition rectangles
|
||||
this._northRect.setBounds(this._northBounds);
|
||||
this._westRect.setBounds(this._westBounds);
|
||||
this._eastRect.setBounds(this._eastBounds);
|
||||
this._southRect.setBounds(this._southBounds);
|
||||
this._innerRect.setBounds(this.getBounds());
|
||||
|
||||
// Reposition resize markers
|
||||
if (options.repositionResizeMarkers) {
|
||||
this._nwMarker.setLatLng(this._nw);
|
||||
this._neMarker.setLatLng(this._ne);
|
||||
this._swMarker.setLatLng(this._sw);
|
||||
this._seMarker.setLatLng(this._se);
|
||||
}
|
||||
|
||||
// Reposition the move marker
|
||||
this._moveMarker.setLatLng(this._nw);
|
||||
},
|
||||
|
||||
/* Adjust the location filter to the current map bounds */
|
||||
_adjustToMap: function() {
|
||||
this.setBounds(this._map.getBounds());
|
||||
this._map.zoomOut();
|
||||
},
|
||||
|
||||
/* Enable the location filter */
|
||||
enable: function() {
|
||||
if (this._enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize corners
|
||||
var bounds;
|
||||
if (this._sw && this._ne) {
|
||||
bounds = new L.LatLngBounds(this._sw, this._ne);
|
||||
} else if (this.options.bounds) {
|
||||
bounds = this.options.bounds;
|
||||
} else {
|
||||
bounds = this._map.getBounds();
|
||||
}
|
||||
this._map.invalidateSize();
|
||||
this._nw = bounds.getNorthWest();
|
||||
this._ne = bounds.getNorthEast();
|
||||
this._sw = bounds.getSouthWest();
|
||||
this._se = bounds.getSouthEast();
|
||||
|
||||
|
||||
// Update buttons
|
||||
this._buttonContainer.addClass("enabled");
|
||||
|
||||
if (this._enableButton) {
|
||||
this._enableButton.setText(this.options.enableButton.disableText);
|
||||
}
|
||||
|
||||
if (this.options.adjustButton) {
|
||||
this._createAdjustButton();
|
||||
}
|
||||
|
||||
// Draw filter
|
||||
this._initialDraw();
|
||||
this._draw();
|
||||
|
||||
// Set up map move event listener
|
||||
var that = this;
|
||||
this._moveHandler = function() {
|
||||
that._draw();
|
||||
};
|
||||
this._map.on("move", this._moveHandler);
|
||||
|
||||
// Add the filter layer to the map
|
||||
this._layer.addTo(this._map);
|
||||
|
||||
// Zoom out the map if necessary
|
||||
var mapBounds = this._map.getBounds();
|
||||
bounds = new L.LatLngBounds(this._sw, this._ne).modify(this._map, 10);
|
||||
if (!mapBounds.contains(bounds.getSouthWest()) || !mapBounds.contains(bounds.getNorthEast())) {
|
||||
this._map.fitBounds(bounds);
|
||||
}
|
||||
|
||||
this._enabled = true;
|
||||
|
||||
// Call the enabled callback
|
||||
this._callCallback("onEnabled");
|
||||
},
|
||||
|
||||
/* Disable the location filter */
|
||||
disable: function() {
|
||||
if (!this._enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update buttons
|
||||
this._buttonContainer.removeClass("enabled");
|
||||
|
||||
if (this._enableButton) {
|
||||
this._enableButton.setText(this.options.enableButton.enableText);
|
||||
}
|
||||
|
||||
if (this._adjustButton) {
|
||||
this._adjustButton.remove();
|
||||
}
|
||||
|
||||
// Remove event listener
|
||||
this._map.off("move", this._moveHandler);
|
||||
|
||||
// Remove rectangle layer from map
|
||||
this._map.removeLayer(this._layer);
|
||||
|
||||
this._enabled = false;
|
||||
|
||||
// Call the disabled callback
|
||||
this._callCallback("onDisabled");
|
||||
},
|
||||
|
||||
/* Create a button that allows the user to adjust the location
|
||||
filter to the current zoom */
|
||||
_createAdjustButton: function() {
|
||||
var that = this;
|
||||
this._adjustButton = new L.Control.Button({
|
||||
className: "adjust-button",
|
||||
text: this.options.adjustButton.text,
|
||||
|
||||
onClick: function(event) {
|
||||
that._adjustToMap();
|
||||
that._callCallback("onAdjustToZoomClick");
|
||||
}
|
||||
}).addTo(this._buttonContainer);
|
||||
},
|
||||
|
||||
/* Create the location filter button container and the button that
|
||||
toggles the location filter */
|
||||
_initializeButtonContainer: function() {
|
||||
var that = this;
|
||||
this._buttonContainer = new L.Control.ButtonContainer({className: "location-filter button-container"});
|
||||
|
||||
if (this.options.enableButton) {
|
||||
this._enableButton = new L.Control.Button({
|
||||
className: "enable-button",
|
||||
text: this.options.enableButton.enableText,
|
||||
|
||||
onClick: function(event) {
|
||||
if (!that._enabled) {
|
||||
// Enable the location filter
|
||||
that.enable();
|
||||
that._callCallback("onEnableClick");
|
||||
} else {
|
||||
// Disable the location filter
|
||||
that.disable();
|
||||
that._callCallback("onDisableClick");
|
||||
}
|
||||
}
|
||||
}).addTo(this._buttonContainer);
|
||||
}
|
||||
|
||||
this._buttonContainer.addTo(this._map);
|
||||
}
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue