leaflet-rails 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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' %>