diff --git a/CHANGELOG.md b/CHANGELOG.md
index a56fb04e..5cd50f42 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -133,7 +133,6 @@ These changes were targeted at removing any hardcoded projection-specific logic
* Fixed `ImageOverlay` mercator distortion on lower zoom levels.
* Fixed a bug where layers didn't fire `popupopen` and `popupclose` events when manually creating a popup object and passing it to `bindPopup`. [#2354](https://github.com/Leaflet/Leaflet/issues/2354)
* Fixed box-zoom overlay appearing under markers. [#1813](https://github.com/Leaflet/Leaflet/issues/1813)
-* Fixed an issue where clicks on Android were skipped when happened too fast. [#2303](https://github.com/Leaflet/Leaflet/issues/2303)
### Misc improvements
@@ -143,6 +142,19 @@ These changes were targeted at removing any hardcoded projection-specific logic
* Added reference to Leaflet CSS in `package.json` (by [@bclinkinbeard](https://github.com/bclinkinbeard)). [#2432](https://github.com/Leaflet/Leaflet/pull/2432)
+## 0.7.3 (May 23, 2014)
+
+* Added proper **bower** and **component** support (by [@calvinmetcalf](https://github.com/calvinmetcalf)). [#2561](https://github.com/Leaflet/Leaflet/pull/2561) [#1903](https://github.com/Leaflet/Leaflet/issues/1903)
+* Fixed a bug where dragging the map outside the window caused an error on FF. [#2610](https://github.com/Leaflet/Leaflet/issues/2610)
+* Fixed a bug where some taps on Android where not working, often falsely perceived as drags (by [@axefrog](https://github.com/axefrog)). [#2503](https://github.com/Leaflet/Leaflet/pull/2503)
+* Fixed a bug where clicks on Android were skipped when happened too fast. [#2303](https://github.com/Leaflet/Leaflet/issues/2303)
+* Fixed a bug where calling `setView` (or similar methods) several times in succession could freeze the map. [#2521](https://github.com/Leaflet/Leaflet/issues/2521) [#2236](https://github.com/Leaflet/Leaflet/issues/2236) [#2485](https://github.com/Leaflet/Leaflet/issues/2485)
+* Fixed a bug where `Control.Layers` wasn't properly removed (by [@jack-kerouac](https://github.com/jack-kerouac)). [#2569](https://github.com/Leaflet/Leaflet/pull/2569)
+* Fixed a bug that caused `TileLayer` `load` event not to fire properly. [#2510](https://github.com/Leaflet/Leaflet/issues/2510)
+* Fixed Canvas-based paths not triggering `remove` event when removed (by @adimitrov). [#2486](https://github.com/Leaflet/Leaflet/pull/2486)
+* Fixed a bug where you could end up with fractional zoom after pinch-zooming in some cases (by [@danzel](https://github.com/danzel). [#2400](https://github.com/Leaflet/Leaflet/pull/2400) [#1943](https://github.com/Leaflet/Leaflet/issues/1934)
+
+
## 0.7.2 (January 17, 2014)
* Fixed a bug that appeared with **Chrome 32 update** that made all **mouse events shifted on scrolled pages**. [#2352](https://github.com/Leaflet/Leaflet/issues/2352)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 052240d1..1e4ec7f6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -44,7 +44,7 @@ try asking [on the Leaflet forum](https://groups.google.com/forum/#!forum/leafle
### Considerations for Accepting Patches
-While we happily accept patches, we're also commited to keeping Leaflet simple, lightweight and blazingly fast.
+While we happily accept patches, we're also committed to keeping Leaflet simple, lightweight and blazingly fast.
So bugfixes, performance optimizations and small improvements that don't add a lot of code
are much more likely to get accepted quickly.
@@ -53,7 +53,7 @@ Before sending a pull request with a new feature, first check if it's been discu
or [Leaflet UserVoice](http://leaflet.uservoice.com/)),
and then ask yourself two questions:
- 1. Are you sure that this new feature is important enough to justify its presense in the Leaflet core?
+ 1. Are you sure that this new feature is important enough to justify its presence in the Leaflet core?
Or will it look better as a plugin in a separate repository?
2. Is it written in a simple, concise way that doesn't add bulk to the codebase?
@@ -85,7 +85,7 @@ Please do not commit to the `master` branch, or your unrelated changes will go i
You should also follow the code style and whitespace conventions of the original codebase.
In particular, use tabs for indentation and spaces for alignment.
-Before commiting your changes, run `jake lint` to catch any JS errors in the code and fix them.
+Before committing your changes, run `jake lint` to catch any JS errors in the code and fix them.
If you add any new files to the Leaflet source, make sure to also add them to `build/deps.js`
so that the build system knows about them.
@@ -142,7 +142,7 @@ If you need to make edits in a local repository to see how it looks in the proce
4. Open `localhost:4000` in your browser.
Now any file changes will be updated when you reload pages automatically.
-After commiting the changes, just send a pull request.
+After committing the changes, just send a pull request.
If you need to update documentation according to a new feature that only appeared in the master version (not stable one),
you need to make changes to `gh-pages-master` branch instead of `gh-pages`.
diff --git a/FAQ.md b/FAQ.md
index 669662ae..47f24966 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -26,10 +26,10 @@ You can roll your own tiles as well.
but there are providers that use other sources.
Check out [this example](http://leaflet-extras.github.io/leaflet-providers/preview/)
-with half a hundred different layers to choose from.
+with over seventy different layers to choose from.
Popular commercial options, free up to a particular number of requests, include
[MapBox](http://mapbox.com),
-[Bing Maps](http://www.microsoft.com/maps/choose-your-binge's-maps-API.aspx) (using a [plugin](https://github.com/shramov/leaflet-plugins)),
+[Bing Maps](http://www.microsoft.com/maps/choose-your-bing-maps-API.aspx) (using a [plugin](https://github.com/shramov/leaflet-plugins)),
[Esri ArcGIS](http://www.arcgis.com/features/maps/imagery.html) ([official plugin](https://github.com/Esri/esri-leaflet))
and [Nokia Here](http://developer.here.com/web-experiences).
A notable exception is [MapQuest Open](http://developer.mapquest.com/web/products/open/map), which is free for any number of requests.
@@ -45,7 +45,7 @@ and [MapQuest Open](http://developer.mapquest.com/web/products/open/map) provide
#### I want to use Google Maps API tiles with Leaflet, can I do that?
-The problem with Google is that its [Terms of Use](https://developers.google.com/maps/terms?hl=ru) forbid any means of tile access other than through the Google Maps API.
+The problem with Google is that its [Terms of Use](https://developers.google.com/maps/terms) forbid any means of tile access other than through the Google Maps API.
You can add the Google Maps API as a Leaflet layer with a [plugin](https://github.com/shramov/leaflet-plugins). But note that the map experience will not be perfect, because Leaflet will just act as a proxy to the Google Maps JS engine, so you won't get all the performance and usability benefits of using Leaflet when the Google layer is on.
diff --git a/Jakefile.js b/Jakefile.js
index bb965e41..1e3599c9 100644
--- a/Jakefile.js
+++ b/Jakefile.js
@@ -23,7 +23,7 @@ function hint(msg, paths) {
console.log('\tCheck passed.\n');
complete();
});
- }
+ };
}
desc('Check Leaflet source for errors with JSHint');
@@ -36,12 +36,14 @@ desc('Combine and compress Leaflet source files');
task('build', {async: true}, function (compsBase32, buildName) {
var v;
- jake.exec('git log -1 --pretty=format:"%h"', {}, function () {
+ jake.exec('git log -1 --pretty=format:"%h"', {breakOnError: false}, function () {
build.build(complete, v, compsBase32, buildName);
}).on('stdout', function (data) {
v = version + ' (' + data.toString() + ')';
- })
+ }).on('error', function () {
+ v = version;
+ });
});
desc('Run PhantomJS tests');
diff --git a/build/bower.json b/build/bower.json
index 7dde3788..ca85bde2 100644
--- a/build/bower.json
+++ b/build/bower.json
@@ -2,7 +2,6 @@
"name": "leaflet",
"description": "JavaScript library for mobile-friendly interactive maps",
"main": [
- "dist/leaflet.js",
"dist/leaflet.css",
"dist/leaflet-src.js",
"dist/images/layers-2x.png",
@@ -20,4 +19,4 @@
"src",
"build"
]
-}
\ No newline at end of file
+}
diff --git a/debug/map/markers.html b/debug/map/markers.html
new file mode 100644
index 00000000..1bf803cf
--- /dev/null
+++ b/debug/map/markers.html
@@ -0,0 +1,68 @@
+
+
+
+ Leaflet debug page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/debug/tests/click_on_canvas.html b/debug/tests/click_on_canvas.html
index f4a6b9c0..ac9b21f4 100644
--- a/debug/tests/click_on_canvas.html
+++ b/debug/tests/click_on_canvas.html
@@ -35,7 +35,7 @@
opacity: 1,
smoothFactor: 1,
color: 'red',
- clickable:true
+ interactive:true
}));
polygons.on('click', function(m) {
diff --git a/debug/tests/svg_clicks.html b/debug/tests/svg_clicks.html
index 11be258e..706f3456 100644
--- a/debug/tests/svg_clicks.html
+++ b/debug/tests/svg_clicks.html
@@ -43,7 +43,7 @@
[51, 7.000],
[51.002, 7.004]
],
- { clickable:false,color:'#f00' }
+ { interactive:false,color:'#f00' }
).addTo(map);
// when the mouse hovers over the red route2, you cannot click through the blue route1 beneath
diff --git a/dist/leaflet.css b/dist/leaflet.css
index 1edf2b14..5f3d8abc 100644
--- a/dist/leaflet.css
+++ b/dist/leaflet.css
@@ -24,7 +24,7 @@
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
- -webkit-user-drag: none;
+ -webkit-user-drag: none;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
@@ -40,7 +40,9 @@
.leaflet-marker-shadow {
display: block;
}
-/* map is broken in FF if you have max-width: 100% on tiles */
+/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
+/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
+.leaflet-container svg,
.leaflet-container img {
max-width: none !important;
}
@@ -171,7 +173,7 @@
/* cursors */
-.leaflet-clickable {
+.leaflet-interactive {
cursor: pointer;
}
.leaflet-container {
@@ -179,7 +181,7 @@
cursor: -moz-grab;
}
.leaflet-crosshair,
-.leaflet-crosshair .leaflet-clickable {
+.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
@@ -187,7 +189,7 @@
cursor: auto;
}
.leaflet-dragging .leaflet-container,
-.leaflet-dragging .leaflet-clickable {
+.leaflet-dragging .leaflet-interactive {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
diff --git a/package.json b/package.json
index 802f5d23..33bf5f43 100644
--- a/package.json
+++ b/package.json
@@ -3,18 +3,18 @@
"version": "0.7.0",
"description": "JavaScript library for mobile-friendly interactive maps",
"devDependencies": {
- "jake": "~0.7.9",
- "jshint": "~2.4.4",
+ "jake": "~0.7.14",
+ "jshint": "~2.5.1",
"uglify-js": "~2.4.13",
- "mocha": "~1.17.1",
+ "mocha": "~1.19.0",
"happen": "~0.1.3",
- "karma": "~0.12.0",
- "karma-mocha": "~0.1.1",
- "karma-coverage": "~0.2.0",
- "karma-phantomjs-launcher": "^0.1.2",
- "karma-chrome-launcher": "^0.1.2",
- "tin": "^0.4.0",
- "copyfiles": "0.0.1"
+ "karma": "~0.12.16",
+ "karma-mocha": "~0.1.3",
+ "karma-coverage": "~0.2.3",
+ "karma-phantomjs-launcher": "^0.1.4",
+ "karma-chrome-launcher": "^0.1.4",
+ "tin": "^0.5.0",
+ "copyfiles": "0.1.0"
},
"main": "dist/leaflet-src.js",
"style": "dist/leaflet.css",
diff --git a/spec/index.html b/spec/index.html
index 2be65391..fe8a8c1b 100644
--- a/spec/index.html
+++ b/spec/index.html
@@ -4,6 +4,7 @@
Leaflet Spec Runner
+
diff --git a/spec/suites/geo/LatLngSpec.js b/spec/suites/geo/LatLngSpec.js
index 5552aff9..1c050df0 100644
--- a/spec/suites/geo/LatLngSpec.js
+++ b/spec/suites/geo/LatLngSpec.js
@@ -64,6 +64,12 @@ describe('LatLng', function () {
expect(Math.abs(Math.round(a.distanceTo(b) / 1000) - 2084) < 5).to.eql(true);
});
+ it('does not return NaN if input points are equal', function () {
+ var a = new L.LatLng(50.5, 30.5);
+ var b = new L.LatLng(50.5, 30.5);
+
+ expect(a.distanceTo(b)).to.eql(0);
+ });
});
describe('L.latLng factory', function () {
diff --git a/spec/suites/layer/tile/TileLayerSpec.js b/spec/suites/layer/tile/TileLayerSpec.js
index 34c9b498..f4439b9b 100644
--- a/spec/suites/layer/tile/TileLayerSpec.js
+++ b/spec/suites/layer/tile/TileLayerSpec.js
@@ -105,4 +105,98 @@ describe('TileLayer', function () {
});
});
});
+
+ describe("'loading' event", function() {
+ var tileUrl1 = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
+ tileUrl2 = 'http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png';
+
+ // Add map div to DOM. The map panning tests do not work reliably unless
+ // the Leaflet map is properly styled and part of the DOM
+ var mapDiv = document.createElement('div');
+ mapDiv.style.height = '256px';
+ mapDiv.style.width = '256px';
+ document.body.appendChild(mapDiv);
+
+ this.afterAll(function() {
+ document.body.removeChild(mapDiv);
+ });
+
+ // Set the map zoom high enough that panning by 256 pixels necessarily loads more tiles
+ var myMap = L.map(mapDiv).setView([0, 0], 13);
+
+ describe("after a tilelayer has been initialized with an empty string", function() {
+ var layer = L.tileLayer('');
+ var updateInterval = layer.options.updateInterval + 500;
+
+ var loadingSpy;
+ beforeEach(function() {
+ loadingSpy = sinon.spy();
+ layer.on('loading', function() { loadingSpy(); });
+ });
+ afterEach(function() {
+ layer.off('loading');
+ });
+
+ it("is fired when the tilelayer is added to the map", function() {
+ layer.addTo(myMap);
+ expect(loadingSpy.calledOnce).to.be.ok();
+ });
+
+ it("is fired again when the tilelayer has its url set to a real tile url", function(done) {
+ layer.setUrl(tileUrl2);
+
+ setTimeout(function() {
+ expect(loadingSpy.calledOnce).to.be.ok();
+ done();
+ }, updateInterval);
+ });
+
+ it("is fired again when the map is panned enough to load more tiles", function(done) {
+ myMap.panBy([256,256]);
+
+ setTimeout(function() {
+ expect(loadingSpy.calledOnce).to.be.ok();
+ done();
+ }, updateInterval);
+ });
+ });
+
+ describe("after a tilelayer has been initialized with a real tile url", function() {
+ var layer = L.tileLayer(tileUrl1);
+ var updateInterval = layer.options.updateInterval + 500;
+
+ var loadingSpy;
+ beforeEach(function() {
+ loadingSpy = sinon.spy();
+ layer.on('loading', function() { loadingSpy(); });
+ });
+ afterEach(function() {
+ layer.off('loading');
+ });
+
+ it("is fired when the tilelayer is added to the map", function() {
+ layer.addTo(myMap);
+ expect(loadingSpy.calledOnce).to.be.ok();
+ });
+
+ it("is fired again when the tilelayer has its url set to a real tile url", function(done) {
+ layer.setUrl(tileUrl2);
+
+ setTimeout(function() {
+ expect(loadingSpy.calledOnce).to.be.ok();
+ done();
+ }, updateInterval);
+ });
+
+ it("is fired again when the map is panned enough to load more tiles", function(done) {
+ myMap.panBy([256,256]);
+
+ setTimeout(function() {
+ expect(loadingSpy.calledOnce).to.be.ok();
+ done();
+ }, updateInterval);
+ });
+ });
+ });
+
});
diff --git a/src/Leaflet.js b/src/Leaflet.js
index 507c781d..14604f42 100644
--- a/src/Leaflet.js
+++ b/src/Leaflet.js
@@ -21,8 +21,9 @@ if (typeof module === 'object' && typeof module.exports === 'object') {
// define Leaflet as an AMD module
} else if (typeof define === 'function' && define.amd) {
define(L);
+}
// define Leaflet as a global L variable, saving the original L to restore later if needed
-} else {
+if (typeof window !== 'undefined') {
expose();
}
diff --git a/src/control/Control.Layers.js b/src/control/Control.Layers.js
index 3e8417ff..f5234a00 100644
--- a/src/control/Control.Layers.js
+++ b/src/control/Control.Layers.js
@@ -124,8 +124,8 @@ L.Control.Layers = L.Control.extend({
_update: function () {
if (!this._container) { return; }
- this._baseLayersList.innerHTML = '';
- this._overlaysList.innerHTML = '';
+ L.DomUtil.empty(this._baseLayersList);
+ L.DomUtil.empty(this._overlaysList);
var baseLayersPresent, overlaysPresent, i, obj;
diff --git a/src/control/Control.Scale.js b/src/control/Control.Scale.js
index 80b1a146..2dab3100 100644
--- a/src/control/Control.Scale.js
+++ b/src/control/Control.Scale.js
@@ -80,7 +80,7 @@ L.Control.Scale = L.Control.extend({
},
_updateScale: function (scale, text, ratio) {
- scale.style.width = (Math.round(this.options.maxWidth * ratio) - 10) + 'px';
+ scale.style.width = Math.round(this.options.maxWidth * ratio) + 'px';
scale.innerHTML = text;
},
diff --git a/src/core/Util.js b/src/core/Util.js
index bd9ccafc..fc66a76e 100644
--- a/src/core/Util.js
+++ b/src/core/Util.js
@@ -5,11 +5,10 @@
L.Util = {
// extend an object with properties of one or more other objects
extend: function (dest) {
- var sources = Array.prototype.slice.call(arguments, 1),
- i, j, len, src;
+ var i, j, len, src;
- for (j = 0, len = sources.length; j < len; j++) {
- src = sources[j];
+ for (j = 1, len = arguments.length; j < len; j++) {
+ src = arguments[j];
for (i in src) {
dest[i] = src[i];
}
@@ -174,11 +173,11 @@ L.Util = {
getPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); };
- L.Util.requestAnimFrame = function (fn, context, immediate, element) {
+ L.Util.requestAnimFrame = function (fn, context, immediate) {
if (immediate && requestFn === timeoutDefer) {
fn.call(context);
} else {
- return requestFn.call(window, L.bind(fn, context), element);
+ return requestFn.call(window, L.bind(fn, context));
}
};
diff --git a/src/dom/DomUtil.js b/src/dom/DomUtil.js
index ba77e735..c13c41e7 100644
--- a/src/dom/DomUtil.js
+++ b/src/dom/DomUtil.js
@@ -38,6 +38,12 @@ L.DomUtil = {
}
},
+ empty: function (el) {
+ while (el.firstChild) {
+ el.removeChild(el.firstChild);
+ }
+ },
+
toFront: function (el) {
el.parentNode.appendChild(el);
},
diff --git a/src/dom/Draggable.js b/src/dom/Draggable.js
index a6650ec6..c743c11c 100644
--- a/src/dom/Draggable.js
+++ b/src/dom/Draggable.js
@@ -90,7 +90,9 @@ L.Draggable = L.Evented.extend({
this._startPos = L.DomUtil.getPosition(this._element).subtract(offset);
L.DomUtil.addClass(document.body, 'leaflet-dragging');
- L.DomUtil.addClass(e.target || e.srcElement, 'leaflet-drag-target');
+
+ this._lastTarget = e.target || e.srcElement;
+ L.DomUtil.addClass(this._lastTarget, 'leaflet-drag-target');
}
this._newPos = this._startPos.add(offset);
@@ -106,9 +108,13 @@ L.Draggable = L.Evented.extend({
this.fire('drag');
},
- _onUp: function (e) {
+ _onUp: function () {
L.DomUtil.removeClass(document.body, 'leaflet-dragging');
- L.DomUtil.removeClass(e.target || e.srcElement, 'leaflet-drag-target');
+
+ if (this._lastTarget) {
+ L.DomUtil.removeClass(this._lastTarget, 'leaflet-drag-target');
+ this._lastTarget = null;
+ }
for (var i in L.Draggable.MOVE) {
L.DomEvent
diff --git a/src/dom/PosAnimation.js b/src/dom/PosAnimation.js
index f5b00da5..ff67853a 100644
--- a/src/dom/PosAnimation.js
+++ b/src/dom/PosAnimation.js
@@ -19,9 +19,6 @@ L.PosAnimation = L.Evented.extend({
L.DomEvent.on(el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this);
L.DomUtil.setPosition(el, newPos);
- // toggle reflow, Chrome flickers for some reason if you don't do this
- L.Util.falseFn(el.offsetWidth);
-
// there's no native way to track value updates of transitioned properties, so we imitate this
this._stepTimer = setInterval(L.bind(this._onStep, this), 50);
},
@@ -32,8 +29,11 @@ L.PosAnimation = L.Evented.extend({
// if we just removed the transition property, the element would jump to its final position,
// so we need to make it stay at the current position
+ // Only setPosition if _getPos actually returns a valid position.
this._newPos = this._getPos();
- L.DomUtil.setPosition(this._el, this._newPos);
+ if (this._newPos) {
+ L.DomUtil.setPosition(this._el, this._newPos);
+ }
this._onTransitionEnd();
L.Util.falseFn(this._el.offsetWidth); // force reflow in case we are about to start a new animation
diff --git a/src/geo/crs/CRS.Earth.js b/src/geo/crs/CRS.Earth.js
index 3eb09873..b1fb4458 100644
--- a/src/geo/crs/CRS.Earth.js
+++ b/src/geo/crs/CRS.Earth.js
@@ -11,9 +11,10 @@ L.CRS.Earth = L.extend({}, L.CRS, {
distance: function (latlng1, latlng2) {
var rad = Math.PI / 180,
lat1 = latlng1.lat * rad,
- lat2 = latlng2.lat * rad;
+ lat2 = latlng2.lat * rad,
+ a = Math.sin(lat1) * Math.sin(lat2) +
+ Math.cos(lat1) * Math.cos(lat2) * Math.cos((latlng2.lng - latlng1.lng) * rad);
- return this.R * Math.acos(Math.sin(lat1) * Math.sin(lat2) +
- Math.cos(lat1) * Math.cos(lat2) * Math.cos((latlng2.lng - latlng1.lng) * rad));
+ return this.R * Math.acos(Math.min(a, 1));
}
});
diff --git a/src/layer/ImageOverlay.js b/src/layer/ImageOverlay.js
index 42deb3b8..0c9bca02 100644
--- a/src/layer/ImageOverlay.js
+++ b/src/layer/ImageOverlay.js
@@ -5,7 +5,8 @@
L.ImageOverlay = L.Layer.extend({
options: {
- opacity: 1
+ opacity: 1,
+ alt: ''
},
initialize: function (url, bounds, options) { // (String, LatLngBounds, Object)
@@ -80,6 +81,10 @@ L.ImageOverlay = L.Layer.extend({
return events;
},
+
+ getBounds: function() {
+ return this._bounds;
+ },
_initImage: function () {
var img = this._image = L.DomUtil.create('img',
@@ -90,6 +95,7 @@ L.ImageOverlay = L.Layer.extend({
img.onload = L.bind(this.fire, this, 'load');
img.src = this._url;
+ img.alt = this.options.alt;
},
_animateZoom: function (e) {
diff --git a/src/layer/marker/Marker.js b/src/layer/marker/Marker.js
index 434b4e43..6256cd84 100644
--- a/src/layer/marker/Marker.js
+++ b/src/layer/marker/Marker.js
@@ -10,7 +10,7 @@ L.Marker = L.Layer.extend({
icon: new L.Icon.Default(),
// title: '',
// alt: '',
- clickable: true,
+ interactive: true,
// draggable: false,
keyboard: true,
zIndexOffset: 0,
@@ -76,7 +76,7 @@ L.Marker = L.Layer.extend({
}
if (this._popup) {
- this.bindPopup(this._popup);
+ this.bindPopup(this._popup, this._popup.options);
}
return this;
@@ -201,14 +201,18 @@ L.Marker = L.Layer.extend({
_initInteraction: function () {
- if (!this.options.clickable) { return; }
+ if (!this.options.interactive) { return; }
- L.DomUtil.addClass(this._icon, 'leaflet-clickable');
+ L.DomUtil.addClass(this._icon, 'leaflet-interactive');
- L.DomEvent.on(this._icon, 'click dblclick mousedown mouseup mouseover mouseout contextmenu keypress',
+ L.DomEvent.on(this._icon, 'click dblclick mousedown mouseup mouseover mousemove mouseout contextmenu keypress',
this._fireMouseEvent, this);
if (L.Handler.MarkerDrag) {
+ if (this.dragging) {
+ this.dragging.disable();
+ }
+
this.dragging = new L.Handler.MarkerDrag(this);
if (this.options.draggable) {
@@ -223,8 +227,6 @@ L.Marker = L.Layer.extend({
L.DomEvent.preventDefault(e);
}
- if (e.type === 'click' && this.dragging && this.dragging.moved()) { return; }
-
if (e.type === 'keypress' && e.keyCode === 13) {
type = 'click';
}
diff --git a/src/layer/tile/GridLayer.js b/src/layer/tile/GridLayer.js
index dec97f1c..2999f358 100644
--- a/src/layer/tile/GridLayer.js
+++ b/src/layer/tile/GridLayer.js
@@ -191,11 +191,15 @@ L.GridLayer = L.Layer.extend({
});
}
+ if (this._abortLoading) {
+ this._abortLoading();
+ }
+
this._tiles = {};
this._tilesToLoad = 0;
this._tilesTotal = 0;
- this._tileContainer.innerHTML = '';
+ L.DomUtil.empty(this._tileContainer);
if (this._zoomAnimated && e && e.hard) {
this._clearBgBuffer();
@@ -241,7 +245,10 @@ L.GridLayer = L.Layer.extend({
tileSize = this._getTileSize();
if (zoom > this.options.maxZoom ||
- zoom < this.options.minZoom) { return; }
+ zoom < this.options.minZoom) {
+ this._clearBgBuffer();
+ return;
+ }
// tile coordinates range for the current view
var tileBounds = L.bounds(
@@ -324,7 +331,7 @@ L.GridLayer = L.Layer.extend({
_tileCoordsToBounds: function (coords) {
var map = this._map,
- tileSize = this.options.tileSize,
+ tileSize = this._getTileSize(),
nwPoint = coords.multiplyBy(tileSize),
sePoint = nwPoint.add([tileSize, tileSize]),
@@ -340,7 +347,7 @@ L.GridLayer = L.Layer.extend({
return coords.x + ':' + coords.y;
},
- // converts tile cache key to coordiantes
+ // converts tile cache key to coordinates
_keyToTileCoords: function (key) {
var kArr = key.split(':'),
x = parseInt(kArr[0], 10),
@@ -494,7 +501,7 @@ L.GridLayer = L.Layer.extend({
bg = this._bgBuffer;
if (map && !map._animatingZoom && !map.touchZoom._zooming && bg) {
- bg.innerHTML = '';
+ L.DomUtil.empty(bg);
L.DomUtil.setTransform(bg);
}
},
diff --git a/src/layer/tile/TileLayer.WMS.js b/src/layer/tile/TileLayer.WMS.js
index 48da0ab1..c76dcee2 100644
--- a/src/layer/tile/TileLayer.WMS.js
+++ b/src/layer/tile/TileLayer.WMS.js
@@ -22,7 +22,9 @@ L.TileLayer.WMS = L.TileLayer.extend({
// all keys that are not TileLayer options go to WMS params
for (var i in options) {
- if (!this.options.hasOwnProperty(i) && i !== 'crs') {
+ if (!this.options.hasOwnProperty(i) &&
+ i !== 'crs' &&
+ i !== 'uppercase') {
wmsParams[i] = options[i];
}
}
@@ -38,6 +40,7 @@ L.TileLayer.WMS = L.TileLayer.extend({
onAdd: function (map) {
this._crs = this.options.crs || map.options.crs;
+ this._uppercase = this.options.uppercase || false;
this._wmsVersion = parseFloat(this.wmsParams.version);
@@ -57,9 +60,11 @@ L.TileLayer.WMS = L.TileLayer.extend({
[se.y, nw.x, nw.y, se.x] :
[nw.x, se.y, se.x, nw.y]).join(','),
- url = L.Util.template(this._url, {s: this._getSubdomain(coords)});
+ url = L.TileLayer.prototype.getTileUrl.call(this, coords);
- return url + L.Util.getParamString(this.wmsParams, url, true) + '&BBOX=' + bbox;
+ return url +
+ L.Util.getParamString(this.wmsParams, url, this._uppercase) +
+ (this._uppercase ? '&BBOX=' : '&bbox=') + bbox;
},
setParams: function (params, noRedraw) {
diff --git a/src/layer/tile/TileLayer.js b/src/layer/tile/TileLayer.js
index 276f50f2..2e5aa9d5 100644
--- a/src/layer/tile/TileLayer.js
+++ b/src/layer/tile/TileLayer.js
@@ -16,7 +16,8 @@ L.TileLayer = L.GridLayer.extend({
maxNativeZoom: ,
tms: ,
zoomReverse: ,
- detectRetina: ,
+ detectRetina: ,
+ crossOrigin: ,
*/
},
@@ -55,7 +56,11 @@ L.TileLayer = L.GridLayer.extend({
tile.onload = L.bind(this._tileOnLoad, this, done, tile);
tile.onerror = L.bind(this._tileOnError, this, done, tile);
-
+
+ if (this.options.crossOrigin) {
+ tile.crossOrigin = '';
+ }
+
/*
Alt tag is set to empty string to keep screen readers from reading URL and for compliance reasons
http://www.w3.org/TR/WCAG20-TECHS/H67
@@ -138,11 +143,11 @@ L.TileLayer = L.GridLayer.extend({
for (i in this._tiles) {
tile = this._tiles[i];
- if (!tile.complete) {
- tile.onload = L.Util.falseFn;
- tile.onerror = L.Util.falseFn;
- tile.src = L.Util.emptyImageUrl;
+ tile.onload = L.Util.falseFn;
+ tile.onerror = L.Util.falseFn;
+ if (!tile.complete) {
+ tile.src = L.Util.emptyImageUrl;
L.DomUtil.remove(tile);
}
}
diff --git a/src/layer/vector/Canvas.js b/src/layer/vector/Canvas.js
index 59580090..e05f2d3e 100644
--- a/src/layer/vector/Canvas.js
+++ b/src/layer/vector/Canvas.js
@@ -207,12 +207,12 @@ L.Canvas = L.Renderer.extend({
},
_handleHover: function (layer, e, point) {
- if (!layer.options.clickable) { return; }
+ if (!layer.options.interactive) { return; }
if (layer._containsPoint(point)) {
// if we just got inside the layer, fire mouseover
if (!layer._mouseInside) {
- L.DomUtil.addClass(this._container, 'leaflet-clickable'); // change cursor
+ L.DomUtil.addClass(this._container, 'leaflet-interactive'); // change cursor
layer._fireMouseEvent(e, 'mouseover');
layer._mouseInside = true;
}
@@ -221,7 +221,7 @@ L.Canvas = L.Renderer.extend({
} else if (layer._mouseInside) {
// if we're leaving the layer, fire mouseout
- L.DomUtil.removeClass(this._container, 'leaflet-clickable');
+ L.DomUtil.removeClass(this._container, 'leaflet-interactive');
layer._fireMouseEvent(e, 'mouseout');
layer._mouseInside = false;
}
diff --git a/src/layer/vector/Path.js b/src/layer/vector/Path.js
index d4dea2a2..70e575ad 100644
--- a/src/layer/vector/Path.js
+++ b/src/layer/vector/Path.js
@@ -19,7 +19,7 @@ L.Path = L.Layer.extend({
fillOpacity: 0.2,
// className: ''
- clickable: true
+ interactive: true
},
onAdd: function () {
diff --git a/src/layer/vector/SVG.VML.js b/src/layer/vector/SVG.VML.js
index 2cc1d244..95b3735b 100644
--- a/src/layer/vector/SVG.VML.js
+++ b/src/layer/vector/SVG.VML.js
@@ -106,7 +106,7 @@ L.SVG.include(!L.Browser.vml ? {} : {
},
_updateCircle: function (layer) {
- var p = layer._point,
+ var p = layer._point.round(),
r = Math.round(layer._radius),
r2 = Math.round(layer._radiusY || r);
diff --git a/src/layer/vector/SVG.js b/src/layer/vector/SVG.js
index 196a269d..553bb7e4 100644
--- a/src/layer/vector/SVG.js
+++ b/src/layer/vector/SVG.js
@@ -31,11 +31,17 @@ L.SVG = L.Renderer.extend({
L.DomUtil.setPosition(container, b.min);
- // update container viewBox so that we don't have to change coordinates of individual layers
- container.setAttribute('width', size.x);
- container.setAttribute('height', size.y);
- container.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' '));
+ // set size of svg-container if changed
+ if (!this._svgSize || !this._svgSize.equals(size)) {
+ this._svgSize = size;
+ container.setAttribute('width', size.x);
+ container.setAttribute('height', size.y);
+ }
+ // movement: update container viewBox so that we don't have to change coordinates of individual layers
+ L.DomUtil.setPosition(container, b.min);
+ container.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' '));
+
if (L.Browser.mobileWebkit) {
pane.appendChild(container);
}
@@ -50,8 +56,8 @@ L.SVG = L.Renderer.extend({
L.DomUtil.addClass(path, layer.options.className);
}
- if (layer.options.clickable) {
- L.DomUtil.addClass(path, 'leaflet-clickable');
+ if (layer.options.interactive) {
+ L.DomUtil.addClass(path, 'leaflet-interactive');
}
this._updateStyle(layer);
@@ -110,7 +116,7 @@ L.SVG = L.Renderer.extend({
path.setAttribute('fill', 'none');
}
- path.setAttribute('pointer-events', options.pointerEvents || (options.clickable ? 'visiblePainted' : 'none'));
+ path.setAttribute('pointer-events', options.pointerEvents || (options.interactive ? 'visiblePainted' : 'none'));
},
_updatePoly: function (layer, closed) {
@@ -152,7 +158,10 @@ L.SVG = L.Renderer.extend({
},
_fireMouseEvent: function (e) {
- this._paths[L.stamp(e.target || e.srcElement)]._fireMouseEvent(e);
+ var path = this._paths[L.stamp(e.target || e.srcElement)];
+ if (path) {
+ path._fireMouseEvent(e);
+ }
}
});
diff --git a/src/map/Map.js b/src/map/Map.js
index 31c7d072..7fda5050 100644
--- a/src/map/Map.js
+++ b/src/map/Map.js
@@ -33,6 +33,10 @@ L.Map = L.Evented.extend({
this.setMaxBounds(options.maxBounds);
}
+ if (options.zoom !== undefined) {
+ this._zoom = this._limitZoom(options.zoom);
+ }
+
if (options.center && options.zoom !== undefined) {
this.setView(L.latLng(options.center), options.zoom, {reset: true});
}
@@ -566,9 +570,9 @@ L.Map = L.Evented.extend({
type = type || e.type;
if (L.DomEvent._skipped(e)) { return; }
-
if (type === 'click') {
- if (!e._simulated && ((this.dragging && this.dragging.moved()) ||
+ var draggableObj = obj.options.draggable === true ? obj : this;
+ if (!e._simulated && ((draggableObj.dragging && draggableObj.dragging.moved()) ||
(this.boxZoom && this.boxZoom.moved()))) { return; }
obj.fire('preclick');
}
diff --git a/src/map/anim/Map.PanAnimation.js b/src/map/anim/Map.PanAnimation.js
index 777ea7b9..8de67e3c 100644
--- a/src/map/anim/Map.PanAnimation.js
+++ b/src/map/anim/Map.PanAnimation.js
@@ -46,6 +46,11 @@ L.Map.include({
if (!offset.x && !offset.y) {
return this;
}
+ //If we pan too far then chrome gets issues with tiles
+ // and makes them disappear or appear in the wrong place (slightly offset) #2602
+ if (options.animate !== true && !this.getSize().contains(offset)) {
+ return this._resetView(this.unproject(this.project(this.getCenter()).add(offset)), this.getZoom());
+ }
if (!this._panAnim) {
this._panAnim = new L.PosAnimation();
diff --git a/src/map/handler/Map.BoxZoom.js b/src/map/handler/Map.BoxZoom.js
index cad8a236..fcca466c 100644
--- a/src/map/handler/Map.BoxZoom.js
+++ b/src/map/handler/Map.BoxZoom.js
@@ -27,19 +27,20 @@ L.Map.BoxZoom = L.Handler.extend({
},
_onMouseDown: function (e) {
- this._moved = false;
-
if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }
+ this._moved = false;
+
L.DomUtil.disableTextSelection();
L.DomUtil.disableImageDrag();
this._startPoint = this._map.mouseEventToContainerPoint(e);
L.DomEvent.on(document, {
+ contextmenu: L.DomEvent.stop,
mousemove: this._onMouseMove,
- mouseup: this._onMouseUp,
- keydown: this._onKeyDown
+ mouseup: this._onMouseUp,
+ keydown: this._onKeyDown
}, this);
},
@@ -74,13 +75,15 @@ L.Map.BoxZoom = L.Handler.extend({
L.DomUtil.enableImageDrag();
L.DomEvent.off(document, {
+ contextmenu: L.DomEvent.stop,
mousemove: this._onMouseMove,
- mouseup: this._onMouseUp,
- keydown: this._onKeyDown
+ mouseup: this._onMouseUp,
+ keydown: this._onKeyDown
}, this);
},
- _onMouseUp: function () {
+ _onMouseUp: function (e) {
+ if ((e.which !== 1) && (e.button !== 1)) { return false; }
this._finish();
diff --git a/src/map/handler/Map.ScrollWheelZoom.js b/src/map/handler/Map.ScrollWheelZoom.js
index df2e614b..77ada016 100644
--- a/src/map/handler/Map.ScrollWheelZoom.js
+++ b/src/map/handler/Map.ScrollWheelZoom.js
@@ -3,7 +3,8 @@
*/
L.Map.mergeOptions({
- scrollWheelZoom: true
+ scrollWheelZoom: true,
+ wheelDebounceTime: 40
});
L.Map.ScrollWheelZoom = L.Handler.extend({
@@ -25,6 +26,7 @@ L.Map.ScrollWheelZoom = L.Handler.extend({
_onWheelScroll: function (e) {
var delta = L.DomEvent.getWheelDelta(e);
+ var debounce = this._map.options.wheelDebounceTime;
this._delta += delta;
this._lastMousePos = this._map.mouseEventToContainerPoint(e);
@@ -33,7 +35,7 @@ L.Map.ScrollWheelZoom = L.Handler.extend({
this._startTime = +new Date();
}
- var left = Math.max(40 - (+new Date() - this._startTime), 0);
+ var left = Math.max(debounce - (+new Date() - this._startTime), 0);
clearTimeout(this._timer);
this._timer = setTimeout(L.bind(this._performZoom, this), left);
diff --git a/src/map/handler/Map.TouchZoom.js b/src/map/handler/Map.TouchZoom.js
index 741f83ea..ab90795e 100644
--- a/src/map/handler/Map.TouchZoom.js
+++ b/src/map/handler/Map.TouchZoom.js
@@ -54,9 +54,11 @@ L.Map.TouchZoom = L.Handler.extend({
this._scale = p1.distanceTo(p2) / this._startDist;
this._delta = p1._add(p2)._divideBy(2)._subtract(this._startCenter);
- if (!map.options.bounceAtZoomLimits &&
- ((map.getZoom() === map.getMinZoom() && this._scale < 1) ||
- (map.getZoom() === map.getMaxZoom() && this._scale > 1))) { return; }
+ if (!map.options.bounceAtZoomLimits) {
+ var currentZoom = map.getScaleZoom(this._scale);
+ if ((currentZoom <= map.getMinZoom() && this._scale < 1) ||
+ (currentZoom >= map.getMaxZoom() && this._scale > 1)) { return; }
+ }
if (!this._moved) {
map