leaflet-rails 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5d40985851694fd24e0e12816b77f1a0ca6bcb85d9e12a4f19f22763e2caba0
4
- data.tar.gz: 0ae4945719c7722201ddcb555a19c4babb37981b383bdfe1b02b669b8c699e51
3
+ metadata.gz: 15f37698a05926fbca11a20befcd9f8711d631251607f2d38d509339120e82e0
4
+ data.tar.gz: b4113c803b8bfd40bbecc348f6d6b06583811a62e396ebe4a097d48a4dc123c6
5
5
  SHA512:
6
- metadata.gz: 29575d0360d8555ffa0d234e934ddc9fa28112d103d166ba7937150f7cb1aa3552cd52dcd1a262053fdb8fad072cef10599eb476def688ffa8bc88aa99052972
7
- data.tar.gz: 0a1bae11fa45a4e1addb3bc4407db943551019e1295d9dbb5a151c410e3843d5918fc6767bc6096e9fc58fa54313a30897b865896df61f69ca17e8156891a394
6
+ metadata.gz: 83774653a86501dd75c802bb19ac17dbd5b801627eaf62776dad7c722531204a79171246232d76e2f51045a669ae18e6076e5728327b7baac3923b42b6344429
7
+ data.tar.gz: 436af48719b99969e8ec40ea7db9bd699ce1fb4e51c075c55006b2445508e2e2c5e8578b232cfa1ebc32f383ad7d0bd819ad8ccad756349a9ba033a3239029d5
@@ -1,5 +1,5 @@
1
1
  module Leaflet
2
2
  module Rails
3
- VERSION = "1.3.1"
3
+ VERSION = "1.4.0"
4
4
  end
5
5
  end
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,6 +1,6 @@
1
1
  /* @preserve
2
- * Leaflet 1.3.1+Detached: ba6f97fff8647e724e4dfe66d2ed7da11f908989.ba6f97f, a JS library for interactive maps. http://leafletjs.com
3
- * (c) 2010-2017 Vladimir Agafonkin, (c) 2010-2011 CloudMade
2
+ * Leaflet 1.4.0, a JS library for interactive maps. http://leafletjs.com
3
+ * (c) 2010-2018 Vladimir Agafonkin, (c) 2010-2011 CloudMade
4
4
  */
5
5
 
