leaflet-rails 1.0.2 → 1.0.3

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
  SHA1:
3
- metadata.gz: e7af20726cf087075dc8c98f2fcdb828d11f7d56
4
- data.tar.gz: d18e1d715af0b4a073582736ac5443a0f0705e48
3
+ metadata.gz: bc0632e7cd8566f7fe86c3ac3f08ec67085cf609
4
+ data.tar.gz: 91b0d158c06340badf388a11745d4c0f00924672
5
5
  SHA512:
6
- metadata.gz: 95f5d7b0fd3523b677efffa888ee3b307488410e1966c92787c449e0f301d96e39f3da008bba6d1d9db270f65311e9c897d9ff4cb244e174662380cdca753863
7
- data.tar.gz: c97b6c2c3b0752f549a72fab30b5de7d515b0f4207028d738f3503175d463b82552ef6d6884698601a1ef40f4911348c18a79fa14858352592c5d70e3665081b
6
+ metadata.gz: bf8ec06aa08fb6086491c0bd9405e2063a42bfa3bc47e2e355e3efdf0984f1620bc3c855ef169de09e79bc9834e97bcc4dcf62dc7bdd423d22d70e9a0ff164c6
7
+ data.tar.gz: b2be300ad70bbd21d4bb8cb1e81f46254075b0f611ceee1b0fb9cf5b5ce3da6686707165056d9276b2a6aa82402e6ab04fb4a9bfa27f302833b0318b74f811f6
data/.travis.yml CHANGED
@@ -1,14 +1,20 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  cache: bundler
4
- rvm:
5
- - ruby-head
6
- - jruby-head
7
- - 2.0.0
8
- - 2.1.8
9
- - 2.2.4
10
- - 2.3.0
11
4
  matrix:
5
+ include:
6
+ - rvm: 2.0.0
7
+ gemfile: gemfiles/Gemfile.rails4
8
+ - rvm: 2.1.8
9
+ gemfile: gemfiles/Gemfile.rails4
10
+ - rvm: 2.2.4
11
+ gemfile: Gemfile
12
+ - rvm: 2.3.0
13
+ gemfile: Gemfile
14
+ - rvm: ruby-head
15
+ gemfile: Gemfile
16
+ - rvm: jruby-head
17
+ gemfile: Gemfile
12
18
  allow_failures:
13
19
  - rvm: ruby-head
14
20
  - rvm: jruby-head
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ #ruby=1.9.3-p374
4
+ #ruby-gemset=leaflet-rails
5
+
6
+ # Specify your gem's dependencies in leaflet-rails.gemspec
7
+ gemspec :path => '../'
8
+
9
+ gem "actionpack", '~> 4.2.0'
10
+ gem "activesupport", '~> 4.2.0'
11
+ gem "railties", '~> 4.2.0'
@@ -19,9 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
21
 
22
+ s.add_dependency "rails", '>= 4.2.0'
22
23
  s.add_development_dependency "rspec", '<= 3.4.0'
23
24
  s.add_development_dependency "simplecov-rcov"
24
- s.add_development_dependency "actionpack", '>= 4.2.0'
25
- s.add_development_dependency "activesupport", '>= 4.2.0'
26
- s.add_development_dependency "railties", '>= 4.2.0'
27
25
  end
data/lib/leaflet-rails.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "leaflet-rails/version"
2
2
  require "leaflet-rails/view_helpers"
3
+ require "rails"
3
4
 
4
5
  module Leaflet
5
6
  mattr_accessor :tile_layer
@@ -10,7 +11,9 @@ module Leaflet
10
11
  module Rails
11
12
  class Engine < ::Rails::Engine
12
13
  initializer 'leaflet-rails.precompile' do |app|
13
- app.config.assets.precompile += %w(layers-2x.png layers.png marker-icon-2x.png marker-icon.png marker-shadow.png)
14
+ if app.config.respond_to? (:assets)
15
+ app.config.assets.precompile += %w(layers-2x.png layers.png marker-icon-2x.png marker-icon.png marker-shadow.png)
16
+ end
14
17
  end
15
18
 
16
19
  initializer 'leaflet-rails.helpers' do
