/* @preserve
- * Leaflet 1.3.2, a JS library for interactive maps. http://leafletjs.com
+ * Leaflet 1.5.1+build.2e3e0ff, a JS library for interactive maps. http://leafletjs.com
* (c) 2010-2018 Vladimir Agafonkin, (c) 2010-2011 CloudMade
*/
(factory((global.L = {})));
}(this, (function (exports) { 'use strict';
-var version = "1.3.2";
+var version = "1.5.1+build.2e3e0ffb";
/*
* @namespace Util
// @function formatNum(num: Number, digits?: Number): Number
// Returns the number `num` rounded to `digits` decimals, or to 6 decimals by default.
function formatNum(num, digits) {
- var pow = Math.pow(10, (digits === undefined ? 6 : digits));
- return Math.round(num * pow) / pow;
+ digits = (digits === undefined ? 6 : digits);
+ return +(Math.round(num + ('e+' + digits)) + ('e-' + digits));
}
// @function trim(str: String): String
*
* @alternative
* @method off: this
- * Removes all listeners to all events on the object.
+ * Removes all listeners to all events on the object. This includes implicitly attached events.
*/
off: function (types, fn, context) {
* a sphere. Used by the `EPSG:3857` CRS.
*/
+var earthRadius = 6378137;
+
var SphericalMercator = {
- R: 6378137,
+ R: earthRadius,
MAX_LATITUDE: 85.0511287798,
project: function (latlng) {
},
bounds: (function () {
- var d = 6378137 * Math.PI;
+ var d = earthRadius * Math.PI;
return new Bounds([-d, -d], [d, d]);
})()
};
touch$$1 = newTouch;
}
touch$$1.type = 'dblclick';
+ touch$$1.button = 0;
handler(touch$$1);
last = null;
}
// @property TRANSFORM: String
// Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit).
var TRANSFORM = testProp(
- ['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
+ ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
// webkitTransition comes first because some browser versions that drop vendor prefix don't do
// the same for the transitionend event, in particular the Android 4.1 stock browser
// 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);
}
}
// 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);
}
}
// @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;
}
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();
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
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
// this event. Also fired on mobile when the user holds a single touch
// for a second (also called long press).
// @event keypress: KeyboardEvent
- // Fired when the user presses a key from the keyboard while the map is focused.
+ // Fired when the user presses a key from the keyboard that produces a character value while the map is focused.
+ // @event keydown: KeyboardEvent
+ // Fired when the user presses a key from the keyboard while the map is focused. Unlike the `keypress` event,
+ // the `keydown` event is fired for keys that produce a character value and for keys
+ // that do not produce a character value.
+ // @event keyup: KeyboardEvent
+ // Fired when the user releases a key from the keyboard while the map is focused.
onOff(this._container, 'click dblclick mousedown mouseup ' +
- 'mouseover mouseout mousemove contextmenu keypress', this._handleDOMEvent, this);
+ 'mouseover mouseout mousemove contextmenu keypress keydown keyup', this._handleDOMEvent, this);
if (this.options.trackResize) {
onOff(window, 'resize', this._onResize, this);
var type = e.type;
- if (type === 'mousedown' || type === 'keypress') {
+ if (type === 'mousedown' || type === 'keypress' || type === 'keyup' || type === 'keydown') {
// prevents outline when clicking on keyboard-focusable element
preventOutline(e.target || e.srcElement);
}
originalEvent: e
};
- if (e.type !== 'keypress') {
+ if (e.type !== 'keypress' && e.type !== 'keydown' && e.type !== 'keyup') {
var isMarker = target.getLatLng && (!target._radius || target._radius <= 10);
data.containerPoint = isMarker ?
this.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e);
}
// @event zoomanim: ZoomAnimEvent
- // Fired on every frame of a zoom animation
+ // Fired at least once per zoom animation. For continuous zoom, like pinch zooming, fired once per frame during zoom.
this.fire('zoomanim', {
center: center,
zoom: zoom,
corner.appendChild(container);
}
+ this._map.on('unload', this.remove, this);
+
return this;
},
this.onRemove(this._map);
}
+ this._map.off('unload', this.remove, this);
this._map = null;
return this;
// 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;
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);
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) {
input.className = 'leaflet-control-layers-selector';
input.defaultChecked = checked;
} else {
- input = this._createRadioElement('leaflet-base-layers', checked);
+ input = this._createRadioElement('leaflet-base-layers_' + stamp(this), checked);
}
this._layerControlInputs.push(input);
Map.addInitHook(function () {
if (this.options.zoomControl) {
+ // @section Controls
+ // @property zoomControl: Control.Zoom
+ // The default zoom control (only available if the
+ // [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map).
this.zoomControl = new Zoom();
this.addControl(this.zoomControl);
}
// @option prefix: String = 'Leaflet'
// The HTML text shown before the attributions. Pass `false` to disable.
- prefix: '<a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>'
+ prefix: '<a href="https://leafletjs.com" title="A JS library for interactive maps">Leaflet</a>'
},
initialize: function (options) {
* @namespace Projection
* @projection L.Projection.Mercator
*
- * Elliptical Mercator projection — more complex than Spherical Mercator. Takes into account that Earth is a geoid, not a perfect sphere. Used by the EPSG:3395 CRS.
+ * Elliptical Mercator projection — more complex than Spherical Mercator. Assumes that Earth is an ellipsoid. Used by the EPSG:3395 CRS.
*/
var Mercator = {
* @example
*
* ```js
- * var layer = L.Marker(latlng).addTo(map);
+ * var layer = L.marker(latlng).addTo(map);
* layer.addTo(map);
* layer.remove();
* ```
pane: 'overlayPane',
// @option attribution: String = null
- // String to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ // 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
options: {
popupAnchor: [0, 0],
- tooltipAnchor: [0, 0],
+ tooltipAnchor: [0, 0]
},
initialize: function (options) {
// Option inherited from "Interactive layer" abstract class
interactive: true,
- // @option draggable: Boolean = false
- // Whether the marker is draggable with mouse/touch or not.
- draggable: false,
-
- // @option autoPan: Boolean = false
- // Set it to `true` if you want the map to do panning animation when marker hits the edges.
- autoPan: false,
-
- // @option autoPanPadding: Point = Point(50, 50)
- // Equivalent of setting both top left and bottom right autopan padding to the same value.
- autoPanPadding: [50, 50],
-
- // @option autoPanSpeed: Number = 10
- // Number of pixels the map should move by.
- autoPanSpeed: 10,
-
// @option keyboard: Boolean = true
// Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.
keyboard: true,
// `Map pane` where the markers icon will be added.
pane: 'markerPane',
+ // @option pane: String = 'shadowPane'
+ // `Map pane` where the markers shadow will be added.
+ shadowPane: 'shadowPane',
+
// @option bubblingMouseEvents: Boolean = false
// When `true`, a mouse event on this marker will trigger the same event on the map
// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
- bubblingMouseEvents: false
+ bubblingMouseEvents: false,
+
+ // @section Draggable marker options
+ // @option draggable: Boolean = false
+ // Whether the marker is draggable with mouse/touch or not.
+ draggable: false,
+
+ // @option autoPan: Boolean = false
+ // Whether to pan the map when dragging this marker near its edge or not.
+ autoPan: false,
+
+ // @option autoPanPadding: Point = Point(50, 50)
+ // Distance (in pixels to the left/right and to the top/bottom) of the
+ // map edge to start panning the map.
+ autoPanPadding: [50, 50],
+
+ // @option autoPanSpeed: Number = 10
+ // Number of pixels the map should pan by.
+ autoPanSpeed: 10
},
/* @section
return this.update();
},
+ // @method getIcon: Icon
+ // Returns the current icon used by the marker
+ getIcon: function () {
+ return this.options.icon;
+ },
+
// @method setIcon(icon: Icon): this
// Changes the marker icon.
setIcon: function (icon) {
}
this._initInteraction();
if (newShadow && addShadow) {
- this.getPane('shadowPane').appendChild(this._shadow);
+ this.getPane(options.shadowPane).appendChild(this._shadow);
}
},
_updateOpacity: function () {
var opacity = this.options.opacity;
- setOpacity(this._icon, opacity);
+ if (this._icon) {
+ setOpacity(this._icon, opacity);
+ }
if (this._shadow) {
setOpacity(this._shadow, opacity);
setOptions(this, style);
if (this._renderer) {
this._renderer._updateStyle(this);
+ if (this.options.stroke && style.hasOwnProperty('weight')) {
+ this._updateBounds();
+ }
}
return this;
},
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;
+ this._rawPxBounds = pxBounds;
+ this._updateBounds();
}
},
+ _updateBounds: function () {
+ var w = this._clickTolerance(),
+ p = new Point(w, w);
+ this._pxBounds = new Bounds([
+ this._rawPxBounds.min.subtract(p),
+ this._rawPxBounds.max.add(p)
+ ]);
+ },
+
// recursively turns latlngs into a set of rings with projected coordinates
_projectLatlngs: function (latlngs, result, projectedBounds) {
var flat = latlngs[0] instanceof LatLng,
},
_setLayerStyle: function (layer, style) {
- if (typeof style === 'function') {
- style = style(layer.feature);
- }
if (layer.setStyle) {
+ if (typeof style === 'function') {
+ style = style(layer.feature);
+ }
layer.setStyle(style);
}
}
};
// @namespace Marker
-// @method toGeoJSON(): Object
+// @method toGeoJSON(precision?: Number): Object
+// `precision` is the number of decimal places for coordinates.
+// The default value is 6 places.
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature).
Marker.include(PointToGeoJSON);
// @namespace CircleMarker
-// @method toGeoJSON(): Object
+// @method toGeoJSON(precision?: Number): Object
+// `precision` is the number of decimal places for coordinates.
+// The default value is 6 places.
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature).
Circle.include(PointToGeoJSON);
CircleMarker.include(PointToGeoJSON);
// @namespace Polyline
-// @method toGeoJSON(): Object
+// @method toGeoJSON(precision?: Number): Object
+// `precision` is the number of decimal places for coordinates.
+// The default value is 6 places.
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature).
Polyline.include({
toGeoJSON: function (precision) {
});
// @namespace Polygon
-// @method toGeoJSON(): Object
+// @method toGeoJSON(precision?: Number): Object
+// `precision` is the number of decimal places for coordinates.
+// The default value is 6 places.
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature).
Polygon.include({
toGeoJSON: function (precision) {
});
},
- // @method toGeoJSON(): Object
+ // @method toGeoJSON(precision?: Number): Object
+ // `precision` is the number of decimal places for coordinates.
+ // The default value is 6 places.
// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `FeatureCollection`, `GeometryCollection`, or `MultiPoint`).
toGeoJSON: function (precision) {
errorOverlayUrl: '',
// @option zIndex: Number = 1
- // The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the tile layer.
+ // The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer.
zIndex: 1,
// @option className: String = ''
// A custom class name to assign to the image. Empty by default.
- className: '',
+ className: ''
},
initialize: function (url, bounds, options) { // (String, LatLngBounds, Object)
return events;
},
- // @method: setZIndex(value: Number) : this
+ // @method setZIndex(value: Number): this
// Changes the [zIndex](#imageoverlay-zindex) of the image overlay.
setZIndex: function (value) {
this.options.zIndex = value;
_overlayOnError: function () {
// @event error: Event
- // Fired when the ImageOverlay layer has loaded its image
+ // Fired when the ImageOverlay layer fails to load its image
this.fire('error');
var errorUrl = this.options.errorOverlayUrl;
// @option loop: Boolean = true
// Whether the video will loop back to the beginning when played.
- loop: true
+ loop: true,
+
+ // @option keepAspectRatio: Boolean = true
+ // Whether the video will save aspect ratio after the projection.
+ // Relevant for supported browsers. Browser compatibility- https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit
+ keepAspectRatio: true
},
_initImage: function () {
if (!isArray(this._url)) { this._url = [this._url]; }
+ if (!this.options.keepAspectRatio && vid.style.hasOwnProperty('objectFit')) { vid.style['objectFit'] = 'fill'; }
vid.autoplay = !!this.options.autoplay;
vid.loop = !!this.options.loop;
for (var i = 0; i < this._url.length; i++) {
return new VideoOverlay(video, bounds, options);
}
+/*
+ * @class SVGOverlay
+ * @aka L.SVGOverlay
+ * @inherits ImageOverlay
+ *
+ * Used to load, display and provide DOM access to an SVG file over specific bounds of the map. Extends `ImageOverlay`.
+ *
+ * An SVG overlay uses the [`<svg>`](https://developer.mozilla.org/docs/Web/SVG/Element/svg) element.
+ *
+ * @example
+ *
+ * ```js
+ * var element = '<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" height="200" width="200"/></svg>',
+ * elementBounds = [ [ 32, -130 ], [ 13, -100 ] ];
+ * L.svgOverlay(element, elementBounds).addTo(map);
+ * ```
+ */
+
+var SVGOverlay = ImageOverlay.extend({
+ _initImage: function () {
+ var el = this._image = this._url;
+
+ addClass(el, 'leaflet-image-layer');
+ if (this._zoomAnimated) { addClass(el, 'leaflet-zoom-animated'); }
+
+ el.onselectstart = falseFn;
+ el.onmousemove = falseFn;
+ }
+
+ // @method getElement(): SVGElement
+ // Returns the instance of [`SVGElement`](https://developer.mozilla.org/docs/Web/API/SVGElement)
+ // used by this overlay.
+});
+
+
+// @factory L.svgOverlay(svg: String|SVGElement, bounds: LatLngBounds, options?: SVGOverlay options)
+// Instantiates an image overlay object given an SVG element and the geographical bounds it is tied to.
+// A viewBox attribute is required on the SVG element to zoom in and out properly.
+
+function svgOverlay(el, bounds, options) {
+ return new SVGOverlay(el, bounds, options);
+}
+
/*
* @class DivOverlay
* @inherits Layer
return this;
},
+ _prepareOpen: function (parent, layer, latlng) {
+ if (!(layer instanceof Layer)) {
+ latlng = layer;
+ layer = parent;
+ }
+
+ if (layer instanceof FeatureGroup) {
+ for (var id in parent._layers) {
+ layer = parent._layers[id];
+ break;
+ }
+ }
+
+ if (!latlng) {
+ if (layer.getCenter) {
+ latlng = layer.getCenter();
+ } else if (layer.getLatLng) {
+ latlng = layer.getLatLng();
+ } else {
+ throw new Error('Unable to get source layer LatLng.');
+ }
+ }
+
+ // set overlay source to this layer
+ this._source = layer;
+
+ // update the overlay (content, layout, ect...)
+ this.update();
+
+ return latlng;
+ },
+
_updateContent: function () {
if (!this._content) { return; }
},
_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,
// @method openPopup(latlng?: LatLng): this
// Opens the bound popup at the specified `latlng` or at the default popup anchor if no `latlng` is passed.
openPopup: 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._popup && this._map) {
- // set popup source to this layer
- this._popup._source = layer;
-
- // update the popup (content, layout, ect...)
- this._popup.update();
+ latlng = this._popup._prepareOpen(this, layer, latlng);
// open the popup on the map
this._map.openPopup(this._popup, latlng);
// @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();
+ latlng = this._tooltip._prepareOpen(this, layer, latlng);
// open the tooltip on the map
this._map.openTooltip(this._tooltip, latlng);
// iconAnchor: (Point),
// popupAnchor: (Point),
- // @option html: String = ''
- // Custom HTML code to put inside the div element, empty by default.
+ // @option html: String|HTMLElement = ''
+ // Custom HTML code to put inside the div element, empty by default. Alternatively,
+ // an instance of `HTMLElement`.
html: false,
// @option bgPos: Point = [0, 0]
var div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'),
options = this.options;
- div.innerHTML = options.html !== false ? options.html : '';
+ if (options.html instanceof Element) {
+ empty(div);
+ div.appendChild(options.html);
+ } else {
+ div.innerHTML = options.html !== false ? options.html : '';
+ }
if (options.bgPos) {
var bgPos = toPoint(options.bgPos);
var tile = this._tiles[key];
if (!tile) { return; }
- // Cancels any pending http requests associated with the tile
- // unless we're on Android's stock browser,
- // see https://github.com/Leaflet/Leaflet/issues/137
- if (!androidStock) {
- tile.el.setAttribute('src', emptyImageUrl);
- }
remove(tile.el);
delete this._tiles[key];
},
_tileReady: function (coords, err, tile) {
- if (!this._map || tile.getAttribute('src') === emptyImageUrl) { return; }
-
if (err) {
// @event tileerror: TileErrorEvent
// Fired when there is an error loading a tile.
* @class TileLayer
* @inherits GridLayer
* @aka L.TileLayer
- * Used to load and display tile layers on the map. Extends `GridLayer`.
+ * Used to load and display tile layers on the map. Note that most tile servers require attribution, which you can set under `Layer`. Extends `GridLayer`.
*
* @example
*
* ```js
- * L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
+ * L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar', attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'}).addTo(map);
* ```
*
* @section URL template
// @method setUrl(url: String, noRedraw?: Boolean): this
// Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).
+ // If the URL does not change, the layer will not be redrawn unless
+ // the noRedraw parameter is set to false.
setUrl: function (url, noRedraw) {
+ if (this._url === url && noRedraw === undefined) {
+ noRedraw = true;
+ }
+
this._url = url;
if (!noRedraw) {
}
}
}
+ },
+
+ _removeTile: function (key) {
+ var tile = this._tiles[key];
+ if (!tile) { return; }
+
+ // Cancels any pending http requests associated with the tile
+ // unless we're on Android's stock browser,
+ // see https://github.com/Leaflet/Leaflet/issues/137
+ if (!androidStock) {
+ tile.el.setAttribute('src', emptyImageUrl);
+ }
+
+ return GridLayer.prototype._removeTile.call(this, key);
+ },
+
+ _tileReady: function (coords, err, tile) {
+ if (!this._map || (tile && tile.getAttribute('src') === emptyImageUrl)) {
+ return;
+ }
+
+ return GridLayer.prototype._tileReady.call(this, coords, err, tile);
}
});
_update: function () {
if (this._map._animatingZoom && this._bounds) { return; }
- this._drawnLayers = {};
-
Renderer.prototype._update.call(this);
var b = this._bounds,
this._drawFirst = next;
}
- delete this._drawnLayers[layer._leaflet_id];
-
delete layer._order;
delete this._layers[stamp(layer)];
_updateDashArray: function (layer) {
if (typeof layer.options.dashArray === 'string') {
- var parts = layer.options.dashArray.split(','),
+ var parts = layer.options.dashArray.split(/[, ]+/),
dashArray = [],
+ dashValue,
i;
for (i = 0; i < parts.length; i++) {
- dashArray.push(Number(parts[i]));
+ dashValue = Number(parts[i]);
+ // Ignore dash array containing invalid lengths
+ if (isNaN(dashValue)) { return; }
+ dashArray.push(dashValue);
}
layer.options._dashArray = dashArray;
} else {
if (!len) { return; }
- this._drawnLayers[layer._leaflet_id] = layer;
-
ctx.beginPath();
for (i = 0; i < len; i++) {
r = Math.max(Math.round(layer._radius), 1),
s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;
- this._drawnLayers[layer._leaflet_id] = layer;
-
if (s !== 1) {
ctx.save();
ctx.scale(1, s);
_bringToFront: function (layer) {
var order = layer._order;
+
+ if (!order) { return; }
+
var next = order.next;
var prev = order.prev;
_bringToBack: function (layer) {
var order = layer._order;
+
+ if (!order) { return; }
+
var next = order.next;
var prev = order.prev;
/*
* @class SVG
*
- * Although SVG is not available on IE7 and IE8, these browsers support [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language), and the SVG renderer will fall back to VML in this case.
*
* VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility
* with old versions of Internet Explorer.
exports.imageOverlay = imageOverlay;
exports.VideoOverlay = VideoOverlay;
exports.videoOverlay = videoOverlay;
+exports.SVGOverlay = SVGOverlay;
+exports.svgOverlay = svgOverlay;
exports.DivOverlay = DivOverlay;
exports.Popup = Popup;
exports.popup = popup;