6
6
  (function (global, factory) {
@@ -9,7 +9,7 @@
9
9
  (factory((global.L = {})));
10
10
  }(this, (function (exports) { 'use strict';
11
11
 
12
- var version = "1.3.1+HEAD.ba6f97f";
12
+ var version = "1.4.0";
13
13
 
14
14
  /*
15
15
  * @namespace Util
@@ -1360,7 +1360,7 @@ function toLatLngBounds(a, b) {
1360
1360
  * map.panTo(L.latLng(50, 30));
1361
1361
  * ```
1362
1362
  *
1363
- * Note that `LatLng` does not inherit from Leafet's `Class` object,
1363
+ * Note that `LatLng` does not inherit from Leaflet's `Class` object,
1364
1364
  * which means new classes can't inherit from it, and new methods
1365
1365
  * can't be added to it with the `include` function.
1366
1366
  */
@@ -1922,7 +1922,7 @@ var mobileOpera = mobile && opera;
1922
1922
  var mobileGecko = mobile && gecko;
1923
1923
 
1924
1924
  // @property retina: Boolean
1925
- // `true` for browsers on a high-resolution "retina" screen.
1925
+ // `true` for browsers on a high-resolution "retina" screen or on any screen when browser's display zoom is more than 100%.
1926
1926
  var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1;
1927
1927
 
1928
1928
 
@@ -2206,6 +2206,384 @@ function removeDoubleTapListener(obj, id) {
2206
2206
  return this;
2207
2207
  }
2208
2208
 
2209
+ /*
2210
+ * @namespace DomUtil
2211
+ *
2212
+ * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)
2213
+ * tree, used by Leaflet internally.
2214
+ *
2215
+ * Most functions expecting or returning a `HTMLElement` also work for
2216
+ * SVG elements. The only difference is that classes refer to CSS classes
2217
+ * in HTML and SVG classes in SVG.
2218
+ */
2219
+
2220
+
2221
+ // @property TRANSFORM: String
2222
+ // Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit).
2223
+ var TRANSFORM = testProp(
2224
+ ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
2225
+
2226
+ // webkitTransition comes first because some browser versions that drop vendor prefix don't do
2227
+ // the same for the transitionend event, in particular the Android 4.1 stock browser
2228
+
2229
+ // @property TRANSITION: String
2230
+ // Vendor-prefixed transition style name.
2231
+ var TRANSITION = testProp(
2232
+ ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);
2233
+
2234
+ // @property TRANSITION_END: String
2235
+ // Vendor-prefixed transitionend event name.
2236
+ var TRANSITION_END =
2237
+ TRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend';
2238
+
2239
+
2240
+ // @function get(id: String|HTMLElement): HTMLElement
2241
+ // Returns an element given its DOM id, or returns the element itself
2242
+ // if it was passed directly.
2243
+ function get(id) {
2244
+ return typeof id === 'string' ? document.getElementById(id) : id;
2245
+ }
2246
+
2247
+ // @function getStyle(el: HTMLElement, styleAttrib: String): String
2248
+ // Returns the value for a certain style attribute on an element,
2249
+ // including computed values or values set through CSS.
2250
+ function getStyle(el, style) {
2251
+ var value = el.style[style] || (el.currentStyle && el.currentStyle[style]);
2252
+
2253
+ if ((!value || value === 'auto') && document.defaultView) {
2254
+ var css = document.defaultView.getComputedStyle(el, null);
2255
+ value = css ? css[style] : null;
2256
+ }
2257
+ return value === 'auto' ? null : value;
2258
+ }
2259
+
2260
+ // @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement
2261
+ // Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element.
2262
+ function create$1(tagName, className, container) {
2263
+ var el = document.createElement(tagName);
2264
+ el.className = className || '';
2265
+
2266
+ if (container) {
2267
+ container.appendChild(el);
2268
+ }
2269
+ return el;
2270
+ }
2271
+
2272
+ // @function remove(el: HTMLElement)
2273
+ // Removes `el` from its parent element
2274
+ function remove(el) {
2275
+ var parent = el.parentNode;
2276
+ if (parent) {
2277
+ parent.removeChild(el);
2278
+ }
2279
+ }
2280
+
2281
+ // @function empty(el: HTMLElement)
2282
+ // Removes all of `el`'s children elements from `el`
2283
+ function empty(el) {
2284
+ while (el.firstChild) {
2285
+ el.removeChild(el.firstChild);
2286
+ }
2287
+ }
2288
+
2289
+ // @function toFront(el: HTMLElement)
2290
+ // Makes `el` the last child of its parent, so it renders in front of the other children.
2291
+ function toFront(el) {
2292
+ var parent = el.parentNode;
2293
+ if (parent && parent.lastChild !== el) {
2294
+ parent.appendChild(el);
2295
+ }
2296
+ }
2297
+
2298
+ // @function toBack(el: HTMLElement)
2299
+ // Makes `el` the first child of its parent, so it renders behind the other children.
2300
+ function toBack(el) {
2301
+ var parent = el.parentNode;
2302
+ if (parent && parent.firstChild !== el) {
2303
+ parent.insertBefore(el, parent.firstChild);
2304
+ }
2305
+ }
2306
+
2307
+ // @function hasClass(el: HTMLElement, name: String): Boolean
2308
+ // Returns `true` if the element's class attribute contains `name`.
2309
+ function hasClass(el, name) {
2310
+ if (el.classList !== undefined) {
2311
+ return el.classList.contains(name);
2312
+ }
2313
+ var className = getClass(el);
2314
+ return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className);
2315
+ }
2316
+
2317
+ // @function addClass(el: HTMLElement, name: String)
2318
+ // Adds `name` to the element's class attribute.
2319
+ function addClass(el, name) {
2320
+ if (el.classList !== undefined) {
2321
+ var classes = splitWords(name);
2322
+ for (var i = 0, len = classes.length; i < len; i++) {
2323
+ el.classList.add(classes[i]);
2324
+ }
2325
+ } else if (!hasClass(el, name)) {
2326
+ var className = getClass(el);
2327
+ setClass(el, (className ? className + ' ' : '') + name);
2328
+ }
2329
+ }
2330
+
2331
+ // @function removeClass(el: HTMLElement, name: String)
2332
+ // Removes `name` from the element's class attribute.
2333
+ function removeClass(el, name) {
2334
+ if (el.classList !== undefined) {
2335
+ el.classList.remove(name);
2336
+ } else {
2337
+ setClass(el, trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' ')));
2338
+ }
2339
+ }
2340
+
2341
+ // @function setClass(el: HTMLElement, name: String)
2342
+ // Sets the element's class.
2343
+ function setClass(el, name) {
2344
+ if (el.className.baseVal === undefined) {
2345
+ el.className = name;
2346
+ } else {
2347
+ // in case of SVG element
2348
+ el.className.baseVal = name;
2349
+ }
2350
+ }
2351
+
2352
+ // @function getClass(el: HTMLElement): String
2353
+ // Returns the element's class.
2354
+ function getClass(el) {
2355
+ // Check if the element is an SVGElementInstance and use the correspondingElement instead
2356
+ // (Required for linked SVG elements in IE11.)
2357
+ if (el.correspondingElement) {
2358
+ el = el.correspondingElement;
2359
+ }
2360
+ return el.className.baseVal === undefined ? el.className : el.className.baseVal;
2361
+ }
2362
+
2363
+ // @function setOpacity(el: HTMLElement, opacity: Number)
2364
+ // Set the opacity of an element (including old IE support).
2365
+ // `opacity` must be a number from `0` to `1`.
2366
+ function setOpacity(el, value) {
2367
+ if ('opacity' in el.style) {
2368
+ el.style.opacity = value;
2369
+ } else if ('filter' in el.style) {
2370
+ _setOpacityIE(el, value);
2371
+ }
2372
+ }
2373
+
2374
+ function _setOpacityIE(el, value) {
2375
+ var filter = false,
2376
+ filterName = 'DXImageTransform.Microsoft.Alpha';
2377
+
2378
+ // filters collection throws an error if we try to retrieve a filter that doesn't exist
2379
+ try {
2380
+ filter = el.filters.item(filterName);
2381
+ } catch (e) {
2382
+ // don't set opacity to 1 if we haven't already set an opacity,
2383
+ // it isn't needed and breaks transparent pngs.
2384
+ if (value === 1) { return; }
2385
+ }
2386
+
2387
+ value = Math.round(value * 100);
2388
+
2389
+ if (filter) {
2390
+ filter.Enabled = (value !== 100);
2391
+ filter.Opacity = value;
2392
+ } else {
2393
+ el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';
2394
+ }
2395
+ }
2396
+
2397
+ // @function testProp(props: String[]): String|false
2398
+ // Goes through the array of style names and returns the first name
2399
+ // that is a valid style name for an element. If no such name is found,
2400
+ // it returns false. Useful for vendor-prefixed styles like `transform`.
2401
+ function testProp(props) {
2402
+ var style = document.documentElement.style;
2403
+
2404
+ for (var i = 0; i < props.length; i++) {
2405
+ if (props[i] in style) {
2406
+ return props[i];
2407
+ }
2408
+ }
2409
+ return false;
2410
+ }
2411
+
2412
+ // @function setTransform(el: HTMLElement, offset: Point, scale?: Number)
2413
+ // Resets the 3D CSS transform of `el` so it is translated by `offset` pixels
2414
+ // and optionally scaled by `scale`. Does not have an effect if the
2415
+ // browser doesn't support 3D CSS transforms.
2416
+ function setTransform(el, offset, scale) {
2417
+ var pos = offset || new Point(0, 0);
2418
+
2419
+ el.style[TRANSFORM] =
2420
+ (ie3d ?
2421
+ 'translate(' + pos.x + 'px,' + pos.y + 'px)' :
2422
+ 'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +
2423
+ (scale ? ' scale(' + scale + ')' : '');
2424
+ }
2425
+
2426
+ // @function setPosition(el: HTMLElement, position: Point)
2427
+ // Sets the position of `el` to coordinates specified by `position`,
2428
+ // using CSS translate or top/left positioning depending on the browser
2429
+ // (used by Leaflet internally to position its layers).
2430
+ function setPosition(el, point) {
2431
+
2432
+ /*eslint-disable */
2433
+ el._leaflet_pos = point;
2434
+ /* eslint-enable */
2435
+
2436
+ if (any3d) {
2437
+ setTransform(el, point);
2438
+ } else {
2439
+ el.style.left = point.x + 'px';
2440
+ el.style.top = point.y + 'px';
2441
+ }
2442
+ }
2443
+
2444
+ // @function getPosition(el: HTMLElement): Point
2445
+ // Returns the coordinates of an element previously positioned with setPosition.
2446
+ function getPosition(el) {
2447
+ // this method is only used for elements previously positioned using setPosition,
2448
+ // so it's safe to cache the position for performance
2449
+
2450
+ return el._leaflet_pos || new Point(0, 0);
2451
+ }
2452
+
2453
+ // @function disableTextSelection()
2454
+ // Prevents the user from generating `selectstart` DOM events, usually generated
2455
+ // when the user drags the mouse through a page with text. Used internally
2456
+ // by Leaflet to override the behaviour of any click-and-drag interaction on
2457
+ // the map. Affects drag interactions on the whole document.
2458
+
2459
+ // @function enableTextSelection()
2460
+ // Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection).
2461
+ var disableTextSelection;
2462
+ var enableTextSelection;
2463
+ var _userSelect;
2464
+ if ('onselectstart' in document) {
2465
+ disableTextSelection = function () {
2466
+ on(window, 'selectstart', preventDefault);
2467
+ };
2468
+ enableTextSelection = function () {
2469
+ off(window, 'selectstart', preventDefault);
2470
+ };
2471
+ } else {
2472
+ var userSelectProperty = testProp(
2473
+ ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);
2474
+
2475
+ disableTextSelection = function () {
2476
+ if (userSelectProperty) {
2477
+ var style = document.documentElement.style;
2478
+ _userSelect = style[userSelectProperty];
2479
+ style[userSelectProperty] = 'none';
2480
+ }
2481
+ };
2482
+ enableTextSelection = function () {
2483
+ if (userSelectProperty) {
2484
+ document.documentElement.style[userSelectProperty] = _userSelect;
2485
+ _userSelect = undefined;
2486
+ }
2487
+ };
2488
+ }
2489
+
2490
+ // @function disableImageDrag()
2491
+ // As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but
2492
+ // for `dragstart` DOM events, usually generated when the user drags an image.
2493
+ function disableImageDrag() {
2494
+ on(window, 'dragstart', preventDefault);
2495
+ }
2496
+
2497
+ // @function enableImageDrag()
2498
+ // Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection).
2499
+ function enableImageDrag() {
2500
+ off(window, 'dragstart', preventDefault);
2501
+ }
2502
+
2503
+ var _outlineElement;
2504
+ var _outlineStyle;
2505
+ // @function preventOutline(el: HTMLElement)
2506
+ // Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline)
2507
+ // of the element `el` invisible. Used internally by Leaflet to prevent
2508
+ // focusable elements from displaying an outline when the user performs a
2509
+ // drag interaction on them.
2510
+ function preventOutline(element) {
2511
+ while (element.tabIndex === -1) {
2512
+ element = element.parentNode;
2513
+ }
2514
+ if (!element.style) { return; }
2515
+ restoreOutline();
2516
+ _outlineElement = element;
2517
+ _outlineStyle = element.style.outline;
2518
+ element.style.outline = 'none';
2519
+ on(window, 'keydown', restoreOutline);
2520
+ }
2521
+
2522
+ // @function restoreOutline()
2523
+ // Cancels the effects of a previous [`L.DomUtil.preventOutline`]().
2524
+ function restoreOutline() {
2525
+ if (!_outlineElement) { return; }
2526
+ _outlineElement.style.outline = _outlineStyle;
2527
+ _outlineElement = undefined;
2528
+ _outlineStyle = undefined;
2529
+ off(window, 'keydown', restoreOutline);
2530
+ }
2531
+
2532
+ // @function getSizedParentNode(el: HTMLElement): HTMLElement
2533
+ // Finds the closest parent node which size (width and height) is not null.
2534
+ function getSizedParentNode(element) {
2535
+ do {
2536
+ element = element.parentNode;
2537
+ } while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body);
2538
+ return element;
2539
+ }
2540
+
2541
+ // @function getScale(el: HTMLElement): Object
2542
+ // Computes the CSS scale currently applied on the element.
2543
+ // Returns an object with `x` and `y` members as horizontal and vertical scales respectively,
2544
+ // and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect).
2545
+ function getScale(element) {
2546
+ var rect = element.getBoundingClientRect(); // Read-only in old browsers.
2547
+
2548
+ return {
2549
+ x: rect.width / element.offsetWidth || 1,
2550
+ y: rect.height / element.offsetHeight || 1,
2551
+ boundingClientRect: rect
2552
+ };
2553
+ }
2554
+
2555
+
2556
+ var DomUtil = (Object.freeze || Object)({
2557
+ TRANSFORM: TRANSFORM,
2558
+ TRANSITION: TRANSITION,
2559
+ TRANSITION_END: TRANSITION_END,
2560
+ get: get,
2561
+ getStyle: getStyle,
2562
+ create: create$1,
2563
+ remove: remove,
2564
+ empty: empty,
2565
+ toFront: toFront,
2566
+ toBack: toBack,
2567
+ hasClass: hasClass,
2568
+ addClass: addClass,
2569
+ removeClass: removeClass,
2570
+ setClass: setClass,
2571
+ getClass: getClass,
2572
+ setOpacity: setOpacity,
2573
+ testProp: testProp,
2574
+ setTransform: setTransform,
2575
+ setPosition: setPosition,
2576
+ getPosition: getPosition,
2577
+ disableTextSelection: disableTextSelection,
2578
+ enableTextSelection: enableTextSelection,
2579
+ disableImageDrag: disableImageDrag,
2580
+ enableImageDrag: enableImageDrag,
2581
+ preventOutline: preventOutline,
2582
+ restoreOutline: restoreOutline,
2583
+ getSizedParentNode: getSizedParentNode,
2584
+ getScale: getScale
2585
+ });
2586
+
2209
2587
  /*
2210
2588
  * @namespace DomEvent
2211
2589
  * Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally.
@@ -2303,575 +2681,229 @@ function addOne(obj, type, fn, context) {
2303
2681
  if (isExternalTarget(obj, e)) {
2304
2682
  originalHandler(e);
2305
2683
  }
2306
- };
2307
- obj.addEventListener(type === 'mouseenter' ? 'mouseover' : 'mouseout', handler, false);
2308
-
2309
- } else {
2310
- if (type === 'click' && android) {
2311
- handler = function (e) {
2312
- filterClick(e, originalHandler);
2313
- };
2314
- }
2315
- obj.addEventListener(type, handler, false);
2316
- }
2317
-
2318
- } else if ('attachEvent' in obj) {
2319
- obj.attachEvent('on' + type, handler);
2320
- }
2321
-
2322
- obj[eventsKey] = obj[eventsKey] || {};
2323
- obj[eventsKey][id] = handler;
2324
- }
2325
-
2326
- function removeOne(obj, type, fn, context) {
2327
-
2328
- var id = type + stamp(fn) + (context ? '_' + stamp(context) : ''),
2329
- handler = obj[eventsKey] && obj[eventsKey][id];
2330
-
2331
- if (!handler) { return this; }
2332
-
2333
- if (pointer && type.indexOf('touch') === 0) {
2334
- removePointerListener(obj, type, id);
2335
-
2336
- } else if (touch && (type === 'dblclick') && removeDoubleTapListener &&
2337
- !(pointer && chrome)) {
2338
- removeDoubleTapListener(obj, id);
2339
-
2340
- } else if ('removeEventListener' in obj) {
2341
-
2342
- if (type === 'mousewheel') {
2343
- obj.removeEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false);
2344
-
2345
- } else {
2346
- obj.removeEventListener(
2347
- type === 'mouseenter' ? 'mouseover' :
2348
- type === 'mouseleave' ? 'mouseout' : type, handler, false);
2349
- }
2350
-
2351
- } else if ('detachEvent' in obj) {
2352
- obj.detachEvent('on' + type, handler);
2353
- }
2354
-
2355
- obj[eventsKey][id] = null;
2356
- }
2357
-
2358
- // @function stopPropagation(ev: DOMEvent): this
2359
- // Stop the given event from propagation to parent elements. Used inside the listener functions:
2360
- // ```js
2361
- // L.DomEvent.on(div, 'click', function (ev) {
2362
- // L.DomEvent.stopPropagation(ev);
2363
- // });
2364
- // ```
2365
- function stopPropagation(e) {
2366
-
2367
- if (e.stopPropagation) {
2368
- e.stopPropagation();
2369
- } else if (e.originalEvent) { // In case of Leaflet event.
2370
- e.originalEvent._stopped = true;
2371
- } else {
2372
- e.cancelBubble = true;
2373
- }
2374
- skipped(e);
2375
-
2376
- return this;
2377
- }
2378
-
2379
- // @function disableScrollPropagation(el: HTMLElement): this
2380
- // Adds `stopPropagation` to the element's `'mousewheel'` events (plus browser variants).
2381
- function disableScrollPropagation(el) {
2382
- addOne(el, 'mousewheel', stopPropagation);
2383
- return this;
2384
- }
2385
-
2386
- // @function disableClickPropagation(el: HTMLElement): this
2387
- // Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`,
2388
- // `'mousedown'` and `'touchstart'` events (plus browser variants).
2389
- function disableClickPropagation(el) {
2390
- on(el, 'mousedown touchstart dblclick', stopPropagation);
2391
- addOne(el, 'click', fakeStop);
2392
- return this;
2393
- }
2394
-
2395
- // @function preventDefault(ev: DOMEvent): this
2396
- // Prevents the default action of the DOM Event `ev` from happening (such as
2397
- // following a link in the href of the a element, or doing a POST request
2398
- // with page reload when a `<form>` is submitted).
2399
- // Use it inside listener functions.
2400
- function preventDefault(e) {
2401
- if (e.preventDefault) {
2402
- e.preventDefault();
2403
- } else {
2404
- e.returnValue = false;
2405
- }
2406
- return this;
2407
- }
2408
-
2409
- // @function stop(ev: DOMEvent): this
2410
- // Does `stopPropagation` and `preventDefault` at the same time.
2411
- function stop(e) {
2412
- preventDefault(e);
2413
- stopPropagation(e);
2414
- return this;
2415
- }
2416
-
2417
- // @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point
2418
- // Gets normalized mouse position from a DOM event relative to the
2419
- // `container` or to the whole page if not specified.
2420
- function getMousePosition(e, container) {
2421
- if (!container) {
2422
- return new Point(e.clientX, e.clientY);
2423
- }
2424
-
2425
- var rect = container.getBoundingClientRect();
2426
-
2427
- var scaleX = rect.width / container.offsetWidth || 1;
2428
- var scaleY = rect.height / container.offsetHeight || 1;
2429
- return new Point(
2430
- e.clientX / scaleX - rect.left - container.clientLeft,
2431
- e.clientY / scaleY - rect.top - container.clientTop);
2432
- }
2433
-
2434
- // Chrome on Win scrolls double the pixels as in other platforms (see #4538),
2435
- // and Firefox scrolls device pixels, not CSS pixels
2436
- var wheelPxFactor =
2437
- (win && chrome) ? 2 * window.devicePixelRatio :
2438
- gecko ? window.devicePixelRatio : 1;
2439
-
2440
- // @function getWheelDelta(ev: DOMEvent): Number
2441
- // Gets normalized wheel delta from a mousewheel DOM event, in vertical
2442
- // pixels scrolled (negative if scrolling down).
2443
- // Events from pointing devices without precise scrolling are mapped to
2444
- // a best guess of 60 pixels.
2445
- function getWheelDelta(e) {
2446
- return (edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta
2447
- (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels
2448
- (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines
2449
- (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages
2450
- (e.deltaX || e.deltaZ) ? 0 : // Skip horizontal/depth wheel events
2451
- e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels
2452
- (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines
2453
- e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages
2454
- 0;
2455
- }
2456
-
2457
- var skipEvents = {};
2458
-
2459
- function fakeStop(e) {
2460
- // fakes stopPropagation by setting a special event flag, checked/reset with skipped(e)
2461
- skipEvents[e.type] = true;
2462
- }
2463
-
2464
- function skipped(e) {
2465
- var events = skipEvents[e.type];
2466
- // reset when checking, as it's only used in map container and propagates outside of the map
2467
- skipEvents[e.type] = false;
2468
- return events;
2469
- }
2470
-
2471
- // check if element really left/entered the event target (for mouseenter/mouseleave)
2472
- function isExternalTarget(el, e) {
2473
-
2474
- var related = e.relatedTarget;
2475
-
2476
- if (!related) { return true; }
2477
-
2478
- try {
2479
- while (related && (related !== el)) {
2480
- related = related.parentNode;
2481
- }
2482
- } catch (err) {
2483
- return false;
2484
- }
2485
- return (related !== el);
2486
- }
2487
-
2488
- var lastClick;
2489
-
2490
- // this is a horrible workaround for a bug in Android where a single touch triggers two click events
2491
- function filterClick(e, handler) {
2492
- var timeStamp = (e.timeStamp || (e.originalEvent && e.originalEvent.timeStamp)),
2493
- elapsed = lastClick && (timeStamp - lastClick);
2494
-
2495
- // are they closer together than 500ms yet more than 100ms?
2496
- // Android typically triggers them ~300ms apart while multiple listeners
2497
- // on the same event should be triggered far faster;
2498
- // or check if click is simulated on the element, and if it is, reject any non-simulated events
2499
-
2500
- if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) {
2501
- stop(e);
2502
- return;
2503
- }
2504
- lastClick = timeStamp;
2505
-
2506
- handler(e);
2507
- }
2508
-
2509
-
2510
-
2511
-
2512
- var DomEvent = (Object.freeze || Object)({
2513
- on: on,
2514
- off: off,
2515
- stopPropagation: stopPropagation,
2516
- disableScrollPropagation: disableScrollPropagation,
2517
- disableClickPropagation: disableClickPropagation,
2518
- preventDefault: preventDefault,
2519
- stop: stop,
2520
- getMousePosition: getMousePosition,
2521
- getWheelDelta: getWheelDelta,
2522
- fakeStop: fakeStop,
2523
- skipped: skipped,
2524
- isExternalTarget: isExternalTarget,
2525
- addListener: on,
2526
- removeListener: off
2527
- });
2528
-
2529
- /*
2530
- * @namespace DomUtil
2531
- *
2532
- * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)
2533
- * tree, used by Leaflet internally.
2534
- *
2535
- * Most functions expecting or returning a `HTMLElement` also work for
2536
- * SVG elements. The only difference is that classes refer to CSS classes
2537
- * in HTML and SVG classes in SVG.
2538
- */
2539
-
2540
-
2541
- // @property TRANSFORM: String
2542
- // Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit).
2543
- var TRANSFORM = testProp(
2544
- ['transform', 'WebkitTransform', 'OTransform', 'MozTransform', 'msTransform']);
2545
-
2546
- // webkitTransition comes first because some browser versions that drop vendor prefix don't do
2547
- // the same for the transitionend event, in particular the Android 4.1 stock browser
2548
-
2549
- // @property TRANSITION: String
2550
- // Vendor-prefixed transition style name.
2551
- var TRANSITION = testProp(
2552
- ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);
2553
-
2554
- // @property TRANSITION_END: String
2555
- // Vendor-prefixed transitionend event name.
2556
- var TRANSITION_END =
2557
- TRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend';
2558
-
2559
-
2560
- // @function get(id: String|HTMLElement): HTMLElement
2561
- // Returns an element given its DOM id, or returns the element itself
2562
- // if it was passed directly.
2563
- function get(id) {
2564
- return typeof id === 'string' ? document.getElementById(id) : id;
2565
- }
2684
+ };
2685
+ obj.addEventListener(type === 'mouseenter' ? 'mouseover' : 'mouseout', handler, false);
2566
2686
 
2567
- // @function getStyle(el: HTMLElement, styleAttrib: String): String
2568
- // Returns the value for a certain style attribute on an element,
2569
- // including computed values or values set through CSS.
2570
- function getStyle(el, style) {
2571
- var value = el.style[style] || (el.currentStyle && el.currentStyle[style]);
2687
+ } else {
2688
+ if (type === 'click' && android) {
2689
+ handler = function (e) {
2690
+ filterClick(e, originalHandler);
2691
+ };
2692
+ }
2693
+ obj.addEventListener(type, handler, false);
2694
+ }
2572
2695
 
2573
- if ((!value || value === 'auto') && document.defaultView) {
2574
- var css = document.defaultView.getComputedStyle(el, null);
2575
- value = css ? css[style] : null;
2696
+ } else if ('attachEvent' in obj) {
2697
+ obj.attachEvent('on' + type, handler);
2576
2698
  }
2577
- return value === 'auto' ? null : value;
2699
+
2700
+ obj[eventsKey] = obj[eventsKey] || {};
2701
+ obj[eventsKey][id] = handler;
2578
2702
  }