@@ -1,5 +1,5 @@
1
1
  module Leaflet
2
2
  module Rails
3
- VERSION = "1.0.2"
3
+ VERSION = "1.0.3"
4
4
  end
5
5
  end
@@ -1,10 +1,10 @@
1
1
  /*
2
- Leaflet 1.0.2, a JS library for interactive maps. http://leafletjs.com
2
+ Leaflet 1.0.3, a JS library for interactive maps. http://leafletjs.com
3
3
  (c) 2010-2016 Vladimir Agafonkin, (c) 2010-2011 CloudMade
4
4
  */
5
5
  (function (window, document, undefined) {
6
6
  var L = {
7
- version: "1.0.2"
7
+ version: "1.0.3"
8
8
  };
9
9
 
10
10
  function expose() {
@@ -516,7 +516,6 @@ L.Evented = L.Class.extend({
516
516
  }
517
517
 
518
518
  listeners.push(newListener);
519
- typeListeners.count++;
520
519
  },
521
520
 
522
521
  _off: function (type, fn, context) {
@@ -824,6 +823,9 @@ L.Mixin = {Events: proto};
824
823
 
825
824
  // @property touch: Boolean
826
825
  // `true` for all browsers supporting [touch events](https://developer.mozilla.org/docs/Web/API/Touch_events).
826
+ // This does not necessarily mean that the browser is running in a computer with
827
+ // a touchscreen, it only means that the browser is capable of understanding
828
+ // touch events.
827
829
  touch: !!touch,
828
830
 
829
831
  // @property msPointer: Boolean
@@ -1662,7 +1664,7 @@ L.LatLng.prototype = {
1662
1664
  },
1663
1665
 
1664
1666
  // @method toBounds(sizeInMeters: Number): LatLngBounds
1665
- // Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters` meters apart from the `LatLng`.
1667
+ // Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`.
1666
1668
  toBounds: function (sizeInMeters) {
1667
1669
  var latAccuracy = 180 * sizeInMeters / 40075017,
1668
1670
  lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat);
@@ -1869,7 +1871,7 @@ L.LatLngBounds.prototype = {
1869
1871
  // @method contains (latlng: LatLng): Boolean
1870
1872
  // Returns `true` if the rectangle contains the given point.
1871
1873
  contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean
1872
- if (typeof obj[0] === 'number' || obj instanceof L.LatLng) {
1874
+ if (typeof obj[0] === 'number' || obj instanceof L.LatLng || 'lat' in obj) {
1873
1875
  obj = L.latLng(obj);
1874
1876
  } else {
1875
1877
  obj = L.latLngBounds(obj);
@@ -2132,12 +2134,35 @@ L.CRS = {
2132
2134
  // @method wrapLatLng(latlng: LatLng): LatLng
2133
2135
  // Returns a `LatLng` where lat and lng has been wrapped according to the
2134
2136
  // CRS's `wrapLat` and `wrapLng` properties, if they are outside the CRS's bounds.
2137
+ // Only accepts actual `L.LatLng` instances, not arrays.
2135
2138
  wrapLatLng: function (latlng) {
2136
2139
  var lng = this.wrapLng ? L.Util.wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng,
2137
2140
  lat = this.wrapLat ? L.Util.wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat,
2138
2141
  alt = latlng.alt;
2139
2142
 
2140
2143
  return L.latLng(lat, lng, alt);
2144
+ },
2145
+
2146
+ // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds
2147
+ // Returns a `LatLngBounds` with the same size as the given one, ensuring
2148
+ // that its center is within the CRS's bounds.
2149
+ // Only accepts actual `L.LatLngBounds` instances, not arrays.
2150
+ wrapLatLngBounds: function (bounds) {
2151
+ var center = bounds.getCenter(),
2152
+ newCenter = this.wrapLatLng(center),
2153
+ latShift = center.lat - newCenter.lat,
2154
+ lngShift = center.lng - newCenter.lng;
2155
+
2156
+ if (latShift === 0 && lngShift === 0) {
2157
+ return bounds;
2158
+ }
2159
+
2160
+ var sw = bounds.getSouthWest(),
2161
+ ne = bounds.getNorthEast(),
2162
+ newSw = L.latLng({lat: sw.lat - latShift, lng: sw.lng - lngShift}),
2163
+ newNe = L.latLng({lat: ne.lat - latShift, lng: ne.lng - lngShift});
2164
+
2165
+ return new L.LatLngBounds(newSw, newNe);
2141
2166
  }
2142
2167
  };
2143
2168
 
@@ -2305,7 +2330,7 @@ L.Map = L.Evented.extend({
2305
2330
 
2306
2331
  // @option maxBounds: LatLngBounds = null
2307
2332
  // When this option is set, the map restricts the view to the given
2308
- // geographical bounds, bouncing the user back when he tries to pan
2333
+ // geographical bounds, bouncing the user back if the user tries to pan
2309
2334
  // outside the view. To set the restriction dynamically, use
2310
2335
  // [`setMaxBounds`](#map-setmaxbounds) method.
2311
2336
  maxBounds: undefined,
@@ -2512,7 +2537,7 @@ L.Map = L.Evented.extend({
2512
2537
  };
2513
2538
  },
2514
2539
 
2515
- // @method fitBounds(bounds: LatLngBounds, options: fitBounds options): this
2540
+ // @method fitBounds(bounds: LatLngBounds, options?: fitBounds options): this
2516
2541
  // Sets a map view that contains the given geographical bounds with the
2517
2542
  // maximum zoom level possible.
2518
2543
  fitBounds: function (bounds, options) {
@@ -3041,7 +3066,7 @@ L.Map = L.Evented.extend({
3041
3066
  nw = bounds.getNorthWest(),
3042
3067
  se = bounds.getSouthEast(),
3043
3068
  size = this.getSize().subtract(padding),
3044
- boundsSize = this.project(se, zoom).subtract(this.project(nw, zoom)),
3069
+ boundsSize = L.bounds(this.project(se, zoom), this.project(nw, zoom)).getSize(),
3045
3070
  snap = L.Browser.any3d ? this.options.zoomSnap : 1;
3046
3071
 
3047
3072
  var scale = Math.min(size.x / boundsSize.x, size.y / boundsSize.y);
@@ -3060,8 +3085,8 @@ L.Map = L.Evented.extend({
3060
3085
  getSize: function () {
3061
3086
  if (!this._size || this._sizeChanged) {
3062
3087
  this._size = new L.Point(
3063
- this._container.clientWidth,
3064
- this._container.clientHeight);
3088
+ this._container.clientWidth || 0,
3089
+ this._container.clientHeight || 0);
3065
3090
 
3066
3091
  this._sizeChanged = false;
3067
3092
  }
@@ -3182,6 +3207,16 @@ L.Map = L.Evented.extend({
3182
3207
  return this.options.crs.wrapLatLng(L.latLng(latlng));
3183
3208
  },
3184
3209
 
3210
+ // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds
3211
+ // Returns a `LatLngBounds` with the same size as the given one, ensuring that
3212
+ // its center is within the CRS's bounds.
3213
+ // By default this means the center longitude is wrapped around the dateline so its
3214
+ // value is between -180 and +180 degrees, and the majority of the bounds
3215
+ // overlaps the CRS's bounds.
3216
+ wrapLatLngBounds: function (latlng) {
3217
+ return this.options.crs.wrapLatLngBounds(L.latLngBounds(latlng));
3218
+ },
3219
+
3185
3220
  // @method distance(latlng1: LatLng, latlng2: LatLng): Number
3186
3221
  // Returns the distance between two geographical coordinates according to
3187
3222
  // the map's CRS. By default this measures distance in meters.
@@ -3203,7 +3238,7 @@ L.Map = L.Evented.extend({
3203
3238
  return L.point(point).add(this._getMapPanePos());
3204
3239
  },
3205
3240
 
3206
- // @method containerPointToLatLng(point: Point): Point
3241
+ // @method containerPointToLatLng(point: Point): LatLng
3207
3242
  // Given a pixel coordinate relative to the map container, returns
3208
3243
  // the corresponding geographical coordinate (for the current zoom level).
3209
3244
  containerPointToLatLng: function (point) {
@@ -3889,7 +3924,7 @@ L.Layer = L.Evented.extend({
3889
3924
 
3890
3925
  // @option attribution: String = null
3891
3926
  // String to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
3892
- attribution: null,
3927
+ attribution: null
3893
3928
  },
3894
3929
 
3895
3930
  /* @section
@@ -3959,8 +3994,8 @@ L.Layer = L.Evented.extend({
3959
3994
 
3960
3995
  this.onAdd(map);
3961
3996
 
3962
- if (this.getAttribution && this._map.attributionControl) {
3963
- this._map.attributionControl.addAttribution(this.getAttribution());
3997
+ if (this.getAttribution && map.attributionControl) {
3998
+ map.attributionControl.addAttribution(this.getAttribution());
3964
3999
  }
3965
4000
 
3966
4001
  this.fire('add');
@@ -4205,7 +4240,10 @@ L.DomEvent = {
4205
4240
  if (L.Browser.pointer && type.indexOf('touch') === 0) {
4206
4241
  this.addPointerListener(obj, type, handler, id);
4207
4242
 
4208
- } else if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) {
4243
+ } else if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener &&
4244
+ !(L.Browser.pointer && L.Browser.chrome)) {
4245
+ // Chrome >55 does not need the synthetic dblclicks from addDoubleTapListener
4246
+ // See #5180
4209
4247
  this.addDoubleTapListener(obj, handler, id);
4210
4248
 
4211
4249
  } else if ('addEventListener' in obj) {
@@ -4712,7 +4750,9 @@ L.GridLayer = L.Layer.extend({
4712
4750
  // @option noWrap: Boolean = false
4713
4751
  // Whether the layer is wrapped around the antimeridian. If `true`, the
4714
4752
  // GridLayer will only be displayed once at low zoom levels. Has no
4715
- // effect when the [map CRS](#map-crs) doesn't wrap around.
4753
+ // effect when the [map CRS](#map-crs) doesn't wrap around. Can be used
4754
+ // in combination with [`bounds`](#gridlayer-bounds) to prevent requesting
4755
+ // tiles outside the CRS limits.
4716
4756
  noWrap: false,
4717
4757
 
4718
4758
  // @option pane: String = 'tilePane'
@@ -5283,14 +5323,14 @@ L.GridLayer = L.Layer.extend({
5283
5323
  sePoint = nwPoint.add(tileSize),
5284
5324
 
5285
5325
  nw = map.unproject(nwPoint, coords.z),
5286
- se = map.unproject(sePoint, coords.z);
5326
+ se = map.unproject(sePoint, coords.z),
5327
+ bounds = new L.LatLngBounds(nw, se);
5287
5328
 
5288
5329
  if (!this.options.noWrap) {
5289
- nw = map.wrapLatLng(nw);
5290
- se = map.wrapLatLng(se);
5330
+ map.wrapLatLngBounds(bounds);
5291
5331
  }
5292
5332
 
5293
- return new L.LatLngBounds(nw, se);
5333
+ return bounds;
5294
5334
  },
5295
5335
 
5296
5336
  // converts tile coordinates to key for the tile cache
@@ -5476,7 +5516,7 @@ L.gridLayer = function (options) {
5476
5516
  * @example
5477
5517
  *
5478
5518
  * ```js
5479
- * L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
5519
+ * L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
5480
5520
  * ```
5481
5521
  *
5482
5522
  * @section URL template
@@ -5662,7 +5702,7 @@ L.TileLayer = L.GridLayer.extend({
5662
5702
 
5663
5703
  _tileOnError: function (done, tile, e) {
5664
5704
  var errorUrl = this.options.errorTileUrl;
5665
- if (errorUrl) {
5705
+ if (errorUrl && tile.src !== errorUrl) {
5666
5706
  tile.src = errorUrl;
5667
5707
  }
5668
5708
  done(e, tile);
@@ -6000,6 +6040,8 @@ L.ImageOverlay = L.Layer.extend({
6000
6040
  return this;
6001
6041
  },
6002
6042
 
6043
+ // @method setBounds(bounds: LatLngBounds): this
6044
+ // Update the bounds that this ImageOverlay covers
6003
6045
  setBounds: function (bounds) {
6004
6046
  this._bounds = bounds;
6005
6047
 
@@ -6022,10 +6064,14 @@ L.ImageOverlay = L.Layer.extend({
6022
6064
  return events;
6023
6065
  },
6024
6066
 
6067
+ // @method getBounds(): LatLngBounds
6068
+ // Get the bounds that this ImageOverlay covers
6025
6069
  getBounds: function () {
6026
6070
  return this._bounds;
6027
6071
  },
6028
6072
 
6073
+ // @method getElement(): HTMLElement
6074
+ // Get the img element that represents the ImageOverlay on the map
6029
6075
  getElement: function () {
6030
6076
  return this._image;
6031
6077
  },
@@ -6493,6 +6539,7 @@ L.Marker = L.Layer.extend({
6493
6539
 
6494
6540
  if (newShadow) {
6495
6541
  L.DomUtil.addClass(newShadow, classToAdd);
6542
+ newShadow.alt = '';
6496
6543
  }
6497
6544
  this._shadow = newShadow;
6498
6545
 
@@ -7348,7 +7395,7 @@ L.Layer.include({
7348
7395
  // @method isPopupOpen(): boolean
7349
7396
  // Returns `true` if the popup bound to this layer is currently open.
7350
7397
  isPopupOpen: function () {
7351
- return this._popup.isOpen();
7398
+ return (this._popup ? this._popup.isOpen() : false);
7352
7399
  },
7353
7400
 
7354
7401
  // @method setPopupContent(content: String|HTMLElement|Popup): this
@@ -8622,9 +8669,9 @@ L.LineUtil = {
8622
8669
  * ```js
8623
8670
  * // create a red polyline from an array of LatLng points
8624
8671
  * var latlngs = [
8625
- * [-122.68, 45.51],
8626
- * [-122.43, 37.77],
8627
- * [-118.2, 34.04]
8672
+ * [45.51, -122.68],
8673
+ * [37.77, -122.43],
8674
+ * [34.04, -118.2]
8628
8675
  * ];
8629
8676
  *
8630
8677
  * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
@@ -8638,12 +8685,12 @@ L.LineUtil = {
8638
8685
  * ```js
8639
8686
  * // create a red polyline from an array of arrays of LatLng points
8640
8687
  * var latlngs = [
8641
- * [[-122.68, 45.51],
8642
- * [-122.43, 37.77],
8643
- * [-118.2, 34.04]],
8644
- * [[-73.91, 40.78],
8645
- * [-87.62, 41.83],
8646
- * [-96.72, 32.76]]
8688
+ * [[45.51, -122.68],
8689
+ * [37.77, -122.43],
8690
+ * [34.04, -118.2]],
8691
+ * [[40.78, -73.91],
8692
+ * [41.83, -87.62],
8693
+ * [32.76, -96.72]]
8647
8694
  * ];
8648
8695
  * ```
8649
8696
  */
@@ -8983,7 +9030,7 @@ L.PolyUtil.clipPolygon = function (points, bounds, round) {
8983
9030
  *
8984
9031
  * ```js
8985
9032
  * // create a red polygon from an array of LatLng points
8986
- * var latlngs = [[-111.03, 41],[-111.04, 45],[-104.05, 45],[-104.05, 41]];
9033
+ * var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
8987
9034
  *
8988
9035
  * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
8989
9036
  *
@@ -8995,8 +9042,8 @@ L.PolyUtil.clipPolygon = function (points, bounds, round) {
8995
9042
  *
8996
9043
  * ```js
8997
9044
  * var latlngs = [
8998
- * [[-111.03, 41],[-111.04, 45],[-104.05, 45],[-104.05, 41]], // outer ring
8999
- * [[-108.58,37.29],[-108.58,40.71],[-102.50,40.71],[-102.50,37.29]] // hole
9045
+ * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
9046
+ * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
9000
9047
  * ];
9001
9048
  * ```
9002
9049
  *
@@ -9005,11 +9052,11 @@ L.PolyUtil.clipPolygon = function (points, bounds, round) {
9005
9052
  * ```js
9006
9053
  * var latlngs = [
9007
9054
  * [ // first polygon
9008
- * [[-111.03, 41],[-111.04, 45],[-104.05, 45],[-104.05, 41]], // outer ring
9009
- * [[-108.58,37.29],[-108.58,40.71],[-102.50,40.71],[-102.50,37.29]] // hole
9055
+ * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
9056
+ * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
9010
9057
  * ],
9011
9058
  * [ // second polygon
9012
- * [[-109.05, 37],[-109.03, 41],[-102.05, 41],[-102.04, 37],[-109.05, 38]]
9059
+ * [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]
9013
9060
  * ]
9014
9061
  * ];
9015
9062
  * ```
@@ -9679,6 +9726,7 @@ L.SVG.include(!L.Browser.vml ? {} : {
9679
9726
  container.appendChild(layer._path);
9680
9727
 
9681
9728
  this._updateStyle(layer);
9729
+ this._layers[L.stamp(layer)] = layer;
9682
9730
  },
9683
9731
 
9684
9732
  _addPath: function (layer) {
@@ -9694,6 +9742,7 @@ L.SVG.include(!L.Browser.vml ? {} : {
9694
9742
  var container = layer._container;
9695
9743
  L.DomUtil.remove(container);
9696
9744
  layer.removeInteractiveTarget(container);
9745
+ delete this._layers[L.stamp(layer)];
9697
9746
  },
9698
9747
 
9699
9748
  _updateStyle: function (layer) {
@@ -9815,6 +9864,16 @@ if (L.Browser.vml) {
9815
9864
  */
9816
9865
 
9817
9866
  L.Canvas = L.Renderer.extend({
9867
+ getEvents: function () {
9868
+ var events = L.Renderer.prototype.getEvents.call(this);
9869
+ events.viewprereset = this._onViewPreReset;
9870
+ return events;
9871
+ },
9872
+
9873
+ _onViewPreReset: function () {
9874
+ // Set a flag so that a viewprereset+moveend+viewreset only updates&redraws once
9875
+ this._postponeUpdatePaths = true;
9876
+ },
9818
9877
 
9819
9878
  onAdd: function () {
9820
9879
  L.Renderer.prototype.onAdd.call(this);
@@ -9836,6 +9895,8 @@ L.Canvas = L.Renderer.extend({
9836
9895
  },
9837
9896
 
9838
9897
  _updatePaths: function () {
9898
+ if (this._postponeUpdatePaths) { return; }
9899
+
9839
9900
  var layer;
9840
9901
  this._redrawBounds = null;
9841
9902
  for (var id in this._layers) {
@@ -9876,6 +9937,15 @@ L.Canvas = L.Renderer.extend({
9876
9937
  this.fire('update');
9877
9938
  },
9878
9939
 
9940
+ _reset: function () {
9941
+ L.Renderer.prototype._reset.call(this);
9942
+
9943
+ if (this._postponeUpdatePaths) {
9944
+ this._postponeUpdatePaths = false;
9945
+ this._updatePaths();
9946
+ }
9947
+ },
9948
+
9879
9949
  _initPath: function (layer) {
9880
9950
  this._updateDashArray(layer);
9881
9951
  this._layers[L.stamp(layer)] = layer;
@@ -9962,6 +10032,11 @@ L.Canvas = L.Renderer.extend({
9962
10032
  _redraw: function () {
9963
10033
  this._redrawRequest = null;
9964
10034
 
10035
+ if (this._redrawBounds) {
10036
+ this._redrawBounds.min._floor();
10037
+ this._redrawBounds.max._ceil();
10038
+ }
10039
+
9965
10040
  this._clear(); // clear layers in redraw bounds
9966
10041
  this._draw(); // draw layers
9967
10042
 
@@ -11325,6 +11400,7 @@ L.extend(L.DomEvent, {
11325
11400
  var count;
11326
11401
 
11327
11402
  if (L.Browser.pointer) {
11403
+ if ((!L.Browser.edge) || e.pointerType === 'mouse') { return; }
11328
11404
  count = L.DomEvent._pointersCount;
11329
11405
  } else {
11330
11406
  count = e.touches.length;
@@ -11340,9 +11416,11 @@ L.extend(L.DomEvent, {
11340
11416
  last = now;
11341
11417
  }
11342
11418
 
11343
- function onTouchEnd() {
11419
+ function onTouchEnd(e) {
11344
11420
  if (doubleTap && !touch.cancelBubble) {
11345
11421
  if (L.Browser.pointer) {
11422
+ if ((!L.Browser.edge) || e.pointerType === 'mouse') { return; }
11423
+
11346
11424
  // work around .type being readonly with MSPointer* events
11347
11425
  var newTouch = {},
11348
11426
  prop, i;
@@ -11370,12 +11448,11 @@ L.extend(L.DomEvent, {
11370
11448
  obj.addEventListener(touchstart, onTouchStart, false);
11371
11449
  obj.addEventListener(touchend, onTouchEnd, false);
11372
11450
 
11373
- // On some platforms (notably, chrome on win10 + touchscreen + mouse),
11451
+ // On some platforms (notably, chrome<55 on win10 + touchscreen + mouse),
11374
11452
  // the browser doesn't fire touchend/pointerup events but does fire
11375
11453
  // native dblclicks. See #4127.
11376
- if (!L.Browser.edge) {
11377
- obj.addEventListener('dblclick', handler, false);
11378
- }
11454
+ // Edge 14 also fires native dblclicks, but only for pointerType mouse, see #5180.
11455
+ obj.addEventListener('dblclick', handler, false);
11379
11456
 
11380
11457
  return this;
11381
11458
  },
@@ -11450,7 +11527,7 @@ L.extend(L.DomEvent, {
11450
11527
 
11451
11528
  _addPointerStart: function (obj, handler, id) {
11452
11529
  var onDown = L.bind(function (e) {
11453
- if (e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
11530
+ if (e.pointerType !== 'mouse' && e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
11454
11531
  // In IE11, some touch events needs to fire for form controls, or
11455
11532
  // the controls will stop working. We keep a whitelist of tag names that
11456
11533
  // need these events. For other target tags, we prevent default on the event.
@@ -12916,7 +12993,8 @@ L.Control.Layers = L.Control.extend({
12916
12993
 
12917
12994
  _initLayout: function () {
12918
12995
  var className = 'leaflet-control-layers',
12919
- container = this._container = L.DomUtil.create('div', className);
12996
+ container = this._container = L.DomUtil.create('div', className),
12997
+ collapsed = this.options.collapsed;
12920
12998
 
12921
12999
  // makes this work on IE touch devices by stopping it from firing a mouseout event when the touch is released
12922
13000
  container.setAttribute('aria-haspopup', true);
@@ -12928,11 +13006,15 @@ L.Control.Layers = L.Control.extend({
12928
13006
 
12929
13007
  var form = this._form = L.DomUtil.create('form', className + '-list');
12930
13008
 
12931
- if (!L.Browser.android) {
12932
- L.DomEvent.on(container, {
12933
- mouseenter: this.expand,
12934
- mouseleave: this.collapse
12935
- }, this);
13009
+ if (collapsed) {
13010
+ this._map.on('click', this.collapse, this);
13011
+
13012
+ if (!L.Browser.android) {
13013
+ L.DomEvent.on(container, {
13014
+ mouseenter: this.expand,
13015
+ mouseleave: this.collapse
13016
+ }, this);
13017
+ }
12936
13018
  }
12937
13019
 
12938
13020
  var link = this._layersLink = L.DomUtil.create('a', className + '-toggle', container);
@@ -12952,10 +13034,9 @@ L.Control.Layers = L.Control.extend({
12952
13034
  setTimeout(L.bind(this._onInputClick, this), 0);
12953
13035
  }, this);
12954
13036
 
12955
- this._map.on('click', this.collapse, this);
12956
13037
  // TODO keyboard accessibility
12957
13038
 
12958
- if (!this.options.collapsed) {
13039
+ if (!collapsed) {
12959
13040
  this.expand();
12960
13041
  }
12961
13042