leaflet-rails 1.2.0 → 1.3.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
- SHA1:
3
- metadata.gz: ee7c67fd6f07cb0b7b467e04d22667781a33cc36
4
- data.tar.gz: 483f1222824f6bb72f31095f5bdaa8e02b282668
2
+ SHA256:
3
+ metadata.gz: 78b6afc48a50ce5cf8e2f439b037a0c2607fa2a2b431acedb796e1f7adead522
4
+ data.tar.gz: d5a68b45e906359fa77a4b8a356766fc1d65cb292820bcf3851ca54af2c3133a
5
5
  SHA512:
6
- metadata.gz: fa9a8cfab3f44a62950d1001fb24b7ec663b24759b8f389dcea4451ab5076072b6c7ce0ba1282573a2c65d8631ee71c6e76ca7830b820c9c0f479b713b1bbdc4
7
- data.tar.gz: b703bf4f556ee14297fa2329ee6848933740eeb55c968eafff2b446127b269e0827f5538ef809818a0c251ea98c08ba3e223aca0ba54595d0dbcfcf0a663a917
6
+ metadata.gz: e664e5bf49d2fc99f22493f5cba226d420dfd89541550aa525ce2cc45877a687ea3788c2285c48eac71f8aba681d1a87574137029b62be2ef51bb568804f61c2
7
+ data.tar.gz: ec58a9ac0d61c758f14c47d89502f2d4b392bb9974df66ebd0c36efd7ce5b665e9a3ba11cf66f25791edb6f905db54da2f0773dcd91ab8921aa1d8dde97de911
@@ -1,5 +1,5 @@
1
1
  module Leaflet
2
2
  module Rails
3
- VERSION = "1.2.0"
3
+ VERSION = "1.3.0"
4
4
  end
5
5
  end
File without changes
File without changes
File without changes
File without changes
@@ -1,14 +1,15 @@
1
1
  /* @preserve
2
- * Leaflet 1.2.0, a JS library for interactive maps. http://leafletjs.com
2
+ * Leaflet 1.3.0+Detached: 1a38558f7b22f5ffacda5f6a1b8e60d54c361873.1a38558, a JS library for interactive maps. http://leafletjs.com
3
3
  * (c) 2010-2017 Vladimir Agafonkin, (c) 2010-2011 CloudMade
4
4
  */