2579
2703
 
2580
- // @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement
2581
- // Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element.
2582
- function create$1(tagName, className, container) {
2583
- var el = document.createElement(tagName);
2584
- el.className = className || '';
2704
+ function removeOne(obj, type, fn, context) {
2585
2705
 
2586
- if (container) {
2587
- container.appendChild(el);
2588
- }
2589
- return el;
2590
- }
2706
+ var id = type + stamp(fn) + (context ? '_' + stamp(context) : ''),
2707
+ handler = obj[eventsKey] && obj[eventsKey][id];
2591
2708
 
2592
- // @function remove(el: HTMLElement)
2593
- // Removes `el` from its parent element
2594
- function remove(el) {
2595
- var parent = el.parentNode;
2596
- if (parent) {
2597
- parent.removeChild(el);
2598
- }
2599
- }
2709
+ if (!handler) { return this; }
2600
2710
 
2601
- // @function empty(el: HTMLElement)
2602
- // Removes all of `el`'s children elements from `el`
2603
- function empty(el) {
2604
- while (el.firstChild) {
2605
- el.removeChild(el.firstChild);
2606
- }
2607
- }
2711
+ if (pointer && type.indexOf('touch') === 0) {
2712
+ removePointerListener(obj, type, id);
2608
2713
 
2609
- // @function toFront(el: HTMLElement)
2610
- // Makes `el` the last child of its parent, so it renders in front of the other children.
2611
- function toFront(el) {
2612
- var parent = el.parentNode;
2613
- if (parent.lastChild !== el) {
2614
- parent.appendChild(el);
2615
- }
2616
- }
2714
+ } else if (touch && (type === 'dblclick') && removeDoubleTapListener &&
2715
+ !(pointer && chrome)) {
2716
+ removeDoubleTapListener(obj, id);
2617
2717
 
2618
- // @function toBack(el: HTMLElement)
2619
- // Makes `el` the first child of its parent, so it renders behind the other children.
2620
- function toBack(el) {
2621
- var parent = el.parentNode;
2622
- if (parent.firstChild !== el) {
2623
- parent.insertBefore(el, parent.firstChild);
2624
- }
2625
- }
2718
+ } else if ('removeEventListener' in obj) {
2626
2719
 
2627
- // @function hasClass(el: HTMLElement, name: String): Boolean
2628
- // Returns `true` if the element's class attribute contains `name`.
2629
- function hasClass(el, name) {
2630
- if (el.classList !== undefined) {
2631
- return el.classList.contains(name);
2632
- }
2633
- var className = getClass(el);
2634
- return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className);
2635
- }
2720
+ if (type === 'mousewheel') {
2721
+ obj.removeEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false);
2636
2722
 
2637
- // @function addClass(el: HTMLElement, name: String)
2638
- // Adds `name` to the element's class attribute.
2639
- function addClass(el, name) {
2640
- if (el.classList !== undefined) {
2641
- var classes = splitWords(name);
2642
- for (var i = 0, len = classes.length; i < len; i++) {
2643
- el.classList.add(classes[i]);
2723
+ } else {
2724
+ obj.removeEventListener(
2725
+ type === 'mouseenter' ? 'mouseover' :
2726
+ type === 'mouseleave' ? 'mouseout' : type, handler, false);
2644
2727
  }
2645
- } else if (!hasClass(el, name)) {
2646
- var className = getClass(el);
2647
- setClass(el, (className ? className + ' ' : '') + name);
2648
- }
2649
- }
2650
2728
 
2651
- // @function removeClass(el: HTMLElement, name: String)
2652
- // Removes `name` from the element's class attribute.
2653
- function removeClass(el, name) {
2654
- if (el.classList !== undefined) {
2655
- el.classList.remove(name);
2656
- } else {
2657
- setClass(el, trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' ')));
2729
+ } else if ('detachEvent' in obj) {
2730
+ obj.detachEvent('on' + type, handler);
2658
2731
  }
