X-Git-Url: https://git.openstreetmap.org./rails.git/blobdiff_plain/effb1b7f4170bb7244c4dfffcbe6134fe00e2bc4..4b2d6436cee11c0b3d751ef15cace053e26fbf3d:/vendor/assets/leaflet/leaflet.js?ds=sidebyside diff --git a/vendor/assets/leaflet/leaflet.js b/vendor/assets/leaflet/leaflet.js index 0f239b11e..a845eb6ae 100644 --- a/vendor/assets/leaflet/leaflet.js +++ b/vendor/assets/leaflet/leaflet.js @@ -1,14 +1,15 @@ /* @preserve - * Leaflet 1.2.0, a JS library for interactive maps. http://leafletjs.com - * (c) 2010-2017 Vladimir Agafonkin, (c) 2010-2011 CloudMade + * Leaflet 1.5.1+build.2e3e0ff, a JS library for interactive maps. http://leafletjs.com + * (c) 2010-2018 Vladimir Agafonkin, (c) 2010-2011 CloudMade */ + (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.L = {}))); }(this, (function (exports) { 'use strict'; -var version = "1.2.0"; +var version = "1.5.1+build.2e3e0ffb"; /* * @namespace Util @@ -65,12 +66,12 @@ function bind(fn, obj) { var lastId = 0; // @function stamp(obj: Object): Number -// Returns the unique ID of an object, assiging it one if it doesn't have it. +// Returns the unique ID of an object, assigning it one if it doesn't have it. function stamp(obj) { /*eslint-disable */ obj._leaflet_id = obj._leaflet_id || ++lastId; return obj._leaflet_id; - /*eslint-enable */ + /* eslint-enable */ } // @function throttle(fn: Function, time: Number, context: Object): Function @@ -124,10 +125,10 @@ function wrapNum(x, range, includeMax) { function falseFn() { return false; } // @function formatNum(num: Number, digits?: Number): Number -// Returns the number `num` rounded to `digits` decimals, or to 5 decimals by default. +// Returns the number `num` rounded to `digits` decimals, or to 6 decimals by default. function formatNum(num, digits) { - var pow = Math.pow(10, digits || 5); - return Math.round(num * pow) / pow; + digits = (digits === undefined ? 6 : digits); + return +(Math.round(num + ('e+' + digits)) + ('e-' + digits)); } // @function trim(str: String): String @@ -167,7 +168,7 @@ function getParamString(obj, existingUrl, uppercase) { return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); } -var templateRe = /\{ *([\w_\-]+) *\}/g; +var templateRe = /\{ *([\w_-]+) *\}/g; // @function template(str: String, data: Object): String // Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'` @@ -390,7 +391,7 @@ Class.addInitHook = function (fn) { // (Function) || (String, args...) }; function checkDeprecatedMixinEvents(includes) { - if (!L || !L.Mixin) { return; } + if (typeof L === 'undefined' || !L || !L.Mixin) { return; } includes = isArray(includes) ? includes : [includes]; @@ -467,7 +468,7 @@ var Events = { * * @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) { @@ -576,7 +577,11 @@ var Events = { fire: function (type, data, propagate) { if (!this.listens(type, propagate)) { return this; } - var event = extend({}, data, {type: type, target: this}); + var event = extend({}, data, { + type: type, + target: this, + sourceTarget: data && data.sourceTarget || this + }); if (this._events) { var listeners = this._events[type]; @@ -657,7 +662,10 @@ var Events = { _propagateEvent: function (e) { for (var id in this._eventParents) { - this._eventParents[id].fire(e.type, extend({layer: e.target}, e), true); + this._eventParents[id].fire(e.type, extend({ + layer: e.target, + propagatedFrom: e.target + }, e), true); } } }; @@ -707,6 +715,10 @@ var Evented = Class.extend(Events); * map.panBy([200, 300]); * map.panBy(L.point(200, 300)); * ``` + * + * Note that `Point` does not inherit from Leafet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. */ function Point(x, y, round) { @@ -716,6 +728,10 @@ function Point(x, y, round) { this.y = (round ? Math.round(y) : y); } +var trunc = Math.trunc || function (v) { + return v > 0 ? Math.floor(v) : Math.ceil(v); +}; + Point.prototype = { // @method clone(): Point @@ -826,6 +842,18 @@ Point.prototype = { return this; }, + // @method trunc(): Point + // Returns a copy of the current point with truncated coordinates (rounded towards zero). + trunc: function () { + return this.clone()._trunc(); + }, + + _trunc: function () { + this.x = trunc(this.x); + this.y = trunc(this.y); + return this; + }, + // @method distanceTo(otherPoint: Point): Number // Returns the cartesian distance between the current and the given points. distanceTo: function (point) { @@ -909,6 +937,10 @@ function toPoint(x, y, round) { * ```js * otherBounds.intersects([[10, 10], [40, 60]]); * ``` + * + * Note that `Bounds` does not inherit from Leafet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. */ function Bounds(a, b) { @@ -1082,6 +1114,10 @@ function toBounds(a, b) { * ``` * * Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners _outside_ the [-180, 180] degrees longitude range. + * + * Note that `LatLngBounds` does not inherit from Leafet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. */ function LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[]) @@ -1135,7 +1171,9 @@ LatLngBounds.prototype = { }, // @method pad(bufferRatio: Number): LatLngBounds - // Returns bigger bounds created by extending the current bounds by a given percentage in each direction. + // Returns bounds created by extending or retracting the current bounds by a given ratio in each direction. + // For example, a ratio of 0.5 extends the bounds by 50% in each direction. + // Negative values will retract the bounds. pad: function (bufferRatio) { var sw = this._southWest, ne = this._northEast, @@ -1270,7 +1308,7 @@ LatLngBounds.prototype = { }, // @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean - // Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overriden by setting `maxMargin` to a small number. + // Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting `maxMargin` to a small number. equals: function (bounds, maxMargin) { if (!bounds) { return false; } @@ -1321,6 +1359,10 @@ function toLatLngBounds(a, b) { * map.panTo({lat: 50, lng: 30}); * map.panTo(L.latLng(50, 30)); * ``` + * + * Note that `LatLng` does not inherit from Leaflet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. */ function LatLng(lat, lng, alt) { @@ -1345,7 +1387,7 @@ function LatLng(lat, lng, alt) { LatLng.prototype = { // @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean - // Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overriden by setting `maxMargin` to a small number. + // Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number. equals: function (obj, maxMargin) { if (!obj) { return false; } @@ -1367,7 +1409,7 @@ LatLng.prototype = { }, // @method distanceTo(otherLatLng: LatLng): Number - // Returns the distance (in meters) to the given `LatLng` calculated using the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula). + // Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines). distanceTo: function (other) { return Earth.distance(this, toLatLng(other)); }, @@ -1443,6 +1485,10 @@ function toLatLng(a, b, c) { * Leaflet defines the most usual CRSs by default. If you want to use a * CRS not defined by default, take a look at the * [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin. + * + * Note that the CRS 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 CRS = { @@ -1585,10 +1631,11 @@ var Earth = extend({}, CRS, { var rad = Math.PI / 180, lat1 = latlng1.lat * rad, lat2 = latlng2.lat * rad, - a = Math.sin(lat1) * Math.sin(lat2) + - Math.cos(lat1) * Math.cos(lat2) * Math.cos((latlng2.lng - latlng1.lng) * rad); - - return this.R * Math.acos(Math.min(a, 1)); + 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; } }); @@ -1601,9 +1648,11 @@ var Earth = extend({}, CRS, { * a sphere. Used by the `EPSG:3857` CRS. */ +var earthRadius = 6378137; + var SphericalMercator = { - R: 6378137, + R: earthRadius, MAX_LATITUDE: 85.0511287798, project: function (latlng) { @@ -1613,8 +1662,8 @@ var SphericalMercator = { sin = Math.sin(lat * d); return new Point( - this.R * latlng.lng * d, - this.R * Math.log((1 + sin) / (1 - sin)) / 2); + this.R * latlng.lng * d, + this.R * Math.log((1 + sin) / (1 - sin)) / 2); }, unproject: function (point) { @@ -1626,7 +1675,7 @@ var SphericalMercator = { }, bounds: (function () { - var d = 6378137 * Math.PI; + var d = earthRadius * Math.PI; return new Bounds([-d, -d], [d, d]); })() }; @@ -1701,7 +1750,7 @@ Transformation.prototype = { // @alternative // @factory L.transformation(coefficients: Array): Transformation -// Expects an coeficients array of the form +// Expects an coefficients array of the form // `[a: Number, b: Number, c: Number, d: Number]`. function toTransformation(a, b, c, d) { @@ -1802,6 +1851,11 @@ var android = userAgentContains('android'); // @property android23: Boolean; `true` for browsers running on Android 2 or Android 3. var android23 = userAgentContains('android 2') || userAgentContains('android 3'); +/* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */ +var webkitVer = parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit +// @property androidStock: Boolean; `true` for the Android stock browser (i.e. not Chrome) +var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window); + // @property opera: Boolean; `true` for the Opera browser var opera = !!window.opera; @@ -1870,7 +1924,7 @@ var mobileOpera = mobile && opera; var mobileGecko = mobile && gecko; // @property retina: Boolean -// `true` for browsers on a high-resolution "retina" screen. +// `true` for browsers on a high-resolution "retina" screen or on any screen when browser's display zoom is more than 100%. var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1; @@ -1914,6 +1968,7 @@ var Browser = (Object.freeze || Object)({ webkit: webkit, android: android, android23: android23, + androidStock: androidStock, opera: opera, chrome: chrome, gecko: gecko, @@ -1949,6 +2004,7 @@ 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; @@ -1991,7 +2047,7 @@ function removePointerListener(obj, type, id) { function _addPointerStart(obj, handler, id) { var onDown = bind(function (e) { - if (e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) { + 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. @@ -2117,6 +2173,7 @@ function addDoubleTapListener(obj, handler, id) { touch$$1 = newTouch; } touch$$1.type = 'dblclick'; + touch$$1.button = 0; handler(touch$$1); last = null; } @@ -2153,673 +2210,703 @@ function removeDoubleTapListener(obj, id) { } /* - * @namespace DomEvent - * Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally. + * @namespace DomUtil + * + * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) + * tree, used by Leaflet internally. + * + * Most functions expecting or returning a `HTMLElement` also work for + * SVG elements. The only difference is that classes refer to CSS classes + * in HTML and SVG classes in SVG. */ -// Inspired by John Resig, Dean Edwards and YUI addEvent implementations. -// @function on(el: HTMLElement, types: String, fn: Function, context?: Object): this -// Adds a listener function (`fn`) to a particular DOM event type of the -// element `el`. You can optionally specify the context of the listener -// (object the `this` keyword will point to). You can also pass several -// space-separated types (e.g. `'click dblclick'`). +// @property TRANSFORM: String +// Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit). +var TRANSFORM = testProp( + ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']); -// @alternative -// @function on(el: HTMLElement, eventMap: Object, context?: Object): this -// Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` -function on(obj, types, fn, context) { +// 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 - if (typeof types === 'object') { - for (var type in types) { - addOne(obj, type, types[type], fn); - } - } else { - types = splitWords(types); +// @property TRANSITION: String +// Vendor-prefixed transition style name. +var TRANSITION = testProp( + ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); - for (var i = 0, len = types.length; i < len; i++) { - addOne(obj, types[i], fn, context); - } - } +// @property TRANSITION_END: String +// Vendor-prefixed transitionend event name. +var TRANSITION_END = + TRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend'; - return this; + +// @function get(id: String|HTMLElement): HTMLElement +// Returns an element given its DOM id, or returns the element itself +// if it was passed directly. +function get(id) { + return typeof id === 'string' ? document.getElementById(id) : id; } -var eventsKey = '_leaflet_events'; +// @function getStyle(el: HTMLElement, styleAttrib: String): String +// Returns the value for a certain style attribute on an element, +// including computed values or values set through CSS. +function getStyle(el, style) { + var value = el.style[style] || (el.currentStyle && el.currentStyle[style]); -// @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this -// Removes a previously added listener function. If no function is specified, -// it will remove all the listeners of that particular DOM event from the element. -// Note that if you passed a custom context to on, you must pass the same -// context to `off` in order to remove the listener. + if ((!value || value === 'auto') && document.defaultView) { + var css = document.defaultView.getComputedStyle(el, null); + value = css ? css[style] : null; + } + return value === 'auto' ? null : value; +} -// @alternative -// @function off(el: HTMLElement, eventMap: Object, context?: Object): this -// Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` +// @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement +// Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element. +function create$1(tagName, className, container) { + var el = document.createElement(tagName); + el.className = className || ''; -// @alternative -// @function off(el: HTMLElement): this -// Removes all known event listeners -function off(obj, types, fn, context) { + if (container) { + container.appendChild(el); + } + return el; +} - if (typeof types === 'object') { - for (var type in types) { - removeOne(obj, type, types[type], fn); - } - } else if (types) { - types = splitWords(types); +// @function remove(el: HTMLElement) +// Removes `el` from its parent element +function remove(el) { + var parent = el.parentNode; + if (parent) { + parent.removeChild(el); + } +} - for (var i = 0, len = types.length; i < len; i++) { - removeOne(obj, types[i], fn, context); - } - } else { - for (var j in obj[eventsKey]) { - removeOne(obj, j, obj[eventsKey][j]); - } - delete obj[eventsKey]; +// @function empty(el: HTMLElement) +// Removes all of `el`'s children elements from `el` +function empty(el) { + while (el.firstChild) { + el.removeChild(el.firstChild); } +} - return this; +// @function toFront(el: HTMLElement) +// 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 && parent.lastChild !== el) { + parent.appendChild(el); + } } -function addOne(obj, type, fn, context) { - var id = type + stamp(fn) + (context ? '_' + stamp(context) : ''); +// @function toBack(el: HTMLElement) +// Makes `el` the first child of its parent, so it renders behind the other children. +function toBack(el) { + var parent = el.parentNode; + if (parent && parent.firstChild !== el) { + parent.insertBefore(el, parent.firstChild); + } +} - if (obj[eventsKey] && obj[eventsKey][id]) { return this; } +// @function hasClass(el: HTMLElement, name: String): Boolean +// Returns `true` if the element's class attribute contains `name`. +function hasClass(el, name) { + if (el.classList !== undefined) { + return el.classList.contains(name); + } + var className = getClass(el); + return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className); +} - var handler = function (e) { - return fn.call(context || obj, e || window.event); - }; +// @function addClass(el: HTMLElement, name: String) +// Adds `name` to the element's class attribute. +function addClass(el, name) { + if (el.classList !== undefined) { + var classes = splitWords(name); + for (var i = 0, len = classes.length; i < len; i++) { + el.classList.add(classes[i]); + } + } else if (!hasClass(el, name)) { + var className = getClass(el); + setClass(el, (className ? className + ' ' : '') + name); + } +} - var originalHandler = handler; +// @function removeClass(el: HTMLElement, name: String) +// Removes `name` from the element's class attribute. +function removeClass(el, name) { + if (el.classList !== undefined) { + el.classList.remove(name); + } else { + setClass(el, trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' '))); + } +} - if (pointer && type.indexOf('touch') === 0) { - // Needs DomEvent.Pointer.js - addPointerListener(obj, type, handler, id); +// @function setClass(el: HTMLElement, name: String) +// Sets the element's class. +function setClass(el, name) { + if (el.className.baseVal === undefined) { + el.className = name; + } else { + // in case of SVG element + el.className.baseVal = name; + } +} - } else if (touch && (type === 'dblclick') && addDoubleTapListener && - !(pointer && chrome)) { - // Chrome >55 does not need the synthetic dblclicks from addDoubleTapListener - // See #5180 - addDoubleTapListener(obj, handler, id); +// @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; +} - } else if ('addEventListener' in obj) { +// @function setOpacity(el: HTMLElement, opacity: Number) +// Set the opacity of an element (including old IE support). +// `opacity` must be a number from `0` to `1`. +function setOpacity(el, value) { + if ('opacity' in el.style) { + el.style.opacity = value; + } else if ('filter' in el.style) { + _setOpacityIE(el, value); + } +} - if (type === 'mousewheel') { - obj.addEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false); +function _setOpacityIE(el, value) { + var filter = false, + filterName = 'DXImageTransform.Microsoft.Alpha'; - } else if ((type === 'mouseenter') || (type === 'mouseleave')) { - handler = function (e) { - e = e || window.event; - if (isExternalTarget(obj, e)) { - originalHandler(e); - } - }; - obj.addEventListener(type === 'mouseenter' ? 'mouseover' : 'mouseout', handler, false); + // filters collection throws an error if we try to retrieve a filter that doesn't exist + try { + filter = el.filters.item(filterName); + } catch (e) { + // don't set opacity to 1 if we haven't already set an opacity, + // it isn't needed and breaks transparent pngs. + if (value === 1) { return; } + } - } else { - if (type === 'click' && android) { - handler = function (e) { - filterClick(e, originalHandler); - }; - } - obj.addEventListener(type, handler, false); - } + value = Math.round(value * 100); - } else if ('attachEvent' in obj) { - obj.attachEvent('on' + type, handler); + if (filter) { + filter.Enabled = (value !== 100); + filter.Opacity = value; + } else { + el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')'; } - - obj[eventsKey] = obj[eventsKey] || {}; - obj[eventsKey][id] = handler; } -function removeOne(obj, type, fn, context) { - - var id = type + stamp(fn) + (context ? '_' + stamp(context) : ''), - handler = obj[eventsKey] && obj[eventsKey][id]; - - if (!handler) { return this; } +// @function testProp(props: String[]): String|false +// Goes through the array of style names and returns the first name +// that is a valid style name for an element. If no such name is found, +// it returns false. Useful for vendor-prefixed styles like `transform`. +function testProp(props) { + var style = document.documentElement.style; - if (pointer && type.indexOf('touch') === 0) { - removePointerListener(obj, type, id); + for (var i = 0; i < props.length; i++) { + if (props[i] in style) { + return props[i]; + } + } + return false; +} - } else if (touch && (type === 'dblclick') && removeDoubleTapListener) { - removeDoubleTapListener(obj, id); +// @function setTransform(el: HTMLElement, offset: Point, scale?: Number) +// Resets the 3D CSS transform of `el` so it is translated by `offset` pixels +// and optionally scaled by `scale`. Does not have an effect if the +// browser doesn't support 3D CSS transforms. +function setTransform(el, offset, scale) { + var pos = offset || new Point(0, 0); - } else if ('removeEventListener' in obj) { + el.style[TRANSFORM] = + (ie3d ? + 'translate(' + pos.x + 'px,' + pos.y + 'px)' : + 'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') + + (scale ? ' scale(' + scale + ')' : ''); +} - if (type === 'mousewheel') { - obj.removeEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false); +// @function setPosition(el: HTMLElement, position: Point) +// Sets the position of `el` to coordinates specified by `position`, +// using CSS translate or top/left positioning depending on the browser +// (used by Leaflet internally to position its layers). +function setPosition(el, point) { - } else { - obj.removeEventListener( - type === 'mouseenter' ? 'mouseover' : - type === 'mouseleave' ? 'mouseout' : type, handler, false); - } + /*eslint-disable */ + el._leaflet_pos = point; + /* eslint-enable */ - } else if ('detachEvent' in obj) { - obj.detachEvent('on' + type, handler); + if (any3d) { + setTransform(el, point); + } else { + el.style.left = point.x + 'px'; + el.style.top = point.y + 'px'; } +} - obj[eventsKey][id] = null; +// @function getPosition(el: HTMLElement): Point +// Returns the coordinates of an element previously positioned with setPosition. +function getPosition(el) { + // this method is only used for elements previously positioned using setPosition, + // so it's safe to cache the position for performance + + return el._leaflet_pos || new Point(0, 0); } -// @function stopPropagation(ev: DOMEvent): this -// Stop the given event from propagation to parent elements. Used inside the listener functions: -// ```js -// L.DomEvent.on(div, 'click', function (ev) { -// L.DomEvent.stopPropagation(ev); -// }); -// ``` -function stopPropagation(e) { +// @function disableTextSelection() +// Prevents the user from generating `selectstart` DOM events, usually generated +// when the user drags the mouse through a page with text. Used internally +// by Leaflet to override the behaviour of any click-and-drag interaction on +// the map. Affects drag interactions on the whole document. - if (e.stopPropagation) { - e.stopPropagation(); - } else if (e.originalEvent) { // In case of Leaflet event. - e.originalEvent._stopped = true; - } else { - e.cancelBubble = true; - } - skipped(e); +// @function enableTextSelection() +// Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection). +var disableTextSelection; +var enableTextSelection; +var _userSelect; +if ('onselectstart' in document) { + disableTextSelection = function () { + on(window, 'selectstart', preventDefault); + }; + enableTextSelection = function () { + off(window, 'selectstart', preventDefault); + }; +} else { + var userSelectProperty = testProp( + ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']); - return this; + disableTextSelection = function () { + if (userSelectProperty) { + var style = document.documentElement.style; + _userSelect = style[userSelectProperty]; + style[userSelectProperty] = 'none'; + } + }; + enableTextSelection = function () { + if (userSelectProperty) { + document.documentElement.style[userSelectProperty] = _userSelect; + _userSelect = undefined; + } + }; } -// @function disableScrollPropagation(el: HTMLElement): this -// Adds `stopPropagation` to the element's `'mousewheel'` events (plus browser variants). -function disableScrollPropagation(el) { - addOne(el, 'mousewheel', stopPropagation); - return this; +// @function disableImageDrag() +// As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but +// for `dragstart` DOM events, usually generated when the user drags an image. +function disableImageDrag() { + on(window, 'dragstart', preventDefault); } -// @function disableClickPropagation(el: HTMLElement): this -// Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`, -// `'mousedown'` and `'touchstart'` events (plus browser variants). -function disableClickPropagation(el) { - on(el, 'mousedown touchstart dblclick', stopPropagation); - addOne(el, 'click', fakeStop); - return this; +// @function enableImageDrag() +// Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection). +function enableImageDrag() { + off(window, 'dragstart', preventDefault); } -// @function preventDefault(ev: DOMEvent): this -// Prevents the default action of the DOM Event `ev` from happening (such as -// following a link in the href of the a element, or doing a POST request -// with page reload when a `