5
+
5
6
  (function (global, factory) {
6
7
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
7
8
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
8
9
  (factory((global.L = {})));
9
10
  }(this, (function (exports) { 'use strict';
10
11
 
11
- var version = "1.2.0";
12
+ var version = "1.3.0+HEAD.1a38558";
12
13
 
13
14
  /*
14
15
  * @namespace Util
@@ -65,12 +66,12 @@ function bind(fn, obj) {
65
66
  var lastId = 0;
66
67
 
67
68
  // @function stamp(obj: Object): Number
68
- // Returns the unique ID of an object, assiging it one if it doesn't have it.
69
+ // Returns the unique ID of an object, assigning it one if it doesn't have it.
69
70
  function stamp(obj) {
70
71
  /*eslint-disable */
71
72
  obj._leaflet_id = obj._leaflet_id || ++lastId;
72
73
  return obj._leaflet_id;
73
- /*eslint-enable */
74
+ /* eslint-enable */
74
75
  }
75
76
 
76
77
  // @function throttle(fn: Function, time: Number, context: Object): Function
@@ -124,9 +125,9 @@ function wrapNum(x, range, includeMax) {
124
125
  function falseFn() { return false; }
125
126
 
126
127
  // @function formatNum(num: Number, digits?: Number): Number
127
- // Returns the number `num` rounded to `digits` decimals, or to 5 decimals by default.
128
+ // Returns the number `num` rounded to `digits` decimals, or to 6 decimals by default.
128
129
  function formatNum(num, digits) {
129
- var pow = Math.pow(10, digits || 5);
130
+ var pow = Math.pow(10, (digits === undefined ? 6 : digits));
130
131
  return Math.round(num * pow) / pow;
131
132
  }
132
133
 
@@ -167,7 +168,7 @@ function getParamString(obj, existingUrl, uppercase) {
167
168
  return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');
168
169
  }
169
170
 
170
- var templateRe = /\{ *([\w_\-]+) *\}/g;
171
+ var templateRe = /\{ *([\w_-]+) *\}/g;
171
172
 
172
173
  // @function template(str: String, data: Object): String
173
174
  // Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'`
@@ -390,7 +391,7 @@ Class.addInitHook = function (fn) { // (Function) || (String, args...)
390
391
  };
391
392
 
392
393
  function checkDeprecatedMixinEvents(includes) {
393
- if (!L || !L.Mixin) { return; }
394
+ if (typeof L === 'undefined' || !L || !L.Mixin) { return; }
394
395
 
395
396
  includes = isArray(includes) ? includes : [includes];
396
397
 
@@ -576,7 +577,11 @@ var Events = {
576
577
  fire: function (type, data, propagate) {
577
578
  if (!this.listens(type, propagate)) { return this; }
578
579
 
579
- var event = extend({}, data, {type: type, target: this});
580
+ var event = extend({}, data, {
581
+ type: type,
582
+ target: this,
583
+ sourceTarget: data && data.sourceTarget || this
584
+ });
580
585
 
581
586
  if (this._events) {
582
587
  var listeners = this._events[type];
@@ -657,7 +662,10 @@ var Events = {
657
662
 
658
663
  _propagateEvent: function (e) {
659
664
  for (var id in this._eventParents) {
660
- this._eventParents[id].fire(e.type, extend({layer: e.target}, e), true);
665
+ this._eventParents[id].fire(e.type, extend({
666
+ layer: e.target,
667
+ propagatedFrom: e.target
668
+ }, e), true);
661
669
  }
662
670
  }
663
671
  };
@@ -707,6 +715,10 @@ var Evented = Class.extend(Events);
707
715
  * map.panBy([200, 300]);
708
716
  * map.panBy(L.point(200, 300));
709
717
  * ```
718
+ *
719
+ * Note that `Point` does not inherit from Leafet's `Class` object,
720
+ * which means new classes can't inherit from it, and new methods
721
+ * can't be added to it with the `include` function.
710
722
  */
711
723
 
712
724
  function Point(x, y, round) {
@@ -716,6 +728,10 @@ function Point(x, y, round) {
716
728
  this.y = (round ? Math.round(y) : y);
717
729
  }
718
730
 
731
+ var trunc = Math.trunc || function (v) {
732
+ return v > 0 ? Math.floor(v) : Math.ceil(v);
733
+ };
734
+
719
735
  Point.prototype = {
720
736
 
721
737
  // @method clone(): Point
@@ -826,6 +842,18 @@ Point.prototype = {
826
842
  return this;
827
843
  },
828
844
 
845
+ // @method trunc(): Point
846
+ // Returns a copy of the current point with truncated coordinates (rounded towards zero).
847
+ trunc: function () {
848
+ return this.clone()._trunc();
849
+ },
850
+
851
+ _trunc: function () {
852
+ this.x = trunc(this.x);
853
+ this.y = trunc(this.y);
854
+ return this;
855
+ },
856
+
829
857
  // @method distanceTo(otherPoint: Point): Number
830
858
  // Returns the cartesian distance between the current and the given points.
831
859
  distanceTo: function (point) {
@@ -909,6 +937,10 @@ function toPoint(x, y, round) {
909
937
  * ```js
910
938
  * otherBounds.intersects([[10, 10], [40, 60]]);
911
939
  * ```
940
+ *
941
+ * Note that `Bounds` does not inherit from Leafet's `Class` object,
942
+ * which means new classes can't inherit from it, and new methods
943
+ * can't be added to it with the `include` function.
912
944
  */
913
945
 
914
946
  function Bounds(a, b) {
@@ -1082,6 +1114,10 @@ function toBounds(a, b) {
1082
1114
  * ```
1083
1115
  *
1084
1116
  * Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners _outside_ the [-180, 180] degrees longitude range.
1117
+ *
1118
+ * Note that `LatLngBounds` does not inherit from Leafet's `Class` object,
1119
+ * which means new classes can't inherit from it, and new methods
1120
+ * can't be added to it with the `include` function.
1085
1121
  */
1086
1122
 
1087
1123
  function LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[])
@@ -1135,7 +1171,9 @@ LatLngBounds.prototype = {
1135
1171
  },
1136
1172
 
1137
1173
  // @method pad(bufferRatio: Number): LatLngBounds
1138
- // Returns bigger bounds created by extending the current bounds by a given percentage in each direction.
1174
+ // Returns bounds created by extending or retracting the current bounds by a given ratio in each direction.
1175
+ // For example, a ratio of 0.5 extends the bounds by 50% in each direction.
1176
+ // Negative values will retract the bounds.
1139
1177
  pad: function (bufferRatio) {
1140
1178
  var sw = this._southWest,
1141
1179
  ne = this._northEast,
@@ -1270,7 +1308,7 @@ LatLngBounds.prototype = {
1270
1308
  },
1271
1309
 
1272
1310
  // @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean
1273
- // Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overriden by setting `maxMargin` to a small number.
1311
+ // Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting `maxMargin` to a small number.
1274
1312
  equals: function (bounds, maxMargin) {
1275
1313
  if (!bounds) { return false; }
1276
1314
 
@@ -1321,6 +1359,10 @@ function toLatLngBounds(a, b) {
1321
1359
  * map.panTo({lat: 50, lng: 30});
1322
1360
  * map.panTo(L.latLng(50, 30));
1323
1361
  * ```
1362
+ *
1363
+ * Note that `LatLng` does not inherit from Leafet's `Class` object,
1364
+ * which means new classes can't inherit from it, and new methods
1365
+ * can't be added to it with the `include` function.
1324
1366
  */
1325
1367
 
1326
1368
  function LatLng(lat, lng, alt) {
@@ -1345,7 +1387,7 @@ function LatLng(lat, lng, alt) {
1345
1387
 
1346
1388
  LatLng.prototype = {
1347
1389
  // @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean
1348
- // Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overriden by setting `maxMargin` to a small number.
1390
+ // Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number.
1349
1391
  equals: function (obj, maxMargin) {
1350
1392
  if (!obj) { return false; }
1351
1393
 
@@ -1367,7 +1409,7 @@ LatLng.prototype = {
1367
1409
  },
1368
1410
 
1369
1411
  // @method distanceTo(otherLatLng: LatLng): Number
1370
- // Returns the distance (in meters) to the given `LatLng` calculated using the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula).
1412
+ // Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines).
1371
1413
  distanceTo: function (other) {
1372
1414
  return Earth.distance(this, toLatLng(other));
1373
1415
  },
@@ -1443,6 +1485,10 @@ function toLatLng(a, b, c) {
1443
1485
  * Leaflet defines the most usual CRSs by default. If you want to use a
1444
1486
  * CRS not defined by default, take a look at the
1445
1487
  * [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin.
1488
+ *
1489
+ * Note that the CRS instances do not inherit from Leafet's `Class` object,
1490
+ * and can't be instantiated. Also, new classes can't inherit from them,
1491
+ * and methods can't be added to them with the `include` function.
1446
1492
  */
1447
1493
 
1448
1494
  var CRS = {
@@ -1585,10 +1631,11 @@ var Earth = extend({}, CRS, {
1585
1631
  var rad = Math.PI / 180,
1586
1632
  lat1 = latlng1.lat * rad,
1587
1633
  lat2 = latlng2.lat * rad,
1588
- a = Math.sin(lat1) * Math.sin(lat2) +
1589
- Math.cos(lat1) * Math.cos(lat2) * Math.cos((latlng2.lng - latlng1.lng) * rad);
1590
-
1591
- return this.R * Math.acos(Math.min(a, 1));
1634
+ sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2),
1635
+ sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2),
1636
+ a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon,
1637
+ c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
1638
+ return this.R * c;
1592
1639
  }
1593
1640
  });
1594
1641
 
@@ -1613,8 +1660,8 @@ var SphericalMercator = {
1613
1660
  sin = Math.sin(lat * d);
1614
1661
 
1615
1662
  return new Point(
1616
- this.R * latlng.lng * d,
1617
- this.R * Math.log((1 + sin) / (1 - sin)) / 2);
1663
+ this.R * latlng.lng * d,
1664
+ this.R * Math.log((1 + sin) / (1 - sin)) / 2);
1618
1665
  },
1619
1666
 
1620
1667
  unproject: function (point) {
@@ -1701,7 +1748,7 @@ Transformation.prototype = {
1701
1748
 
1702
1749
  // @alternative
1703
1750
  // @factory L.transformation(coefficients: Array): Transformation
1704
- // Expects an coeficients array of the form
1751
+ // Expects an coefficients array of the form
1705
1752
  // `[a: Number, b: Number, c: Number, d: Number]`.
1706
1753
 
1707
1754
  function toTransformation(a, b, c, d) {
@@ -1802,6 +1849,11 @@ var android = userAgentContains('android');
1802
1849
  // @property android23: Boolean; `true` for browsers running on Android 2 or Android 3.
1803
1850
  var android23 = userAgentContains('android 2') || userAgentContains('android 3');
1804
1851
 
1852
+ /* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */
1853
+ var webkitVer = parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit
1854
+ // @property androidStock: Boolean; `true` for the Android stock browser (i.e. not Chrome)
1855
+ var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window);
1856
+
1805
1857
  // @property opera: Boolean; `true` for the Opera browser
1806
1858
  var opera = !!window.opera;
1807
1859
 
@@ -1914,6 +1966,7 @@ var Browser = (Object.freeze || Object)({
1914
1966
  webkit: webkit,
1915
1967
  android: android,
1916
1968
  android23: android23,
1969
+ androidStock: androidStock,
1917
1970
  opera: opera,
1918
1971
  chrome: chrome,
1919
1972
  gecko: gecko,
@@ -1949,6 +2002,7 @@ var POINTER_MOVE = msPointer ? 'MSPointerMove' : 'pointermove';
1949
2002
  var POINTER_UP = msPointer ? 'MSPointerUp' : 'pointerup';
1950
2003
  var POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel';
1951
2004
  var TAG_WHITE_LIST = ['INPUT', 'SELECT', 'OPTION'];
2005
+
1952
2006
  var _pointers = {};
1953
2007
  var _pointerDocListener = false;
1954
2008
 
@@ -1991,7 +2045,7 @@ function removePointerListener(obj, type, id) {
1991
2045
 
1992
2046
  function _addPointerStart(obj, handler, id) {
1993
2047
  var onDown = bind(function (e) {
1994
- if (e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
2048
+ if (e.pointerType !== 'mouse' && e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
1995
2049
  // In IE11, some touch events needs to fire for form controls, or
1996
2050
  // the controls will stop working. We keep a whitelist of tag names that
1997
2051
  // need these events. For other target tags, we prevent default on the event.
@@ -2072,8 +2126,8 @@ function _addPointerEnd(obj, handler, id) {
2072
2126
  * Extends the event handling code with double tap support for mobile browsers.
2073
2127
  */
2074
2128
 
2075
- var _touchstart = msPointer ? 'MSPointerDown' : pointer ? 'pointerdown' : 'touchstart';
2076
- var _touchend = msPointer ? 'MSPointerUp' : pointer ? 'pointerup' : 'touchend';
2129
+ var _touchstart = msPointer ? 'MSPointerDown' : pointer ? 'pointerdown' : 'touchstart';
2130
+ var _touchend = msPointer ? 'MSPointerUp' : pointer ? 'pointerup' : 'touchend';
2077
2131
  var _pre = '_leaflet_';
2078
2132
 
2079
2133
  // inspired by Zepto touch code by Thomas Fuchs
@@ -2188,18 +2242,13 @@ function on(obj, types, fn, context) {
2188
2242
  var eventsKey = '_leaflet_events';
2189
2243
 
2190
2244
  // @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this
2191
- // Removes a previously added listener function. If no function is specified,
2192
- // it will remove all the listeners of that particular DOM event from the element.
2245
+ // Removes a previously added listener function.
2193
2246
  // Note that if you passed a custom context to on, you must pass the same
2194
2247
  // context to `off` in order to remove the listener.
2195
2248
 
2196
2249
  // @alternative
2197
2250
  // @function off(el: HTMLElement, eventMap: Object, context?: Object): this
2198
2251
  // Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`
2199
-
2200
- // @alternative
2201
- // @function off(el: HTMLElement): this
2202
- // Removes all known event listeners
2203
2252
  function off(obj, types, fn, context) {
2204
2253
 
2205
2254
  if (typeof types === 'object') {
@@ -2284,7 +2333,8 @@ function removeOne(obj, type, fn, context) {
2284
2333
  if (pointer && type.indexOf('touch') === 0) {
2285
2334
  removePointerListener(obj, type, id);
2286
2335
 
2287
- } else if (touch && (type === 'dblclick') && removeDoubleTapListener) {
2336
+ } else if (touch && (type === 'dblclick') && removeDoubleTapListener &&
2337
+ !(pointer && chrome)) {
2288
2338
  removeDoubleTapListener(obj, id);
2289
2339
 
2290
2340
  } else if ('removeEventListener' in obj) {
@@ -2356,7 +2406,7 @@ function preventDefault(e) {
2356
2406
  return this;
2357
2407
  }
2358
2408
 
2359
- // @function stop(ev): this
2409
+ // @function stop(ev: DOMEvent): this
2360
2410
  // Does `stopPropagation` and `preventDefault` at the same time.
2361
2411
  function stop(e) {
2362
2412
  preventDefault(e);
@@ -2374,9 +2424,11 @@ function getMousePosition(e, container) {
2374
2424
 
2375
2425
  var rect = container.getBoundingClientRect();
2376
2426
 
2427
+ var scaleX = rect.width / container.offsetWidth || 1;
2428
+ var scaleY = rect.height / container.offsetHeight || 1;
2377
2429
  return new Point(
2378
- e.clientX - rect.left - container.clientLeft,
2379
- e.clientY - rect.top - container.clientTop);
2430
+ e.clientX / scaleX - rect.left - container.clientLeft,
2431
+ e.clientY / scaleY - rect.top - container.clientTop);
2380
2432
  }
2381
2433
 
2382
2434
  // Chrome on Win scrolls double the pixels as in other platforms (see #4538),
@@ -2694,7 +2746,7 @@ function setPosition(el, point) {
2694
2746
 
2695
2747
  /*eslint-disable */
2696
2748
  el._leaflet_pos = point;
2697
- /*eslint-enable */
2749
+ /* eslint-enable */
2698
2750
 
2699
2751
  if (any3d) {
2700
2752
  setTransform(el, point);
@@ -3333,7 +3385,7 @@ var Map = Evented.extend({
3333
3385
  }
3334
3386
  }
3335
3387
 
3336
- this._moveStart(true);
3388
+ this._moveStart(true, options.noMoveStart);
3337
3389
 
3338
3390
  frame.call(this);
3339
3391
  return this;
@@ -3371,10 +3423,15 @@ var Map = Evented.extend({
3371
3423
  // @method setMinZoom(zoom: Number): this
3372
3424
  // Sets the lower limit for the available zoom levels (see the [minZoom](#map-minzoom) option).
3373
3425
  setMinZoom: function (zoom) {
3426
+ var oldZoom = this.options.minZoom;
3374
3427
  this.options.minZoom = zoom;
3375
3428
 
3376
- if (this._loaded && this.getZoom() < this.options.minZoom) {
3377
- return this.setZoom(zoom);
3429
+ if (this._loaded && oldZoom !== zoom) {
3430
+ this.fire('zoomlevelschange');
3431
+
3432
+ if (this.getZoom() < this.options.minZoom) {
3433
+ return this.setZoom(zoom);
3434
+ }
3378
3435
  }
3379
3436
 
3380
3437
  return this;
@@ -3383,10 +3440,15 @@ var Map = Evented.extend({
3383
3440
  // @method setMaxZoom(zoom: Number): this
3384
3441
  // Sets the upper limit for the available zoom levels (see the [maxZoom](#map-maxzoom) option).
3385
3442
  setMaxZoom: function (zoom) {
3443
+ var oldZoom = this.options.maxZoom;
3386
3444
  this.options.maxZoom = zoom;
3387
3445
 
3388
- if (this._loaded && (this.getZoom() > this.options.maxZoom)) {
3389
- return this.setZoom(zoom);
3446
+ if (this._loaded && oldZoom !== zoom) {
3447
+ this.fire('zoomlevelschange');
3448
+
3449
+ if (this.getZoom() > this.options.maxZoom) {
3450
+ return this.setZoom(zoom);
3451
+ }
3390
3452
  }
3391
3453
 
3392
3454
  return this;
@@ -3407,7 +3469,7 @@ var Map = Evented.extend({
3407
3469
  return this;
3408
3470
  },
3409
3471
 
3410
- // @method invalidateSize(options: Zoom/Pan options): this
3472
+ // @method invalidateSize(options: Zoom/pan options): this
3411
3473
  // Checks if the map container size changed and updates the map if so —
3412
3474
  // call it after you've changed the map size dynamically, also animating
3413
3475
  // pan by default. If `options.pan` is `false`, panning will not occur.
@@ -3580,8 +3642,7 @@ var Map = Evented.extend({
3580
3642
  this.fire('locationfound', data);
3581
3643
  },
3582
3644
 
3583
- // TODO handler.addTo
3584
- // TODO Appropiate docs section?
3645
+ // TODO Appropriate docs section?
3585
3646
  // @section Other Methods
3586
3647
  // @method addHandler(name: String, HandlerClass: Function): this
3587
3648
  // Adds a new `Handler` to the map, given its name and constructor function.
@@ -3616,10 +3677,16 @@ var Map = Evented.extend({
3616
3677
  } catch (e) {
3617
3678
  /*eslint-disable */
3618
3679
  this._container._leaflet_id = undefined;
3619
- /*eslint-enable */
3680
+ /* eslint-enable */
3620
3681
  this._containerId = undefined;
3621
3682
  }
3622
3683
 
3684
+ if (this._locationWatchId !== undefined) {
3685
+ this.stopLocate();
3686
+ }
3687
+
3688
+ this._stop();
3689
+
3623
3690
  remove(this._mapPane);
3624
3691
 
3625
3692
  if (this._clearControlPos) {
@@ -3998,7 +4065,7 @@ var Map = Evented.extend({
3998
4065
  // Pane for `GridLayer`s and `TileLayer`s
3999
4066
  this.createPane('tilePane');
4000
4067
  // @pane overlayPane: HTMLElement = 400
4001
- // Pane for vector overlays (`Path`s), like `Polyline`s and `Polygon`s
4068
+ // Pane for vectors (`Path`s, like `Polyline`s and `Polygon`s), `ImageOverlay`s and `VideoOverlay`s
4002
4069
  this.createPane('shadowPane');
4003
4070
  // @pane shadowPane: HTMLElement = 500
4004
4071
  // Pane for overlay shadows (e.g. `Marker` shadows)
@@ -4007,7 +4074,7 @@ var Map = Evented.extend({
4007
4074
  // Pane for `Icon`s of `Marker`s
4008
4075
  this.createPane('markerPane');
4009
4076
  // @pane tooltipPane: HTMLElement = 650
4010
- // Pane for tooltip.
4077
+ // Pane for `Tooltip`s.
4011
4078
  this.createPane('tooltipPane');
4012
4079
  // @pane popupPane: HTMLElement = 700
4013
4080
  // Pane for `Popup`s.
@@ -4034,7 +4101,7 @@ var Map = Evented.extend({
4034
4101
 
4035
4102
  var zoomChanged = this._zoom !== zoom;
4036
4103
  this
4037
- ._moveStart(zoomChanged)
4104
+ ._moveStart(zoomChanged, false)
4038
4105
  ._move(center, zoom)
4039
4106
  ._moveEnd(zoomChanged);
4040
4107
 
@@ -4051,7 +4118,7 @@ var Map = Evented.extend({
4051
4118
  }
4052
4119
  },
4053
4120
 
4054
- _moveStart: function (zoomChanged) {
4121
+ _moveStart: function (zoomChanged, noMoveStart) {
4055
4122
  // @event zoomstart: Event
4056
4123
  // Fired when the map zoom is about to change (e.g. before zoom animation).
4057
4124
  // @event movestart: Event
@@ -4059,7 +4126,10 @@ var Map = Evented.extend({
4059
4126
  if (zoomChanged) {
4060
4127
  this.fire('zoomstart');
4061
4128
  }
4062
- return this.fire('movestart');
4129
+ if (!noMoveStart) {
4130
+ this.fire('movestart');
4131
+ }
4132
+ return this;
4063
4133
  },
4064
4134
 
4065
4135
  _move: function (center, zoom, data) {
@@ -4261,9 +4331,9 @@ var Map = Evented.extend({
4261
4331
  };
4262
4332
 
4263
4333
  if (e.type !== 'keypress') {
4264
- var isMarker = (target.options && 'icon' in target.options);
4334
+ var isMarker = target.getLatLng && (!target._radius || target._radius <= 10);
4265
4335
  data.containerPoint = isMarker ?
4266
- this.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e);
4336
+ this.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e);
4267
4337
  data.layerPoint = this.containerPointToLayerPoint(data.containerPoint);
4268
4338
  data.latlng = isMarker ? target.getLatLng() : this.layerPointToLatLng(data.layerPoint);
4269
4339
  }
@@ -4422,7 +4492,7 @@ var Map = Evented.extend({
4422
4492
 
4423
4493
  _tryAnimatedPan: function (center, options) {
4424
4494
  // difference between the new and current centers in pixels
4425
- var offset = this._getCenterOffset(center)._floor();
4495
+ var offset = this._getCenterOffset(center)._trunc();
4426
4496
 
4427
4497
  // don't animate too far unless animate: true specified in options
4428
4498
  if ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; }
@@ -4492,7 +4562,7 @@ var Map = Evented.extend({
4492
4562
 
4493
4563
  requestAnimFrame(function () {
4494
4564
  this
4495
- ._moveStart(true)
4565
+ ._moveStart(true, false)
4496
4566
  ._animateZoom(center, zoom, true);
4497
4567
  }, this);
4498
4568
 
@@ -4500,6 +4570,8 @@ var Map = Evented.extend({
4500
4570
  },
4501
4571
 
4502
4572
  _animateZoom: function (center, zoom, startAnim, noUpdate) {
4573
+ if (!this._mapPane) { return; }
4574
+
4503
4575
  if (startAnim) {
4504
4576
  this._animatingZoom = true;
4505
4577
 
@@ -4525,7 +4597,9 @@ var Map = Evented.extend({
4525
4597
  _onZoomTransitionEnd: function () {
4526
4598
  if (!this._animatingZoom) { return; }
4527
4599
 
4528
- removeClass(this._mapPane, 'leaflet-zoom-anim');
4600
+ if (this._mapPane) {
4601
+ removeClass(this._mapPane, 'leaflet-zoom-anim');
4602
+ }
4529
4603
 
4530
4604
  this._animatingZoom = false;
4531
4605
 
@@ -5343,8 +5417,8 @@ var Scale = Control.extend({
5343
5417
  y = map.getSize().y / 2;
5344
5418
 
5345
5419
  var maxMeters = map.distance(
5346
- map.containerPointToLatLng([0, y]),
5347
- map.containerPointToLatLng([this.options.maxWidth, y]));
5420
+ map.containerPointToLatLng([0, y]),
5421
+ map.containerPointToLatLng([this.options.maxWidth, y]));
5348
5422
 
5349
5423
  this._updateScales(maxMeters);
5350
5424
  },
@@ -5586,6 +5660,14 @@ var Handler = Class.extend({
5586
5660
  // Called when the handler is disabled, should remove the event hooks added previously.
5587
5661
  });
5588
5662
 
5663
+ // @section There is static function which can be called without instantiating L.Handler:
5664
+ // @function addTo(map: Map, name: String): this
5665
+ // Adds a new Handler to the given map with the given name.
5666
+ Handler.addTo = function (map, name) {
5667
+ map.addHandler(name, this);
5668
+ return this;
5669
+ };
5670
+
5589
5671
  var Mixin = {Events: Events};
5590
5672
 
5591
5673
  /*
@@ -5812,7 +5894,7 @@ var Draggable = Evented.extend({
5812
5894
  /*
5813
5895
  * @namespace LineUtil
5814
5896
  *
5815
- * Various utility functions for polyine points processing, used by Leaflet internally to make polylines lightning-fast.
5897
+ * Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast.
5816
5898
  */
5817
5899
 
5818
5900
  // Simplify polyline with vertex reduction and Douglas-Peucker simplification.
@@ -6067,10 +6149,10 @@ var LineUtil = (Object.freeze || Object)({
6067
6149
  */
6068
6150
 
6069
6151
  /* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[]
6070
- * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgeman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)).
6152
+ * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)).
6071
6153
  * Used by Leaflet to only show polygon points that are on the screen or near, increasing
6072
6154
  * performance. Note that polygon points needs different algorithm for clipping
6073
- * than polyline, so there's a seperate method for it.
6155
+ * than polyline, so there's a separate method for it.
6074
6156
  */
6075
6157
  function clipPolygon(points, bounds, round) {
6076
6158
  var clippedPoints,
@@ -6208,6 +6290,10 @@ var Mercator = {
6208
6290
  * The inverse of `project`. Projects a 2D point into a geographical location.
6209
6291
  * Only accepts actual `L.Point` instances, not arrays.
6210
6292
 
6293
+ * Note that the projection instances do not inherit from Leafet's `Class` object,
6294
+ * and can't be instantiated. Also, new classes can't inherit from them,
6295
+ * and methods can't be added to them with the `include` function.
6296
+
6211
6297
  */
6212
6298
 
6213
6299
 
@@ -6589,7 +6675,9 @@ Map.include({
6589
6675
 
6590
6676
  var LayerGroup = Layer.extend({
6591
6677
 
6592
- initialize: function (layers) {
6678
+ initialize: function (layers, options) {
6679
+ setOptions(this, options);
6680
+
6593
6681
  this._layers = {};
6594
6682
 
6595
6683
  var i, len;
@@ -6644,10 +6732,7 @@ var LayerGroup = Layer.extend({
6644
6732
  // @method clearLayers(): this
6645
6733
  // Removes all the layers from the group.
6646
6734
  clearLayers: function () {
6647
- for (var i in this._layers) {
6648
- this.removeLayer(this._layers[i]);
6649
- }
6650
- return this;
6735
+ return this.eachLayer(this.removeLayer, this);
6651
6736
  },
6652
6737
 
6653
6738
  // @method invoke(methodName: String, …): this
@@ -6670,15 +6755,11 @@ var LayerGroup = Layer.extend({
6670
6755
  },
6671
6756
 
6672
6757
  onAdd: function (map) {
6673
- for (var i in this._layers) {
6674
- map.addLayer(this._layers[i]);
6675
- }
6758
+ this.eachLayer(map.addLayer, map);
6676
6759
  },
6677
6760
 
6678
6761
  onRemove: function (map) {
6679
- for (var i in this._layers) {
6680
- map.removeLayer(this._layers[i]);
6681
- }
6762
+ this.eachLayer(map.removeLayer, map);
6682
6763
  },
6683
6764
 
6684
6765
  // @method eachLayer(fn: Function, context?: Object): this
@@ -6705,10 +6786,7 @@ var LayerGroup = Layer.extend({
6705
6786
  // Returns an array of all the layers added to the group.
6706
6787
  getLayers: function () {
6707
6788
  var layers = [];
6708
-
6709
- for (var i in this._layers) {
6710
- layers.push(this._layers[i]);
6711
- }
6789
+ this.eachLayer(layers.push, layers);
6712
6790
  return layers;
6713
6791
  },
6714
6792
 
@@ -6726,10 +6804,10 @@ var LayerGroup = Layer.extend({
6726
6804
  });
6727
6805
 
6728
6806
 
6729
- // @factory L.layerGroup(layers?: Layer[])
6730
- // Create a layer group, optionally given an initial set of layers.
6731
- var layerGroup = function (layers) {
6732
- return new LayerGroup(layers);
6807
+ // @factory L.layerGroup(layers?: Layer[], options?: Object)
6808
+ // Create a layer group, optionally given an initial set of layers and an `options` object.
6809
+ var layerGroup = function (layers, options) {
6810
+ return new LayerGroup(layers, options);
6733
6811
  };
6734
6812
 
6735
6813
  /*
@@ -6800,7 +6878,7 @@ var FeatureGroup = LayerGroup.extend({
6800
6878
  },
6801
6879
 
6802
6880
  // @method bringToBack(): this
6803
- // Brings the layer group to the top of all other layers
6881
+ // Brings the layer group to the back of all other layers
6804
6882
  bringToBack: function () {
6805
6883
  return this.invoke('bringToBack');
6806
6884
  },
@@ -6872,9 +6950,12 @@ var Icon = Class.extend({
6872
6950
  * will be aligned so that this point is at the marker's geographical location. Centered
6873
6951
  * by default if size is specified, also can be set in CSS with negative margins.
6874
6952
  *
6875
- * @option popupAnchor: Point = null
6953
+ * @option popupAnchor: Point = [0, 0]
6876
6954
  * The coordinates of the point from which popups will "open", relative to the icon anchor.
6877
6955
  *
6956
+ * @option tooltipAnchor: Point = [0, 0]
6957
+ * The coordinates of the point from which tooltips will "open", relative to the icon anchor.
6958
+ *
6878
6959
  * @option shadowUrl: String = null
6879
6960
  * The URL to the icon shadow image. If not specified, no shadow image will be created.
6880
6961
  *
@@ -6891,6 +6972,11 @@ var Icon = Class.extend({
6891
6972
  * A custom class name to assign to both icon and shadow images. Empty by default.
6892
6973
  */
6893
6974
 
6975
+ options: {
6976
+ popupAnchor: [0, 0],
6977
+ tooltipAnchor: [0, 0],
6978
+ },
6979
+
6894
6980
  initialize: function (options) {
6895
6981
  setOptions(this, options);
6896
6982
  },
@@ -7002,9 +7088,9 @@ var IconDefault = Icon.extend({
7002
7088
  }
7003
7089
 
7004
7090
  // @option imagePath: String
7005
- // `Icon.Default` will try to auto-detect the absolute location of the
7091
+ // `Icon.Default` will try to auto-detect the location of the
7006
7092
  // blue icon images. If you are placing these images in a non-standard
7007
- // way, set this option to point to the right absolute path.
7093
+ // way, set this option to point to the right path.
7008
7094
  return (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name);
7009
7095
  },
7010
7096
 
@@ -7018,7 +7104,7 @@ var IconDefault = Icon.extend({
7018
7104
  if (path === null || path.indexOf('url') !== 0) {
7019
7105
  path = '';
7020
7106
  } else {
7021
- path = path.replace(/^url\([\"\']?/, '').replace(/marker-icon\.png[\"\']?\)$/, '');
7107
+ path = path.replace(/^url\(["']?/, '').replace(/marker-icon\.png["']?\)$/, '');
7022
7108
  }
7023
7109
 
7024
7110
  return path;
@@ -7057,6 +7143,7 @@ var MarkerDrag = Handler.extend({
7057
7143
 
7058
7144
  this._draggable.on({
7059
7145
  dragstart: this._onDragStart,
7146
+ predrag: this._onPreDrag,
7060
7147
  drag: this._onDrag,
7061
7148
  dragend: this._onDragEnd
7062
7149
  }, this).enable();
@@ -7067,6 +7154,7 @@ var MarkerDrag = Handler.extend({
7067
7154
  removeHooks: function () {
7068
7155
  this._draggable.off({
7069
7156
  dragstart: this._onDragStart,
7157
+ predrag: this._onPreDrag,
7070
7158
  drag: this._onDrag,
7071
7159
  dragend: this._onDragEnd
7072
7160
  }, this).disable();
@@ -7080,6 +7168,42 @@ var MarkerDrag = Handler.extend({
7080
7168
  return this._draggable && this._draggable._moved;
7081
7169
  },
7082
7170
 
7171
+ _adjustPan: function (e) {
7172
+ var marker = this._marker,
7173
+ map = marker._map,
7174
+ speed = this._marker.options.autoPanSpeed,
7175
+ padding = this._marker.options.autoPanPadding,
7176
+ iconPos = L.DomUtil.getPosition(marker._icon),
7177
+ bounds = map.getPixelBounds(),
7178
+ origin = map.getPixelOrigin();
7179
+
7180
+ var panBounds = toBounds(
7181
+ bounds.min._subtract(origin).add(padding),
7182
+ bounds.max._subtract(origin).subtract(padding)
7183
+ );
7184
+
7185
+ if (!panBounds.contains(iconPos)) {
7186
+ // Compute incremental movement
7187
+ var movement = toPoint(
7188
+ (Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) -
7189
+ (Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x),
7190
+
7191
+ (Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) -
7192
+ (Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y)
7193
+ ).multiplyBy(speed);
7194
+
7195
+ map.panBy(movement, {animate: false});
7196
+
7197
+ this._draggable._newPos._add(movement);
7198
+ this._draggable._startPos._add(movement);
7199
+
7200
+ L.DomUtil.setPosition(marker._icon, this._draggable._newPos);
7201
+ this._onDrag(e);
7202
+
7203
+ this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
7204
+ }
7205
+ },
7206
+
7083
7207
  _onDragStart: function () {
7084
7208
  // @section Dragging events
7085
7209
  // @event dragstart: Event
@@ -7095,6 +7219,13 @@ var MarkerDrag = Handler.extend({
7095
7219
  .fire('dragstart');
7096
7220
  },
7097
7221
 
7222
+ _onPreDrag: function (e) {
7223
+ if (this._marker.options.autoPan) {
7224
+ cancelAnimFrame(this._panRequest);
7225
+ this._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));
7226
+ }
7227
+ },
7228
+
7098
7229
  _onDrag: function (e) {
7099
7230
  var marker = this._marker,
7100
7231
  shadow = marker._shadow,
@@ -7121,6 +7252,8 @@ var MarkerDrag = Handler.extend({
7121
7252
  // @event dragend: DragEndEvent
7122
7253
  // Fired when the user stops dragging the marker.
7123
7254
 
7255
+ cancelAnimFrame(this._panRequest);
7256
+
7124
7257
  // @event moveend: Event
7125
7258
  // Fired when the marker stops moving (because of dragging).
7126
7259
  delete this._oldLatLng;
@@ -7161,6 +7294,18 @@ var Marker = Layer.extend({
7161
7294
  // Whether the marker is draggable with mouse/touch or not.
7162
7295
  draggable: false,
7163
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
+
7164
7309
  // @option keyboard: Boolean = true
7165
7310
  // Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.
7166
7311
  keyboard: true,
@@ -7291,7 +7436,7 @@ var Marker = Layer.extend({
7291
7436
 
7292
7437
  update: function () {
7293
7438
 
7294
- if (this._icon) {
7439
+ if (this._icon && this._map) {
7295
7440
  var pos = this._map.latLngToLayerPoint(this._latlng).round();
7296
7441
  this._setPos(pos);
7297
7442
  }
@@ -7316,8 +7461,9 @@ var Marker = Layer.extend({
7316
7461
  if (options.title) {
7317
7462
  icon.title = options.title;
7318
7463
  }
7319
- if (options.alt) {
7320
- icon.alt = options.alt;
7464
+
7465
+ if (icon.tagName === 'IMG') {
7466
+ icon.alt = options.alt || '';
7321
7467
  }
7322
7468
  }
7323
7469
 
@@ -7461,11 +7607,11 @@ var Marker = Layer.extend({
7461
7607
  },
7462
7608
 
7463
7609
  _getPopupAnchor: function () {
7464
- return this.options.icon.options.popupAnchor || [0, 0];
7610
+ return this.options.icon.options.popupAnchor;
7465
7611
  },
7466
7612
 
7467
7613
  _getTooltipAnchor: function () {
7468
- return this.options.icon.options.tooltipAnchor || [0, 0];
7614
+ return this.options.icon.options.tooltipAnchor;
7469
7615
  }
7470
7616
  });
7471
7617
 
@@ -7616,7 +7762,7 @@ var Path = Layer.extend({
7616
7762
 
7617
7763
  _clickTolerance: function () {
7618
7764
  // used when doing hit detection for Canvas layers
7619
- return (this.options.stroke ? this.options.weight / 2 : 0) + (touch ? 10 : 0);
7765
+ return (this.options.stroke ? this.options.weight / 2 : 0) + this._renderer.options.tolerance;
7620
7766
  }
7621
7767
  });
7622
7768
 
@@ -7801,8 +7947,8 @@ var Circle = CircleMarker.extend({
7801
7947
  }
7802
7948
 
7803
7949
  this._point = p.subtract(map.getPixelOrigin());
7804
- this._radius = isNaN(lngR) ? 0 : Math.max(Math.round(p.x - map.project([lat2, lng - lngR]).x), 1);
7805
- this._radiusY = Math.max(Math.round(p.y - top.y), 1);
7950
+ this._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;
7951
+ this._radiusY = p.y - top.y;
7806
7952
 
7807
7953
  } else {
7808
7954
  var latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));
@@ -7904,6 +8050,8 @@ var Polyline = Path.extend({
7904
8050
  return !this._latlngs.length;
7905
8051
  },
7906
8052
 
8053
+ // @method closestLayerPoint: Point
8054
+ // Returns the point closest to `p` on the Polyline.
7907
8055
  closestLayerPoint: function (p) {
7908
8056
  var minDistance = Infinity,
7909
8057
  minPoint = null,
@@ -8544,8 +8692,8 @@ function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {
8544
8692
 
8545
8693
  for (var i = 0, len = coords.length, latlng; i < len; i++) {
8546
8694
  latlng = levelsDeep ?
8547
- coordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) :
8548
- (_coordsToLatLng || coordsToLatLng)(coords[i]);
8695
+ coordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) :
8696
+ (_coordsToLatLng || coordsToLatLng)(coords[i]);
8549
8697
 
8550
8698
  latlngs.push(latlng);
8551
8699
  }
@@ -8558,8 +8706,8 @@ function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {
8558
8706
  function latLngToCoords(latlng, precision) {
8559
8707
  precision = typeof precision === 'number' ? precision : 6;
8560
8708
  return latlng.alt !== undefined ?
8561
- [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision), formatNum(latlng.alt, precision)] :
8562
- [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)];
8709
+ [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision), formatNum(latlng.alt, precision)] :
8710
+ [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)];
8563
8711
  }
8564
8712
 
8565
8713
  // @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean): Array
@@ -8583,8 +8731,8 @@ function latLngsToCoords(latlngs, levelsDeep, closed, precision) {
8583
8731
 
8584
8732
  function getFeature(layer, newGeometry) {
8585
8733
  return layer.feature ?
8586
- extend({}, layer.feature, {geometry: newGeometry}) :
8587
- asFeature(newGeometry);
8734
+ extend({}, layer.feature, {geometry: newGeometry}) :
8735
+ asFeature(newGeometry);
8588
8736
  }
8589
8737
 
8590
8738
  // @function asFeature(geojson: Object): Object
@@ -8906,9 +9054,12 @@ var ImageOverlay = Layer.extend({
8906
9054
  },
8907
9055
 
8908
9056
  _initImage: function () {
8909
- var img = this._image = create$1('img',
8910
- 'leaflet-image-layer ' + (this._zoomAnimated ? 'leaflet-zoom-animated' : '') +
8911
- (this.options.className || ''));
9057
+ var wasElementSupplied = this._url.tagName === 'IMG';
9058
+ var img = this._image = wasElementSupplied ? this._url : create$1('img');
9059
+
9060
+ addClass(img, 'leaflet-image-layer');
9061
+ if (this._zoomAnimated) { addClass(img, 'leaflet-zoom-animated'); }
9062
+ if (this.options.className) { addClass(img, this.options.className); }
8912
9063
 
8913
9064
  img.onselectstart = falseFn;
8914
9065
  img.onmousemove = falseFn;
@@ -8926,6 +9077,11 @@ var ImageOverlay = Layer.extend({
8926
9077
  this._updateZIndex();
8927
9078
  }
8928
9079
 
9080
+ if (wasElementSupplied) {
9081
+ this._url = img.src;
9082
+ return;
9083
+ }
9084
+
8929
9085
  img.src = this._url;
8930
9086
  img.alt = this.options.alt;
8931
9087
  },
@@ -9017,8 +9173,8 @@ var VideoOverlay = ImageOverlay.extend({
9017
9173
  var wasElementSupplied = this._url.tagName === 'VIDEO';
9018
9174
  var vid = this._image = wasElementSupplied ? this._url : create$1('video');
9019
9175
 
9020
- vid.class = vid.class || '';
9021
- vid.class += 'leaflet-image-layer ' + (this._zoomAnimated ? 'leaflet-zoom-animated' : '');
9176
+ addClass(vid, 'leaflet-image-layer');
9177
+ if (this._zoomAnimated) { addClass(vid, 'leaflet-zoom-animated'); }
9022
9178
 
9023
9179
  vid.onselectstart = falseFn;
9024
9180
  vid.onmousemove = falseFn;
@@ -9027,7 +9183,16 @@ var VideoOverlay = ImageOverlay.extend({
9027
9183
  // Fired when the video has finished loading the first frame
9028
9184
  vid.onloadeddata = bind(this.fire, this, 'load');
9029
9185
 
9030
- if (wasElementSupplied) { return; }
9186
+ if (wasElementSupplied) {
9187
+ var sourceElements = vid.getElementsByTagName('source');
9188
+ var sources = [];
9189
+ for (var j = 0; j < sourceElements.length; j++) {
9190
+ sources.push(sourceElements[j].src);
9191
+ }
9192
+
9193
+ this._url = (sourceElements.length > 0) ? sources : [vid.src];
9194
+ return;
9195
+ }
9031
9196
 
9032
9197
  if (!isArray(this._url)) { this._url = [this._url]; }
9033
9198
 
@@ -9331,6 +9496,11 @@ var Popup = DivOverlay.extend({
9331
9496
  // the popup closing when another popup is opened.
9332
9497
  autoClose: true,
9333
9498
 
9499
+ // @option closeOnEscapeKey: Boolean = true
9500
+ // Set it to `false` if you want to override the default behavior of
9501
+ // the ESC key for closing of the popup.
9502
+ closeOnEscapeKey: true,
9503
+
9334
9504
  // @option closeOnClick: Boolean = *
9335
9505
  // Set it if you want to override the default behavior of the popup closing when user clicks
9336
9506
  // on the map. Defaults to the map's [`closePopupOnClick`](#map-closepopuponclick) option.
@@ -9654,7 +9824,7 @@ Layer.include({
9654
9824
  },
9655
9825
 
9656
9826
  // @method openPopup(latlng?: LatLng): this
9657
- // Opens the bound popup at the specificed `latlng` or at the default popup anchor if no `latlng` is passed.
9827
+ // Opens the bound popup at the specified `latlng` or at the default popup anchor if no `latlng` is passed.
9658
9828
  openPopup: function (layer, latlng) {
9659
9829
  if (!(layer instanceof Layer)) {
9660
9830
  latlng = layer;
@@ -9782,7 +9952,7 @@ Layer.include({
9782
9952
  * marker.bindTooltip("my tooltip text").openTooltip();
9783
9953
  * ```
9784
9954
  * Note about tooltip offset. Leaflet takes two options in consideration
9785
- * for computing tooltip offseting:
9955
+ * for computing tooltip offsetting:
9786
9956
  * - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip.
9787
9957
  * Add a positive x offset to move the tooltip to the right, and a positive y offset to
9788
9958
  * move it to the bottom. Negatives will move to the left and top.
@@ -9808,7 +9978,7 @@ var Tooltip = DivOverlay.extend({
9808
9978
  // @option direction: String = 'auto'
9809
9979
  // Direction where to open the tooltip. Possible values are: `right`, `left`,
9810
9980
  // `top`, `bottom`, `center`, `auto`.
9811
- // `auto` will dynamicaly switch between `right` and `left` according to the tooltip
9981
+ // `auto` will dynamically switch between `right` and `left` according to the tooltip
9812
9982
  // position on the map.
9813
9983
  direction: 'auto',
9814
9984
 
@@ -10072,7 +10242,7 @@ Layer.include({
10072
10242
  },
10073
10243
 
10074
10244
  // @method openTooltip(latlng?: LatLng): this
10075
- // Opens the bound tooltip at the specificed `latlng` or at the default tooltip anchor if no `latlng` is passed.
10245
+ // Opens the bound tooltip at the specified `latlng` or at the default tooltip anchor if no `latlng` is passed.
10076
10246
  openTooltip: function (layer, latlng) {
10077
10247
  if (!(layer instanceof Layer)) {
10078
10248
  latlng = layer;
@@ -10412,7 +10582,7 @@ var GridLayer = Layer.extend({
10412
10582
  remove(this._container);
10413
10583
  map._removeZoomLimit(this);
10414
10584
  this._container = null;
10415
- this._tileZoom = null;
10585
+ this._tileZoom = undefined;
10416
10586
  },
10417
10587
 
10418
10588
  // @method bringToFront: this
@@ -10501,7 +10671,7 @@ var GridLayer = Layer.extend({
10501
10671
  // @section Extension methods
10502
10672
  // Layers extending `GridLayer` shall reimplement the following method.
10503
10673
  // @method createTile(coords: Object, done?: Function): HTMLElement
10504
- // Called only internally, must be overriden by classes extending `GridLayer`.
10674
+ // Called only internally, must be overridden by classes extending `GridLayer`.
10505
10675
  // Returns the `HTMLElement` corresponding to the given `coords`. If the `done` callback
10506
10676
  // is specified, it must be called when the tile has finished loading and drawing.
10507
10677
  createTile: function () {
@@ -10706,7 +10876,7 @@ var GridLayer = Layer.extend({
10706
10876
  }
10707
10877
  this._removeAllTiles();
10708
10878
 
10709
- this._tileZoom = null;
10879
+ this._tileZoom = undefined;
10710
10880
  },
10711
10881
 
10712
10882
  _retainParent: function (x, y, z, minZoom) {
@@ -10916,7 +11086,10 @@ var GridLayer = Layer.extend({
10916
11086
 
10917
11087
  if (!this._isValidTile(coords)) { continue; }
10918
11088
 
10919
- if (!this._tiles[this._tileCoordsToKey(coords)]) {
11089
+ var tile = this._tiles[this._tileCoordsToKey(coords)];
11090
+ if (tile) {
11091
+ tile.current = true;
11092
+ } else {
10920
11093
  queue.push(coords);
10921
11094
  }
10922
11095
  }
@@ -10968,26 +11141,26 @@ var GridLayer = Layer.extend({
10968
11141
  return this._tileCoordsToBounds(this._keyToTileCoords(key));
10969
11142
  },
10970
11143
 
10971
- // converts tile coordinates to its geographical bounds
10972
- _tileCoordsToBounds: function (coords) {
10973
-
11144
+ _tileCoordsToNwSe: function (coords) {
10974
11145
  var map = this._map,
10975
11146
  tileSize = this.getTileSize(),
10976
-
10977
11147
  nwPoint = coords.scaleBy(tileSize),
10978
11148
  sePoint = nwPoint.add(tileSize),
10979
-
10980
11149
  nw = map.unproject(nwPoint, coords.z),
10981
- se = map.unproject(sePoint, coords.z),
10982
- bounds = new LatLngBounds(nw, se);
11150
+ se = map.unproject(sePoint, coords.z);
11151
+ return [nw, se];
11152
+ },
11153
+
11154
+ // converts tile coordinates to its geographical bounds
11155
+ _tileCoordsToBounds: function (coords) {
11156
+ var bp = this._tileCoordsToNwSe(coords),
11157
+ bounds = new LatLngBounds(bp[0], bp[1]);
10983
11158
 
10984
11159
  if (!this.options.noWrap) {
10985
- map.wrapLatLngBounds(bounds);
11160
+ bounds = this._map.wrapLatLngBounds(bounds);
10986
11161
  }
10987
-
10988
11162
  return bounds;
10989
11163
  },
10990
-
10991
11164
  // converts tile coordinates to key for the tile cache
10992
11165
  _tileCoordsToKey: function (coords) {
10993
11166
  return coords.x + ':' + coords.y + ':' + coords.z;
@@ -11005,6 +11178,12 @@ var GridLayer = Layer.extend({
11005
11178
  var tile = this._tiles[key];
11006
11179
  if (!tile) { return; }
11007
11180
 
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
+ }
11008
11187
  remove(tile.el);
11009
11188
 
11010
11189
  delete this._tiles[key];
@@ -11278,7 +11457,7 @@ var TileLayer = GridLayer.extend({
11278
11457
 
11279
11458
  // @method createTile(coords: Object, done?: Function): HTMLElement
11280
11459
  // Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile)
11281
- // to return an `<img>` HTML element with the appropiate image URL given `coords`. The `done`
11460
+ // to return an `<img>` HTML element with the appropriate image URL given `coords`. The `done`
11282
11461
  // callback is called when the tile has been loaded.
11283
11462
  createTile: function (coords, done) {
11284
11463
  var tile = document.createElement('img');
@@ -11319,7 +11498,7 @@ var TileLayer = GridLayer.extend({
11319
11498
  s: this._getSubdomain(coords),
11320
11499
  x: coords.x,
11321
11500
  y: coords.y,
11322
- z: this._getZoomForUrl()
11501
+ z: coords.z ? coords.z : this._getZoomForUrl()
11323
11502
  };
11324
11503
  if (this._map && !this._map.options.crs.infinite) {
11325
11504
  var invertedY = this._globalTileRange.max.y - coords.y;
@@ -11343,7 +11522,7 @@ var TileLayer = GridLayer.extend({
11343
11522
 
11344
11523
  _tileOnError: function (done, tile, e) {
11345
11524
  var errorUrl = this.options.errorTileUrl;
11346
- if (errorUrl && tile.src !== errorUrl) {
11525
+ if (errorUrl && tile.getAttribute('src') !== errorUrl) {
11347
11526
  tile.src = errorUrl;
11348
11527
  }
11349
11528
  done(e, tile);
@@ -11384,6 +11563,7 @@ var TileLayer = GridLayer.extend({
11384
11563
  if (!tile.complete) {
11385
11564
  tile.src = emptyImageUrl;
11386
11565
  remove(tile);
11566
+ delete this._tiles[i];
11387
11567
  }
11388
11568
  }
11389
11569
  }
@@ -11474,7 +11654,10 @@ var TileLayerWMS = TileLayer.extend({
11474
11654
 
11475
11655
  options = setOptions(this, options);
11476
11656
 
11477
- wmsParams.width = wmsParams.height = options.tileSize * (options.detectRetina && retina ? 2 : 1);
11657
+ var realRetina = options.detectRetina && retina ? 2 : 1;
11658
+ var tileSize = this.getTileSize();
11659
+ wmsParams.width = tileSize.x * realRetina;
11660
+ wmsParams.height = tileSize.y * realRetina;
11478
11661
 
11479
11662
  this.wmsParams = wmsParams;
11480
11663
  },
@@ -11492,16 +11675,15 @@ var TileLayerWMS = TileLayer.extend({
11492
11675
 
11493
11676
  getTileUrl: function (coords) {
11494
11677
 
11495
- var tileBounds = this._tileCoordsToBounds(coords),
11496
- nw = this._crs.project(tileBounds.getNorthWest()),
11497
- se = this._crs.project(tileBounds.getSouthEast()),
11498
-
11678
+ var tileBounds = this._tileCoordsToNwSe(coords),
11679
+ crs = this._crs,
11680
+ bounds = toBounds(crs.project(tileBounds[0]), crs.project(tileBounds[1])),
11681
+ min = bounds.min,
11682
+ max = bounds.max,
11499
11683
  bbox = (this._wmsVersion >= 1.3 && this._crs === EPSG4326 ?
11500
- [se.y, nw.x, nw.y, se.x] :
11501
- [nw.x, se.y, se.x, nw.y]).join(','),
11502
-
11503
- url = TileLayer.prototype.getTileUrl.call(this, coords);
11504
-
11684
+ [min.y, min.x, max.y, max.x] :
11685
+ [min.x, min.y, max.x, max.y]).join(','),
11686
+ url = L.TileLayer.prototype.getTileUrl.call(this, coords);
11505
11687
  return url +
11506
11688
  getParamString(this.wmsParams, url, this.options.uppercase) +
11507
11689
  (this.options.uppercase ? '&BBOX=' : '&bbox=') + bbox;
@@ -11559,7 +11741,11 @@ var Renderer = Layer.extend({
11559
11741
  // @option padding: Number = 0.1
11560
11742
  // How much to extend the clip area around the map view (relative to its size)
11561
11743
  // e.g. 0.1 would be 10% of map view in each direction
11562
- padding: 0.1
11744
+ padding: 0.1,
11745
+
11746
+ // @option tolerance: Number = 0
11747
+ // How much to extend click tolerance round a path/object on the map
11748
+ tolerance : 0
11563
11749
  },
11564
11750
 
11565
11751
  initialize: function (options) {
@@ -11949,8 +12135,8 @@ var Canvas = Renderer.extend({
11949
12135
 
11950
12136
  var p = layer._point,
11951
12137
  ctx = this._ctx,
11952
- r = layer._radius,
11953
- s = (layer._radiusY || r) / r;
12138
+ r = Math.max(Math.round(layer._radius), 1),
12139
+ s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;
11954
12140
 
11955
12141
  this._drawnLayers[layer._leaflet_id] = layer;
11956
12142
 
@@ -12071,7 +12257,7 @@ var Canvas = Renderer.extend({
12071
12257
  prev.next = next;
12072
12258
  } else if (next) {
12073
12259
  // Update first entry unless this is the
12074
- // signle entry
12260
+ // single entry
12075
12261
  this._drawFirst = next;
12076
12262
  }
12077
12263
 
@@ -12099,7 +12285,7 @@ var Canvas = Renderer.extend({
12099
12285
  next.prev = prev;
12100
12286
  } else if (prev) {
12101
12287
  // Update last entry unless this is the
12102
- // signle entry
12288
+ // single entry
12103
12289
  this._drawLast = prev;
12104
12290
  }
12105
12291
 
@@ -12243,7 +12429,7 @@ var vmlMixin = {
12243
12429
  r2 = Math.round(layer._radiusY || r);
12244
12430
 
12245
12431
  this._setPath(layer, layer._empty() ? 'M0 0' :
12246
- 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r2 + ' 0,' + (65535 * 360));
12432
+ 'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r2 + ' 0,' + (65535 * 360));
12247
12433
  },
12248
12434
 
12249
12435
  _setPath: function (layer, path) {
@@ -12320,6 +12506,7 @@ var SVG = Renderer.extend({
12320
12506
  off(this._container);
12321
12507
  delete this._container;
12322
12508
  delete this._rootGroup;
12509
+ delete this._svgSize;
12323
12510
  },
12324
12511
 
12325
12512
  _onZoomStart: function () {
@@ -12432,15 +12619,15 @@ var SVG = Renderer.extend({
12432
12619
 
12433
12620
  _updateCircle: function (layer) {
12434
12621
  var p = layer._point,
12435
- r = layer._radius,
12436
- r2 = layer._radiusY || r,
12622
+ r = Math.max(Math.round(layer._radius), 1),
12623
+ r2 = Math.max(Math.round(layer._radiusY), 1) || r,
12437
12624
  arc = 'a' + r + ',' + r2 + ' 0 1,0 ';
12438
12625
 
12439
12626
  // drawing a circle with two half-arcs
12440
12627
  var d = layer._empty() ? 'M0 0' :
12441
- 'M' + (p.x - r) + ',' + p.y +
12442
- arc + (r * 2) + ',0 ' +
12443
- arc + (-r * 2) + ',0 ';
12628
+ 'M' + (p.x - r) + ',' + p.y +
12629
+ arc + (r * 2) + ',0 ' +
12630
+ arc + (-r * 2) + ',0 ';
12444
12631
 
12445
12632
  this._setPath(layer, d);
12446
12633
  },
@@ -12463,6 +12650,7 @@ if (vml) {
12463
12650
  SVG.include(vmlMixin);
12464
12651
  }
12465
12652
 
12653
+ // @namespace SVG
12466
12654
  // @factory L.svg(options?: Renderer options)
12467
12655
  // Creates a SVG renderer with the given options.
12468
12656
  function svg$1(options) {
@@ -12513,7 +12701,7 @@ Map.include({
12513
12701
 
12514
12702
  /*
12515
12703
  * @class Rectangle
12516
- * @aka L.Retangle
12704
+ * @aka L.Rectangle
12517
12705
  * @inherits Polygon
12518
12706
  *
12519
12707
  * A class for drawing rectangle overlays on a map. Extends `Polygon`.
@@ -12891,10 +13079,7 @@ var Drag = Handler.extend({
12891
13079
  this._positions.push(pos);
12892
13080
  this._times.push(time);
12893
13081
 
12894
- if (time - this._times[0] > 50) {
12895
- this._positions.shift();
12896
- this._times.shift();
12897
- }
13082
+ this._prunePositions(time);
12898
13083
  }
12899
13084
 
12900
13085
  this._map
@@ -12902,6 +13087,13 @@ var Drag = Handler.extend({
12902
13087
  .fire('drag', e);
12903
13088
  },
12904
13089
 
13090
+ _prunePositions: function (time) {
13091
+ while (this._positions.length > 1 && time - this._times[0] > 50) {
13092
+ this._positions.shift();
13093
+ this._times.shift();
13094
+ }
13095
+ },
13096
+
12905
13097
  _onZoomEnd: function () {
12906
13098
  var pxCenter = this._map.getSize().divideBy(2),
12907
13099
  pxWorldCenter = this._map.latLngToLayerPoint([0, 0]);
@@ -12954,6 +13146,7 @@ var Drag = Handler.extend({
12954
13146
  map.fire('moveend');
12955
13147
 
12956
13148
  } else {
13149
+ this._prunePositions(+new Date());
12957
13150
 
12958
13151
  var direction = this._lastPos.subtract(this._positions[0]),
12959
13152
  duration = (this._lastTime - this._times[0]) / 1000,
@@ -13150,7 +13343,7 @@ var Keyboard = Handler.extend({
13150
13343
  } else if (key in this._zoomKeys) {
13151
13344
  map.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);
13152
13345
 
13153
- } else if (key === 27 && map._popup) {
13346
+ } else if (key === 27 && map._popup && map._popup.options.closeOnEscapeKey) {
13154
13347
  map.closePopup();
13155
13348
 
13156
13349
  } else {
@@ -13468,7 +13661,7 @@ var TouchZoom = Handler.extend({
13468
13661
  }
13469
13662
 
13470
13663
  if (!this._moved) {
13471
- map._moveStart(true);
13664
+ map._moveStart(true, false);
13472
13665
  this._moved = true;
13473
13666
  }
13474
13667