2732
+
2733
+ obj[eventsKey][id] = null;
2659
2734
  }
2660
2735
 
2661
- // @function setClass(el: HTMLElement, name: String)
2662
- // Sets the element's class.
2663
- function setClass(el, name) {
2664
- if (el.className.baseVal === undefined) {
2665
- el.className = name;
2736
+ // @function stopPropagation(ev: DOMEvent): this
2737
+ // Stop the given event from propagation to parent elements. Used inside the listener functions:
2738
+ // ```js
2739
+ // L.DomEvent.on(div, 'click', function (ev) {
2740
+ // L.DomEvent.stopPropagation(ev);
2741
+ // });
2742
+ // ```
2743
+ function stopPropagation(e) {
2744
+
2745
+ if (e.stopPropagation) {
2746
+ e.stopPropagation();
2747
+ } else if (e.originalEvent) { // In case of Leaflet event.
2748
+ e.originalEvent._stopped = true;
2666
2749
  } else {
2667
- // in case of SVG element
2668
- el.className.baseVal = name;
2750
+ e.cancelBubble = true;
2669
2751
  }
2670
- }
2752
+ skipped(e);
2671
2753
 
2672
- // @function getClass(el: HTMLElement): String
2673
- // Returns the element's class.
2674
- function getClass(el) {
2675
- return el.className.baseVal === undefined ? el.className : el.className.baseVal;
2754
+ return this;
2676
2755
  }
2677
2756
 
2678
- // @function setOpacity(el: HTMLElement, opacity: Number)
2679
- // Set the opacity of an element (including old IE support).
2680
- // `opacity` must be a number from `0` to `1`.
2681
- function setOpacity(el, value) {
2682
- if ('opacity' in el.style) {
2683
- el.style.opacity = value;
2684
- } else if ('filter' in el.style) {
2685
- _setOpacityIE(el, value);
2686
- }
2757
+ // @function disableScrollPropagation(el: HTMLElement): this
2758
+ // Adds `stopPropagation` to the element's `'mousewheel'` events (plus browser variants).
2759
+ function disableScrollPropagation(el) {
2760
+ addOne(el, 'mousewheel', stopPropagation);
2761
+ return this;
2687
2762
  }
2688
2763
 
2689
- function _setOpacityIE(el, value) {
2690
- var filter = false,
2691
- filterName = 'DXImageTransform.Microsoft.Alpha';
2692
-
2693
- // filters collection throws an error if we try to retrieve a filter that doesn't exist
2694
- try {
2695
- filter = el.filters.item(filterName);
2696
- } catch (e) {
2697
- // don't set opacity to 1 if we haven't already set an opacity,
2698
- // it isn't needed and breaks transparent pngs.
2699
- if (value === 1) { return; }
2700
- }
2701
-
2702
- value = Math.round(value * 100);
2764
+ // @function disableClickPropagation(el: HTMLElement): this
2765
+ // Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`,
2766
+ // `'mousedown'` and `'touchstart'` events (plus browser variants).
2767
+ function disableClickPropagation(el) {
2768
+ on(el, 'mousedown touchstart dblclick', stopPropagation);
2769
+ addOne(el, 'click', fakeStop);
2770
+ return this;
2771
+ }
2703
2772
 
2704
- if (filter) {
2705
- filter.Enabled = (value !== 100);
2706
- filter.Opacity = value;
2773
+ // @function preventDefault(ev: DOMEvent): this
2774
+ // Prevents the default action of the DOM Event `ev` from happening (such as
2775
+ // following a link in the href of the a element, or doing a POST request
2776
+ // with page reload when a `<form>` is submitted).
2777
+ // Use it inside listener functions.
2778
+ function preventDefault(e) {
2779
+ if (e.preventDefault) {
2780
+ e.preventDefault();
2707
2781
  } else {
2708
- el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';
2782
+ e.returnValue = false;
2709
2783
  }
2784
+ return this;
2710
2785
  }
2711
2786
 
2712
- // @function testProp(props: String[]): String|false
2713
- // Goes through the array of style names and returns the first name
2714
- // that is a valid style name for an element. If no such name is found,
2715
- // it returns false. Useful for vendor-prefixed styles like `transform`.
2716
- function testProp(props) {
2717
- var style = document.documentElement.style;
2787
+ // @function stop(ev: DOMEvent): this
2788
+ // Does `stopPropagation` and `preventDefault` at the same time.
2789
+ function stop(e) {
2790
+ preventDefault(e);
2791
+ stopPropagation(e);
2792
+ return this;
2793
+ }
2718
2794
 
2719
- for (var i = 0; i < props.length; i++) {
2720
- if (props[i] in style) {
2721
- return props[i];
2722
- }
2795
+ // @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point
2796
+ // Gets normalized mouse position from a DOM event relative to the
2797
+ // `container` (border excluded) or to the whole page if not specified.
2798
+ function getMousePosition(e, container) {
2799
+ if (!container) {
2800
+ return new Point(e.clientX, e.clientY);
2723
2801
  }
2724
- return false;
2725
- }
2726
2802
 
2727
- // @function setTransform(el: HTMLElement, offset: Point, scale?: Number)
2728
- // Resets the 3D CSS transform of `el` so it is translated by `offset` pixels
2729
- // and optionally scaled by `scale`. Does not have an effect if the
2730
- // browser doesn't support 3D CSS transforms.
2731
- function setTransform(el, offset, scale) {
2732
- var pos = offset || new Point(0, 0);
2803
+ var scale = getScale(container),
2804
+ offset = scale.boundingClientRect; // left and top values are in page scale (like the event clientX/Y)
2733
2805
 
2734
- el.style[TRANSFORM] =
2735
- (ie3d ?
2736
- 'translate(' + pos.x + 'px,' + pos.y + 'px)' :
2737
- 'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +
2738
- (scale ? ' scale(' + scale + ')' : '');
2806
+ return new Point(
2807
+ // offset.left/top values are in page scale (like clientX/Y),
2808
+ // whereas clientLeft/Top (border width) values are the original values (before CSS scale applies).
2809
+ (e.clientX - offset.left) / scale.x - container.clientLeft,
2810
+ (e.clientY - offset.top) / scale.y - container.clientTop
2811
+ );
2739
2812
  }
2740
2813
 
2741
- // @function setPosition(el: HTMLElement, position: Point)
2742
- // Sets the position of `el` to coordinates specified by `position`,
2743
- // using CSS translate or top/left positioning depending on the browser
2744
- // (used by Leaflet internally to position its layers).
2745
- function setPosition(el, point) {
2746
-
2747
- /*eslint-disable */
2748
- el._leaflet_pos = point;
2749
- /* eslint-enable */
2814
+ // Chrome on Win scrolls double the pixels as in other platforms (see #4538),
2815
+ // and Firefox scrolls device pixels, not CSS pixels
2816
+ var wheelPxFactor =
2817
+ (win && chrome) ? 2 * window.devicePixelRatio :
2818
+ gecko ? window.devicePixelRatio : 1;
2750
2819
 
2751
- if (any3d) {
2752
- setTransform(el, point);
2753
- } else {
2754
- el.style.left = point.x + 'px';
2755
- el.style.top = point.y + 'px';
2756
- }
2820
+ // @function getWheelDelta(ev: DOMEvent): Number
2821
+ // Gets normalized wheel delta from a mousewheel DOM event, in vertical
2822
+ // pixels scrolled (negative if scrolling down).
2823
+ // Events from pointing devices without precise scrolling are mapped to
2824
+ // a best guess of 60 pixels.
2825
+ function getWheelDelta(e) {
2826
+ return (edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta
2827
+ (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels
2828
+ (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines
2829
+ (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages
2830
+ (e.deltaX || e.deltaZ) ? 0 : // Skip horizontal/depth wheel events
2831
+ e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels
2832
+ (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines
2833
+ e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages
2834
+ 0;
2757
2835
  }
2758
2836
 
2759
- // @function getPosition(el: HTMLElement): Point
2760
- // Returns the coordinates of an element previously positioned with setPosition.
2761
- function getPosition(el) {
2762
- // this method is only used for elements previously positioned using setPosition,
2763
- // so it's safe to cache the position for performance
2837
+ var skipEvents = {};
2764
2838
 
2765
- return el._leaflet_pos || new Point(0, 0);
2839
+ function fakeStop(e) {
2840
+ // fakes stopPropagation by setting a special event flag, checked/reset with skipped(e)
2841
+ skipEvents[e.type] = true;
2766
2842
  }
2767
2843
 
2768
- // @function disableTextSelection()
2769
- // Prevents the user from generating `selectstart` DOM events, usually generated
2770
- // when the user drags the mouse through a page with text. Used internally
2771
- // by Leaflet to override the behaviour of any click-and-drag interaction on
2772
- // the map. Affects drag interactions on the whole document.
2844
+ function skipped(e) {
2845
+ var events = skipEvents[e.type];
2846
+ // reset when checking, as it's only used in map container and propagates outside of the map
2847
+ skipEvents[e.type] = false;
2848
+ return events;
2849
+ }
2773
2850
 
2774
- // @function enableTextSelection()
2775
- // Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection).
2776
- var disableTextSelection;
2777
- var enableTextSelection;
2778
- var _userSelect;
2779
- if ('onselectstart' in document) {
2780
- disableTextSelection = function () {
2781
- on(window, 'selectstart', preventDefault);
2782
- };
2783
- enableTextSelection = function () {
2784
- off(window, 'selectstart', preventDefault);
2785
- };
2786
- } else {
2787
- var userSelectProperty = testProp(
2788
- ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);
2851
+ // check if element really left/entered the event target (for mouseenter/mouseleave)
2852
+ function isExternalTarget(el, e) {
2789
2853
 
2790
- disableTextSelection = function () {
2791
- if (userSelectProperty) {
2792
- var style = document.documentElement.style;
2793
- _userSelect = style[userSelectProperty];
2794
- style[userSelectProperty] = 'none';
2795
- }
2796
- };
2797
- enableTextSelection = function () {
2798
- if (userSelectProperty) {
2799
- document.documentElement.style[userSelectProperty] = _userSelect;
2800
- _userSelect = undefined;
2854
+ var related = e.relatedTarget;
2855
+
2856
+ if (!related) { return true; }
2857
+
2858
+ try {
2859
+ while (related && (related !== el)) {
2860
+ related = related.parentNode;
2801
2861
  }
2802
- };
2862
+ } catch (err) {
2863
+ return false;
2864
+ }
2865
+ return (related !== el);
2803
2866
  }
2804
2867
 
2805
- // @function disableImageDrag()
2806
- // As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but
2807
- // for `dragstart` DOM events, usually generated when the user drags an image.
2808
- function disableImageDrag() {
2809
- on(window, 'dragstart', preventDefault);
2810
- }
2868
+ var lastClick;
2811
2869
 
2812
- // @function enableImageDrag()
2813
- // Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection).
2814
- function enableImageDrag() {
2815
- off(window, 'dragstart', preventDefault);
2816
- }
2870
+ // this is a horrible workaround for a bug in Android where a single touch triggers two click events
2871
+ function filterClick(e, handler) {
2872
+ var timeStamp = (e.timeStamp || (e.originalEvent && e.originalEvent.timeStamp)),
2873
+ elapsed = lastClick && (timeStamp - lastClick);
2817
2874
 
2818
- var _outlineElement;
2819
- var _outlineStyle;
2820
- // @function preventOutline(el: HTMLElement)
2821
- // Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline)
2822
- // of the element `el` invisible. Used internally by Leaflet to prevent
2823
- // focusable elements from displaying an outline when the user performs a
2824
- // drag interaction on them.
2825
- function preventOutline(element) {
2826
- while (element.tabIndex === -1) {
2827
- element = element.parentNode;
2875
+ // are they closer together than 500ms yet more than 100ms?
2876
+ // Android typically triggers them ~300ms apart while multiple listeners
2877
+ // on the same event should be triggered far faster;
2878
+ // or check if click is simulated on the element, and if it is, reject any non-simulated events
2879
+
2880
+ if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) {
2881
+ stop(e);
2882
+ return;
2828
2883
  }
2829
- if (!element.style) { return; }
2830
- restoreOutline();
2831
- _outlineElement = element;
2832
- _outlineStyle = element.style.outline;
2833
- element.style.outline = 'none';
2834
- on(window, 'keydown', restoreOutline);
2835
- }
2884
+ lastClick = timeStamp;
2836
2885
 
2837
- // @function restoreOutline()
2838
- // Cancels the effects of a previous [`L.DomUtil.preventOutline`]().
2839
- function restoreOutline() {
2840
- if (!_outlineElement) { return; }
2841
- _outlineElement.style.outline = _outlineStyle;
2842
- _outlineElement = undefined;
2843
- _outlineStyle = undefined;
2844
- off(window, 'keydown', restoreOutline);
2886
+ handler(e);
2845
2887
  }
2888
+
2889
+
2846
2890
 
2847
2891
 
2848
- var DomUtil = (Object.freeze || Object)({
2849
- TRANSFORM: TRANSFORM,
2850
- TRANSITION: TRANSITION,
2851
- TRANSITION_END: TRANSITION_END,
2852
- get: get,
2853
- getStyle: getStyle,
2854
- create: create$1,
2855
- remove: remove,
2856
- empty: empty,
2857
- toFront: toFront,
2858
- toBack: toBack,
2859
- hasClass: hasClass,
2860
- addClass: addClass,
2861
- removeClass: removeClass,
2862
- setClass: setClass,
2863
- getClass: getClass,
2864
- setOpacity: setOpacity,
2865
- testProp: testProp,
2866
- setTransform: setTransform,
2867
- setPosition: setPosition,
2868
- getPosition: getPosition,
2869
- disableTextSelection: disableTextSelection,
2870
- enableTextSelection: enableTextSelection,
2871
- disableImageDrag: disableImageDrag,
2872
- enableImageDrag: enableImageDrag,
2873
- preventOutline: preventOutline,
2874
- restoreOutline: restoreOutline
2892
+ var DomEvent = (Object.freeze || Object)({
2893
+ on: on,
2894
+ off: off,
2895
+ stopPropagation: stopPropagation,
2896
+ disableScrollPropagation: disableScrollPropagation,
2897
+ disableClickPropagation: disableClickPropagation,
2898
+ preventDefault: preventDefault,
2899
+ stop: stop,
2900
+ getMousePosition: getMousePosition,
2901
+ getWheelDelta: getWheelDelta,
2902
+ fakeStop: fakeStop,
2903
+ skipped: skipped,
2904
+ isExternalTarget: isExternalTarget,
2905
+ addListener: on,
2906
+ removeListener: off
2875
2907
  });
2876
2908
 
2877
2909
  /*
@@ -3086,6 +3118,13 @@ var Map = Evented.extend({
3086
3118
  initialize: function (id, options) { // (HTMLElement or String, Object)
3087
3119
  options = setOptions(this, options);
3088
3120
 
3121
+ // Make sure to assign internal flags at the beginning,
3122
+ // to avoid inconsistent state in some edge cases.
3123
+ this._handlers = [];
3124
+ this._layers = {};
3125
+ this._zoomBoundLayers = {};
3126
+ this._sizeChanged = true;
3127
+
3089
3128
  this._initContainer(id);
3090
3129
  this._initLayout();
3091
3130
 
@@ -3106,11 +3145,6 @@ var Map = Evented.extend({
3106
3145
  this.setView(toLatLng(options.center), options.zoom, {reset: true});
3107
3146
  }
3108
3147
 
3109
- this._handlers = [];
3110
- this._layers = {};
3111
- this._zoomBoundLayers = {};
3112
- this._sizeChanged = true;
3113
-
3114
3148
  this.callInitHooks();
3115
3149
 
3116
3150
  // don't animate on browsers without hardware-accelerated transitions or old Android/Opera
@@ -3469,6 +3503,51 @@ var Map = Evented.extend({
3469
3503
  return this;
3470
3504
  },
3471
3505
 
3506
+ // @method panInside(latlng: LatLng, options?: options): this
3507
+ // Pans the map the minimum amount to make the `latlng` visible. Use
3508
+ // `padding`, `paddingTopLeft` and `paddingTopRight` options to fit
3509
+ // the display to more restricted bounds, like [`fitBounds`](#map-fitbounds).
3510
+ // If `latlng` is already within the (optionally padded) display bounds,
3511
+ // the map will not be panned.
3512
+ panInside: function (latlng, options) {
3513
+ options = options || {};
3514
+
3515
+ var paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),
3516
+ paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),
3517
+ center = this.getCenter(),
3518
+ pixelCenter = this.project(center),
3519
+ pixelPoint = this.project(latlng),
3520
+ pixelBounds = this.getPixelBounds(),
3521
+ halfPixelBounds = pixelBounds.getSize().divideBy(2),
3522
+ paddedBounds = toBounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]);
3523
+
3524
+ if (!paddedBounds.contains(pixelPoint)) {
3525
+ this._enforcingBounds = true;
3526
+ var diff = pixelCenter.subtract(pixelPoint),
3527
+ newCenter = toPoint(pixelPoint.x + diff.x, pixelPoint.y + diff.y);
3528
+
3529
+ if (pixelPoint.x < paddedBounds.min.x || pixelPoint.x > paddedBounds.max.x) {
3530
+ newCenter.x = pixelCenter.x - diff.x;
3531
+ if (diff.x > 0) {
3532
+ newCenter.x += halfPixelBounds.x - paddingTL.x;
3533
+ } else {
3534
+ newCenter.x -= halfPixelBounds.x - paddingBR.x;
3535
+ }
3536
+ }
3537
+ if (pixelPoint.y < paddedBounds.min.y || pixelPoint.y > paddedBounds.max.y) {
3538
+ newCenter.y = pixelCenter.y - diff.y;
3539
+ if (diff.y > 0) {
3540
+ newCenter.y += halfPixelBounds.y - paddingTL.y;
3541
+ } else {
3542
+ newCenter.y -= halfPixelBounds.y - paddingBR.y;
3543
+ }
3544
+ }
3545
+ this.panTo(this.unproject(newCenter), options);
3546
+ this._enforcingBounds = false;
3547
+ }
3548
+ return this;
3549
+ },
3550
+
3472
3551
  // @method invalidateSize(options: Zoom/pan options): this
3473
3552
  // Checks if the map container size changed and updates the map if so —
3474
3553
  // call it after you've changed the map size dynamically, also animating
@@ -3616,7 +3695,7 @@ var Map = Evented.extend({
3616
3695
  var lat = pos.coords.latitude,
3617
3696
  lng = pos.coords.longitude,
3618
3697
  latlng = new LatLng(lat, lng),
3619
- bounds = latlng.toBounds(pos.coords.accuracy),
3698
+ bounds = latlng.toBounds(pos.coords.accuracy * 2),
3620
3699
  options = this._locateOptions;
3621
3700
 
3622
3701
  if (options.setView) {
@@ -3692,6 +3771,10 @@ var Map = Evented.extend({
3692
3771
  if (this._clearControlPos) {
3693
3772
  this._clearControlPos();
3694
3773
  }
3774
+ if (this._resizeRequest) {
3775
+ cancelAnimFrame(this._resizeRequest);
3776
+ this._resizeRequest = null;
3777
+ }
3695
3778
 
3696
3779
  this._clearHandlers();
3697
3780
 
@@ -3776,7 +3859,7 @@ var Map = Evented.extend({
3776
3859
  this.options.maxZoom;
3777
3860
  },
3778
3861
 
3779
- // @method getBoundsZoom(bounds: LatLngBounds, inside?: Boolean): Number
3862
+ // @method getBoundsZoom(bounds: LatLngBounds, inside?: Boolean, padding?: Point): Number
3780
3863
  // Returns the maximum zoom level on which the given bounds fit to the map
3781
3864
  // view in its entirety. If `inside` (optional) is set to `true`, the method
3782
3865
  // instead returns the minimum zoom level on which the map view fits into
@@ -4583,7 +4666,7 @@ var Map = Evented.extend({
4583
4666
  }
4584
4667
 
4585
4668
  // @event zoomanim: ZoomAnimEvent
4586
- // Fired on every frame of a zoom animation
4669
+ // Fired at least once per zoom animation. For continous zoom, like pinch zooming, fired once per frame during zoom.
4587
4670
  this.fire('zoomanim', {
4588
4671
  center: center,
4589
4672
  zoom: zoom,
@@ -4939,13 +5022,13 @@ var Layers = Control.extend({
4939
5022
  // Expand the control container if collapsed.
4940
5023
  expand: function () {
4941
5024
  addClass(this._container, 'leaflet-control-layers-expanded');
4942
- this._form.style.height = null;
5025
+ this._section.style.height = null;
4943
5026
  var acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50);
4944
- if (acceptableHeight < this._form.clientHeight) {
4945
- addClass(this._form, 'leaflet-control-layers-scrollbar');
4946
- this._form.style.height = acceptableHeight + 'px';
5027
+ if (acceptableHeight < this._section.clientHeight) {
5028
+ addClass(this._section, 'leaflet-control-layers-scrollbar');
5029
+ this._section.style.height = acceptableHeight + 'px';
4947
5030
  } else {
4948
- removeClass(this._form, 'leaflet-control-layers-scrollbar');
5031
+ removeClass(this._section, 'leaflet-control-layers-scrollbar');
4949
5032
  }
4950
5033
  this._checkDisabledLayers();
4951
5034
  return this;
@@ -4969,7 +5052,7 @@ var Layers = Control.extend({
4969
5052
  disableClickPropagation(container);
4970
5053
  disableScrollPropagation(container);
4971
5054
 
4972
- var form = this._form = create$1('form', className + '-list');
5055
+ var section = this._section = create$1('section', className + '-list');
4973
5056
 
4974
5057
  if (collapsed) {
4975
5058
  this._map.on('click', this.collapse, this);
@@ -4997,11 +5080,11 @@ var Layers = Control.extend({
4997
5080
  this.expand();
4998
5081
  }
4999
5082
 
5000
- this._baseLayersList = create$1('div', className + '-base', form);
5001
- this._separator = create$1('div', className + '-separator', form);
5002
- this._overlaysList = create$1('div', className + '-overlays', form);
5083
+ this._baseLayersList = create$1('div', className + '-base', section);
5084
+ this._separator = create$1('div', className + '-separator', section);
5085
+ this._overlaysList = create$1('div', className + '-overlays', section);
5003
5086
 
5004
- container.appendChild(form);
5087
+ container.appendChild(section);
5005
5088
  },
5006
5089
 
5007
5090
  _getLayer: function (id) {
@@ -5338,6 +5421,10 @@ Map.mergeOptions({
5338
5421
 
5339
5422
  Map.addInitHook(function () {
5340
5423
  if (this.options.zoomControl) {
5424
+ // @section Controls
5425
+ // @property zoomControl: Control.Zoom
5426
+ // The default zoom control (only available if the
5427
+ // [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map).
5341
5428
  this.zoomControl = new Zoom();
5342
5429
  this.addControl(this.zoomControl);
5343
5430
  }
@@ -5777,10 +5864,14 @@ var Draggable = Evented.extend({
5777
5864
  // Fired when a drag is about to start.
5778
5865
  this.fire('down');
5779
5866
 
5780
- var first = e.touches ? e.touches[0] : e;
5867
+ var first = e.touches ? e.touches[0] : e,
5868
+ sizedParent = getSizedParentNode(this._element);
5781
5869
 
5782
5870
  this._startPoint = new Point(first.clientX, first.clientY);
5783
5871
 
5872
+ // Cache the scale, so that we can continuously compensate for it during drag (_onMove).
5873
+ this._parentScale = getScale(sizedParent);
5874
+
5784
5875
  on(document, MOVE[e.type], this._onMove, this);
5785
5876
  on(document, END[e.type], this._onUp, this);
5786
5877
  },
@@ -5799,12 +5890,17 @@ var Draggable = Evented.extend({
5799
5890
  }
5800
5891
 
5801
5892
  var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
5802
- newPoint = new Point(first.clientX, first.clientY),
5803
- offset = newPoint.subtract(this._startPoint);
5893
+ offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint);
5804
5894
 
5805
5895
  if (!offset.x && !offset.y) { return; }
5806
5896
  if (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; }
5807
5897
 
5898
+ // We assume that the parent container's position, border and scale do not change for the duration of the drag.
5899
+ // Therefore there is no need to account for the position and border (they are eliminated by the subtraction)
5900
+ // and we can use the cached value for the scale.
5901
+ offset.x /= this._parentScale.x;
5902
+ offset.y /= this._parentScale.y;
5903
+
5808
5904
  preventDefault(e);
5809
5905
 
5810
5906
  if (!this._moved) {
@@ -6413,7 +6509,7 @@ var Layer = Evented.extend({
6413
6509
  pane: 'overlayPane',
6414
6510
 
6415
6511
  // @option attribution: String = null
6416
- // String to be shown in the attribution control, describes the layer data, e.g. Mapbox".
6512
+ // 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.
6417
6513
  attribution: null,
6418
6514
 
6419
6515
  bubblingMouseEvents: true
@@ -6974,7 +7070,7 @@ var Icon = Class.extend({
6974
7070
 
6975
7071
  options: {
6976
7072
  popupAnchor: [0, 0],
6977
- tooltipAnchor: [0, 0],
7073
+ tooltipAnchor: [0, 0]
6978
7074
  },
6979
7075
 
6980
7076
  initialize: function (options) {
@@ -7173,7 +7269,7 @@ var MarkerDrag = Handler.extend({
7173
7269
  map = marker._map,
7174
7270
  speed = this._marker.options.autoPanSpeed,
7175
7271
  padding = this._marker.options.autoPanPadding,
7176
- iconPos = L.DomUtil.getPosition(marker._icon),
7272
+ iconPos = getPosition(marker._icon),
7177
7273
  bounds = map.getPixelBounds(),
7178
7274
  origin = map.getPixelOrigin();
7179
7275
 
@@ -7197,7 +7293,7 @@ var MarkerDrag = Handler.extend({
7197
7293
  this._draggable._newPos._add(movement);
7198
7294
  this._draggable._startPos._add(movement);
7199
7295
 
7200
- L.DomUtil.setPosition(marker._icon, this._draggable._newPos);
7296
+ setPosition(marker._icon, this._draggable._newPos);
7201
7297
  this._onDrag(e);
7202
7298
 
7203
7299
  this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
@@ -7229,7 +7325,7 @@ var MarkerDrag = Handler.extend({
7229
7325
  _onDrag: function (e) {
7230
7326
  var marker = this._marker,
7231
7327
  shadow = marker._shadow,
7232
- iconPos = getPosition(marker._icon),
7328
+ iconPos = getPosition(marker._icon),
7233
7329
  latlng = marker._map.layerPointToLatLng(iconPos);
7234
7330
 
7235
7331
  // update shadow position
@@ -7290,22 +7386,6 @@ var Marker = Layer.extend({
7290
7386
  // Option inherited from "Interactive layer" abstract class
7291
7387
  interactive: true,
7292
7388
 
7293
- // @option draggable: Boolean = false
7294
- // Whether the marker is draggable with mouse/touch or not.
7295
- draggable: false,
7296
-
7297
- // @option autoPan: Boolean = false
7298
- // Set it to `true` if you want the map to do panning animation when marker hits the edges.
7299
- autoPan: false,
7300
-
7301
- // @option autoPanPadding: Point = Point(50, 50)
7302
- // Equivalent of setting both top left and bottom right autopan padding to the same value.
7303
- autoPanPadding: [50, 50],
7304
-
7305
- // @option autoPanSpeed: Number = 10
7306
- // Number of pixels the map should move by.
7307
- autoPanSpeed: 10,
7308
-
7309
7389
  // @option keyboard: Boolean = true
7310
7390
  // Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.
7311
7391
  keyboard: true,
@@ -7341,7 +7421,25 @@ var Marker = Layer.extend({
7341
7421
  // @option bubblingMouseEvents: Boolean = false
7342
7422
  // When `true`, a mouse event on this marker will trigger the same event on the map
7343
7423
  // (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).
7344
- bubblingMouseEvents: false
7424
+ bubblingMouseEvents: false,
7425
+
7426
+ // @section Draggable marker options
7427
+ // @option draggable: Boolean = false
7428
+ // Whether the marker is draggable with mouse/touch or not.
7429
+ draggable: false,
7430
+
7431
+ // @option autoPan: Boolean = false
7432
+ // Whether to pan the map when dragging this marker near its edge or not.
7433
+ autoPan: false,
7434
+
7435
+ // @option autoPanPadding: Point = Point(50, 50)
7436
+ // Distance (in pixels to the left/right and to the top/bottom) of the
7437
+ // map edge to start panning the map.
7438
+ autoPanPadding: [50, 50],
7439
+
7440
+ // @option autoPanSpeed: Number = 10
7441
+ // Number of pixels the map should pan by.
7442
+ autoPanSpeed: 10
7345
7443
  },
7346
7444
 
7347
7445
  /* @section
@@ -8050,7 +8148,7 @@ var Polyline = Path.extend({
8050
8148
  return !this._latlngs.length;
8051
8149
  },
8052
8150
 
8053
- // @method closestLayerPoint: Point
8151
+ // @method closestLayerPoint(p: Point): Point
8054
8152
  // Returns the point closest to `p` on the Polyline.
8055
8153
  closestLayerPoint: function (p) {
8056
8154
  var minDistance = Infinity,
@@ -8443,7 +8541,7 @@ var Polygon = Polyline.extend({
8443
8541
  var inside = false,
8444
8542
  part, p1, p2, i, j, k, len, len2;
8445
8543
 
8446
- if (!this._pxBounds.contains(p)) { return false; }
8544
+ if (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }
8447
8545
 
8448
8546
  // ray casting algorithm for detecting if point is in polygon
8449
8547
  for (i = 0, len = this._parts.length; i < len; i++) {
@@ -8870,7 +8968,7 @@ LayerGroup.include({
8870
8968
  // @namespace GeoJSON
8871
8969
  // @factory L.geoJSON(geojson?: Object, options?: GeoJSON options)
8872
8970
  // Creates a GeoJSON layer. Optionally accepts an object in
8873
- // [GeoJSON format](http://geojson.org/geojson-spec.html) to display on the map
8971
+ // [GeoJSON format](https://tools.ietf.org/html/rfc7946) to display on the map
8874
8972
  // (you can alternatively add it later with `addData` method) and an `options` object.
8875
8973
  function geoJSON(geojson, options) {
8876
8974
  return new GeoJSON(geojson, options);
@@ -8912,8 +9010,10 @@ var ImageOverlay = Layer.extend({
8912
9010
  // If `true`, the image overlay will emit [mouse events](#interactive-layer) when clicked or hovered.
8913
9011
  interactive: false,
8914
9012
 
8915
- // @option crossOrigin: Boolean = false
8916
- // If true, the image will have its crossOrigin attribute set to ''. This is needed if you want to access image pixel data.
9013
+ // @option crossOrigin: Boolean|String = false
9014
+ // Whether the crossOrigin attribute will be added to the image.
9015
+ // If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data.
9016
+ // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
8917
9017
  crossOrigin: false,
8918
9018
 
8919
9019
  // @option errorOverlayUrl: String = ''
@@ -8921,12 +9021,12 @@ var ImageOverlay = Layer.extend({
8921
9021
  errorOverlayUrl: '',
8922
9022
 
8923
9023
  // @option zIndex: Number = 1
8924
- // The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the tile layer.
9024
+ // The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer.
8925
9025
  zIndex: 1,
8926
9026
 
8927
9027
  // @option className: String = ''
8928
9028
  // A custom class name to assign to the image. Empty by default.
8929
- className: '',
9029
+ className: ''
8930
9030
  },
8931
9031
 
8932
9032
  initialize: function (url, bounds, options) { // (String, LatLngBounds, Object)
@@ -9032,7 +9132,7 @@ var ImageOverlay = Layer.extend({
9032
9132
  return events;
9033
9133
  },
9034
9134
 
9035
- // @method: setZIndex(value: Number) : this
9135
+ // @method setZIndex(value: Number): this
9036
9136
  // Changes the [zIndex](#imageoverlay-zindex) of the image overlay.
9037
9137
  setZIndex: function (value) {
9038
9138
  this.options.zIndex = value;
@@ -9069,8 +9169,8 @@ var ImageOverlay = Layer.extend({
9069
9169
  img.onload = bind(this.fire, this, 'load');
9070
9170
  img.onerror = bind(this._overlayOnError, this, 'error');
9071
9171
 
9072
- if (this.options.crossOrigin) {
9073
- img.crossOrigin = '';
9172
+ if (this.options.crossOrigin || this.options.crossOrigin === '') {
9173
+ img.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
9074
9174
  }
9075
9175
 
9076
9176
  if (this.options.zIndex) {
@@ -9118,7 +9218,7 @@ var ImageOverlay = Layer.extend({
9118
9218
 
9119
9219
  _overlayOnError: function () {
9120
9220
  // @event error: Event
9121
- // Fired when the ImageOverlay layer has loaded its image
9221
+ // Fired when the ImageOverlay layer fails to load its image
9122
9222
  this.fire('error');
9123
9223
 
9124
9224
  var errorUrl = this.options.errorOverlayUrl;
@@ -9151,7 +9251,7 @@ var imageOverlay = function (url, bounds, options) {
9151
9251
  * ```js
9152
9252
  * var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',
9153
9253
  * videoBounds = [[ 32, -130], [ 13, -100]];
9154
- * L.VideoOverlay(videoUrl, videoBounds ).addTo(map);
9254
+ * L.videoOverlay(videoUrl, videoBounds ).addTo(map);
9155
9255
  * ```
9156
9256
  */
9157
9257
 
@@ -9644,7 +9744,8 @@ var Popup = DivOverlay.extend({
9644
9744
  },
9645
9745
 
9646
9746
  _adjustPan: function () {
9647
- if (!this.options.autoPan || (this._map._panAnim && this._map._panAnim._inProgress)) { return; }
9747
+ if (!this.options.autoPan) { return; }
9748
+ if (this._map._panAnim) { this._map._panAnim.stop(); }
9648
9749
 
9649
9750
  var map = this._map,
9650
9751
  marginBottom = parseInt(getStyle(this._container, 'marginBottom'), 10) || 0,
@@ -11178,12 +11279,6 @@ var GridLayer = Layer.extend({
11178
11279
  var tile = this._tiles[key];
11179
11280
  if (!tile) { return; }
11180
11281
 
11181
- // Cancels any pending http requests associated with the tile
11182
- // unless we're on Android's stock browser,
11183
- // see https://github.com/Leaflet/Leaflet/issues/137
11184
- if (!androidStock) {
11185
- tile.el.setAttribute('src', emptyImageUrl);
11186
- }
11187
11282
  remove(tile.el);
11188
11283
 
11189
11284
  delete this._tiles[key];
@@ -11252,8 +11347,6 @@ var GridLayer = Layer.extend({
11252
11347
  },
11253
11348
 
11254
11349
  _tileReady: function (coords, err, tile) {
11255
- if (!this._map) { return; }
11256
-
11257
11350
  if (err) {
11258
11351
  // @event tileerror: TileErrorEvent
11259
11352
  // Fired when there is an error loading a tile.
@@ -11343,12 +11436,12 @@ function gridLayer(options) {
11343
11436
  * @class TileLayer
11344
11437
  * @inherits GridLayer
11345
11438
  * @aka L.TileLayer
11346
- * Used to load and display tile layers on the map. Extends `GridLayer`.
11439
+ * 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`.
11347
11440
  *
11348
11441
  * @example
11349
11442
  *
11350
11443
  * ```js
11351
- * L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
11444
+ * L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar', attribution: 'Map data &copy; <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);
11352
11445
  * ```
11353
11446
  *
11354
11447
  * @section URL template
@@ -11407,8 +11500,10 @@ var TileLayer = GridLayer.extend({
11407
11500
  // If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
11408
11501
  detectRetina: false,
11409
11502
 
11410
- // @option crossOrigin: Boolean = false
11411
- // If true, all tiles will have their crossOrigin attribute set to ''. This is needed if you want to access tile pixel data.
11503
+ // @option crossOrigin: Boolean|String = false
11504
+ // Whether the crossOrigin attribute will be added to the tiles.
11505
+ // If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data.
11506
+ // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.
11412
11507
  crossOrigin: false
11413
11508
  },
11414
11509
 
@@ -11446,7 +11541,13 @@ var TileLayer = GridLayer.extend({
11446
11541
 
11447
11542
  // @method setUrl(url: String, noRedraw?: Boolean): this
11448
11543
  // Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).
11544
+ // If the URL does not change, the layer will not be redrawn unless
11545
+ // the noRedraw parameter is set to false.
11449
11546
  setUrl: function (url, noRedraw) {
11547
+ if (this._url === url && noRedraw === undefined) {
11548
+ noRedraw = true;
11549
+ }
11550
+
11450
11551
  this._url = url;
11451
11552
 
11452
11553
  if (!noRedraw) {
@@ -11465,8 +11566,8 @@ var TileLayer = GridLayer.extend({
11465
11566
  on(tile, 'load', bind(this._tileOnLoad, this, done, tile));
11466
11567
  on(tile, 'error', bind(this._tileOnError, this, done, tile));
11467
11568
 
11468
- if (this.options.crossOrigin) {
11469
- tile.crossOrigin = '';
11569
+ if (this.options.crossOrigin || this.options.crossOrigin === '') {
11570
+ tile.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;
11470
11571
  }
11471
11572
 
11472
11573
  /*
@@ -11567,6 +11668,28 @@ var TileLayer = GridLayer.extend({
11567
11668
  }
11568
11669
  }
11569
11670
  }
11671
+ },
11672
+
11673
+ _removeTile: function (key) {
11674
+ var tile = this._tiles[key];
11675
+ if (!tile) { return; }
11676
+
11677
+ // Cancels any pending http requests associated with the tile
11678
+ // unless we're on Android's stock browser,
11679
+ // see https://github.com/Leaflet/Leaflet/issues/137
11680
+ if (!androidStock) {
11681
+ tile.el.setAttribute('src', emptyImageUrl);
11682
+ }
11683
+
11684
+ return GridLayer.prototype._removeTile.call(this, key);
11685
+ },
11686
+
11687
+ _tileReady: function (coords, err, tile) {
11688
+ if (!this._map || (tile && tile.getAttribute('src') === emptyImageUrl)) {
11689
+ return;
11690
+ }
11691
+
11692
+ return GridLayer.prototype._tileReady.call(this, coords, err, tile);
11570
11693
  }
11571
11694
  });
11572
11695
 
@@ -11683,7 +11806,7 @@ var TileLayerWMS = TileLayer.extend({
11683
11806
  bbox = (this._wmsVersion >= 1.3 && this._crs === EPSG4326 ?
11684
11807
  [min.y, min.x, max.y, max.x] :
11685
11808
  [min.x, min.y, max.x, max.y]).join(','),
11686
- url = L.TileLayer.prototype.getTileUrl.call(this, coords);
11809
+ url = TileLayer.prototype.getTileUrl.call(this, coords);
11687
11810
  return url +
11688
11811
  getParamString(this.wmsParams, url, this.options.uppercase) +
11689
11812
  (this.options.uppercase ? '&BBOX=' : '&bbox=') + bbox;
@@ -11909,6 +12032,7 @@ var Canvas = Renderer.extend({
11909
12032
  },
11910
12033
 
11911
12034
  _destroyContainer: function () {
12035
+ cancelAnimFrame(this._redrawRequest);
11912
12036
  delete this._ctx;
11913
12037
  remove(this._container);
11914
12038
  off(this._container);
@@ -11930,8 +12054,6 @@ var Canvas = Renderer.extend({
11930
12054
  _update: function () {
11931
12055
  if (this._map._animatingZoom && this._bounds) { return; }
11932
12056
 
11933
- this._drawnLayers = {};
11934
-
11935
12057
  Renderer.prototype._update.call(this);
11936
12058
 
11937
12059
  var b = this._bounds,
@@ -12003,7 +12125,7 @@ var Canvas = Renderer.extend({
12003
12125
 
12004
12126
  delete layer._order;
12005
12127
 
12006
- delete this._layers[L.stamp(layer)];
12128
+ delete this._layers[stamp(layer)];
12007
12129
 
12008
12130
  this._requestRedraw(layer);
12009
12131
  },
@@ -12025,14 +12147,20 @@ var Canvas = Renderer.extend({
12025
12147
  },
12026
12148
 
12027
12149
  _updateDashArray: function (layer) {
12028
- if (layer.options.dashArray) {
12029
- var parts = layer.options.dashArray.split(','),
12150
+ if (typeof layer.options.dashArray === 'string') {
12151
+ var parts = layer.options.dashArray.split(/[, ]+/),
12030
12152
  dashArray = [],
12153
+ dashValue,
12031
12154
  i;
12032
12155
  for (i = 0; i < parts.length; i++) {
12033
- dashArray.push(Number(parts[i]));
12156
+ dashValue = Number(parts[i]);
12157
+ // Ignore dash array containing invalid lengths
12158
+ if (isNaN(dashValue)) { return; }
12159
+ dashArray.push(dashValue);
12034
12160
  }
12035
12161
  layer.options._dashArray = dashArray;
12162
+ } else {
12163
+ layer.options._dashArray = layer.options.dashArray;
12036
12164
  }
12037
12165
  },
12038
12166
 
@@ -12110,8 +12238,6 @@ var Canvas = Renderer.extend({
12110
12238
 
12111
12239
  if (!len) { return; }
12112
12240
 
12113
- this._drawnLayers[layer._leaflet_id] = layer;
12114
-
12115
12241
  ctx.beginPath();
12116
12242
 
12117
12243
  for (i = 0; i < len; i++) {
@@ -12138,8 +12264,6 @@ var Canvas = Renderer.extend({
12138
12264
  r = Math.max(Math.round(layer._radius), 1),
12139
12265
  s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;
12140
12266
 
12141
- this._drawnLayers[layer._leaflet_id] = layer;
12142
-
12143
12267
  if (s !== 1) {
12144
12268
  ctx.save();
12145
12269
  ctx.scale(1, s);
@@ -12244,6 +12368,9 @@ var Canvas = Renderer.extend({
12244
12368
 
12245
12369
  _bringToFront: function (layer) {
12246
12370
  var order = layer._order;
12371
+
12372
+ if (!order) { return; }
12373
+
12247
12374
  var next = order.next;
12248
12375
  var prev = order.prev;
12249
12376
 
@@ -12272,6 +12399,9 @@ var Canvas = Renderer.extend({
12272
12399
 
12273
12400
  _bringToBack: function (layer) {
12274
12401
  var order = layer._order;
12402
+
12403
+ if (!order) { return; }
12404
+
12275
12405
  var next = order.next;
12276
12406
  var prev = order.prev;
12277
12407
 
@@ -12327,7 +12457,6 @@ var vmlCreate = (function () {
12327
12457
  /*
12328
12458
  * @class SVG
12329
12459
  *
12330
- * 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.
12331
12460
  *
12332
12461
  * VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility
12333
12462
  * with old versions of Internet Explorer.
@@ -12669,10 +12798,7 @@ Map.include({
12669
12798
  var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;
12670
12799
 
12671
12800
  if (!renderer) {
12672
- // @namespace Map; @option preferCanvas: Boolean = false
12673
- // Whether `Path`s should be rendered on a `Canvas` renderer.
12674
- // By default, all `Path`s are rendered in a `SVG` renderer.
12675
- renderer = this._renderer = (this.options.preferCanvas && canvas$1()) || svg$1();
12801
+ renderer = this._renderer = this._createRenderer();
12676
12802
  }
12677
12803
 
12678
12804
  if (!this.hasLayer(renderer)) {
@@ -12688,10 +12814,17 @@ Map.include({
12688
12814
 
12689
12815
  var renderer = this._paneRenderers[name];
12690
12816
  if (renderer === undefined) {
12691
- renderer = (SVG && svg$1({pane: name})) || (Canvas && canvas$1({pane: name}));
12817
+ renderer = this._createRenderer({pane: name});
12692
12818
  this._paneRenderers[name] = renderer;
12693
12819
  }
12694
12820
  return renderer;
12821
+ },
12822
+
12823
+ _createRenderer: function (options) {
12824
+ // @namespace Map; @option preferCanvas: Boolean = false
12825
+ // Whether `Path`s should be rendered on a `Canvas` renderer.
12826
+ // By default, all `Path`s are rendered in a `SVG` renderer.
12827
+ return (this.options.preferCanvas && canvas$1(options)) || svg$1(options);
12695
12828
  }
12696
12829
  });
12697
12830
 
@@ -13326,20 +13459,18 @@ var Keyboard = Handler.extend({
13326
13459
  offset;
13327
13460
 
13328
13461
  if (key in this._panKeys) {
13462
+ if (!map._panAnim || !map._panAnim._inProgress) {
13463
+ offset = this._panKeys[key];
13464
+ if (e.shiftKey) {
13465
+ offset = toPoint(offset).multiplyBy(3);
13466
+ }
13329
13467
 
13330
- if (map._panAnim && map._panAnim._inProgress) { return; }
13331
-
13332
- offset = this._panKeys[key];
13333
- if (e.shiftKey) {
13334
- offset = toPoint(offset).multiplyBy(3);
13335
- }
13336
-
13337
- map.panBy(offset);
13468
+ map.panBy(offset);
13338
13469
 
13339
- if (map.options.maxBounds) {
13340
- map.panInsideBounds(map.options.maxBounds);
13470
+ if (map.options.maxBounds) {
13471
+ map.panInsideBounds(map.options.maxBounds);
13472
+ }
13341
13473
  }
13342
-
13343
13474
  } else if (key in this._zoomKeys) {
13344
13475
  map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);
13345
13476
 
@@ -13707,21 +13838,9 @@ Map.ScrollWheelZoom = ScrollWheelZoom;
13707
13838
  Map.Tap = Tap;
13708
13839
  Map.TouchZoom = TouchZoom;
13709
13840
 
13710
- // misc
13711
-
13712
- var oldL = window.L;
13713
- function noConflict() {
13714
- window.L = oldL;
13715
- return this;
13716
- }
13717
-
13718
- // Always export us to window global (see #2364)
13719
- window.L = exports;
13720
-
13721
13841
  Object.freeze = freeze;
13722
13842
 
13723
13843
  exports.version = version;
13724
- exports.noConflict = noConflict;
13725
13844
  exports.Control = Control;
13726
13845
  exports.control = control;
13727
13846
  exports.Browser = Browser;
@@ -13798,5 +13917,14 @@ exports.rectangle = rectangle;
13798
13917
  exports.Map = Map;
13799
13918
  exports.map = createMap;
13800
13919
 
13920
+ var oldL = window.L;
13921
+ exports.noConflict = function() {
13922
+ window.L = oldL;
13923
+ return this;
13924
+ }
13925
+
13926
+ // Always export us to window global (see #2364)
13927
+ window.L = exports;
13928
+
13801
13929
  })));
13802
13930
  //# sourceMappingURL=<%= asset_path 'leaflet-src.js.map' %>