diff --git a/Lora-Map/resources/js/leaflet/leaflet-src.esm.js b/Lora-Map/resources/js/leaflet/leaflet-src.esm.js
index 14268cd..f8b161b 100644
--- a/Lora-Map/resources/js/leaflet/leaflet-src.esm.js
+++ b/Lora-Map/resources/js/leaflet/leaflet-src.esm.js
@@ -1,10 +1,10 @@
-/* @preserve
- * Leaflet 1.3.4+Detached: 0e566b2ad5e696ba9f79a9d48a7e51c8f4892441.0e566b2, a JS library for interactive maps. http://leafletjs.com
- * (c) 2010-2018 Vladimir Agafonkin, (c) 2010-2011 CloudMade
- */
-
-var version = "1.3.4+HEAD.0e566b2";
-
+/* @preserve
+ * Leaflet 1.4.0+Detached: 3337f36d2a2d2b33946779057619b31f674ff5dc.3337f36, a JS library for interactive maps. http://leafletjs.com
+ * (c) 2010-2018 Vladimir Agafonkin, (c) 2010-2011 CloudMade
+ */
+
+var version = "1.4.0+HEAD.3337f36";
+
/*
* @namespace Util
*
@@ -246,33 +246,33 @@ function cancelAnimFrame(id) {
cancelFn.call(window, id);
}
}
-
-
-var Util = (Object.freeze || Object)({
- freeze: freeze,
- extend: extend,
- create: create,
- bind: bind,
- lastId: lastId,
- stamp: stamp,
- throttle: throttle,
- wrapNum: wrapNum,
- falseFn: falseFn,
- formatNum: formatNum,
- trim: trim,
- splitWords: splitWords,
- setOptions: setOptions,
- getParamString: getParamString,
- template: template,
- isArray: isArray,
- indexOf: indexOf,
- emptyImageUrl: emptyImageUrl,
- requestFn: requestFn,
- cancelFn: cancelFn,
- requestAnimFrame: requestAnimFrame,
- cancelAnimFrame: cancelAnimFrame
-});
-
+
+
+var Util = (Object.freeze || Object)({
+ freeze: freeze,
+ extend: extend,
+ create: create,
+ bind: bind,
+ lastId: lastId,
+ stamp: stamp,
+ throttle: throttle,
+ wrapNum: wrapNum,
+ falseFn: falseFn,
+ formatNum: formatNum,
+ trim: trim,
+ splitWords: splitWords,
+ setOptions: setOptions,
+ getParamString: getParamString,
+ template: template,
+ isArray: isArray,
+ indexOf: indexOf,
+ emptyImageUrl: emptyImageUrl,
+ requestFn: requestFn,
+ cancelFn: cancelFn,
+ requestAnimFrame: requestAnimFrame,
+ cancelAnimFrame: cancelAnimFrame
+});
+
// @class Class
// @aka L.Class
@@ -396,8 +396,8 @@ function checkDeprecatedMixinEvents(includes) {
'please inherit from L.Evented instead.', new Error().stack);
}
}
-}
-
+}
+
/*
* @class Evented
* @aka L.Evented
@@ -689,8 +689,8 @@ Events.fireEvent = Events.fire;
// Alias to [`listens(…)`](#evented-listens)
Events.hasEventListeners = Events.listens;
-var Evented = Class.extend(Events);
-
+var Evented = Class.extend(Events);
+
/*
* @class Point
* @aka L.Point
@@ -910,8 +910,8 @@ function toPoint(x, y, round) {
return new Point(x.x, x.y);
}
return new Point(x, y, round);
-}
-
+}
+
/*
* @class Bounds
* @aka L.Bounds
@@ -1082,8 +1082,8 @@ function toBounds(a, b) {
return a;
}
return new Bounds(a, b);
-}
-
+}
+
/*
* @class LatLngBounds
* @aka L.LatLngBounds
@@ -1332,8 +1332,8 @@ function toLatLngBounds(a, b) {
return a;
}
return new LatLngBounds(a, b);
-}
-
+}
+
/* @class LatLng
* @aka L.LatLng
*
@@ -1466,8 +1466,8 @@ function toLatLng(a, b, c) {
return null;
}
return new LatLng(a, b, c);
-}
-
+}
+
/*
* @namespace CRS
* @crs L.CRS.Base
@@ -1600,39 +1600,39 @@ var CRS = {
return new LatLngBounds(newSw, newNe);
}
-};
-
-/*
- * @namespace CRS
- * @crs L.CRS.Earth
- *
- * Serves as the base for CRS that are global such that they cover the earth.
- * Can only be used as the base for other CRS and cannot be used directly,
- * since it does not have a `code`, `projection` or `transformation`. `distance()` returns
- * meters.
- */
-
-var Earth = extend({}, CRS, {
- wrapLng: [-180, 180],
-
- // Mean Earth Radius, as recommended for use by
- // the International Union of Geodesy and Geophysics,
- // see http://rosettacode.org/wiki/Haversine_formula
- R: 6371000,
-
- // distance between two geographical points using spherical law of cosines approximation
- distance: function (latlng1, latlng2) {
- var rad = Math.PI / 180,
- lat1 = latlng1.lat * rad,
- lat2 = latlng2.lat * rad,
- sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2),
- sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2),
- a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon,
- c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
- return this.R * c;
- }
-});
-
+};
+
+/*
+ * @namespace CRS
+ * @crs L.CRS.Earth
+ *
+ * Serves as the base for CRS that are global such that they cover the earth.
+ * Can only be used as the base for other CRS and cannot be used directly,
+ * since it does not have a `code`, `projection` or `transformation`. `distance()` returns
+ * meters.
+ */
+
+var Earth = extend({}, CRS, {
+ wrapLng: [-180, 180],
+
+ // Mean Earth Radius, as recommended for use by
+ // the International Union of Geodesy and Geophysics,
+ // see http://rosettacode.org/wiki/Haversine_formula
+ R: 6371000,
+
+ // distance between two geographical points using spherical law of cosines approximation
+ distance: function (latlng1, latlng2) {
+ var rad = Math.PI / 180,
+ lat1 = latlng1.lat * rad,
+ lat2 = latlng2.lat * rad,
+ sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2),
+ sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2),
+ a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon,
+ c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+ return this.R * c;
+ }
+});
+
/*
* @namespace Projection
* @projection L.Projection.SphericalMercator
@@ -1670,8 +1670,8 @@ var SphericalMercator = {
var d = 6378137 * Math.PI;
return new Bounds([-d, -d], [d, d]);
})()
-};
-
+};
+
/*
* @class Transformation
* @aka L.Transformation
@@ -1747,8 +1747,8 @@ Transformation.prototype = {
function toTransformation(a, b, c, d) {
return new Transformation(a, b, c, d);
-}
-
+}
+
/*
* @namespace CRS
* @crs L.CRS.EPSG3857
@@ -1770,42 +1770,42 @@ var EPSG3857 = extend({}, Earth, {
var EPSG900913 = extend({}, EPSG3857, {
code: 'EPSG:900913'
-});
-
-// @namespace SVG; @section
-// There are several static functions which can be called without instantiating L.SVG:
-
-// @function create(name: String): SVGElement
-// Returns a instance of [SVGElement](https://developer.mozilla.org/docs/Web/API/SVGElement),
-// corresponding to the class name passed. For example, using 'line' will return
-// an instance of [SVGLineElement](https://developer.mozilla.org/docs/Web/API/SVGLineElement).
-function svgCreate(name) {
- return document.createElementNS('http://www.w3.org/2000/svg', name);
-}
-
-// @function pointsToPath(rings: Point[], closed: Boolean): String
-// Generates a SVG path string for multiple rings, with each ring turning
-// into "M..L..L.." instructions
-function pointsToPath(rings, closed) {
- var str = '',
- i, j, len, len2, points, p;
-
- for (i = 0, len = rings.length; i < len; i++) {
- points = rings[i];
-
- for (j = 0, len2 = points.length; j < len2; j++) {
- p = points[j];
- str += (j ? 'L' : 'M') + p.x + ' ' + p.y;
- }
-
- // closes the ring for polygons; "x" is VML syntax
- str += closed ? (svg ? 'z' : 'x') : '';
- }
-
- // SVG complains about empty path strings
- return str || 'M0 0';
-}
-
+});
+
+// @namespace SVG; @section
+// There are several static functions which can be called without instantiating L.SVG:
+
+// @function create(name: String): SVGElement
+// Returns a instance of [SVGElement](https://developer.mozilla.org/docs/Web/API/SVGElement),
+// corresponding to the class name passed. For example, using 'line' will return
+// an instance of [SVGLineElement](https://developer.mozilla.org/docs/Web/API/SVGLineElement).
+function svgCreate(name) {
+ return document.createElementNS('http://www.w3.org/2000/svg', name);
+}
+
+// @function pointsToPath(rings: Point[], closed: Boolean): String
+// Generates a SVG path string for multiple rings, with each ring turning
+// into "M..L..L.." instructions
+function pointsToPath(rings, closed) {
+ var str = '',
+ i, j, len, len2, points, p;
+
+ for (i = 0, len = rings.length; i < len; i++) {
+ points = rings[i];
+
+ for (j = 0, len2 = points.length; j < len2; j++) {
+ p = points[j];
+ str += (j ? 'L' : 'M') + p.x + ' ' + p.y;
+ }
+
+ // closes the ring for polygons; "x" is VML syntax
+ str += closed ? (svg ? 'z' : 'x') : '';
+ }
+
+ // SVG complains about empty path strings
+ return str || 'M0 0';
+}
+
/*
* @namespace Browser
* @aka L.Browser
@@ -1951,171 +1951,171 @@ var vml = !svg && (function () {
function userAgentContains(str) {
return navigator.userAgent.toLowerCase().indexOf(str) >= 0;
}
-
-
-var Browser = (Object.freeze || Object)({
- ie: ie,
- ielt9: ielt9,
- edge: edge,
- webkit: webkit,
- android: android,
- android23: android23,
- androidStock: androidStock,
- opera: opera,
- chrome: chrome,
- gecko: gecko,
- safari: safari,
- phantom: phantom,
- opera12: opera12,
- win: win,
- ie3d: ie3d,
- webkit3d: webkit3d,
- gecko3d: gecko3d,
- any3d: any3d,
- mobile: mobile,
- mobileWebkit: mobileWebkit,
- mobileWebkit3d: mobileWebkit3d,
- msPointer: msPointer,
- pointer: pointer,
- touch: touch,
- mobileOpera: mobileOpera,
- mobileGecko: mobileGecko,
- retina: retina,
- canvas: canvas,
- svg: svg,
- vml: vml
-});
-
-/*
- * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
- */
-
-
-var POINTER_DOWN = msPointer ? 'MSPointerDown' : 'pointerdown';
-var POINTER_MOVE = msPointer ? 'MSPointerMove' : 'pointermove';
-var POINTER_UP = msPointer ? 'MSPointerUp' : 'pointerup';
-var POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel';
-var TAG_WHITE_LIST = ['INPUT', 'SELECT', 'OPTION'];
-
-var _pointers = {};
-var _pointerDocListener = false;
-
-// DomEvent.DoubleTap needs to know about this
-var _pointersCount = 0;
-
-// Provides a touch events wrapper for (ms)pointer events.
-// ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890
-
-function addPointerListener(obj, type, handler, id) {
- if (type === 'touchstart') {
- _addPointerStart(obj, handler, id);
-
- } else if (type === 'touchmove') {
- _addPointerMove(obj, handler, id);
-
- } else if (type === 'touchend') {
- _addPointerEnd(obj, handler, id);
- }
-
- return this;
-}
-
-function removePointerListener(obj, type, id) {
- var handler = obj['_leaflet_' + type + id];
-
- if (type === 'touchstart') {
- obj.removeEventListener(POINTER_DOWN, handler, false);
-
- } else if (type === 'touchmove') {
- obj.removeEventListener(POINTER_MOVE, handler, false);
-
- } else if (type === 'touchend') {
- obj.removeEventListener(POINTER_UP, handler, false);
- obj.removeEventListener(POINTER_CANCEL, handler, false);
- }
-
- return this;
-}
-
-function _addPointerStart(obj, handler, id) {
- var onDown = bind(function (e) {
- if (e.pointerType !== 'mouse' && e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
- // In IE11, some touch events needs to fire for form controls, or
- // the controls will stop working. We keep a whitelist of tag names that
- // need these events. For other target tags, we prevent default on the event.
- if (TAG_WHITE_LIST.indexOf(e.target.tagName) < 0) {
- preventDefault(e);
- } else {
- return;
- }
- }
-
- _handlePointer(e, handler);
- });
-
- obj['_leaflet_touchstart' + id] = onDown;
- obj.addEventListener(POINTER_DOWN, onDown, false);
-
- // need to keep track of what pointers and how many are active to provide e.touches emulation
- if (!_pointerDocListener) {
- // we listen documentElement as any drags that end by moving the touch off the screen get fired there
- document.documentElement.addEventListener(POINTER_DOWN, _globalPointerDown, true);
- document.documentElement.addEventListener(POINTER_MOVE, _globalPointerMove, true);
- document.documentElement.addEventListener(POINTER_UP, _globalPointerUp, true);
- document.documentElement.addEventListener(POINTER_CANCEL, _globalPointerUp, true);
-
- _pointerDocListener = true;
- }
-}
-
-function _globalPointerDown(e) {
- _pointers[e.pointerId] = e;
- _pointersCount++;
-}
-
-function _globalPointerMove(e) {
- if (_pointers[e.pointerId]) {
- _pointers[e.pointerId] = e;
- }
-}
-
-function _globalPointerUp(e) {
- delete _pointers[e.pointerId];
- _pointersCount--;
-}
-
-function _handlePointer(e, handler) {
- e.touches = [];
- for (var i in _pointers) {
- e.touches.push(_pointers[i]);
- }
- e.changedTouches = [e];
-
- handler(e);
-}
-
-function _addPointerMove(obj, handler, id) {
- var onMove = function (e) {
- // don't fire touch moves when mouse isn't down
- if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; }
-
- _handlePointer(e, handler);
- };
-
- obj['_leaflet_touchmove' + id] = onMove;
- obj.addEventListener(POINTER_MOVE, onMove, false);
-}
-
-function _addPointerEnd(obj, handler, id) {
- var onUp = function (e) {
- _handlePointer(e, handler);
- };
-
- obj['_leaflet_touchend' + id] = onUp;
- obj.addEventListener(POINTER_UP, onUp, false);
- obj.addEventListener(POINTER_CANCEL, onUp, false);
-}
-
+
+
+var Browser = (Object.freeze || Object)({
+ ie: ie,
+ ielt9: ielt9,
+ edge: edge,
+ webkit: webkit,
+ android: android,
+ android23: android23,
+ androidStock: androidStock,
+ opera: opera,
+ chrome: chrome,
+ gecko: gecko,
+ safari: safari,
+ phantom: phantom,
+ opera12: opera12,
+ win: win,
+ ie3d: ie3d,
+ webkit3d: webkit3d,
+ gecko3d: gecko3d,
+ any3d: any3d,
+ mobile: mobile,
+ mobileWebkit: mobileWebkit,
+ mobileWebkit3d: mobileWebkit3d,
+ msPointer: msPointer,
+ pointer: pointer,
+ touch: touch,
+ mobileOpera: mobileOpera,
+ mobileGecko: mobileGecko,
+ retina: retina,
+ canvas: canvas,
+ svg: svg,
+ vml: vml
+});
+
+/*
+ * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
+ */
+
+
+var POINTER_DOWN = msPointer ? 'MSPointerDown' : 'pointerdown';
+var POINTER_MOVE = msPointer ? 'MSPointerMove' : 'pointermove';
+var POINTER_UP = msPointer ? 'MSPointerUp' : 'pointerup';
+var POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel';
+var TAG_WHITE_LIST = ['INPUT', 'SELECT', 'OPTION'];
+
+var _pointers = {};
+var _pointerDocListener = false;
+
+// DomEvent.DoubleTap needs to know about this
+var _pointersCount = 0;
+
+// Provides a touch events wrapper for (ms)pointer events.
+// ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890
+
+function addPointerListener(obj, type, handler, id) {
+ if (type === 'touchstart') {
+ _addPointerStart(obj, handler, id);
+
+ } else if (type === 'touchmove') {
+ _addPointerMove(obj, handler, id);
+
+ } else if (type === 'touchend') {
+ _addPointerEnd(obj, handler, id);
+ }
+
+ return this;
+}
+
+function removePointerListener(obj, type, id) {
+ var handler = obj['_leaflet_' + type + id];
+
+ if (type === 'touchstart') {
+ obj.removeEventListener(POINTER_DOWN, handler, false);
+
+ } else if (type === 'touchmove') {
+ obj.removeEventListener(POINTER_MOVE, handler, false);
+
+ } else if (type === 'touchend') {
+ obj.removeEventListener(POINTER_UP, handler, false);
+ obj.removeEventListener(POINTER_CANCEL, handler, false);
+ }
+
+ return this;
+}
+
+function _addPointerStart(obj, handler, id) {
+ var onDown = bind(function (e) {
+ if (e.pointerType !== 'mouse' && e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
+ // In IE11, some touch events needs to fire for form controls, or
+ // the controls will stop working. We keep a whitelist of tag names that
+ // need these events. For other target tags, we prevent default on the event.
+ if (TAG_WHITE_LIST.indexOf(e.target.tagName) < 0) {
+ preventDefault(e);
+ } else {
+ return;
+ }
+ }
+
+ _handlePointer(e, handler);
+ });
+
+ obj['_leaflet_touchstart' + id] = onDown;
+ obj.addEventListener(POINTER_DOWN, onDown, false);
+
+ // need to keep track of what pointers and how many are active to provide e.touches emulation
+ if (!_pointerDocListener) {
+ // we listen documentElement as any drags that end by moving the touch off the screen get fired there
+ document.documentElement.addEventListener(POINTER_DOWN, _globalPointerDown, true);
+ document.documentElement.addEventListener(POINTER_MOVE, _globalPointerMove, true);
+ document.documentElement.addEventListener(POINTER_UP, _globalPointerUp, true);
+ document.documentElement.addEventListener(POINTER_CANCEL, _globalPointerUp, true);
+
+ _pointerDocListener = true;
+ }
+}
+
+function _globalPointerDown(e) {
+ _pointers[e.pointerId] = e;
+ _pointersCount++;
+}
+
+function _globalPointerMove(e) {
+ if (_pointers[e.pointerId]) {
+ _pointers[e.pointerId] = e;
+ }
+}
+
+function _globalPointerUp(e) {
+ delete _pointers[e.pointerId];
+ _pointersCount--;
+}
+
+function _handlePointer(e, handler) {
+ e.touches = [];
+ for (var i in _pointers) {
+ e.touches.push(_pointers[i]);
+ }
+ e.changedTouches = [e];
+
+ handler(e);
+}
+
+function _addPointerMove(obj, handler, id) {
+ var onMove = function (e) {
+ // don't fire touch moves when mouse isn't down
+ if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; }
+
+ _handlePointer(e, handler);
+ };
+
+ obj['_leaflet_touchmove' + id] = onMove;
+ obj.addEventListener(POINTER_MOVE, onMove, false);
+}
+
+function _addPointerEnd(obj, handler, id) {
+ var onUp = function (e) {
+ _handlePointer(e, handler);
+ };
+
+ obj['_leaflet_touchend' + id] = onUp;
+ obj.addEventListener(POINTER_UP, onUp, false);
+ obj.addEventListener(POINTER_CANCEL, onUp, false);
+}
+
/*
* Extends the event handling code with double tap support for mobile browsers.
*/
@@ -2198,8 +2198,8 @@ function removeDoubleTapListener(obj, id) {
}
return this;
-}
-
+}
+
/*
* @namespace DomUtil
*
@@ -2284,7 +2284,7 @@ function empty(el) {
// Makes `el` the last child of its parent, so it renders in front of the other children.
function toFront(el) {
var parent = el.parentNode;
- if (parent.lastChild !== el) {
+ if (parent && parent.lastChild !== el) {
parent.appendChild(el);
}
}
@@ -2293,7 +2293,7 @@ function toFront(el) {
// Makes `el` the first child of its parent, so it renders behind the other children.
function toBack(el) {
var parent = el.parentNode;
- if (parent.firstChild !== el) {
+ if (parent && parent.firstChild !== el) {
parent.insertBefore(el, parent.firstChild);
}
}
@@ -2346,6 +2346,11 @@ function setClass(el, name) {
// @function getClass(el: HTMLElement): String
// Returns the element's class.
function getClass(el) {
+ // Check if the element is an SVGElementInstance and use the correspondingElement instead
+ // (Required for linked SVG elements in IE11.)
+ if (el.correspondingElement) {
+ el = el.correspondingElement;
+ }
return el.className.baseVal === undefined ? el.className : el.className.baseVal;
}
@@ -2489,7 +2494,7 @@ function enableImageDrag() {
off(window, 'dragstart', preventDefault);
}
-var _outlineElement;
+var _outlineElement;
var _outlineStyle;
// @function preventOutline(el: HTMLElement)
// Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline)
@@ -2540,39 +2545,39 @@ function getScale(element) {
boundingClientRect: rect
};
}
-
-
-var DomUtil = (Object.freeze || Object)({
- TRANSFORM: TRANSFORM,
- TRANSITION: TRANSITION,
- TRANSITION_END: TRANSITION_END,
- get: get,
- getStyle: getStyle,
- create: create$1,
- remove: remove,
- empty: empty,
- toFront: toFront,
- toBack: toBack,
- hasClass: hasClass,
- addClass: addClass,
- removeClass: removeClass,
- setClass: setClass,
- getClass: getClass,
- setOpacity: setOpacity,
- testProp: testProp,
- setTransform: setTransform,
- setPosition: setPosition,
- getPosition: getPosition,
- disableTextSelection: disableTextSelection,
- enableTextSelection: enableTextSelection,
- disableImageDrag: disableImageDrag,
- enableImageDrag: enableImageDrag,
- preventOutline: preventOutline,
- restoreOutline: restoreOutline,
- getSizedParentNode: getSizedParentNode,
- getScale: getScale
-});
-
+
+
+var DomUtil = (Object.freeze || Object)({
+ TRANSFORM: TRANSFORM,
+ TRANSITION: TRANSITION,
+ TRANSITION_END: TRANSITION_END,
+ get: get,
+ getStyle: getStyle,
+ create: create$1,
+ remove: remove,
+ empty: empty,
+ toFront: toFront,
+ toBack: toBack,
+ hasClass: hasClass,
+ addClass: addClass,
+ removeClass: removeClass,
+ setClass: setClass,
+ getClass: getClass,
+ setOpacity: setOpacity,
+ testProp: testProp,
+ setTransform: setTransform,
+ setPosition: setPosition,
+ getPosition: getPosition,
+ disableTextSelection: disableTextSelection,
+ enableTextSelection: enableTextSelection,
+ disableImageDrag: disableImageDrag,
+ enableImageDrag: enableImageDrag,
+ preventOutline: preventOutline,
+ restoreOutline: restoreOutline,
+ getSizedParentNode: getSizedParentNode,
+ getScale: getScale
+});
+
/*
* @namespace DomEvent
* Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally.
@@ -2876,121 +2881,121 @@ function filterClick(e, handler) {
}
-
-
-var DomEvent = (Object.freeze || Object)({
- on: on,
- off: off,
- stopPropagation: stopPropagation,
- disableScrollPropagation: disableScrollPropagation,
- disableClickPropagation: disableClickPropagation,
- preventDefault: preventDefault,
- stop: stop,
- getMousePosition: getMousePosition,
- getWheelDelta: getWheelDelta,
- fakeStop: fakeStop,
- skipped: skipped,
- isExternalTarget: isExternalTarget,
- addListener: on,
- removeListener: off
-});
-
-/*
- * @class PosAnimation
- * @aka L.PosAnimation
- * @inherits Evented
- * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.
- *
- * @example
- * ```js
- * var fx = new L.PosAnimation();
- * fx.run(el, [300, 500], 0.5);
- * ```
- *
- * @constructor L.PosAnimation()
- * Creates a `PosAnimation` object.
- *
- */
-
-var PosAnimation = Evented.extend({
-
- // @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number)
- // Run an animation of a given element to a new position, optionally setting
- // duration in seconds (`0.25` by default) and easing linearity factor (3rd
- // argument of the [cubic bezier curve](http://cubic-bezier.com/#0,0,.5,1),
- // `0.5` by default).
- run: function (el, newPos, duration, easeLinearity) {
- this.stop();
-
- this._el = el;
- this._inProgress = true;
- this._duration = duration || 0.25;
- this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);
-
- this._startPos = getPosition(el);
- this._offset = newPos.subtract(this._startPos);
- this._startTime = +new Date();
-
- // @event start: Event
- // Fired when the animation starts
- this.fire('start');
-
- this._animate();
- },
-
- // @method stop()
- // Stops the animation (if currently running).
- stop: function () {
- if (!this._inProgress) { return; }
-
- this._step(true);
- this._complete();
- },
-
- _animate: function () {
- // animation loop
- this._animId = requestAnimFrame(this._animate, this);
- this._step();
- },
-
- _step: function (round) {
- var elapsed = (+new Date()) - this._startTime,
- duration = this._duration * 1000;
-
- if (elapsed < duration) {
- this._runFrame(this._easeOut(elapsed / duration), round);
- } else {
- this._runFrame(1);
- this._complete();
- }
- },
-
- _runFrame: function (progress, round) {
- var pos = this._startPos.add(this._offset.multiplyBy(progress));
- if (round) {
- pos._round();
- }
- setPosition(this._el, pos);
-
- // @event step: Event
- // Fired continuously during the animation.
- this.fire('step');
- },
-
- _complete: function () {
- cancelAnimFrame(this._animId);
-
- this._inProgress = false;
- // @event end: Event
- // Fired when the animation ends.
- this.fire('end');
- },
-
- _easeOut: function (t) {
- return 1 - Math.pow(1 - t, this._easeOutPower);
- }
-});
-
+
+
+var DomEvent = (Object.freeze || Object)({
+ on: on,
+ off: off,
+ stopPropagation: stopPropagation,
+ disableScrollPropagation: disableScrollPropagation,
+ disableClickPropagation: disableClickPropagation,
+ preventDefault: preventDefault,
+ stop: stop,
+ getMousePosition: getMousePosition,
+ getWheelDelta: getWheelDelta,
+ fakeStop: fakeStop,
+ skipped: skipped,
+ isExternalTarget: isExternalTarget,
+ addListener: on,
+ removeListener: off
+});
+
+/*
+ * @class PosAnimation
+ * @aka L.PosAnimation
+ * @inherits Evented
+ * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.
+ *
+ * @example
+ * ```js
+ * var fx = new L.PosAnimation();
+ * fx.run(el, [300, 500], 0.5);
+ * ```
+ *
+ * @constructor L.PosAnimation()
+ * Creates a `PosAnimation` object.
+ *
+ */
+
+var PosAnimation = Evented.extend({
+
+ // @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number)
+ // Run an animation of a given element to a new position, optionally setting
+ // duration in seconds (`0.25` by default) and easing linearity factor (3rd
+ // argument of the [cubic bezier curve](http://cubic-bezier.com/#0,0,.5,1),
+ // `0.5` by default).
+ run: function (el, newPos, duration, easeLinearity) {
+ this.stop();
+
+ this._el = el;
+ this._inProgress = true;
+ this._duration = duration || 0.25;
+ this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);
+
+ this._startPos = getPosition(el);
+ this._offset = newPos.subtract(this._startPos);
+ this._startTime = +new Date();
+
+ // @event start: Event
+ // Fired when the animation starts
+ this.fire('start');
+
+ this._animate();
+ },
+
+ // @method stop()
+ // Stops the animation (if currently running).
+ stop: function () {
+ if (!this._inProgress) { return; }
+
+ this._step(true);
+ this._complete();
+ },
+
+ _animate: function () {
+ // animation loop
+ this._animId = requestAnimFrame(this._animate, this);
+ this._step();
+ },
+
+ _step: function (round) {
+ var elapsed = (+new Date()) - this._startTime,
+ duration = this._duration * 1000;
+
+ if (elapsed < duration) {
+ this._runFrame(this._easeOut(elapsed / duration), round);
+ } else {
+ this._runFrame(1);
+ this._complete();
+ }
+ },
+
+ _runFrame: function (progress, round) {
+ var pos = this._startPos.add(this._offset.multiplyBy(progress));
+ if (round) {
+ pos._round();
+ }
+ setPosition(this._el, pos);
+
+ // @event step: Event
+ // Fired continuously during the animation.
+ this.fire('step');
+ },
+
+ _complete: function () {
+ cancelAnimFrame(this._animId);
+
+ this._inProgress = false;
+ // @event end: Event
+ // Fired when the animation ends.
+ this.fire('end');
+ },
+
+ _easeOut: function (t) {
+ return 1 - Math.pow(1 - t, this._easeOutPower);
+ }
+});
+
/*
* @class Map
* @aka L.Map
@@ -3107,6 +3112,13 @@ var Map = Evented.extend({
initialize: function (id, options) { // (HTMLElement or String, Object)
options = setOptions(this, options);
+ // Make sure to assign internal flags at the beginning,
+ // to avoid inconsistent state in some edge cases.
+ this._handlers = [];
+ this._layers = {};
+ this._zoomBoundLayers = {};
+ this._sizeChanged = true;
+
this._initContainer(id);
this._initLayout();
@@ -3127,11 +3139,6 @@ var Map = Evented.extend({
this.setView(toLatLng(options.center), options.zoom, {reset: true});
}
- this._handlers = [];
- this._layers = {};
- this._zoomBoundLayers = {};
- this._sizeChanged = true;
-
this.callInitHooks();
// don't animate on browsers without hardware-accelerated transitions or old Android/Opera
@@ -3490,6 +3497,51 @@ var Map = Evented.extend({
return this;
},
+ // @method panInside(latlng: LatLng, options?: options): this
+ // Pans the map the minimum amount to make the `latlng` visible. Use
+ // `padding`, `paddingTopLeft` and `paddingTopRight` options to fit
+ // the display to more restricted bounds, like [`fitBounds`](#map-fitbounds).
+ // If `latlng` is already within the (optionally padded) display bounds,
+ // the map will not be panned.
+ panInside: function (latlng, options) {
+ options = options || {};
+
+ var paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),
+ paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),
+ center = this.getCenter(),
+ pixelCenter = this.project(center),
+ pixelPoint = this.project(latlng),
+ pixelBounds = this.getPixelBounds(),
+ halfPixelBounds = pixelBounds.getSize().divideBy(2),
+ paddedBounds = toBounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]);
+
+ if (!paddedBounds.contains(pixelPoint)) {
+ this._enforcingBounds = true;
+ var diff = pixelCenter.subtract(pixelPoint),
+ newCenter = toPoint(pixelPoint.x + diff.x, pixelPoint.y + diff.y);
+
+ if (pixelPoint.x < paddedBounds.min.x || pixelPoint.x > paddedBounds.max.x) {
+ newCenter.x = pixelCenter.x - diff.x;
+ if (diff.x > 0) {
+ newCenter.x += halfPixelBounds.x - paddingTL.x;
+ } else {
+ newCenter.x -= halfPixelBounds.x - paddingBR.x;
+ }
+ }
+ if (pixelPoint.y < paddedBounds.min.y || pixelPoint.y > paddedBounds.max.y) {
+ newCenter.y = pixelCenter.y - diff.y;
+ if (diff.y > 0) {
+ newCenter.y += halfPixelBounds.y - paddingTL.y;
+ } else {
+ newCenter.y -= halfPixelBounds.y - paddingBR.y;
+ }
+ }
+ this.panTo(this.unproject(newCenter), options);
+ this._enforcingBounds = false;
+ }
+ return this;
+ },
+
// @method invalidateSize(options: Zoom/pan options): this
// Checks if the map container size changed and updates the map if so —
// call it after you've changed the map size dynamically, also animating
@@ -4608,7 +4660,7 @@ var Map = Evented.extend({
}
// @event zoomanim: ZoomAnimEvent
- // Fired on every frame of a zoom animation
+ // Fired at least once per zoom animation. For continous zoom, like pinch zooming, fired once per frame during zoom.
this.fire('zoomanim', {
center: center,
zoom: zoom,
@@ -4649,8 +4701,8 @@ var Map = Evented.extend({
// and optionally an object literal with `Map options`.
function createMap(id, options) {
return new Map(id, options);
-}
-
+}
+
/*
* @class Control
* @aka L.Control
@@ -4815,8 +4867,8 @@ Map.include({
delete this._controlCorners;
delete this._controlContainer;
}
-});
-
+});
+
/*
* @class Control.Layers
* @aka L.Control.Layers
@@ -4964,13 +5016,13 @@ var Layers = Control.extend({
// Expand the control container if collapsed.
expand: function () {
addClass(this._container, 'leaflet-control-layers-expanded');
- this._form.style.height = null;
+ this._section.style.height = null;
var acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50);
- if (acceptableHeight < this._form.clientHeight) {
- addClass(this._form, 'leaflet-control-layers-scrollbar');
- this._form.style.height = acceptableHeight + 'px';
+ if (acceptableHeight < this._section.clientHeight) {
+ addClass(this._section, 'leaflet-control-layers-scrollbar');
+ this._section.style.height = acceptableHeight + 'px';
} else {
- removeClass(this._form, 'leaflet-control-layers-scrollbar');
+ removeClass(this._section, 'leaflet-control-layers-scrollbar');
}
this._checkDisabledLayers();
return this;
@@ -4994,7 +5046,7 @@ var Layers = Control.extend({
disableClickPropagation(container);
disableScrollPropagation(container);
- var form = this._form = create$1('form', className + '-list');
+ var section = this._section = create$1('section', className + '-list');
if (collapsed) {
this._map.on('click', this.collapse, this);
@@ -5022,11 +5074,11 @@ var Layers = Control.extend({
this.expand();
}
- this._baseLayersList = create$1('div', className + '-base', form);
- this._separator = create$1('div', className + '-separator', form);
- this._overlaysList = create$1('div', className + '-overlays', form);
+ this._baseLayersList = create$1('div', className + '-base', section);
+ this._separator = create$1('div', className + '-separator', section);
+ this._overlaysList = create$1('div', className + '-overlays', section);
- container.appendChild(form);
+ container.appendChild(section);
},
_getLayer: function (id) {
@@ -5240,8 +5292,8 @@ var Layers = Control.extend({
// Creates an attribution control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation.
var layers = function (baseLayers, overlays, options) {
return new Layers(baseLayers, overlays, options);
-};
-
+};
+
/*
* @class Control.Zoom
* @aka L.Control.Zoom
@@ -5377,137 +5429,137 @@ Map.addInitHook(function () {
// Creates a zoom control
var zoom = function (options) {
return new Zoom(options);
-};
-
-/*
- * @class Control.Scale
- * @aka L.Control.Scale
- * @inherits Control
- *
- * A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends `Control`.
- *
- * @example
- *
- * ```js
- * L.control.scale().addTo(map);
- * ```
- */
-
-var Scale = Control.extend({
- // @section
- // @aka Control.Scale options
- options: {
- position: 'bottomleft',
-
- // @option maxWidth: Number = 100
- // Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).
- maxWidth: 100,
-
- // @option metric: Boolean = True
- // Whether to show the metric scale line (m/km).
- metric: true,
-
- // @option imperial: Boolean = True
- // Whether to show the imperial scale line (mi/ft).
- imperial: true
-
- // @option updateWhenIdle: Boolean = false
- // If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)).
- },
-
- onAdd: function (map) {
- var className = 'leaflet-control-scale',
- container = create$1('div', className),
- options = this.options;
-
- this._addScales(options, className + '-line', container);
-
- map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
- map.whenReady(this._update, this);
-
- return container;
- },
-
- onRemove: function (map) {
- map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
- },
-
- _addScales: function (options, className, container) {
- if (options.metric) {
- this._mScale = create$1('div', className, container);
- }
- if (options.imperial) {
- this._iScale = create$1('div', className, container);
- }
- },
-
- _update: function () {
- var map = this._map,
- y = map.getSize().y / 2;
-
- var maxMeters = map.distance(
- map.containerPointToLatLng([0, y]),
- map.containerPointToLatLng([this.options.maxWidth, y]));
-
- this._updateScales(maxMeters);
- },
-
- _updateScales: function (maxMeters) {
- if (this.options.metric && maxMeters) {
- this._updateMetric(maxMeters);
- }
- if (this.options.imperial && maxMeters) {
- this._updateImperial(maxMeters);
- }
- },
-
- _updateMetric: function (maxMeters) {
- var meters = this._getRoundNum(maxMeters),
- label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';
-
- this._updateScale(this._mScale, label, meters / maxMeters);
- },
-
- _updateImperial: function (maxMeters) {
- var maxFeet = maxMeters * 3.2808399,
- maxMiles, miles, feet;
-
- if (maxFeet > 5280) {
- maxMiles = maxFeet / 5280;
- miles = this._getRoundNum(maxMiles);
- this._updateScale(this._iScale, miles + ' mi', miles / maxMiles);
-
- } else {
- feet = this._getRoundNum(maxFeet);
- this._updateScale(this._iScale, feet + ' ft', feet / maxFeet);
- }
- },
-
- _updateScale: function (scale, text, ratio) {
- scale.style.width = Math.round(this.options.maxWidth * ratio) + 'px';
- scale.innerHTML = text;
- },
-
- _getRoundNum: function (num) {
- var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),
- d = num / pow10;
-
- d = d >= 10 ? 10 :
- d >= 5 ? 5 :
- d >= 3 ? 3 :
- d >= 2 ? 2 : 1;
-
- return pow10 * d;
- }
-});
-
-
-// @factory L.control.scale(options?: Control.Scale options)
-// Creates an scale control with the given options.
-var scale = function (options) {
- return new Scale(options);
-};
-
+};
+
+/*
+ * @class Control.Scale
+ * @aka L.Control.Scale
+ * @inherits Control
+ *
+ * A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends `Control`.
+ *
+ * @example
+ *
+ * ```js
+ * L.control.scale().addTo(map);
+ * ```
+ */
+
+var Scale = Control.extend({
+ // @section
+ // @aka Control.Scale options
+ options: {
+ position: 'bottomleft',
+
+ // @option maxWidth: Number = 100
+ // Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).
+ maxWidth: 100,
+
+ // @option metric: Boolean = True
+ // Whether to show the metric scale line (m/km).
+ metric: true,
+
+ // @option imperial: Boolean = True
+ // Whether to show the imperial scale line (mi/ft).
+ imperial: true
+
+ // @option updateWhenIdle: Boolean = false
+ // If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)).
+ },
+
+ onAdd: function (map) {
+ var className = 'leaflet-control-scale',
+ container = create$1('div', className),
+ options = this.options;
+
+ this._addScales(options, className + '-line', container);
+
+ map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
+ map.whenReady(this._update, this);
+
+ return container;
+ },
+
+ onRemove: function (map) {
+ map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);
+ },
+
+ _addScales: function (options, className, container) {
+ if (options.metric) {
+ this._mScale = create$1('div', className, container);
+ }
+ if (options.imperial) {
+ this._iScale = create$1('div', className, container);
+ }
+ },
+
+ _update: function () {
+ var map = this._map,
+ y = map.getSize().y / 2;
+
+ var maxMeters = map.distance(
+ map.containerPointToLatLng([0, y]),
+ map.containerPointToLatLng([this.options.maxWidth, y]));
+
+ this._updateScales(maxMeters);
+ },
+
+ _updateScales: function (maxMeters) {
+ if (this.options.metric && maxMeters) {
+ this._updateMetric(maxMeters);
+ }
+ if (this.options.imperial && maxMeters) {
+ this._updateImperial(maxMeters);
+ }
+ },
+
+ _updateMetric: function (maxMeters) {
+ var meters = this._getRoundNum(maxMeters),
+ label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';
+
+ this._updateScale(this._mScale, label, meters / maxMeters);
+ },
+
+ _updateImperial: function (maxMeters) {
+ var maxFeet = maxMeters * 3.2808399,
+ maxMiles, miles, feet;
+
+ if (maxFeet > 5280) {
+ maxMiles = maxFeet / 5280;
+ miles = this._getRoundNum(maxMiles);
+ this._updateScale(this._iScale, miles + ' mi', miles / maxMiles);
+
+ } else {
+ feet = this._getRoundNum(maxFeet);
+ this._updateScale(this._iScale, feet + ' ft', feet / maxFeet);
+ }
+ },
+
+ _updateScale: function (scale, text, ratio) {
+ scale.style.width = Math.round(this.options.maxWidth * ratio) + 'px';
+ scale.innerHTML = text;
+ },
+
+ _getRoundNum: function (num) {
+ var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),
+ d = num / pow10;
+
+ d = d >= 10 ? 10 :
+ d >= 5 ? 5 :
+ d >= 3 ? 3 :
+ d >= 2 ? 2 : 1;
+
+ return pow10 * d;
+ }
+});
+
+
+// @factory L.control.scale(options?: Control.Scale options)
+// Creates an scale control with the given options.
+var scale = function (options) {
+ return new Scale(options);
+};
+
/*
* @class Control.Attribution
* @aka L.Control.Attribution
@@ -5629,76 +5681,76 @@ Map.addInitHook(function () {
// Creates an attribution control.
var attribution = function (options) {
return new Attribution(options);
-};
-
-Control.Layers = Layers;
-Control.Zoom = Zoom;
-Control.Scale = Scale;
-Control.Attribution = Attribution;
-
-control.layers = layers;
-control.zoom = zoom;
-control.scale = scale;
-control.attribution = attribution;
-
-/*
- L.Handler is a base class for handler classes that are used internally to inject
- interaction features like dragging to classes like Map and Marker.
-*/
-
-// @class Handler
-// @aka L.Handler
-// Abstract class for map interaction handlers
-
-var Handler = Class.extend({
- initialize: function (map) {
- this._map = map;
- },
-
- // @method enable(): this
- // Enables the handler
- enable: function () {
- if (this._enabled) { return this; }
-
- this._enabled = true;
- this.addHooks();
- return this;
- },
-
- // @method disable(): this
- // Disables the handler
- disable: function () {
- if (!this._enabled) { return this; }
-
- this._enabled = false;
- this.removeHooks();
- return this;
- },
-
- // @method enabled(): Boolean
- // Returns `true` if the handler is enabled
- enabled: function () {
- return !!this._enabled;
- }
-
- // @section Extension methods
- // Classes inheriting from `Handler` must implement the two following methods:
- // @method addHooks()
- // Called when the handler is enabled, should add event hooks.
- // @method removeHooks()
- // Called when the handler is disabled, should remove the event hooks added previously.
-});
-
-// @section There is static function which can be called without instantiating L.Handler:
-// @function addTo(map: Map, name: String): this
-// Adds a new Handler to the given map with the given name.
-Handler.addTo = function (map, name) {
- map.addHandler(name, this);
- return this;
-};
-
-var Mixin = {Events: Events};
-
+};
+
+Control.Layers = Layers;
+Control.Zoom = Zoom;
+Control.Scale = Scale;
+Control.Attribution = Attribution;
+
+control.layers = layers;
+control.zoom = zoom;
+control.scale = scale;
+control.attribution = attribution;
+
+/*
+ L.Handler is a base class for handler classes that are used internally to inject
+ interaction features like dragging to classes like Map and Marker.
+*/
+
+// @class Handler
+// @aka L.Handler
+// Abstract class for map interaction handlers
+
+var Handler = Class.extend({
+ initialize: function (map) {
+ this._map = map;
+ },
+
+ // @method enable(): this
+ // Enables the handler
+ enable: function () {
+ if (this._enabled) { return this; }
+
+ this._enabled = true;
+ this.addHooks();
+ return this;
+ },
+
+ // @method disable(): this
+ // Disables the handler
+ disable: function () {
+ if (!this._enabled) { return this; }
+
+ this._enabled = false;
+ this.removeHooks();
+ return this;
+ },
+
+ // @method enabled(): Boolean
+ // Returns `true` if the handler is enabled
+ enabled: function () {
+ return !!this._enabled;
+ }
+
+ // @section Extension methods
+ // Classes inheriting from `Handler` must implement the two following methods:
+ // @method addHooks()
+ // Called when the handler is enabled, should add event hooks.
+ // @method removeHooks()
+ // Called when the handler is disabled, should remove the event hooks added previously.
+});
+
+// @section There is static function which can be called without instantiating L.Handler:
+// @function addTo(map: Map, name: String): this
+// Adds a new Handler to the given map with the given name.
+Handler.addTo = function (map, name) {
+ map.addHandler(name, this);
+ return this;
+};
+
+var Mixin = {Events: Events};
+
/*
* @class Draggable
* @aka L.Draggable
@@ -5927,8 +5979,8 @@ var Draggable = Evented.extend({
Draggable._dragging = false;
}
-});
-
+});
+
/*
* @namespace LineUtil
*
@@ -6167,20 +6219,20 @@ function _flat(latlngs) {
console.warn('Deprecated use of _flat, please use L.LineUtil.isFlat instead.');
return isFlat(latlngs);
}
-
-
-var LineUtil = (Object.freeze || Object)({
- simplify: simplify,
- pointToSegmentDistance: pointToSegmentDistance,
- closestPointOnSegment: closestPointOnSegment,
- clipSegment: clipSegment,
- _getEdgeIntersection: _getEdgeIntersection,
- _getBitCode: _getBitCode,
- _sqClosestPointOnSegment: _sqClosestPointOnSegment,
- isFlat: isFlat,
- _flat: _flat
-});
-
+
+
+var LineUtil = (Object.freeze || Object)({
+ simplify: simplify,
+ pointToSegmentDistance: pointToSegmentDistance,
+ closestPointOnSegment: closestPointOnSegment,
+ clipSegment: clipSegment,
+ _getEdgeIntersection: _getEdgeIntersection,
+ _getBitCode: _getBitCode,
+ _sqClosestPointOnSegment: _sqClosestPointOnSegment,
+ isFlat: isFlat,
+ _flat: _flat
+});
+
/*
* @namespace PolyUtil
* Various utility functions for polygon geometries.
@@ -6234,12 +6286,12 @@ function clipPolygon(points, bounds, round) {
return points;
}
-
-
-var PolyUtil = (Object.freeze || Object)({
- clipPolygon: clipPolygon
-});
-
+
+
+var PolyUtil = (Object.freeze || Object)({
+ clipPolygon: clipPolygon
+});
+
/*
* @namespace Projection
* @section
@@ -6263,8 +6315,8 @@ var LonLat = {
},
bounds: new Bounds([-180, -90], [180, 90])
-};
-
+};
+
/*
* @namespace Projection
* @projection L.Projection.Mercator
@@ -6309,40 +6361,40 @@ var Mercator = {
return new LatLng(phi * d, point.x * d / r);
}
-};
-
-/*
- * @class Projection
-
- * An object with methods for projecting geographical coordinates of the world onto
- * a flat surface (and back). See [Map projection](http://en.wikipedia.org/wiki/Map_projection).
-
- * @property bounds: Bounds
- * The bounds (specified in CRS units) where the projection is valid
-
- * @method project(latlng: LatLng): Point
- * Projects geographical coordinates into a 2D point.
- * Only accepts actual `L.LatLng` instances, not arrays.
-
- * @method unproject(point: Point): LatLng
- * The inverse of `project`. Projects a 2D point into a geographical location.
- * Only accepts actual `L.Point` instances, not arrays.
-
- * Note that the projection instances do not inherit from Leafet's `Class` object,
- * and can't be instantiated. Also, new classes can't inherit from them,
- * and methods can't be added to them with the `include` function.
-
- */
-
-
-
-
-var index = (Object.freeze || Object)({
- LonLat: LonLat,
- Mercator: Mercator,
- SphericalMercator: SphericalMercator
-});
-
+};
+
+/*
+ * @class Projection
+
+ * An object with methods for projecting geographical coordinates of the world onto
+ * a flat surface (and back). See [Map projection](http://en.wikipedia.org/wiki/Map_projection).
+
+ * @property bounds: Bounds
+ * The bounds (specified in CRS units) where the projection is valid
+
+ * @method project(latlng: LatLng): Point
+ * Projects geographical coordinates into a 2D point.
+ * Only accepts actual `L.LatLng` instances, not arrays.
+
+ * @method unproject(point: Point): LatLng
+ * The inverse of `project`. Projects a 2D point into a geographical location.
+ * Only accepts actual `L.Point` instances, not arrays.
+
+ * Note that the projection instances do not inherit from Leafet's `Class` object,
+ * and can't be instantiated. Also, new classes can't inherit from them,
+ * and methods can't be added to them with the `include` function.
+
+ */
+
+
+
+
+var index = (Object.freeze || Object)({
+ LonLat: LonLat,
+ Mercator: Mercator,
+ SphericalMercator: SphericalMercator
+});
+
/*
* @namespace CRS
* @crs L.CRS.EPSG3395
@@ -6357,8 +6409,8 @@ var EPSG3395 = extend({}, Earth, {
var scale = 0.5 / (Math.PI * Mercator.R);
return toTransformation(scale, 0.5, -scale, 0.5);
}())
-});
-
+});
+
/*
* @namespace CRS
* @crs L.CRS.EPSG4326
@@ -6376,323 +6428,323 @@ var EPSG4326 = extend({}, Earth, {
code: 'EPSG:4326',
projection: LonLat,
transformation: toTransformation(1 / 180, 1, -1 / 180, 0.5)
-});
-
-/*
- * @namespace CRS
- * @crs L.CRS.Simple
- *
- * A simple CRS that maps longitude and latitude into `x` and `y` directly.
- * May be used for maps of flat surfaces (e.g. game maps). Note that the `y`
- * axis should still be inverted (going from bottom to top). `distance()` returns
- * simple euclidean distance.
- */
-
-var Simple = extend({}, CRS, {
- projection: LonLat,
- transformation: toTransformation(1, 0, -1, 0),
-
- scale: function (zoom) {
- return Math.pow(2, zoom);
- },
-
- zoom: function (scale) {
- return Math.log(scale) / Math.LN2;
- },
-
- distance: function (latlng1, latlng2) {
- var dx = latlng2.lng - latlng1.lng,
- dy = latlng2.lat - latlng1.lat;
-
- return Math.sqrt(dx * dx + dy * dy);
- },
-
- infinite: true
-});
-
-CRS.Earth = Earth;
-CRS.EPSG3395 = EPSG3395;
-CRS.EPSG3857 = EPSG3857;
-CRS.EPSG900913 = EPSG900913;
-CRS.EPSG4326 = EPSG4326;
-CRS.Simple = Simple;
-
-/*
- * @class Layer
- * @inherits Evented
- * @aka L.Layer
- * @aka ILayer
- *
- * A set of methods from the Layer base class that all Leaflet layers use.
- * Inherits all methods, options and events from `L.Evented`.
- *
- * @example
- *
- * ```js
- * var layer = L.Marker(latlng).addTo(map);
- * layer.addTo(map);
- * layer.remove();
- * ```
- *
- * @event add: Event
- * Fired after the layer is added to a map
- *
- * @event remove: Event
- * Fired after the layer is removed from a map
- */
-
-
-var Layer = Evented.extend({
-
- // Classes extending `L.Layer` will inherit the following options:
- options: {
- // @option pane: String = 'overlayPane'
- // By default the layer will be added to the map's [overlay pane](#map-overlaypane). Overriding this option will cause the layer to be placed on another pane by default.
- pane: 'overlayPane',
-
- // @option attribution: String = null
- // String to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
- attribution: null,
-
- bubblingMouseEvents: true
- },
-
- /* @section
- * Classes extending `L.Layer` will inherit the following methods:
- *
- * @method addTo(map: Map|LayerGroup): this
- * Adds the layer to the given map or layer group.
- */
- addTo: function (map) {
- map.addLayer(this);
- return this;
- },
-
- // @method remove: this
- // Removes the layer from the map it is currently active on.
- remove: function () {
- return this.removeFrom(this._map || this._mapToAdd);
- },
-
- // @method removeFrom(map: Map): this
- // Removes the layer from the given map
- removeFrom: function (obj) {
- if (obj) {
- obj.removeLayer(this);
- }
- return this;
- },
-
- // @method getPane(name? : String): HTMLElement
- // Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer.
- getPane: function (name) {
- return this._map.getPane(name ? (this.options[name] || name) : this.options.pane);
- },
-
- addInteractiveTarget: function (targetEl) {
- this._map._targets[stamp(targetEl)] = this;
- return this;
- },
-
- removeInteractiveTarget: function (targetEl) {
- delete this._map._targets[stamp(targetEl)];
- return this;
- },
-
- // @method getAttribution: String
- // Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution).
- getAttribution: function () {
- return this.options.attribution;
- },
-
- _layerAdd: function (e) {
- var map = e.target;
-
- // check in case layer gets added and then removed before the map is ready
- if (!map.hasLayer(this)) { return; }
-
- this._map = map;
- this._zoomAnimated = map._zoomAnimated;
-
- if (this.getEvents) {
- var events = this.getEvents();
- map.on(events, this);
- this.once('remove', function () {
- map.off(events, this);
- }, this);
- }
-
- this.onAdd(map);
-
- if (this.getAttribution && map.attributionControl) {
- map.attributionControl.addAttribution(this.getAttribution());
- }
-
- this.fire('add');
- map.fire('layeradd', {layer: this});
- }
-});
-
-/* @section Extension methods
- * @uninheritable
- *
- * Every layer should extend from `L.Layer` and (re-)implement the following methods.
- *
- * @method onAdd(map: Map): this
- * Should contain code that creates DOM elements for the layer, adds them to `map panes` where they should belong and puts listeners on relevant map events. Called on [`map.addLayer(layer)`](#map-addlayer).
- *
- * @method onRemove(map: Map): this
- * Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in [`onAdd`](#layer-onadd). Called on [`map.removeLayer(layer)`](#map-removelayer).
- *
- * @method getEvents(): Object
- * This optional method should return an object like `{ viewreset: this._reset }` for [`addEventListener`](#evented-addeventlistener). The event handlers in this object will be automatically added and removed from the map with your layer.
- *
- * @method getAttribution(): String
- * This optional method should return a string containing HTML to be shown on the `Attribution control` whenever the layer is visible.
- *
- * @method beforeAdd(map: Map): this
- * Optional method. Called on [`map.addLayer(layer)`](#map-addlayer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.
- */
-
-
-/* @namespace Map
- * @section Layer events
- *
- * @event layeradd: LayerEvent
- * Fired when a new layer is added to the map.
- *
- * @event layerremove: LayerEvent
- * Fired when some layer is removed from the map
- *
- * @section Methods for Layers and Controls
- */
-Map.include({
- // @method addLayer(layer: Layer): this
- // Adds the given layer to the map
- addLayer: function (layer) {
- if (!layer._layerAdd) {
- throw new Error('The provided object is not a Layer.');
- }
-
- var id = stamp(layer);
- if (this._layers[id]) { return this; }
- this._layers[id] = layer;
-
- layer._mapToAdd = this;
-
- if (layer.beforeAdd) {
- layer.beforeAdd(this);
- }
-
- this.whenReady(layer._layerAdd, layer);
-
- return this;
- },
-
- // @method removeLayer(layer: Layer): this
- // Removes the given layer from the map.
- removeLayer: function (layer) {
- var id = stamp(layer);
-
- if (!this._layers[id]) { return this; }
-
- if (this._loaded) {
- layer.onRemove(this);
- }
-
- if (layer.getAttribution && this.attributionControl) {
- this.attributionControl.removeAttribution(layer.getAttribution());
- }
-
- delete this._layers[id];
-
- if (this._loaded) {
- this.fire('layerremove', {layer: layer});
- layer.fire('remove');
- }
-
- layer._map = layer._mapToAdd = null;
-
- return this;
- },
-
- // @method hasLayer(layer: Layer): Boolean
- // Returns `true` if the given layer is currently added to the map
- hasLayer: function (layer) {
- return !!layer && (stamp(layer) in this._layers);
- },
-
- /* @method eachLayer(fn: Function, context?: Object): this
- * Iterates over the layers of the map, optionally specifying context of the iterator function.
- * ```
- * map.eachLayer(function(layer){
- * layer.bindPopup('Hello');
- * });
- * ```
- */
- eachLayer: function (method, context) {
- for (var i in this._layers) {
- method.call(context, this._layers[i]);
- }
- return this;
- },
-
- _addLayers: function (layers) {
- layers = layers ? (isArray(layers) ? layers : [layers]) : [];
-
- for (var i = 0, len = layers.length; i < len; i++) {
- this.addLayer(layers[i]);
- }
- },
-
- _addZoomLimit: function (layer) {
- if (isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) {
- this._zoomBoundLayers[stamp(layer)] = layer;
- this._updateZoomLevels();
- }
- },
-
- _removeZoomLimit: function (layer) {
- var id = stamp(layer);
-
- if (this._zoomBoundLayers[id]) {
- delete this._zoomBoundLayers[id];
- this._updateZoomLevels();
- }
- },
-
- _updateZoomLevels: function () {
- var minZoom = Infinity,
- maxZoom = -Infinity,
- oldZoomSpan = this._getZoomSpan();
-
- for (var i in this._zoomBoundLayers) {
- var options = this._zoomBoundLayers[i].options;
-
- minZoom = options.minZoom === undefined ? minZoom : Math.min(minZoom, options.minZoom);
- maxZoom = options.maxZoom === undefined ? maxZoom : Math.max(maxZoom, options.maxZoom);
- }
-
- this._layersMaxZoom = maxZoom === -Infinity ? undefined : maxZoom;
- this._layersMinZoom = minZoom === Infinity ? undefined : minZoom;
-
- // @section Map state change events
- // @event zoomlevelschange: Event
- // Fired when the number of zoomlevels on the map is changed due
- // to adding or removing a layer.
- if (oldZoomSpan !== this._getZoomSpan()) {
- this.fire('zoomlevelschange');
- }
-
- if (this.options.maxZoom === undefined && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) {
- this.setZoom(this._layersMaxZoom);
- }
- if (this.options.minZoom === undefined && this._layersMinZoom && this.getZoom() < this._layersMinZoom) {
- this.setZoom(this._layersMinZoom);
- }
- }
-});
-
+});
+
+/*
+ * @namespace CRS
+ * @crs L.CRS.Simple
+ *
+ * A simple CRS that maps longitude and latitude into `x` and `y` directly.
+ * May be used for maps of flat surfaces (e.g. game maps). Note that the `y`
+ * axis should still be inverted (going from bottom to top). `distance()` returns
+ * simple euclidean distance.
+ */
+
+var Simple = extend({}, CRS, {
+ projection: LonLat,
+ transformation: toTransformation(1, 0, -1, 0),
+
+ scale: function (zoom) {
+ return Math.pow(2, zoom);
+ },
+
+ zoom: function (scale) {
+ return Math.log(scale) / Math.LN2;
+ },
+
+ distance: function (latlng1, latlng2) {
+ var dx = latlng2.lng - latlng1.lng,
+ dy = latlng2.lat - latlng1.lat;
+
+ return Math.sqrt(dx * dx + dy * dy);
+ },
+
+ infinite: true
+});
+
+CRS.Earth = Earth;
+CRS.EPSG3395 = EPSG3395;
+CRS.EPSG3857 = EPSG3857;
+CRS.EPSG900913 = EPSG900913;
+CRS.EPSG4326 = EPSG4326;
+CRS.Simple = Simple;
+
+/*
+ * @class Layer
+ * @inherits Evented
+ * @aka L.Layer
+ * @aka ILayer
+ *
+ * A set of methods from the Layer base class that all Leaflet layers use.
+ * Inherits all methods, options and events from `L.Evented`.
+ *
+ * @example
+ *
+ * ```js
+ * var layer = L.Marker(latlng).addTo(map);
+ * layer.addTo(map);
+ * layer.remove();
+ * ```
+ *
+ * @event add: Event
+ * Fired after the layer is added to a map
+ *
+ * @event remove: Event
+ * Fired after the layer is removed from a map
+ */
+
+
+var Layer = Evented.extend({
+
+ // Classes extending `L.Layer` will inherit the following options:
+ options: {
+ // @option pane: String = 'overlayPane'
+ // By default the layer will be added to the map's [overlay pane](#map-overlaypane). Overriding this option will cause the layer to be placed on another pane by default.
+ pane: 'overlayPane',
+
+ // @option attribution: String = null
+ // String to be shown in the attribution control, e.g. "© OpenStreetMap contributors". It describes the layer data and is often a legal obligation towards copyright holders and tile providers.
+ attribution: null,
+
+ bubblingMouseEvents: true
+ },
+
+ /* @section
+ * Classes extending `L.Layer` will inherit the following methods:
+ *
+ * @method addTo(map: Map|LayerGroup): this
+ * Adds the layer to the given map or layer group.
+ */
+ addTo: function (map) {
+ map.addLayer(this);
+ return this;
+ },
+
+ // @method remove: this
+ // Removes the layer from the map it is currently active on.
+ remove: function () {
+ return this.removeFrom(this._map || this._mapToAdd);
+ },
+
+ // @method removeFrom(map: Map): this
+ // Removes the layer from the given map
+ removeFrom: function (obj) {
+ if (obj) {
+ obj.removeLayer(this);
+ }
+ return this;
+ },
+
+ // @method getPane(name? : String): HTMLElement
+ // Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer.
+ getPane: function (name) {
+ return this._map.getPane(name ? (this.options[name] || name) : this.options.pane);
+ },
+
+ addInteractiveTarget: function (targetEl) {
+ this._map._targets[stamp(targetEl)] = this;
+ return this;
+ },
+
+ removeInteractiveTarget: function (targetEl) {
+ delete this._map._targets[stamp(targetEl)];
+ return this;
+ },
+
+ // @method getAttribution: String
+ // Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution).
+ getAttribution: function () {
+ return this.options.attribution;
+ },
+
+ _layerAdd: function (e) {
+ var map = e.target;
+
+ // check in case layer gets added and then removed before the map is ready
+ if (!map.hasLayer(this)) { return; }
+
+ this._map = map;
+ this._zoomAnimated = map._zoomAnimated;
+
+ if (this.getEvents) {
+ var events = this.getEvents();
+ map.on(events, this);
+ this.once('remove', function () {
+ map.off(events, this);
+ }, this);
+ }
+
+ this.onAdd(map);
+
+ if (this.getAttribution && map.attributionControl) {
+ map.attributionControl.addAttribution(this.getAttribution());
+ }
+
+ this.fire('add');
+ map.fire('layeradd', {layer: this});
+ }
+});
+
+/* @section Extension methods
+ * @uninheritable
+ *
+ * Every layer should extend from `L.Layer` and (re-)implement the following methods.
+ *
+ * @method onAdd(map: Map): this
+ * Should contain code that creates DOM elements for the layer, adds them to `map panes` where they should belong and puts listeners on relevant map events. Called on [`map.addLayer(layer)`](#map-addlayer).
+ *
+ * @method onRemove(map: Map): this
+ * Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in [`onAdd`](#layer-onadd). Called on [`map.removeLayer(layer)`](#map-removelayer).
+ *
+ * @method getEvents(): Object
+ * This optional method should return an object like `{ viewreset: this._reset }` for [`addEventListener`](#evented-addeventlistener). The event handlers in this object will be automatically added and removed from the map with your layer.
+ *
+ * @method getAttribution(): String
+ * This optional method should return a string containing HTML to be shown on the `Attribution control` whenever the layer is visible.
+ *
+ * @method beforeAdd(map: Map): this
+ * Optional method. Called on [`map.addLayer(layer)`](#map-addlayer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.
+ */
+
+
+/* @namespace Map
+ * @section Layer events
+ *
+ * @event layeradd: LayerEvent
+ * Fired when a new layer is added to the map.
+ *
+ * @event layerremove: LayerEvent
+ * Fired when some layer is removed from the map
+ *
+ * @section Methods for Layers and Controls
+ */
+Map.include({
+ // @method addLayer(layer: Layer): this
+ // Adds the given layer to the map
+ addLayer: function (layer) {
+ if (!layer._layerAdd) {
+ throw new Error('The provided object is not a Layer.');
+ }
+
+ var id = stamp(layer);
+ if (this._layers[id]) { return this; }
+ this._layers[id] = layer;
+
+ layer._mapToAdd = this;
+
+ if (layer.beforeAdd) {
+ layer.beforeAdd(this);
+ }
+
+ this.whenReady(layer._layerAdd, layer);
+
+ return this;
+ },
+
+ // @method removeLayer(layer: Layer): this
+ // Removes the given layer from the map.
+ removeLayer: function (layer) {
+ var id = stamp(layer);
+
+ if (!this._layers[id]) { return this; }
+
+ if (this._loaded) {
+ layer.onRemove(this);
+ }
+
+ if (layer.getAttribution && this.attributionControl) {
+ this.attributionControl.removeAttribution(layer.getAttribution());
+ }
+
+ delete this._layers[id];
+
+ if (this._loaded) {
+ this.fire('layerremove', {layer: layer});
+ layer.fire('remove');
+ }
+
+ layer._map = layer._mapToAdd = null;
+
+ return this;
+ },
+
+ // @method hasLayer(layer: Layer): Boolean
+ // Returns `true` if the given layer is currently added to the map
+ hasLayer: function (layer) {
+ return !!layer && (stamp(layer) in this._layers);
+ },
+
+ /* @method eachLayer(fn: Function, context?: Object): this
+ * Iterates over the layers of the map, optionally specifying context of the iterator function.
+ * ```
+ * map.eachLayer(function(layer){
+ * layer.bindPopup('Hello');
+ * });
+ * ```
+ */
+ eachLayer: function (method, context) {
+ for (var i in this._layers) {
+ method.call(context, this._layers[i]);
+ }
+ return this;
+ },
+
+ _addLayers: function (layers) {
+ layers = layers ? (isArray(layers) ? layers : [layers]) : [];
+
+ for (var i = 0, len = layers.length; i < len; i++) {
+ this.addLayer(layers[i]);
+ }
+ },
+
+ _addZoomLimit: function (layer) {
+ if (isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) {
+ this._zoomBoundLayers[stamp(layer)] = layer;
+ this._updateZoomLevels();
+ }
+ },
+
+ _removeZoomLimit: function (layer) {
+ var id = stamp(layer);
+
+ if (this._zoomBoundLayers[id]) {
+ delete this._zoomBoundLayers[id];
+ this._updateZoomLevels();
+ }
+ },
+
+ _updateZoomLevels: function () {
+ var minZoom = Infinity,
+ maxZoom = -Infinity,
+ oldZoomSpan = this._getZoomSpan();
+
+ for (var i in this._zoomBoundLayers) {
+ var options = this._zoomBoundLayers[i].options;
+
+ minZoom = options.minZoom === undefined ? minZoom : Math.min(minZoom, options.minZoom);
+ maxZoom = options.maxZoom === undefined ? maxZoom : Math.max(maxZoom, options.maxZoom);
+ }
+
+ this._layersMaxZoom = maxZoom === -Infinity ? undefined : maxZoom;
+ this._layersMinZoom = minZoom === Infinity ? undefined : minZoom;
+
+ // @section Map state change events
+ // @event zoomlevelschange: Event
+ // Fired when the number of zoomlevels on the map is changed due
+ // to adding or removing a layer.
+ if (oldZoomSpan !== this._getZoomSpan()) {
+ this.fire('zoomlevelschange');
+ }
+
+ if (this.options.maxZoom === undefined && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) {
+ this.setZoom(this._layersMaxZoom);
+ }
+ if (this.options.minZoom === undefined && this._layersMinZoom && this.getZoom() < this._layersMinZoom) {
+ this.setZoom(this._layersMinZoom);
+ }
+ }
+});
+
/*
* @class LayerGroup
* @aka L.LayerGroup
@@ -6846,8 +6898,8 @@ var LayerGroup = Layer.extend({
// Create a layer group, optionally given an initial set of layers and an `options` object.
var layerGroup = function (layers, options) {
return new LayerGroup(layers, options);
-};
-
+};
+
/*
* @class FeatureGroup
* @aka L.FeatureGroup
@@ -6938,8 +6990,8 @@ var FeatureGroup = LayerGroup.extend({
// Create a feature group, optionally given an initial set of layers.
var featureGroup = function (layers) {
return new FeatureGroup(layers);
-};
-
+};
+
/*
* @class Icon
* @aka L.Icon
@@ -7089,218 +7141,218 @@ var Icon = Class.extend({
// Creates an icon instance with the given options.
function icon(options) {
return new Icon(options);
-}
-
-/*
- * @miniclass Icon.Default (Icon)
- * @aka L.Icon.Default
- * @section
- *
- * A trivial subclass of `Icon`, represents the icon to use in `Marker`s when
- * no icon is specified. Points to the blue marker image distributed with Leaflet
- * releases.
- *
- * In order to customize the default icon, just change the properties of `L.Icon.Default.prototype.options`
- * (which is a set of `Icon options`).
- *
- * If you want to _completely_ replace the default icon, override the
- * `L.Marker.prototype.options.icon` with your own icon instead.
- */
-
-var IconDefault = Icon.extend({
-
- options: {
- iconUrl: 'marker-icon.png',
- iconRetinaUrl: 'marker-icon-2x.png',
- shadowUrl: 'marker-shadow.png',
- iconSize: [25, 41],
- iconAnchor: [12, 41],
- popupAnchor: [1, -34],
- tooltipAnchor: [16, -28],
- shadowSize: [41, 41]
- },
-
- _getIconUrl: function (name) {
- if (!IconDefault.imagePath) { // Deprecated, backwards-compatibility only
- IconDefault.imagePath = this._detectIconPath();
- }
-
- // @option imagePath: String
- // `Icon.Default` will try to auto-detect the location of the
- // blue icon images. If you are placing these images in a non-standard
- // way, set this option to point to the right path.
- return (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name);
- },
-
- _detectIconPath: function () {
- var el = create$1('div', 'leaflet-default-icon-path', document.body);
- var path = getStyle(el, 'background-image') ||
- getStyle(el, 'backgroundImage'); // IE8
-
- document.body.removeChild(el);
-
- if (path === null || path.indexOf('url') !== 0) {
- path = '';
- } else {
- path = path.replace(/^url\(["']?/, '').replace(/marker-icon\.png["']?\)$/, '');
- }
-
- return path;
- }
-});
-
-/*
- * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable.
- */
-
-
-/* @namespace Marker
- * @section Interaction handlers
- *
- * Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see `Handler` methods). Example:
- *
- * ```js
- * marker.dragging.disable();
- * ```
- *
- * @property dragging: Handler
- * Marker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set [`marker.options.draggable`](#marker-draggable)).
- */
-
-var MarkerDrag = Handler.extend({
- initialize: function (marker) {
- this._marker = marker;
- },
-
- addHooks: function () {
- var icon = this._marker._icon;
-
- if (!this._draggable) {
- this._draggable = new Draggable(icon, icon, true);
- }
-
- this._draggable.on({
- dragstart: this._onDragStart,
- predrag: this._onPreDrag,
- drag: this._onDrag,
- dragend: this._onDragEnd
- }, this).enable();
-
- addClass(icon, 'leaflet-marker-draggable');
- },
-
- removeHooks: function () {
- this._draggable.off({
- dragstart: this._onDragStart,
- predrag: this._onPreDrag,
- drag: this._onDrag,
- dragend: this._onDragEnd
- }, this).disable();
-
- if (this._marker._icon) {
- removeClass(this._marker._icon, 'leaflet-marker-draggable');
- }
- },
-
- moved: function () {
- return this._draggable && this._draggable._moved;
- },
-
- _adjustPan: function (e) {
- var marker = this._marker,
- map = marker._map,
- speed = this._marker.options.autoPanSpeed,
- padding = this._marker.options.autoPanPadding,
- iconPos = getPosition(marker._icon),
- bounds = map.getPixelBounds(),
- origin = map.getPixelOrigin();
-
- var panBounds = toBounds(
- bounds.min._subtract(origin).add(padding),
- bounds.max._subtract(origin).subtract(padding)
- );
-
- if (!panBounds.contains(iconPos)) {
- // Compute incremental movement
- var movement = toPoint(
- (Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) -
- (Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x),
-
- (Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) -
- (Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y)
- ).multiplyBy(speed);
-
- map.panBy(movement, {animate: false});
-
- this._draggable._newPos._add(movement);
- this._draggable._startPos._add(movement);
-
- setPosition(marker._icon, this._draggable._newPos);
- this._onDrag(e);
-
- this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
- }
- },
-
- _onDragStart: function () {
- // @section Dragging events
- // @event dragstart: Event
- // Fired when the user starts dragging the marker.
-
- // @event movestart: Event
- // Fired when the marker starts moving (because of dragging).
-
- this._oldLatLng = this._marker.getLatLng();
- this._marker
- .closePopup()
- .fire('movestart')
- .fire('dragstart');
- },
-
- _onPreDrag: function (e) {
- if (this._marker.options.autoPan) {
- cancelAnimFrame(this._panRequest);
- this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
- }
- },
-
- _onDrag: function (e) {
- var marker = this._marker,
- shadow = marker._shadow,
- iconPos = getPosition(marker._icon),
- latlng = marker._map.layerPointToLatLng(iconPos);
-
- // update shadow position
- if (shadow) {
- setPosition(shadow, iconPos);
- }
-
- marker._latlng = latlng;
- e.latlng = latlng;
- e.oldLatLng = this._oldLatLng;
-
- // @event drag: Event
- // Fired repeatedly while the user drags the marker.
- marker
- .fire('move', e)
- .fire('drag', e);
- },
-
- _onDragEnd: function (e) {
- // @event dragend: DragEndEvent
- // Fired when the user stops dragging the marker.
-
- cancelAnimFrame(this._panRequest);
-
- // @event moveend: Event
- // Fired when the marker stops moving (because of dragging).
- delete this._oldLatLng;
- this._marker
- .fire('moveend')
- .fire('dragend', e);
- }
-});
-
+}
+
+/*
+ * @miniclass Icon.Default (Icon)
+ * @aka L.Icon.Default
+ * @section
+ *
+ * A trivial subclass of `Icon`, represents the icon to use in `Marker`s when
+ * no icon is specified. Points to the blue marker image distributed with Leaflet
+ * releases.
+ *
+ * In order to customize the default icon, just change the properties of `L.Icon.Default.prototype.options`
+ * (which is a set of `Icon options`).
+ *
+ * If you want to _completely_ replace the default icon, override the
+ * `L.Marker.prototype.options.icon` with your own icon instead.
+ */
+
+var IconDefault = Icon.extend({
+
+ options: {
+ iconUrl: 'marker-icon.png',
+ iconRetinaUrl: 'marker-icon-2x.png',
+ shadowUrl: 'marker-shadow.png',
+ iconSize: [25, 41],
+ iconAnchor: [12, 41],
+ popupAnchor: [1, -34],
+ tooltipAnchor: [16, -28],
+ shadowSize: [41, 41]
+ },
+
+ _getIconUrl: function (name) {
+ if (!IconDefault.imagePath) { // Deprecated, backwards-compatibility only
+ IconDefault.imagePath = this._detectIconPath();
+ }
+
+ // @option imagePath: String
+ // `Icon.Default` will try to auto-detect the location of the
+ // blue icon images. If you are placing these images in a non-standard
+ // way, set this option to point to the right path.
+ return (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name);
+ },
+
+ _detectIconPath: function () {
+ var el = create$1('div', 'leaflet-default-icon-path', document.body);
+ var path = getStyle(el, 'background-image') ||
+ getStyle(el, 'backgroundImage'); // IE8
+
+ document.body.removeChild(el);
+
+ if (path === null || path.indexOf('url') !== 0) {
+ path = '';
+ } else {
+ path = path.replace(/^url\(["']?/, '').replace(/marker-icon\.png["']?\)$/, '');
+ }
+
+ return path;
+ }
+});
+
+/*
+ * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable.
+ */
+
+
+/* @namespace Marker
+ * @section Interaction handlers
+ *
+ * Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see `Handler` methods). Example:
+ *
+ * ```js
+ * marker.dragging.disable();
+ * ```
+ *
+ * @property dragging: Handler
+ * Marker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set [`marker.options.draggable`](#marker-draggable)).
+ */
+
+var MarkerDrag = Handler.extend({
+ initialize: function (marker) {
+ this._marker = marker;
+ },
+
+ addHooks: function () {
+ var icon = this._marker._icon;
+
+ if (!this._draggable) {
+ this._draggable = new Draggable(icon, icon, true);
+ }
+
+ this._draggable.on({
+ dragstart: this._onDragStart,
+ predrag: this._onPreDrag,
+ drag: this._onDrag,
+ dragend: this._onDragEnd
+ }, this).enable();
+
+ addClass(icon, 'leaflet-marker-draggable');
+ },
+
+ removeHooks: function () {
+ this._draggable.off({
+ dragstart: this._onDragStart,
+ predrag: this._onPreDrag,
+ drag: this._onDrag,
+ dragend: this._onDragEnd
+ }, this).disable();
+
+ if (this._marker._icon) {
+ removeClass(this._marker._icon, 'leaflet-marker-draggable');
+ }
+ },
+
+ moved: function () {
+ return this._draggable && this._draggable._moved;
+ },
+
+ _adjustPan: function (e) {
+ var marker = this._marker,
+ map = marker._map,
+ speed = this._marker.options.autoPanSpeed,
+ padding = this._marker.options.autoPanPadding,
+ iconPos = getPosition(marker._icon),
+ bounds = map.getPixelBounds(),
+ origin = map.getPixelOrigin();
+
+ var panBounds = toBounds(
+ bounds.min._subtract(origin).add(padding),
+ bounds.max._subtract(origin).subtract(padding)
+ );
+
+ if (!panBounds.contains(iconPos)) {
+ // Compute incremental movement
+ var movement = toPoint(
+ (Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) -
+ (Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x),
+
+ (Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) -
+ (Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y)
+ ).multiplyBy(speed);
+
+ map.panBy(movement, {animate: false});
+
+ this._draggable._newPos._add(movement);
+ this._draggable._startPos._add(movement);
+
+ setPosition(marker._icon, this._draggable._newPos);
+ this._onDrag(e);
+
+ this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
+ }
+ },
+
+ _onDragStart: function () {
+ // @section Dragging events
+ // @event dragstart: Event
+ // Fired when the user starts dragging the marker.
+
+ // @event movestart: Event
+ // Fired when the marker starts moving (because of dragging).
+
+ this._oldLatLng = this._marker.getLatLng();
+ this._marker
+ .closePopup()
+ .fire('movestart')
+ .fire('dragstart');
+ },
+
+ _onPreDrag: function (e) {
+ if (this._marker.options.autoPan) {
+ cancelAnimFrame(this._panRequest);
+ this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
+ }
+ },
+
+ _onDrag: function (e) {
+ var marker = this._marker,
+ shadow = marker._shadow,
+ iconPos = getPosition(marker._icon),
+ latlng = marker._map.layerPointToLatLng(iconPos);
+
+ // update shadow position
+ if (shadow) {
+ setPosition(shadow, iconPos);
+ }
+
+ marker._latlng = latlng;
+ e.latlng = latlng;
+ e.oldLatLng = this._oldLatLng;
+
+ // @event drag: Event
+ // Fired repeatedly while the user drags the marker.
+ marker
+ .fire('move', e)
+ .fire('drag', e);
+ },
+
+ _onDragEnd: function (e) {
+ // @event dragend: DragEndEvent
+ // Fired when the user stops dragging the marker.
+
+ cancelAnimFrame(this._panRequest);
+
+ // @event moveend: Event
+ // Fired when the marker stops moving (because of dragging).
+ delete this._oldLatLng;
+ this._marker
+ .fire('moveend')
+ .fire('dragend', e);
+ }
+});
+
/*
* @class Marker
* @inherits Interactive layer
@@ -7662,855 +7714,855 @@ var Marker = Layer.extend({
// Instantiates a Marker object given a geographical point and optionally an options object.
function marker(latlng, options) {
return new Marker(latlng, options);
-}
-
-/*
- * @class Path
- * @aka L.Path
- * @inherits Interactive layer
- *
- * An abstract class that contains options and constants shared between vector
- * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`.
- */
-
-var Path = Layer.extend({
-
- // @section
- // @aka Path options
- options: {
- // @option stroke: Boolean = true
- // Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles.
- stroke: true,
-
- // @option color: String = '#3388ff'
- // Stroke color
- color: '#3388ff',
-
- // @option weight: Number = 3
- // Stroke width in pixels
- weight: 3,
-
- // @option opacity: Number = 1.0
- // Stroke opacity
- opacity: 1,
-
- // @option lineCap: String= 'round'
- // A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke.
- lineCap: 'round',
-
- // @option lineJoin: String = 'round'
- // A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke.
- lineJoin: 'round',
-
- // @option dashArray: String = null
- // A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
- dashArray: null,
-
- // @option dashOffset: String = null
- // A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
- dashOffset: null,
-
- // @option fill: Boolean = depends
- // Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles.
- fill: false,
-
- // @option fillColor: String = *
- // Fill color. Defaults to the value of the [`color`](#path-color) option
- fillColor: null,
-
- // @option fillOpacity: Number = 0.2
- // Fill opacity.
- fillOpacity: 0.2,
-
- // @option fillRule: String = 'evenodd'
- // A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined.
- fillRule: 'evenodd',
-
- // className: '',
-
- // Option inherited from "Interactive layer" abstract class
- interactive: true,
-
- // @option bubblingMouseEvents: Boolean = true
- // When `true`, a mouse event on this path will trigger the same event on the map
- // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
- bubblingMouseEvents: true
- },
-
- beforeAdd: function (map) {
- // Renderer is set here because we need to call renderer.getEvents
- // before this.getEvents.
- this._renderer = map.getRenderer(this);
- },
-
- onAdd: function () {
- this._renderer._initPath(this);
- this._reset();
- this._renderer._addPath(this);
- },
-
- onRemove: function () {
- this._renderer._removePath(this);
- },
-
- // @method redraw(): this
- // Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.
- redraw: function () {
- if (this._map) {
- this._renderer._updatePath(this);
- }
- return this;
- },
-
- // @method setStyle(style: Path options): this
- // Changes the appearance of a Path based on the options in the `Path options` object.
- setStyle: function (style) {
- setOptions(this, style);
- if (this._renderer) {
- this._renderer._updateStyle(this);
- }
- return this;
- },
-
- // @method bringToFront(): this
- // Brings the layer to the top of all path layers.
- bringToFront: function () {
- if (this._renderer) {
- this._renderer._bringToFront(this);
- }
- return this;
- },
-
- // @method bringToBack(): this
- // Brings the layer to the bottom of all path layers.
- bringToBack: function () {
- if (this._renderer) {
- this._renderer._bringToBack(this);
- }
- return this;
- },
-
- getElement: function () {
- return this._path;
- },
-
- _reset: function () {
- // defined in child classes
- this._project();
- this._update();
- },
-
- _clickTolerance: function () {
- // used when doing hit detection for Canvas layers
- return (this.options.stroke ? this.options.weight / 2 : 0) + this._renderer.options.tolerance;
- }
-});
-
-/*
- * @class CircleMarker
- * @aka L.CircleMarker
- * @inherits Path
- *
- * A circle of a fixed size with radius specified in pixels. Extends `Path`.
- */
-
-var CircleMarker = Path.extend({
-
- // @section
- // @aka CircleMarker options
- options: {
- fill: true,
-
- // @option radius: Number = 10
- // Radius of the circle marker, in pixels
- radius: 10
- },
-
- initialize: function (latlng, options) {
- setOptions(this, options);
- this._latlng = toLatLng(latlng);
- this._radius = this.options.radius;
- },
-
- // @method setLatLng(latLng: LatLng): this
- // Sets the position of a circle marker to a new location.
- setLatLng: function (latlng) {
- this._latlng = toLatLng(latlng);
- this.redraw();
- return this.fire('move', {latlng: this._latlng});
- },
-
- // @method getLatLng(): LatLng
- // Returns the current geographical position of the circle marker
- getLatLng: function () {
- return this._latlng;
- },
-
- // @method setRadius(radius: Number): this
- // Sets the radius of a circle marker. Units are in pixels.
- setRadius: function (radius) {
- this.options.radius = this._radius = radius;
- return this.redraw();
- },
-
- // @method getRadius(): Number
- // Returns the current radius of the circle
- getRadius: function () {
- return this._radius;
- },
-
- setStyle : function (options) {
- var radius = options && options.radius || this._radius;
- Path.prototype.setStyle.call(this, options);
- this.setRadius(radius);
- return this;
- },
-
- _project: function () {
- this._point = this._map.latLngToLayerPoint(this._latlng);
- this._updateBounds();
- },
-
- _updateBounds: function () {
- var r = this._radius,
- r2 = this._radiusY || r,
- w = this._clickTolerance(),
- p = [r + w, r2 + w];
- this._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p));
- },
-
- _update: function () {
- if (this._map) {
- this._updatePath();
- }
- },
-
- _updatePath: function () {
- this._renderer._updateCircle(this);
- },
-
- _empty: function () {
- return this._radius && !this._renderer._bounds.intersects(this._pxBounds);
- },
-
- // Needed by the `Canvas` renderer for interactivity
- _containsPoint: function (p) {
- return p.distanceTo(this._point) <= this._radius + this._clickTolerance();
- }
-});
-
-
-// @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options)
-// Instantiates a circle marker object given a geographical point, and an optional options object.
-function circleMarker(latlng, options) {
- return new CircleMarker(latlng, options);
-}
-
-/*
- * @class Circle
- * @aka L.Circle
- * @inherits CircleMarker
- *
- * A class for drawing circle overlays on a map. Extends `CircleMarker`.
- *
- * It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).
- *
- * @example
- *
- * ```js
- * L.circle([50.5, 30.5], {radius: 200}).addTo(map);
- * ```
- */
-
-var Circle = CircleMarker.extend({
-
- initialize: function (latlng, options, legacyOptions) {
- if (typeof options === 'number') {
- // Backwards compatibility with 0.7.x factory (latlng, radius, options?)
- options = extend({}, legacyOptions, {radius: options});
- }
- setOptions(this, options);
- this._latlng = toLatLng(latlng);
-
- if (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); }
-
- // @section
- // @aka Circle options
- // @option radius: Number; Radius of the circle, in meters.
- this._mRadius = this.options.radius;
- },
-
- // @method setRadius(radius: Number): this
- // Sets the radius of a circle. Units are in meters.
- setRadius: function (radius) {
- this._mRadius = radius;
- return this.redraw();
- },
-
- // @method getRadius(): Number
- // Returns the current radius of a circle. Units are in meters.
- getRadius: function () {
- return this._mRadius;
- },
-
- // @method getBounds(): LatLngBounds
- // Returns the `LatLngBounds` of the path.
- getBounds: function () {
- var half = [this._radius, this._radiusY || this._radius];
-
- return new LatLngBounds(
- this._map.layerPointToLatLng(this._point.subtract(half)),
- this._map.layerPointToLatLng(this._point.add(half)));
- },
-
- setStyle: Path.prototype.setStyle,
-
- _project: function () {
-
- var lng = this._latlng.lng,
- lat = this._latlng.lat,
- map = this._map,
- crs = map.options.crs;
-
- if (crs.distance === Earth.distance) {
- var d = Math.PI / 180,
- latR = (this._mRadius / Earth.R) / d,
- top = map.project([lat + latR, lng]),
- bottom = map.project([lat - latR, lng]),
- p = top.add(bottom).divideBy(2),
- lat2 = map.unproject(p).lat,
- lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) /
- (Math.cos(lat * d) * Math.cos(lat2 * d))) / d;
-
- if (isNaN(lngR) || lngR === 0) {
- lngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425
- }
-
- this._point = p.subtract(map.getPixelOrigin());
- this._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;
- this._radiusY = p.y - top.y;
-
- } else {
- var latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));
-
- this._point = map.latLngToLayerPoint(this._latlng);
- this._radius = this._point.x - map.latLngToLayerPoint(latlng2).x;
- }
-
- this._updateBounds();
- }
-});
-
-// @factory L.circle(latlng: LatLng, options?: Circle options)
-// Instantiates a circle object given a geographical point, and an options object
-// which contains the circle radius.
-// @alternative
-// @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options)
-// Obsolete way of instantiating a circle, for compatibility with 0.7.x code.
-// Do not use in new applications or plugins.
-function circle(latlng, options, legacyOptions) {
- return new Circle(latlng, options, legacyOptions);
-}
-
-/*
- * @class Polyline
- * @aka L.Polyline
- * @inherits Path
- *
- * A class for drawing polyline overlays on a map. Extends `Path`.
- *
- * @example
- *
- * ```js
- * // create a red polyline from an array of LatLng points
- * var latlngs = [
- * [45.51, -122.68],
- * [37.77, -122.43],
- * [34.04, -118.2]
- * ];
- *
- * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
- *
- * // zoom the map to the polyline
- * map.fitBounds(polyline.getBounds());
- * ```
- *
- * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape:
- *
- * ```js
- * // create a red polyline from an array of arrays of LatLng points
- * var latlngs = [
- * [[45.51, -122.68],
- * [37.77, -122.43],
- * [34.04, -118.2]],
- * [[40.78, -73.91],
- * [41.83, -87.62],
- * [32.76, -96.72]]
- * ];
- * ```
- */
-
-
-var Polyline = Path.extend({
-
- // @section
- // @aka Polyline options
- options: {
- // @option smoothFactor: Number = 1.0
- // How much to simplify the polyline on each zoom level. More means
- // better performance and smoother look, and less means more accurate representation.
- smoothFactor: 1.0,
-
- // @option noClip: Boolean = false
- // Disable polyline clipping.
- noClip: false
- },
-
- initialize: function (latlngs, options) {
- setOptions(this, options);
- this._setLatLngs(latlngs);
- },
-
- // @method getLatLngs(): LatLng[]
- // Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.
- getLatLngs: function () {
- return this._latlngs;
- },
-
- // @method setLatLngs(latlngs: LatLng[]): this
- // Replaces all the points in the polyline with the given array of geographical points.
- setLatLngs: function (latlngs) {
- this._setLatLngs(latlngs);
- return this.redraw();
- },
-
- // @method isEmpty(): Boolean
- // Returns `true` if the Polyline has no LatLngs.
- isEmpty: function () {
- return !this._latlngs.length;
- },
-
- // @method closestLayerPoint(p: Point): Point
- // Returns the point closest to `p` on the Polyline.
- closestLayerPoint: function (p) {
- var minDistance = Infinity,
- minPoint = null,
- closest = _sqClosestPointOnSegment,
- p1, p2;
-
- for (var j = 0, jLen = this._parts.length; j < jLen; j++) {
- var points = this._parts[j];
-
- for (var i = 1, len = points.length; i < len; i++) {
- p1 = points[i - 1];
- p2 = points[i];
-
- var sqDist = closest(p, p1, p2, true);
-
- if (sqDist < minDistance) {
- minDistance = sqDist;
- minPoint = closest(p, p1, p2);
- }
- }
- }
- if (minPoint) {
- minPoint.distance = Math.sqrt(minDistance);
- }
- return minPoint;
- },
-
- // @method getCenter(): LatLng
- // Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the polyline.
- getCenter: function () {
- // throws error when not yet added to map as this center calculation requires projected coordinates
- if (!this._map) {
- throw new Error('Must add layer to map before using getCenter()');
- }
-
- var i, halfDist, segDist, dist, p1, p2, ratio,
- points = this._rings[0],
- len = points.length;
-
- if (!len) { return null; }
-
- // polyline centroid algorithm; only uses the first ring if there are multiple
-
- for (i = 0, halfDist = 0; i < len - 1; i++) {
- halfDist += points[i].distanceTo(points[i + 1]) / 2;
- }
-
- // The line is so small in the current view that all points are on the same pixel.
- if (halfDist === 0) {
- return this._map.layerPointToLatLng(points[0]);
- }
-
- for (i = 0, dist = 0; i < len - 1; i++) {
- p1 = points[i];
- p2 = points[i + 1];
- segDist = p1.distanceTo(p2);
- dist += segDist;
-
- if (dist > halfDist) {
- ratio = (dist - halfDist) / segDist;
- return this._map.layerPointToLatLng([
- p2.x - ratio * (p2.x - p1.x),
- p2.y - ratio * (p2.y - p1.y)
- ]);
- }
- }
- },
-
- // @method getBounds(): LatLngBounds
- // Returns the `LatLngBounds` of the path.
- getBounds: function () {
- return this._bounds;
- },
-
- // @method addLatLng(latlng: LatLng, latlngs? LatLng[]): this
- // Adds a given point to the polyline. By default, adds to the first ring of
- // the polyline in case of a multi-polyline, but can be overridden by passing
- // a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)).
- addLatLng: function (latlng, latlngs) {
- latlngs = latlngs || this._defaultShape();
- latlng = toLatLng(latlng);
- latlngs.push(latlng);
- this._bounds.extend(latlng);
- return this.redraw();
- },
-
- _setLatLngs: function (latlngs) {
- this._bounds = new LatLngBounds();
- this._latlngs = this._convertLatLngs(latlngs);
- },
-
- _defaultShape: function () {
- return isFlat(this._latlngs) ? this._latlngs : this._latlngs[0];
- },
-
- // recursively convert latlngs input into actual LatLng instances; calculate bounds along the way
- _convertLatLngs: function (latlngs) {
- var result = [],
- flat = isFlat(latlngs);
-
- for (var i = 0, len = latlngs.length; i < len; i++) {
- if (flat) {
- result[i] = toLatLng(latlngs[i]);
- this._bounds.extend(result[i]);
- } else {
- result[i] = this._convertLatLngs(latlngs[i]);
- }
- }
-
- return result;
- },
-
- _project: function () {
- var pxBounds = new Bounds();
- this._rings = [];
- this._projectLatlngs(this._latlngs, this._rings, pxBounds);
-
- var w = this._clickTolerance(),
- p = new Point(w, w);
-
- if (this._bounds.isValid() && pxBounds.isValid()) {
- pxBounds.min._subtract(p);
- pxBounds.max._add(p);
- this._pxBounds = pxBounds;
- }
- },
-
- // recursively turns latlngs into a set of rings with projected coordinates
- _projectLatlngs: function (latlngs, result, projectedBounds) {
- var flat = latlngs[0] instanceof LatLng,
- len = latlngs.length,
- i, ring;
-
- if (flat) {
- ring = [];
- for (i = 0; i < len; i++) {
- ring[i] = this._map.latLngToLayerPoint(latlngs[i]);
- projectedBounds.extend(ring[i]);
- }
- result.push(ring);
- } else {
- for (i = 0; i < len; i++) {
- this._projectLatlngs(latlngs[i], result, projectedBounds);
- }
- }
- },
-
- // clip polyline by renderer bounds so that we have less to render for performance
- _clipPoints: function () {
- var bounds = this._renderer._bounds;
-
- this._parts = [];
- if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
- return;
- }
-
- if (this.options.noClip) {
- this._parts = this._rings;
- return;
- }
-
- var parts = this._parts,
- i, j, k, len, len2, segment, points;
-
- for (i = 0, k = 0, len = this._rings.length; i < len; i++) {
- points = this._rings[i];
-
- for (j = 0, len2 = points.length; j < len2 - 1; j++) {
- segment = clipSegment(points[j], points[j + 1], bounds, j, true);
-
- if (!segment) { continue; }
-
- parts[k] = parts[k] || [];
- parts[k].push(segment[0]);
-
- // if segment goes out of screen, or it's the last one, it's the end of the line part
- if ((segment[1] !== points[j + 1]) || (j === len2 - 2)) {
- parts[k].push(segment[1]);
- k++;
- }
- }
- }
- },
-
- // simplify each clipped part of the polyline for performance
- _simplifyPoints: function () {
- var parts = this._parts,
- tolerance = this.options.smoothFactor;
-
- for (var i = 0, len = parts.length; i < len; i++) {
- parts[i] = simplify(parts[i], tolerance);
- }
- },
-
- _update: function () {
- if (!this._map) { return; }
-
- this._clipPoints();
- this._simplifyPoints();
- this._updatePath();
- },
-
- _updatePath: function () {
- this._renderer._updatePoly(this);
- },
-
- // Needed by the `Canvas` renderer for interactivity
- _containsPoint: function (p, closed) {
- var i, j, k, len, len2, part,
- w = this._clickTolerance();
-
- if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }
-
- // hit detection for polylines
- for (i = 0, len = this._parts.length; i < len; i++) {
- part = this._parts[i];
-
- for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
- if (!closed && (j === 0)) { continue; }
-
- if (pointToSegmentDistance(p, part[k], part[j]) <= w) {
- return true;
- }
- }
- }
- return false;
- }
-});
-
-// @factory L.polyline(latlngs: LatLng[], options?: Polyline options)
-// Instantiates a polyline object given an array of geographical points and
-// optionally an options object. You can create a `Polyline` object with
-// multiple separate lines (`MultiPolyline`) by passing an array of arrays
-// of geographic points.
-function polyline(latlngs, options) {
- return new Polyline(latlngs, options);
-}
-
-// Retrocompat. Allow plugins to support Leaflet versions before and after 1.1.
-Polyline._flat = _flat;
-
-/*
- * @class Polygon
- * @aka L.Polygon
- * @inherits Polyline
- *
- * A class for drawing polygon overlays on a map. Extends `Polyline`.
- *
- * Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.
- *
- *
- * @example
- *
- * ```js
- * // create a red polygon from an array of LatLng points
- * var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
- *
- * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
- *
- * // zoom the map to the polygon
- * map.fitBounds(polygon.getBounds());
- * ```
- *
- * You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:
- *
- * ```js
- * var latlngs = [
- * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
- * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
- * ];
- * ```
- *
- * Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.
- *
- * ```js
- * var latlngs = [
- * [ // first polygon
- * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
- * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
- * ],
- * [ // second polygon
- * [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]
- * ]
- * ];
- * ```
- */
-
-var Polygon = Polyline.extend({
-
- options: {
- fill: true
- },
-
- isEmpty: function () {
- return !this._latlngs.length || !this._latlngs[0].length;
- },
-
- getCenter: function () {
- // throws error when not yet added to map as this center calculation requires projected coordinates
- if (!this._map) {
- throw new Error('Must add layer to map before using getCenter()');
- }
-
- var i, j, p1, p2, f, area, x, y, center,
- points = this._rings[0],
- len = points.length;
-
- if (!len) { return null; }
-
- // polygon centroid algorithm; only uses the first ring if there are multiple
-
- area = x = y = 0;
-
- for (i = 0, j = len - 1; i < len; j = i++) {
- p1 = points[i];
- p2 = points[j];
-
- f = p1.y * p2.x - p2.y * p1.x;
- x += (p1.x + p2.x) * f;
- y += (p1.y + p2.y) * f;
- area += f * 3;
- }
-
- if (area === 0) {
- // Polygon is so small that all points are on same pixel.
- center = points[0];
- } else {
- center = [x / area, y / area];
- }
- return this._map.layerPointToLatLng(center);
- },
-
- _convertLatLngs: function (latlngs) {
- var result = Polyline.prototype._convertLatLngs.call(this, latlngs),
- len = result.length;
-
- // remove last point if it equals first one
- if (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) {
- result.pop();
- }
- return result;
- },
-
- _setLatLngs: function (latlngs) {
- Polyline.prototype._setLatLngs.call(this, latlngs);
- if (isFlat(this._latlngs)) {
- this._latlngs = [this._latlngs];
- }
- },
-
- _defaultShape: function () {
- return isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0];
- },
-
- _clipPoints: function () {
- // polygons need a different clipping algorithm so we redefine that
-
- var bounds = this._renderer._bounds,
- w = this.options.weight,
- p = new Point(w, w);
-
- // increase clip padding by stroke width to avoid stroke on clip edges
- bounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p));
-
- this._parts = [];
- if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
- return;
- }
-
- if (this.options.noClip) {
- this._parts = this._rings;
- return;
- }
-
- for (var i = 0, len = this._rings.length, clipped; i < len; i++) {
- clipped = clipPolygon(this._rings[i], bounds, true);
- if (clipped.length) {
- this._parts.push(clipped);
- }
- }
- },
-
- _updatePath: function () {
- this._renderer._updatePoly(this, true);
- },
-
- // Needed by the `Canvas` renderer for interactivity
- _containsPoint: function (p) {
- var inside = false,
- part, p1, p2, i, j, k, len, len2;
-
- if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }
-
- // ray casting algorithm for detecting if point is in polygon
- for (i = 0, len = this._parts.length; i < len; i++) {
- part = this._parts[i];
-
- for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
- p1 = part[j];
- p2 = part[k];
-
- if (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {
- inside = !inside;
- }
- }
- }
-
- // also check if it's on polygon stroke
- return inside || Polyline.prototype._containsPoint.call(this, p, true);
- }
-
-});
-
-
-// @factory L.polygon(latlngs: LatLng[], options?: Polyline options)
-function polygon(latlngs, options) {
- return new Polygon(latlngs, options);
-}
-
+}
+
+/*
+ * @class Path
+ * @aka L.Path
+ * @inherits Interactive layer
+ *
+ * An abstract class that contains options and constants shared between vector
+ * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`.
+ */
+
+var Path = Layer.extend({
+
+ // @section
+ // @aka Path options
+ options: {
+ // @option stroke: Boolean = true
+ // Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles.
+ stroke: true,
+
+ // @option color: String = '#3388ff'
+ // Stroke color
+ color: '#3388ff',
+
+ // @option weight: Number = 3
+ // Stroke width in pixels
+ weight: 3,
+
+ // @option opacity: Number = 1.0
+ // Stroke opacity
+ opacity: 1,
+
+ // @option lineCap: String= 'round'
+ // A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke.
+ lineCap: 'round',
+
+ // @option lineJoin: String = 'round'
+ // A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke.
+ lineJoin: 'round',
+
+ // @option dashArray: String = null
+ // A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
+ dashArray: null,
+
+ // @option dashOffset: String = null
+ // A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).
+ dashOffset: null,
+
+ // @option fill: Boolean = depends
+ // Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles.
+ fill: false,
+
+ // @option fillColor: String = *
+ // Fill color. Defaults to the value of the [`color`](#path-color) option
+ fillColor: null,
+
+ // @option fillOpacity: Number = 0.2
+ // Fill opacity.
+ fillOpacity: 0.2,
+
+ // @option fillRule: String = 'evenodd'
+ // A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined.
+ fillRule: 'evenodd',
+
+ // className: '',
+
+ // Option inherited from "Interactive layer" abstract class
+ interactive: true,
+
+ // @option bubblingMouseEvents: Boolean = true
+ // When `true`, a mouse event on this path will trigger the same event on the map
+ // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
+ bubblingMouseEvents: true
+ },
+
+ beforeAdd: function (map) {
+ // Renderer is set here because we need to call renderer.getEvents
+ // before this.getEvents.
+ this._renderer = map.getRenderer(this);
+ },
+
+ onAdd: function () {
+ this._renderer._initPath(this);
+ this._reset();
+ this._renderer._addPath(this);
+ },
+
+ onRemove: function () {
+ this._renderer._removePath(this);
+ },
+
+ // @method redraw(): this
+ // Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.
+ redraw: function () {
+ if (this._map) {
+ this._renderer._updatePath(this);
+ }
+ return this;
+ },
+
+ // @method setStyle(style: Path options): this
+ // Changes the appearance of a Path based on the options in the `Path options` object.
+ setStyle: function (style) {
+ setOptions(this, style);
+ if (this._renderer) {
+ this._renderer._updateStyle(this);
+ }
+ return this;
+ },
+
+ // @method bringToFront(): this
+ // Brings the layer to the top of all path layers.
+ bringToFront: function () {
+ if (this._renderer) {
+ this._renderer._bringToFront(this);
+ }
+ return this;
+ },
+
+ // @method bringToBack(): this
+ // Brings the layer to the bottom of all path layers.
+ bringToBack: function () {
+ if (this._renderer) {
+ this._renderer._bringToBack(this);
+ }
+ return this;
+ },
+
+ getElement: function () {
+ return this._path;
+ },
+
+ _reset: function () {
+ // defined in child classes
+ this._project();
+ this._update();
+ },
+
+ _clickTolerance: function () {
+ // used when doing hit detection for Canvas layers
+ return (this.options.stroke ? this.options.weight / 2 : 0) + this._renderer.options.tolerance;
+ }
+});
+
+/*
+ * @class CircleMarker
+ * @aka L.CircleMarker
+ * @inherits Path
+ *
+ * A circle of a fixed size with radius specified in pixels. Extends `Path`.
+ */
+
+var CircleMarker = Path.extend({
+
+ // @section
+ // @aka CircleMarker options
+ options: {
+ fill: true,
+
+ // @option radius: Number = 10
+ // Radius of the circle marker, in pixels
+ radius: 10
+ },
+
+ initialize: function (latlng, options) {
+ setOptions(this, options);
+ this._latlng = toLatLng(latlng);
+ this._radius = this.options.radius;
+ },
+
+ // @method setLatLng(latLng: LatLng): this
+ // Sets the position of a circle marker to a new location.
+ setLatLng: function (latlng) {
+ this._latlng = toLatLng(latlng);
+ this.redraw();
+ return this.fire('move', {latlng: this._latlng});
+ },
+
+ // @method getLatLng(): LatLng
+ // Returns the current geographical position of the circle marker
+ getLatLng: function () {
+ return this._latlng;
+ },
+
+ // @method setRadius(radius: Number): this
+ // Sets the radius of a circle marker. Units are in pixels.
+ setRadius: function (radius) {
+ this.options.radius = this._radius = radius;
+ return this.redraw();
+ },
+
+ // @method getRadius(): Number
+ // Returns the current radius of the circle
+ getRadius: function () {
+ return this._radius;
+ },
+
+ setStyle : function (options) {
+ var radius = options && options.radius || this._radius;
+ Path.prototype.setStyle.call(this, options);
+ this.setRadius(radius);
+ return this;
+ },
+
+ _project: function () {
+ this._point = this._map.latLngToLayerPoint(this._latlng);
+ this._updateBounds();
+ },
+
+ _updateBounds: function () {
+ var r = this._radius,
+ r2 = this._radiusY || r,
+ w = this._clickTolerance(),
+ p = [r + w, r2 + w];
+ this._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p));
+ },
+
+ _update: function () {
+ if (this._map) {
+ this._updatePath();
+ }
+ },
+
+ _updatePath: function () {
+ this._renderer._updateCircle(this);
+ },
+
+ _empty: function () {
+ return this._radius && !this._renderer._bounds.intersects(this._pxBounds);
+ },
+
+ // Needed by the `Canvas` renderer for interactivity
+ _containsPoint: function (p) {
+ return p.distanceTo(this._point) <= this._radius + this._clickTolerance();
+ }
+});
+
+
+// @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options)
+// Instantiates a circle marker object given a geographical point, and an optional options object.
+function circleMarker(latlng, options) {
+ return new CircleMarker(latlng, options);
+}
+
+/*
+ * @class Circle
+ * @aka L.Circle
+ * @inherits CircleMarker
+ *
+ * A class for drawing circle overlays on a map. Extends `CircleMarker`.
+ *
+ * It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).
+ *
+ * @example
+ *
+ * ```js
+ * L.circle([50.5, 30.5], {radius: 200}).addTo(map);
+ * ```
+ */
+
+var Circle = CircleMarker.extend({
+
+ initialize: function (latlng, options, legacyOptions) {
+ if (typeof options === 'number') {
+ // Backwards compatibility with 0.7.x factory (latlng, radius, options?)
+ options = extend({}, legacyOptions, {radius: options});
+ }
+ setOptions(this, options);
+ this._latlng = toLatLng(latlng);
+
+ if (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); }
+
+ // @section
+ // @aka Circle options
+ // @option radius: Number; Radius of the circle, in meters.
+ this._mRadius = this.options.radius;
+ },
+
+ // @method setRadius(radius: Number): this
+ // Sets the radius of a circle. Units are in meters.
+ setRadius: function (radius) {
+ this._mRadius = radius;
+ return this.redraw();
+ },
+
+ // @method getRadius(): Number
+ // Returns the current radius of a circle. Units are in meters.
+ getRadius: function () {
+ return this._mRadius;
+ },
+
+ // @method getBounds(): LatLngBounds
+ // Returns the `LatLngBounds` of the path.
+ getBounds: function () {
+ var half = [this._radius, this._radiusY || this._radius];
+
+ return new LatLngBounds(
+ this._map.layerPointToLatLng(this._point.subtract(half)),
+ this._map.layerPointToLatLng(this._point.add(half)));
+ },
+
+ setStyle: Path.prototype.setStyle,
+
+ _project: function () {
+
+ var lng = this._latlng.lng,
+ lat = this._latlng.lat,
+ map = this._map,
+ crs = map.options.crs;
+
+ if (crs.distance === Earth.distance) {
+ var d = Math.PI / 180,
+ latR = (this._mRadius / Earth.R) / d,
+ top = map.project([lat + latR, lng]),
+ bottom = map.project([lat - latR, lng]),
+ p = top.add(bottom).divideBy(2),
+ lat2 = map.unproject(p).lat,
+ lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) /
+ (Math.cos(lat * d) * Math.cos(lat2 * d))) / d;
+
+ if (isNaN(lngR) || lngR === 0) {
+ lngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425
+ }
+
+ this._point = p.subtract(map.getPixelOrigin());
+ this._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;
+ this._radiusY = p.y - top.y;
+
+ } else {
+ var latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));
+
+ this._point = map.latLngToLayerPoint(this._latlng);
+ this._radius = this._point.x - map.latLngToLayerPoint(latlng2).x;
+ }
+
+ this._updateBounds();
+ }
+});
+
+// @factory L.circle(latlng: LatLng, options?: Circle options)
+// Instantiates a circle object given a geographical point, and an options object
+// which contains the circle radius.
+// @alternative
+// @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options)
+// Obsolete way of instantiating a circle, for compatibility with 0.7.x code.
+// Do not use in new applications or plugins.
+function circle(latlng, options, legacyOptions) {
+ return new Circle(latlng, options, legacyOptions);
+}
+
+/*
+ * @class Polyline
+ * @aka L.Polyline
+ * @inherits Path
+ *
+ * A class for drawing polyline overlays on a map. Extends `Path`.
+ *
+ * @example
+ *
+ * ```js
+ * // create a red polyline from an array of LatLng points
+ * var latlngs = [
+ * [45.51, -122.68],
+ * [37.77, -122.43],
+ * [34.04, -118.2]
+ * ];
+ *
+ * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
+ *
+ * // zoom the map to the polyline
+ * map.fitBounds(polyline.getBounds());
+ * ```
+ *
+ * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape:
+ *
+ * ```js
+ * // create a red polyline from an array of arrays of LatLng points
+ * var latlngs = [
+ * [[45.51, -122.68],
+ * [37.77, -122.43],
+ * [34.04, -118.2]],
+ * [[40.78, -73.91],
+ * [41.83, -87.62],
+ * [32.76, -96.72]]
+ * ];
+ * ```
+ */
+
+
+var Polyline = Path.extend({
+
+ // @section
+ // @aka Polyline options
+ options: {
+ // @option smoothFactor: Number = 1.0
+ // How much to simplify the polyline on each zoom level. More means
+ // better performance and smoother look, and less means more accurate representation.
+ smoothFactor: 1.0,
+
+ // @option noClip: Boolean = false
+ // Disable polyline clipping.
+ noClip: false
+ },
+
+ initialize: function (latlngs, options) {
+ setOptions(this, options);
+ this._setLatLngs(latlngs);
+ },
+
+ // @method getLatLngs(): LatLng[]
+ // Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.
+ getLatLngs: function () {
+ return this._latlngs;
+ },
+
+ // @method setLatLngs(latlngs: LatLng[]): this
+ // Replaces all the points in the polyline with the given array of geographical points.
+ setLatLngs: function (latlngs) {
+ this._setLatLngs(latlngs);
+ return this.redraw();
+ },
+
+ // @method isEmpty(): Boolean
+ // Returns `true` if the Polyline has no LatLngs.
+ isEmpty: function () {
+ return !this._latlngs.length;
+ },
+
+ // @method closestLayerPoint(p: Point): Point
+ // Returns the point closest to `p` on the Polyline.
+ closestLayerPoint: function (p) {
+ var minDistance = Infinity,
+ minPoint = null,
+ closest = _sqClosestPointOnSegment,
+ p1, p2;
+
+ for (var j = 0, jLen = this._parts.length; j < jLen; j++) {
+ var points = this._parts[j];
+
+ for (var i = 1, len = points.length; i < len; i++) {
+ p1 = points[i - 1];
+ p2 = points[i];
+
+ var sqDist = closest(p, p1, p2, true);
+
+ if (sqDist < minDistance) {
+ minDistance = sqDist;
+ minPoint = closest(p, p1, p2);
+ }
+ }
+ }
+ if (minPoint) {
+ minPoint.distance = Math.sqrt(minDistance);
+ }
+ return minPoint;
+ },
+
+ // @method getCenter(): LatLng
+ // Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the polyline.
+ getCenter: function () {
+ // throws error when not yet added to map as this center calculation requires projected coordinates
+ if (!this._map) {
+ throw new Error('Must add layer to map before using getCenter()');
+ }
+
+ var i, halfDist, segDist, dist, p1, p2, ratio,
+ points = this._rings[0],
+ len = points.length;
+
+ if (!len) { return null; }
+
+ // polyline centroid algorithm; only uses the first ring if there are multiple
+
+ for (i = 0, halfDist = 0; i < len - 1; i++) {
+ halfDist += points[i].distanceTo(points[i + 1]) / 2;
+ }
+
+ // The line is so small in the current view that all points are on the same pixel.
+ if (halfDist === 0) {
+ return this._map.layerPointToLatLng(points[0]);
+ }
+
+ for (i = 0, dist = 0; i < len - 1; i++) {
+ p1 = points[i];
+ p2 = points[i + 1];
+ segDist = p1.distanceTo(p2);
+ dist += segDist;
+
+ if (dist > halfDist) {
+ ratio = (dist - halfDist) / segDist;
+ return this._map.layerPointToLatLng([
+ p2.x - ratio * (p2.x - p1.x),
+ p2.y - ratio * (p2.y - p1.y)
+ ]);
+ }
+ }
+ },
+
+ // @method getBounds(): LatLngBounds
+ // Returns the `LatLngBounds` of the path.
+ getBounds: function () {
+ return this._bounds;
+ },
+
+ // @method addLatLng(latlng: LatLng, latlngs? LatLng[]): this
+ // Adds a given point to the polyline. By default, adds to the first ring of
+ // the polyline in case of a multi-polyline, but can be overridden by passing
+ // a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)).
+ addLatLng: function (latlng, latlngs) {
+ latlngs = latlngs || this._defaultShape();
+ latlng = toLatLng(latlng);
+ latlngs.push(latlng);
+ this._bounds.extend(latlng);
+ return this.redraw();
+ },
+
+ _setLatLngs: function (latlngs) {
+ this._bounds = new LatLngBounds();
+ this._latlngs = this._convertLatLngs(latlngs);
+ },
+
+ _defaultShape: function () {
+ return isFlat(this._latlngs) ? this._latlngs : this._latlngs[0];
+ },
+
+ // recursively convert latlngs input into actual LatLng instances; calculate bounds along the way
+ _convertLatLngs: function (latlngs) {
+ var result = [],
+ flat = isFlat(latlngs);
+
+ for (var i = 0, len = latlngs.length; i < len; i++) {
+ if (flat) {
+ result[i] = toLatLng(latlngs[i]);
+ this._bounds.extend(result[i]);
+ } else {
+ result[i] = this._convertLatLngs(latlngs[i]);
+ }
+ }
+
+ return result;
+ },
+
+ _project: function () {
+ var pxBounds = new Bounds();
+ this._rings = [];
+ this._projectLatlngs(this._latlngs, this._rings, pxBounds);
+
+ var w = this._clickTolerance(),
+ p = new Point(w, w);
+
+ if (this._bounds.isValid() && pxBounds.isValid()) {
+ pxBounds.min._subtract(p);
+ pxBounds.max._add(p);
+ this._pxBounds = pxBounds;
+ }
+ },
+
+ // recursively turns latlngs into a set of rings with projected coordinates
+ _projectLatlngs: function (latlngs, result, projectedBounds) {
+ var flat = latlngs[0] instanceof LatLng,
+ len = latlngs.length,
+ i, ring;
+
+ if (flat) {
+ ring = [];
+ for (i = 0; i < len; i++) {
+ ring[i] = this._map.latLngToLayerPoint(latlngs[i]);
+ projectedBounds.extend(ring[i]);
+ }
+ result.push(ring);
+ } else {
+ for (i = 0; i < len; i++) {
+ this._projectLatlngs(latlngs[i], result, projectedBounds);
+ }
+ }
+ },
+
+ // clip polyline by renderer bounds so that we have less to render for performance
+ _clipPoints: function () {
+ var bounds = this._renderer._bounds;
+
+ this._parts = [];
+ if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
+ return;
+ }
+
+ if (this.options.noClip) {
+ this._parts = this._rings;
+ return;
+ }
+
+ var parts = this._parts,
+ i, j, k, len, len2, segment, points;
+
+ for (i = 0, k = 0, len = this._rings.length; i < len; i++) {
+ points = this._rings[i];
+
+ for (j = 0, len2 = points.length; j < len2 - 1; j++) {
+ segment = clipSegment(points[j], points[j + 1], bounds, j, true);
+
+ if (!segment) { continue; }
+
+ parts[k] = parts[k] || [];
+ parts[k].push(segment[0]);
+
+ // if segment goes out of screen, or it's the last one, it's the end of the line part
+ if ((segment[1] !== points[j + 1]) || (j === len2 - 2)) {
+ parts[k].push(segment[1]);
+ k++;
+ }
+ }
+ }
+ },
+
+ // simplify each clipped part of the polyline for performance
+ _simplifyPoints: function () {
+ var parts = this._parts,
+ tolerance = this.options.smoothFactor;
+
+ for (var i = 0, len = parts.length; i < len; i++) {
+ parts[i] = simplify(parts[i], tolerance);
+ }
+ },
+
+ _update: function () {
+ if (!this._map) { return; }
+
+ this._clipPoints();
+ this._simplifyPoints();
+ this._updatePath();
+ },
+
+ _updatePath: function () {
+ this._renderer._updatePoly(this);
+ },
+
+ // Needed by the `Canvas` renderer for interactivity
+ _containsPoint: function (p, closed) {
+ var i, j, k, len, len2, part,
+ w = this._clickTolerance();
+
+ if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }
+
+ // hit detection for polylines
+ for (i = 0, len = this._parts.length; i < len; i++) {
+ part = this._parts[i];
+
+ for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
+ if (!closed && (j === 0)) { continue; }
+
+ if (pointToSegmentDistance(p, part[k], part[j]) <= w) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+});
+
+// @factory L.polyline(latlngs: LatLng[], options?: Polyline options)
+// Instantiates a polyline object given an array of geographical points and
+// optionally an options object. You can create a `Polyline` object with
+// multiple separate lines (`MultiPolyline`) by passing an array of arrays
+// of geographic points.
+function polyline(latlngs, options) {
+ return new Polyline(latlngs, options);
+}
+
+// Retrocompat. Allow plugins to support Leaflet versions before and after 1.1.
+Polyline._flat = _flat;
+
+/*
+ * @class Polygon
+ * @aka L.Polygon
+ * @inherits Polyline
+ *
+ * A class for drawing polygon overlays on a map. Extends `Polyline`.
+ *
+ * Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.
+ *
+ *
+ * @example
+ *
+ * ```js
+ * // create a red polygon from an array of LatLng points
+ * var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
+ *
+ * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
+ *
+ * // zoom the map to the polygon
+ * map.fitBounds(polygon.getBounds());
+ * ```
+ *
+ * You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:
+ *
+ * ```js
+ * var latlngs = [
+ * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
+ * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
+ * ];
+ * ```
+ *
+ * Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.
+ *
+ * ```js
+ * var latlngs = [
+ * [ // first polygon
+ * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
+ * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
+ * ],
+ * [ // second polygon
+ * [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]
+ * ]
+ * ];
+ * ```
+ */
+
+var Polygon = Polyline.extend({
+
+ options: {
+ fill: true
+ },
+
+ isEmpty: function () {
+ return !this._latlngs.length || !this._latlngs[0].length;
+ },
+
+ getCenter: function () {
+ // throws error when not yet added to map as this center calculation requires projected coordinates
+ if (!this._map) {
+ throw new Error('Must add layer to map before using getCenter()');
+ }
+
+ var i, j, p1, p2, f, area, x, y, center,
+ points = this._rings[0],
+ len = points.length;
+
+ if (!len) { return null; }
+
+ // polygon centroid algorithm; only uses the first ring if there are multiple
+
+ area = x = y = 0;
+
+ for (i = 0, j = len - 1; i < len; j = i++) {
+ p1 = points[i];
+ p2 = points[j];
+
+ f = p1.y * p2.x - p2.y * p1.x;
+ x += (p1.x + p2.x) * f;
+ y += (p1.y + p2.y) * f;
+ area += f * 3;
+ }
+
+ if (area === 0) {
+ // Polygon is so small that all points are on same pixel.
+ center = points[0];
+ } else {
+ center = [x / area, y / area];
+ }
+ return this._map.layerPointToLatLng(center);
+ },
+
+ _convertLatLngs: function (latlngs) {
+ var result = Polyline.prototype._convertLatLngs.call(this, latlngs),
+ len = result.length;
+
+ // remove last point if it equals first one
+ if (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) {
+ result.pop();
+ }
+ return result;
+ },
+
+ _setLatLngs: function (latlngs) {
+ Polyline.prototype._setLatLngs.call(this, latlngs);
+ if (isFlat(this._latlngs)) {
+ this._latlngs = [this._latlngs];
+ }
+ },
+
+ _defaultShape: function () {
+ return isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0];
+ },
+
+ _clipPoints: function () {
+ // polygons need a different clipping algorithm so we redefine that
+
+ var bounds = this._renderer._bounds,
+ w = this.options.weight,
+ p = new Point(w, w);
+
+ // increase clip padding by stroke width to avoid stroke on clip edges
+ bounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p));
+
+ this._parts = [];
+ if (!this._pxBounds || !this._pxBounds.intersects(bounds)) {
+ return;
+ }
+
+ if (this.options.noClip) {
+ this._parts = this._rings;
+ return;
+ }
+
+ for (var i = 0, len = this._rings.length, clipped; i < len; i++) {
+ clipped = clipPolygon(this._rings[i], bounds, true);
+ if (clipped.length) {
+ this._parts.push(clipped);
+ }
+ }
+ },
+
+ _updatePath: function () {
+ this._renderer._updatePoly(this, true);
+ },
+
+ // Needed by the `Canvas` renderer for interactivity
+ _containsPoint: function (p) {
+ var inside = false,
+ part, p1, p2, i, j, k, len, len2;
+
+ if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }
+
+ // ray casting algorithm for detecting if point is in polygon
+ for (i = 0, len = this._parts.length; i < len; i++) {
+ part = this._parts[i];
+
+ for (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {
+ p1 = part[j];
+ p2 = part[k];
+
+ if (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {
+ inside = !inside;
+ }
+ }
+ }
+
+ // also check if it's on polygon stroke
+ return inside || Polyline.prototype._containsPoint.call(this, p, true);
+ }
+
+});
+
+
+// @factory L.polygon(latlngs: LatLng[], options?: Polyline options)
+function polygon(latlngs, options) {
+ return new Polygon(latlngs, options);
+}
+
/*
* @class GeoJSON
* @aka L.GeoJSON
@@ -8917,8 +8969,8 @@ function geoJSON(geojson, options) {
}
// Backward compatibility.
-var geoJson = geoJSON;
-
+var geoJson = geoJSON;
+
/*
* @class ImageOverlay
* @aka L.ImageOverlay
@@ -9176,8 +9228,8 @@ var ImageOverlay = Layer.extend({
// geographical bounds it is tied to.
var imageOverlay = function (url, bounds, options) {
return new ImageOverlay(url, bounds, options);
-};
-
+};
+
/*
* @class VideoOverlay
* @aka L.VideoOverlay
@@ -9259,8 +9311,8 @@ var VideoOverlay = ImageOverlay.extend({
function videoOverlay(video, bounds, options) {
return new VideoOverlay(video, bounds, options);
-}
-
+}
+
/*
* @class DivOverlay
* @inherits Layer
@@ -9457,8 +9509,8 @@ var DivOverlay = Layer.extend({
return [0, 0];
}
-});
-
+});
+
/*
* @class Popup
* @inherits DivOverlay
@@ -9686,7 +9738,8 @@ var Popup = DivOverlay.extend({
},
_adjustPan: function () {
- if (!this.options.autoPan || (this._map._panAnim && this._map._panAnim._inProgress)) { return; }
+ if (!this.options.autoPan) { return; }
+ if (this._map._panAnim) { this._map._panAnim.stop(); }
var map = this._map,
marginBottom = parseInt(getStyle(this._container, 'marginBottom'), 10) || 0,
@@ -9980,1409 +10033,1409 @@ Layer.include({
this._openPopup(e);
}
}
-});
-
-/*
- * @class Tooltip
- * @inherits DivOverlay
- * @aka L.Tooltip
- * Used to display small texts on top of map layers.
- *
- * @example
- *
- * ```js
- * marker.bindTooltip("my tooltip text").openTooltip();
- * ```
- * Note about tooltip offset. Leaflet takes two options in consideration
- * for computing tooltip offsetting:
- * - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip.
- * Add a positive x offset to move the tooltip to the right, and a positive y offset to
- * move it to the bottom. Negatives will move to the left and top.
- * - the `tooltipAnchor` Icon option: this will only be considered for Marker. You
- * should adapt this value if you use a custom icon.
- */
-
-
-// @namespace Tooltip
-var Tooltip = DivOverlay.extend({
-
- // @section
- // @aka Tooltip options
- options: {
- // @option pane: String = 'tooltipPane'
- // `Map pane` where the tooltip will be added.
- pane: 'tooltipPane',
-
- // @option offset: Point = Point(0, 0)
- // Optional offset of the tooltip position.
- offset: [0, 0],
-
- // @option direction: String = 'auto'
- // Direction where to open the tooltip. Possible values are: `right`, `left`,
- // `top`, `bottom`, `center`, `auto`.
- // `auto` will dynamically switch between `right` and `left` according to the tooltip
- // position on the map.
- direction: 'auto',
-
- // @option permanent: Boolean = false
- // Whether to open the tooltip permanently or only on mouseover.
- permanent: false,
-
- // @option sticky: Boolean = false
- // If true, the tooltip will follow the mouse instead of being fixed at the feature center.
- sticky: false,
-
- // @option interactive: Boolean = false
- // If true, the tooltip will listen to the feature events.
- interactive: false,
-
- // @option opacity: Number = 0.9
- // Tooltip container opacity.
- opacity: 0.9
- },
-
- onAdd: function (map) {
- DivOverlay.prototype.onAdd.call(this, map);
- this.setOpacity(this.options.opacity);
-
- // @namespace Map
- // @section Tooltip events
- // @event tooltipopen: TooltipEvent
- // Fired when a tooltip is opened in the map.
- map.fire('tooltipopen', {tooltip: this});
-
- if (this._source) {
- // @namespace Layer
- // @section Tooltip events
- // @event tooltipopen: TooltipEvent
- // Fired when a tooltip bound to this layer is opened.
- this._source.fire('tooltipopen', {tooltip: this}, true);
- }
- },
-
- onRemove: function (map) {
- DivOverlay.prototype.onRemove.call(this, map);
-
- // @namespace Map
- // @section Tooltip events
- // @event tooltipclose: TooltipEvent
- // Fired when a tooltip in the map is closed.
- map.fire('tooltipclose', {tooltip: this});
-
- if (this._source) {
- // @namespace Layer
- // @section Tooltip events
- // @event tooltipclose: TooltipEvent
- // Fired when a tooltip bound to this layer is closed.
- this._source.fire('tooltipclose', {tooltip: this}, true);
- }
- },
-
- getEvents: function () {
- var events = DivOverlay.prototype.getEvents.call(this);
-
- if (touch && !this.options.permanent) {
- events.preclick = this._close;
- }
-
- return events;
- },
-
- _close: function () {
- if (this._map) {
- this._map.closeTooltip(this);
- }
- },
-
- _initLayout: function () {
- var prefix = 'leaflet-tooltip',
- className = prefix + ' ' + (this.options.className || '') + ' leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');
-
- this._contentNode = this._container = create$1('div', className);
- },
-
- _updateLayout: function () {},
-
- _adjustPan: function () {},
-
- _setPosition: function (pos) {
- var map = this._map,
- container = this._container,
- centerPoint = map.latLngToContainerPoint(map.getCenter()),
- tooltipPoint = map.layerPointToContainerPoint(pos),
- direction = this.options.direction,
- tooltipWidth = container.offsetWidth,
- tooltipHeight = container.offsetHeight,
- offset = toPoint(this.options.offset),
- anchor = this._getAnchor();
-
- if (direction === 'top') {
- pos = pos.add(toPoint(-tooltipWidth / 2 + offset.x, -tooltipHeight + offset.y + anchor.y, true));
- } else if (direction === 'bottom') {
- pos = pos.subtract(toPoint(tooltipWidth / 2 - offset.x, -offset.y, true));
- } else if (direction === 'center') {
- pos = pos.subtract(toPoint(tooltipWidth / 2 + offset.x, tooltipHeight / 2 - anchor.y + offset.y, true));
- } else if (direction === 'right' || direction === 'auto' && tooltipPoint.x < centerPoint.x) {
- direction = 'right';
- pos = pos.add(toPoint(offset.x + anchor.x, anchor.y - tooltipHeight / 2 + offset.y, true));
- } else {
- direction = 'left';
- pos = pos.subtract(toPoint(tooltipWidth + anchor.x - offset.x, tooltipHeight / 2 - anchor.y - offset.y, true));
- }
-
- removeClass(container, 'leaflet-tooltip-right');
- removeClass(container, 'leaflet-tooltip-left');
- removeClass(container, 'leaflet-tooltip-top');
- removeClass(container, 'leaflet-tooltip-bottom');
- addClass(container, 'leaflet-tooltip-' + direction);
- setPosition(container, pos);
- },
-
- _updatePosition: function () {
- var pos = this._map.latLngToLayerPoint(this._latlng);
- this._setPosition(pos);
- },
-
- setOpacity: function (opacity) {
- this.options.opacity = opacity;
-
- if (this._container) {
- setOpacity(this._container, opacity);
- }
- },
-
- _animateZoom: function (e) {
- var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);
- this._setPosition(pos);
- },
-
- _getAnchor: function () {
- // Where should we anchor the tooltip on the source layer?
- return toPoint(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]);
- }
-
-});
-
-// @namespace Tooltip
-// @factory L.tooltip(options?: Tooltip options, source?: Layer)
-// Instantiates a Tooltip object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the tooltip with a reference to the Layer to which it refers.
-var tooltip = function (options, source) {
- return new Tooltip(options, source);
-};
-
-// @namespace Map
-// @section Methods for Layers and Controls
-Map.include({
-
- // @method openTooltip(tooltip: Tooltip): this
- // Opens the specified tooltip.
- // @alternative
- // @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this
- // Creates a tooltip with the specified content and options and open it.
- openTooltip: function (tooltip, latlng, options) {
- if (!(tooltip instanceof Tooltip)) {
- tooltip = new Tooltip(options).setContent(tooltip);
- }
-
- if (latlng) {
- tooltip.setLatLng(latlng);
- }
-
- if (this.hasLayer(tooltip)) {
- return this;
- }
-
- return this.addLayer(tooltip);
- },
-
- // @method closeTooltip(tooltip?: Tooltip): this
- // Closes the tooltip given as parameter.
- closeTooltip: function (tooltip) {
- if (tooltip) {
- this.removeLayer(tooltip);
- }
- return this;
- }
-
-});
-
-/*
- * @namespace Layer
- * @section Tooltip methods example
- *
- * All layers share a set of methods convenient for binding tooltips to it.
- *
- * ```js
- * var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
- * layer.openTooltip();
- * layer.closeTooltip();
- * ```
- */
-
-// @section Tooltip methods
-Layer.include({
-
- // @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this
- // Binds a tooltip to the layer with the passed `content` and sets up the
- // necessary event listeners. If a `Function` is passed it will receive
- // the layer as the first argument and should return a `String` or `HTMLElement`.
- bindTooltip: function (content, options) {
-
- if (content instanceof Tooltip) {
- setOptions(content, options);
- this._tooltip = content;
- content._source = this;
- } else {
- if (!this._tooltip || options) {
- this._tooltip = new Tooltip(options, this);
- }
- this._tooltip.setContent(content);
-
- }
-
- this._initTooltipInteractions();
-
- if (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) {
- this.openTooltip();
- }
-
- return this;
- },
-
- // @method unbindTooltip(): this
- // Removes the tooltip previously bound with `bindTooltip`.
- unbindTooltip: function () {
- if (this._tooltip) {
- this._initTooltipInteractions(true);
- this.closeTooltip();
- this._tooltip = null;
- }
- return this;
- },
-
- _initTooltipInteractions: function (remove$$1) {
- if (!remove$$1 && this._tooltipHandlersAdded) { return; }
- var onOff = remove$$1 ? 'off' : 'on',
- events = {
- remove: this.closeTooltip,
- move: this._moveTooltip
- };
- if (!this._tooltip.options.permanent) {
- events.mouseover = this._openTooltip;
- events.mouseout = this.closeTooltip;
- if (this._tooltip.options.sticky) {
- events.mousemove = this._moveTooltip;
- }
- if (touch) {
- events.click = this._openTooltip;
- }
- } else {
- events.add = this._openTooltip;
- }
- this[onOff](events);
- this._tooltipHandlersAdded = !remove$$1;
- },
-
- // @method openTooltip(latlng?: LatLng): this
- // Opens the bound tooltip at the specified `latlng` or at the default tooltip anchor if no `latlng` is passed.
- openTooltip: function (layer, latlng) {
- if (!(layer instanceof Layer)) {
- latlng = layer;
- layer = this;
- }
-
- if (layer instanceof FeatureGroup) {
- for (var id in this._layers) {
- layer = this._layers[id];
- break;
- }
- }
-
- if (!latlng) {
- latlng = layer.getCenter ? layer.getCenter() : layer.getLatLng();
- }
-
- if (this._tooltip && this._map) {
-
- // set tooltip source to this layer
- this._tooltip._source = layer;
-
- // update the tooltip (content, layout, ect...)
- this._tooltip.update();
-
- // open the tooltip on the map
- this._map.openTooltip(this._tooltip, latlng);
-
- // Tooltip container may not be defined if not permanent and never
- // opened.
- if (this._tooltip.options.interactive && this._tooltip._container) {
- addClass(this._tooltip._container, 'leaflet-clickable');
- this.addInteractiveTarget(this._tooltip._container);
- }
- }
-
- return this;
- },
-
- // @method closeTooltip(): this
- // Closes the tooltip bound to this layer if it is open.
- closeTooltip: function () {
- if (this._tooltip) {
- this._tooltip._close();
- if (this._tooltip.options.interactive && this._tooltip._container) {
- removeClass(this._tooltip._container, 'leaflet-clickable');
- this.removeInteractiveTarget(this._tooltip._container);
- }
- }
- return this;
- },
-
- // @method toggleTooltip(): this
- // Opens or closes the tooltip bound to this layer depending on its current state.
- toggleTooltip: function (target) {
- if (this._tooltip) {
- if (this._tooltip._map) {
- this.closeTooltip();
- } else {
- this.openTooltip(target);
- }
- }
- return this;
- },
-
- // @method isTooltipOpen(): boolean
- // Returns `true` if the tooltip bound to this layer is currently open.
- isTooltipOpen: function () {
- return this._tooltip.isOpen();
- },
-
- // @method setTooltipContent(content: String|HTMLElement|Tooltip): this
- // Sets the content of the tooltip bound to this layer.
- setTooltipContent: function (content) {
- if (this._tooltip) {
- this._tooltip.setContent(content);
- }
- return this;
- },
-
- // @method getTooltip(): Tooltip
- // Returns the tooltip bound to this layer.
- getTooltip: function () {
- return this._tooltip;
- },
-
- _openTooltip: function (e) {
- var layer = e.layer || e.target;
-
- if (!this._tooltip || !this._map) {
- return;
- }
- this.openTooltip(layer, this._tooltip.options.sticky ? e.latlng : undefined);
- },
-
- _moveTooltip: function (e) {
- var latlng = e.latlng, containerPoint, layerPoint;
- if (this._tooltip.options.sticky && e.originalEvent) {
- containerPoint = this._map.mouseEventToContainerPoint(e.originalEvent);
- layerPoint = this._map.containerPointToLayerPoint(containerPoint);
- latlng = this._map.layerPointToLatLng(layerPoint);
- }
- this._tooltip.setLatLng(latlng);
- }
-});
-
-/*
- * @class DivIcon
- * @aka L.DivIcon
- * @inherits Icon
- *
- * Represents a lightweight icon for markers that uses a simple `
`
- * element instead of an image. Inherits from `Icon` but ignores the `iconUrl` and shadow options.
- *
- * @example
- * ```js
- * var myIcon = L.divIcon({className: 'my-div-icon'});
- * // you can set .my-div-icon styles in CSS
- *
- * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
- * ```
- *
- * By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.
- */
-
-var DivIcon = Icon.extend({
- options: {
- // @section
- // @aka DivIcon options
- iconSize: [12, 12], // also can be set through CSS
-
- // iconAnchor: (Point),
- // popupAnchor: (Point),
-
- // @option html: String = ''
- // Custom HTML code to put inside the div element, empty by default.
- html: false,
-
- // @option bgPos: Point = [0, 0]
- // Optional relative position of the background, in pixels
- bgPos: null,
-
- className: 'leaflet-div-icon'
- },
-
- createIcon: function (oldIcon) {
- var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'),
- options = this.options;
-
- div.innerHTML = options.html !== false ? options.html : '';
-
- if (options.bgPos) {
- var bgPos = toPoint(options.bgPos);
- div.style.backgroundPosition = (-bgPos.x) + 'px ' + (-bgPos.y) + 'px';
- }
- this._setIconStyles(div, 'icon');
-
- return div;
- },
-
- createShadow: function () {
- return null;
- }
-});
-
-// @factory L.divIcon(options: DivIcon options)
-// Creates a `DivIcon` instance with the given options.
-function divIcon(options) {
- return new DivIcon(options);
-}
-
-Icon.Default = IconDefault;
-
-/*
- * @class GridLayer
- * @inherits Layer
- * @aka L.GridLayer
- *
- * Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces `TileLayer.Canvas`.
- * GridLayer can be extended to create a tiled grid of HTML elements like `