merge master
This commit is contained in:
commit
45a06f7859
142
CHANGELOG.md
142
CHANGELOG.md
@ -5,9 +5,149 @@ Leaflet Changelog
|
||||
|
||||
## 0.7-dev (master)
|
||||
|
||||
An in-progress version being developed on the `master` branch. Includes all fixes from the `stable` branch.
|
||||
An in-progress version being developed on the `master` branch.
|
||||
|
||||
### Improvements
|
||||
|
||||
#### Usability improvements
|
||||
|
||||
* Added **support for IE11 touch devices** (by [@danzel](https://github.com/danzel), [@DanielX2](https://github.com/DanielX2) and [@fnicollet](https://github.com/fnicollet)). [#2039](https://github.com/Leaflet/Leaflet/pull/2039) [#2066](https://github.com/Leaflet/Leaflet/pull/2066) [#2037](https://github.com/Leaflet/Leaflet/issues/2037) [#2102](https://github.com/Leaflet/Leaflet/issues/2102)
|
||||
* Added shift-double-click to zoom out shortcut. [#2185](https://github.com/Leaflet/Leaflet/issues/2185)
|
||||
* Significantly improved **controls design on mobile** devices. [#1868](https://github.com/Leaflet/Leaflet/issues/1868) [#2012](https://github.com/Leaflet/Leaflet/issues/2012)
|
||||
* Fixed and improved IE7-8 control and popup styles.
|
||||
* Made subtle improvements to control styles on desktop browsers.
|
||||
* Improved keyboard nav support so that map doesn't loose focus when you click on a control (by [@jacobtoye](https://github.com/jacobtoye)). [#2150](https://github.com/Leaflet/Leaflet/issues/2150) [#2148](https://github.com/Leaflet/Leaflet/issues/2148)
|
||||
* Improved `maxBounds` behavior: now it doesn't force higher minimal zoom, and anchors to max bounds edges properly when zooming (by [@kapouer](https://github.com/kapouer) and [@mourner](https://github.com/mourner)). [#2187](https://github.com/Leaflet/Leaflet/pull/2187) [#1946](https://github.com/Leaflet/Leaflet/pull/1946) [#2081](https://github.com/Leaflet/Leaflet/issues/2081) [#2168](https://github.com/Leaflet/Leaflet/issues/2168) [#1908](https://github.com/Leaflet/Leaflet/issues/1908)
|
||||
|
||||
#### Map API improvements
|
||||
|
||||
* Made `Map` `setView` `zoom` argument optional. [#2056](https://github.com/Leaflet/Leaflet/issues/2056)
|
||||
* Added `maxZoom` option to `Map` `fitBounds`. [#2101](https://github.com/Leaflet/Leaflet/issues/2101)
|
||||
* Added `Map` `bounceAtZoomLimits` option that makes the map bounce when you pinch-zoom past limits (it worked like this before, but now you can disable this) (by [@trevorpowell](https://github.com/trevorpowell)). [#1864](https://github.com/Leaflet/Leaflet/issues/1864) [#2072](https://github.com/Leaflet/Leaflet/pull/2072)
|
||||
* Added `distance` property to `Map` and `Marker` `dragend` events. [#2158](https://github.com/Leaflet/Leaflet/issues/2158) [#872](https://github.com/Leaflet/Leaflet/issues/872)
|
||||
* Added optional support for center-oriented scroll and double-click zoom (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1939](https://github.com/Leaflet/Leaflet/issues/1939)
|
||||
* Added `timestamp` to `Map` `locationfound` event. [#584](https://github.com/Leaflet/Leaflet/pull/584)
|
||||
* Improved `Map` `invalidateSize` to call `moveend` immediately unless given `debounceMoveend: true` option (by [@jfirebaugh](https://github.com/jfirebaugh)). [#2181](https://github.com/Leaflet/Leaflet/issues/2181)
|
||||
|
||||
#### TileLayer API improvements
|
||||
|
||||
* Added `TileLayer` `maxNativeZoom` option that allows displaying tile layers on zoom levels above their maximum by **upscaling tiles**. [#1802](https://github.com/Leaflet/Leaflet/issues/1802) [#1798](https://github.com/Leaflet/Leaflet/issues/1798)
|
||||
* Added `TileLayer` `tileloadstart` event (by [@tmcw](https://github.com/tmcw)). [#2142](https://github.com/Leaflet/Leaflet/pull/2142) [#2140](https://github.com/Leaflet/Leaflet/issues/2140)
|
||||
* Improved `TileLayer` world size (used for wrapping and limiting tiles) to be derived from CRS instead of hardcoded, making it easier to use with custom projections (by [@perliedman](https://github.com/perliedman)). [#2160](https://github.com/Leaflet/Leaflet/pull/2160)
|
||||
|
||||
#### Marker API improvements
|
||||
|
||||
* Added CSS classes to draggable markers for easier customization (by [@snkashis](https://github.com/snkashis)). [#1902](https://github.com/Leaflet/Leaflet/issues/1902) [#1916](https://github.com/Leaflet/Leaflet/issues/1916)
|
||||
* Added `Marker` `add` event (by [@tohaocean](https://github.com/tohaocean)). [#1942](https://github.com/Leaflet/Leaflet/issues/1942)
|
||||
* Added `Marker` `getPopup` method (by [@scottharvey](https://github.com/scottharvey)). [#618](https://github.com/Leaflet/Leaflet/issues/618) [#1197](https://github.com/Leaflet/Leaflet/pull/1197)
|
||||
* Added `Marker` `alt` option for adding `alt` text to markers (by [@jimmytidey](https://github.com/jimmytidey)). [#2112](https://github.com/Leaflet/Leaflet/pull/2112)
|
||||
|
||||
#### Vector layers API improvements
|
||||
|
||||
* Added `Path` `className` option for adding custom class names to vector layers.
|
||||
* Added `Path` `lineCap` and `lineJoin` options (by [@palewire](https://github.com/palewire)). [#1843](https://github.com/Leaflet/Leaflet/issues/1843) [#1863](https://github.com/Leaflet/Leaflet/issues/1863) [#1881](https://github.com/Leaflet/Leaflet/issues/1881)
|
||||
* Added ability to pass vector options to `GeoJSON` (by [@kapouer](https://github.com/kapouer)). [#2075](https://github.com/Leaflet/Leaflet/pull/2075)
|
||||
* Improved `Polygon` `setLatLngs` to also accept holes (by [@aparshin](https://github.com/aparshin)). [#2095](https://github.com/Leaflet/Leaflet/pull/2095) [#1518](https://github.com/Leaflet/Leaflet/issues/1518)
|
||||
* Added `GeoJSON` 3D format support and optional `altitude` argument to `LatLng` constructor (by [@Starefossen](https://github.com/Starefossen)). [#1822](https://github.com/Leaflet/Leaflet/pull/1822)
|
||||
* Added `MultiPolygon` and `MultiPolyline` `openPopup` method. [#2046](https://github.com/Leaflet/Leaflet/issues/2046)
|
||||
|
||||
#### Popup API improvements
|
||||
|
||||
* Added `Popup` `update` method. [#1959](https://github.com/Leaflet/Leaflet/issues/1959)
|
||||
* Added `Popup` `autoPanPaddingTopLeft` and `autoPanPaddingBottomRight` options (by [@albburtsev](https://github.com/albburtsev)). [#1972](https://github.com/Leaflet/Leaflet/issues/1972) [#1588](https://github.com/Leaflet/Leaflet/issues/1588)
|
||||
* Added `Popup` `getContent` method. [#2100](https://github.com/Leaflet/Leaflet/issues/2100)
|
||||
* Added `Popup` `getLatLng` method (by [@AndreyGeonya](https://github.com/AndreyGeonya)). [#2097](https://github.com/Leaflet/Leaflet/pull/2097)
|
||||
|
||||
#### Misc API improvements
|
||||
|
||||
* Added `ImageOverlay` `setUrl` and `getAttribution` methods and `attribution` option (by [@stsydow](https://github.com/stsydow)). [#1957](https://github.com/Leaflet/Leaflet/issues/1957) [#1958](https://github.com/Leaflet/Leaflet/issues/1958)
|
||||
* Added localization support for the zoom control (by [@Danielku15](https://github.com/Danielku15)). [#1953](https://github.com/Leaflet/Leaflet/issues/1953) [#1643](https://github.com/Leaflet/Leaflet/issues/1643) [#1953](https://github.com/Leaflet/Leaflet/pull/1953)
|
||||
* Significantly improved `L.Util.template` performance (affects `L.TileLayer`) by introducing cached template compilation (by [@calvinmetcalf](https://github.com/calvinmetcalf)). [#1969](https://github.com/Leaflet/Leaflet/issues/1969) [#1968](https://github.com/Leaflet/Leaflet/issues/1968) [#1554](https://github.com/Leaflet/Leaflet/issues/1554)
|
||||
* Added `CRS` `getSize` for getting the world size in pixels (by [@perliedman](https://github.com/perliedman)). [#2160](https://github.com/Leaflet/Leaflet/pull/2160)
|
||||
* Added `leaflet-drag-target` CSS class to an element under cursor when dragging for more flexible customization. [#2164](https://github.com/Leaflet/Leaflet/issues/2164) [#1902](https://github.com/Leaflet/Leaflet/issues/1902)
|
||||
* Improved `L.DomUtil` `addClass`, `removeClass`, `hasClass` methods performance and fixed it to work with SVG elements. [#2164](https://github.com/Leaflet/Leaflet/issues/2164)
|
||||
|
||||
#### Dev workflow improvements
|
||||
|
||||
* Added an [official FAQ](https://github.com/Leaflet/Leaflet/blob/master/FAQ.md).
|
||||
* Cleaned up and moved old IE styles to `leaflet.css` and removed `leaflet.ie.css`, so **no need for IE conditional comment** when including Leaflet now. [#2159](https://github.com/Leaflet/Leaflet/issues/2159)
|
||||
* Added `leaflet-oldie` CSS class to map container in IE7-8 for easier styling. [#2159](https://github.com/Leaflet/Leaflet/issues/2159)
|
||||
* Officially **dropped support for IE6**. Nobody cares anyway, and Leaflet should still be accessible on it. [#2159](https://github.com/Leaflet/Leaflet/issues/2159)
|
||||
* Improved the build system to check JS errors in spec files. [#2151](https://github.com/Leaflet/Leaflet/issues/2151)
|
||||
* Fixed `jake` command to run tests before building the source. [#2151](https://github.com/Leaflet/Leaflet/issues/2151)
|
||||
* Switched the main file in `package.json` to unminified version for NPM/Browserify (by [@icetan](https://github.com/icetan)). [#2109](https://github.com/Leaflet/Leaflet/pull/2109)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
#### 0.6 regression fixes
|
||||
|
||||
* Fixed a **memory leak in iOS7** that could crash Safari when handling lots of objects (e.g. 1000 markers) (by [@danzel](https://github.com/danzel)). [#2149](https://github.com/Leaflet/Leaflet/pull/2149) [#2122](https://github.com/Leaflet/Leaflet/issues/2122)
|
||||
* Fixed a bug that caused lag at the beginning of panning in Chrome (by [@jfirebaugh](https://github.com/jfirebaugh)). [#2163](https://github.com/Leaflet/Leaflet/issues/2163)
|
||||
* Fixed a regression that made the layers control unscrollable in Firefox. [#2029](https://github.com/Leaflet/Leaflet/issues/2029)
|
||||
* Fixed a regression that broke `worldCopyJump: true` option (by [@fastrde](https://github.com/fastrde)). [#1904](https://github.com/Leaflet/Leaflet/issues/1904) [#1831](https://github.com/Leaflet/Leaflet/issues/1831) [#1982](https://github.com/Leaflet/Leaflet/issues/1982)
|
||||
* Fixed a regression where a first map click after popup close button click was ignored (by [@fastrde](https://github.com/fastrde)). [#1537](https://github.com/Leaflet/Leaflet/issues/1537) [#1963](https://github.com/Leaflet/Leaflet/issues/1963) [#1925](https://github.com/Leaflet/Leaflet/issues/1925)
|
||||
* Fixed a regression where `L.DomUtil.getMousePosition` would throw an error if container argument not provided (by [@scooterw](https://github.com/scooterw)). [#1826](https://github.com/Leaflet/Leaflet/issues/1826) [#1928](https://github.com/Leaflet/Leaflet/issues/1928) [#1926](https://github.com/Leaflet/Leaflet/issues/1926)
|
||||
* Fixed a regression with vector layers positioning when zooming on IE10+ touch devices (by [@danzel](https://github.com/danzel)). [#2002](https://github.com/Leaflet/Leaflet/issues/2002) [#2000](https://github.com/Leaflet/Leaflet/issues/2000)
|
||||
* Fixed a regression with `maxBounds` behaving weirdly on panning inertia out of bounds. [#2168](https://github.com/Leaflet/Leaflet/issues/2168)
|
||||
|
||||
#### General bugfixes
|
||||
|
||||
* Fixed a bug where the map could freeze if centered and immediately recentered on initialization. [#2071](https://github.com/Leaflet/Leaflet/issues/2071)
|
||||
* Fixed a bug where all maps except the first one on a page didn't track window resize. [#1980](https://github.com/Leaflet/Leaflet/issues/1980)
|
||||
* Fixed a bug where tiles in `EPSG:3395` projection were shifted (by [@aparshin](https://github.com/aparshin)). [#2020](https://github.com/Leaflet/Leaflet/issues/2020)
|
||||
* Fixed a bug where scale control displayed wrong scale when on pages with `box-sizing: border-box`.
|
||||
* Fixed a bug where zoom control button didn't appear as disabled if map was initialized at the zoom limit. [#2083](https://github.com/Leaflet/Leaflet/issues/2083)
|
||||
* Fixed a bug where box zoom also triggered a map click event (by [@fastrde](https://github.com/fastrde)). [#1951](https://github.com/Leaflet/Leaflet/issues/1951) [#1884](https://github.com/Leaflet/Leaflet/issues/1884)
|
||||
* Fixed a bug where shift-clicking on a map immediately after a drag didn't trigger a click event (by [@fastrde](https://github.com/fastrde)). [#1952](https://github.com/Leaflet/Leaflet/issues/1952) [#1950](https://github.com/Leaflet/Leaflet/issues/1950)
|
||||
* Fixed a bug where content was updated twice when opening a popup. [#2137](https://github.com/Leaflet/Leaflet/issues/2137)
|
||||
* Fixed a bug that could sometimes cause infinite panning loop when using `maxBounds` (by [@kapouer](https://github.com/kapouer) and [@mourner](https://github.com/mourner)). [#2187](https://github.com/Leaflet/Leaflet/pull/2187) [#1946](https://github.com/Leaflet/Leaflet/pull/1946) [#2081](https://github.com/Leaflet/Leaflet/issues/2081) [#2168](https://github.com/Leaflet/Leaflet/issues/2168) [#1908](https://github.com/Leaflet/Leaflet/issues/1908)
|
||||
|
||||
#### Browser bugfixes
|
||||
|
||||
* Fixed a bug where keyboard `+` no longer zoomed the map on FF 22+ (by [@fastrde](https://github.com/fastrde)). [#1943](https://github.com/Leaflet/Leaflet/issues/1943) [#1981](https://github.com/Leaflet/Leaflet/issues/1981)
|
||||
* Fixed a bug where calling `Map` `remove` throwed an error in IE6-8. [#2015](https://github.com/Leaflet/Leaflet/issues/2015)
|
||||
* Fixed a bug where `isArray` didn't work in rare cases in IE9. [#2077](https://github.com/Leaflet/Leaflet/issues/2077)
|
||||
* Fixed a bug where FF sometimes produced console warnings when animating markers. [#2090](https://github.com/Leaflet/Leaflet/issues/2090)
|
||||
* Fixed a bug where mouse wasn't handled correctly on RTL pages in some cases (by [@danzel](https://github.com/danzel)). [#1986](https://github.com/Leaflet/Leaflet/issues/1986) [#2136](https://github.com/Leaflet/Leaflet/pull/2136)
|
||||
|
||||
#### Mobile bugfixes
|
||||
|
||||
* Fixed a bug where tiles could **disappear after zooming on Chrome 30+ for Android** (by [@danzel](https://github.com/danzel)). [#2152](https://github.com/Leaflet/Leaflet/pull/2152) [#2078](https://github.com/Leaflet/Leaflet/issues/2078)
|
||||
* Fixed a bug on IE10+ touch where pinch-zoom also caused click (by [@danzel](https://github.com/danzel)). [#2117](https://github.com/Leaflet/Leaflet/pull/2117) [#2094](https://github.com/Leaflet/Leaflet/issues/2094)
|
||||
* Fixed a bug on IE10+ touch where controls didn't loose the pressed state after tapping (by [@danzel](https://github.com/danzel)). [#2111](https://github.com/Leaflet/Leaflet/pull/2111) [#2103](https://github.com/Leaflet/Leaflet/issues/2103)
|
||||
* Fixed a bug where clicking on layers control labels on iOS throwed an error (by [@olemarkus](https://github.com/olemarkus) and [@dagjomar](https://github.com/dagjomar)). [#1984](https://github.com/Leaflet/Leaflet/issues/1984) [#1989](https://github.com/Leaflet/Leaflet/issues/1989)
|
||||
|
||||
#### Map API bugfixes
|
||||
|
||||
* Fixed a bug where `Map` `getCenter` returned old result after map container size changed (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1940](https://github.com/Leaflet/Leaflet/issues/1940) [#1919](https://github.com/Leaflet/Leaflet/issues/1919)
|
||||
* Fixed `Map` `invalidateSize` rounding issues when changing map size by an odd pixel amount (by [@russelldavis](https://github.com/russelldavis)). [#1931](https://github.com/Leaflet/Leaflet/issues/1931)
|
||||
* Fixed a bug where `Map` `removeLayer` didn't return `this` in a corner case (by [@jfirebaugh](https://github.com/jfirebaugh)).
|
||||
* Fixed a bug where calling `Map` `setZoom` before `setView` would throw an error. [#1449](https://github.com/Leaflet/Leaflet/issues/1449)
|
||||
|
||||
#### Layers API bugfixes
|
||||
|
||||
* Fixed a bug where `Popup` `setLatLng` unnecessarily reset content and updated layout; works much faster now. [#2167](https://github.com/Leaflet/Leaflet/issues/2167)
|
||||
* Fixed a bug where `toGeoJSON` of layers originated from GeoJSON GeometryCollection and MultiPoint didn't work properly (wasn't round-tripped). [#1956](https://github.com/Leaflet/Leaflet/issues/1956)
|
||||
* Fixed `GeoJSON` dependencies in build configuration that could lead to a broken custom build in some situations (by [@alubchuk](https://github.com/alubchuk)). [#1909](https://github.com/Leaflet/Leaflet/issues/1909)
|
||||
* Fixed a bug where `CircleMarker` popup placement wasn't updated after calling `setLatLng` (by [@snkashis](https://github.com/snkashis)). [#1921](https://github.com/Leaflet/Leaflet/issues/1921) [#1927](https://github.com/Leaflet/Leaflet/issues/1927)
|
||||
* Fixed a bug where popup anchor wasn't updated on `Marker` `setIcon` (by [@snkashis](https://github.com/snkashis)). [#1874](https://github.com/Leaflet/Leaflet/issues/1874) [#1891](https://github.com/Leaflet/Leaflet/issues/1891)
|
||||
* Fixed a bug with GeoJSON not throwing a descriptive error if a polygon has zero length inner ring (by [@snkashis](https://github.com/snkashis)). [#1917](https://github.com/Leaflet/Leaflet/issues/1917) [#1918](https://github.com/Leaflet/Leaflet/issues/1918)
|
||||
* Fixed a bug where `FeatureGroup` would break when using non-evented children layers (by [@tmcw](https://github.com/tmcw)). [#2032](https://github.com/Leaflet/Leaflet/pull/2032) [#1962](https://github.com/Leaflet/Leaflet/issues/1962)
|
||||
* Fixed a bug where `CircleMarker` `getRadius` would always return `null`. [#2016](https://github.com/Leaflet/Leaflet/issues/2016) [#2017](https://github.com/Leaflet/Leaflet/pull/2017)
|
||||
* Fixed a bug where `TileLayer.WMS` didn't work with WMS 1.3 & EPSG4326 projection (by [@Bobboya](https://github.com/Bobboya)). [#1897](https://github.com/Leaflet/Leaflet/pull/1897)
|
||||
* Fixed a bug where `FeatureGroup` events `e.layer` was sometimes empty in old IE. [#1938](https://github.com/Leaflet/Leaflet/issues/1938)
|
||||
|
||||
#### Misc API bugfixes
|
||||
|
||||
* Fixed a bug where `L.latLngBounds` didn't accept simple object `LatLng` form (by [@Gnurfos](https://github.com/Gnurfos)). [#2025](https://github.com/Leaflet/Leaflet/issues/2025) [#1915](https://github.com/Leaflet/Leaflet/issues/1915)
|
||||
* Fixed a bug where `L.Util.tempalate` wouldn't work with double quotes in the string (by [@jieter](https://github.com/jieter)). [#1968](https://github.com/Leaflet/Leaflet/issues/1968) [#2121](https://github.com/Leaflet/Leaflet/pull/2121) [#2120](https://github.com/Leaflet/Leaflet/issues/2120)
|
||||
* Fixed a bug where attribution control that was added to a map after attributed layers didn't have the corresponding attributions (by [@snkashis](https://github.com/snkashis)). [#2177](https://github.com/Leaflet/Leaflet/issues/2177) [#2178](https://github.com/Leaflet/Leaflet/pull/2178)
|
||||
|
||||
|
||||
## 0.6.4 (July 25, 2013)
|
||||
|
||||
* Fixed a regression where `fitBounds` and `setMaxBounds` could freeze the browser in some situations. [#1895](https://github.com/Leaflet/Leaflet/issues/1895) [1866](https://github.com/Leaflet/Leaflet/issues/1866)
|
||||
* Fixed a bug where click on a map on a page with horizontal scroll caused the page to scroll right (by [@mstrelan](https://github.com/mstrelan)). [#1901](https://github.com/Leaflet/Leaflet/issues/1901)
|
||||
|
||||
## 0.6.3 (July 17, 2013)
|
||||
|
||||
|
138
FAQ.md
Normal file
138
FAQ.md
Normal file
@ -0,0 +1,138 @@
|
||||
# Leaflet FAQ
|
||||
|
||||
This is a collection of answers to the most frequently asked questions about Leaflet.
|
||||
|
||||
1. [Data Providers](#data-providers)
|
||||
2. [Commercial Use and Licensing](#commercial-use-and-licensing)
|
||||
3. [Features](#features)
|
||||
4. [Performance](#performance)
|
||||
5. [Misc](#misc)
|
||||
|
||||
## Data Providers
|
||||
|
||||
#### The map is wrong in my neighborhood, could you fix it?
|
||||
|
||||
Nope, but you can.
|
||||
The map you see on Leaflet examples is based on [OpenStreetMap](http://openstreetmap.org),
|
||||
a free editable map of the world.
|
||||
Signing up and editing the map there is easy,
|
||||
and the changes will be reflected on the map in a few minutes.
|
||||
|
||||
#### What map tiles can I use with Leaflet? Is it limited to OpenStreetMap?
|
||||
|
||||
Leaflet is provider-agnostic, meaning you can use any map provider as long as you conform to its terms of use.
|
||||
You can roll your own tiles as well.
|
||||
[OpenStreetMap](http://openstreetmap.org) is the most popular data source among different tile providers,
|
||||
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.
|
||||
Popular commercial options, free up to a particular number of requests, include
|
||||
[MapBox](http://mapbox.com),
|
||||
[CloudMade](http://cloudmade.com),
|
||||
[Bing Maps](http://www.microsoft.com/maps/choose-your-binge's-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.
|
||||
|
||||
Always be sure to **read the terms of use** of a chosen tile provider, **know its limitations**, and **attribute it properly** in your app.
|
||||
|
||||
#### I'm looking for satellite imagery to use with my Leaflet map, any options?
|
||||
|
||||
[MapBox](http://mapbox.com),
|
||||
[Bing Maps](http://www.microsoft.com/maps/choose-your-bing-maps-API.aspx),
|
||||
[ArcGIS](http://www.arcgis.com/features/maps/imagery.html)
|
||||
and [MapQuest Open](http://developer.mapquest.com/web/products/open/map) provide satellite imagery among others.
|
||||
|
||||
#### 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.
|
||||
|
||||
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.
|
||||
|
||||
#### I want to roll my own OSM tile server for Leaflet, where do I start?
|
||||
|
||||
Check out [this excellent guide](http://switch2osm.org/serving-tiles/).
|
||||
|
||||
#### I want to create tiles from my own data for use with Leaflet, what are the options?
|
||||
|
||||
There's a number of services that allow you to do this easily,
|
||||
notably [MapBox](https://www.mapbox.com/), [CartoDB](http://cartodb.com/) and [GIS Cloud](http://www.giscloud.com/).
|
||||
If you want to make tiles on your own, probably the easiest way is using [TileMill](https://www.mapbox.com/tilemill/).
|
||||
TileMill can export your map as a single [.mbtiles](https://www.mapbox.com/developers/mbtiles/) file, which can be copied to a webserver and accessed by Leaflet with [a small PHP script](https://github.com/infostreams/mbtiles-php).
|
||||
Alternatively, you can [extract](https://github.com/mapbox/mbutil) the tiled images from the .mbtiles database and place them directly on your webserver with absolutely no server-side dependencies.
|
||||
|
||||
## Commercial Use and Licensing
|
||||
|
||||
#### I have an app that gets lots of hits a day, and I want to switch from Google/Bing/whatever to Leaflet. Is there a fee for using it?
|
||||
|
||||
Leaflet, unlike Google Maps and other all-in-one solutions, is just a JavaScript library.
|
||||
It's free to use, but doesn't provide map imagery on its own —
|
||||
you have to choose a tile service to combine with it.
|
||||
|
||||
There are [plenty of options](#what-map-tiles-can-i-use-with-leaflet-is-it-limited-to-openstreetmap) for a tile service,
|
||||
each with their own terms of use, prices (some of them free), features, limitations, etc.
|
||||
Choice is yours.
|
||||
|
||||
#### I'm building a commercial app that I plan to sell. Can I use Leaflet in it?
|
||||
|
||||
You're welcome, as the code is published under the very permissive [2-clause BSD License](https://github.com/Leaflet/Leaflet/blob/master/LICENSE).
|
||||
Just make sure to attribute the use of the library somewhere in the app UI or the distribution
|
||||
(e.g. keep the Leaflet link on the map, or mention the use on the About page or a Readme file, etc.) and you'll be fine.
|
||||
|
||||
That only applies to the code though.
|
||||
Make sure you conform to the terms of use of the tile images provider(s) that you choose as well.
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
#### Why is there still no feature X in Leaflet?
|
||||
|
||||
First of all, did you check out the [Leaflet plugins page](http://leafletjs.com/plugins.html)?
|
||||
It lists about a hundred plugins doing all kinds of crazy stuff,
|
||||
and there's a high possibility that it has what you're looking for.
|
||||
|
||||
Generally, we do our best to keep the Leaflet core small, lightweight and simple,
|
||||
focusing on _quality_ instead of _quantity_, and leaving all the rest to plugin authors.
|
||||
|
||||
Check out [this video](http://www.youtube.com/watch?v=_P2SaCPbJ4w) of a talk by the Leaflet creator for more background on the story and philosophy behind Leaflet.
|
||||
Another essential read is [Advocating Simplicity in Open Source](http://blog.universalmind.com/advocating-simplicity-in-open-source/) by the same guy.
|
||||
|
||||
|
||||
## Performance
|
||||
|
||||
#### I have thousands of markers on my map. How do I make it faster and more usable?
|
||||
|
||||
Check out the [Leaflet.markercluster](https://github.com/Leaflet/Leaflet.markercluster) plugin. It's amazing.
|
||||
|
||||
#### I have vector data with many thousands of points on my map. Any performance tips?
|
||||
|
||||
Leaflet generally does a pretty good job of handling heavy vector data
|
||||
with its real-time clipping and simplification algorithms,
|
||||
but browser technology still has its limits.
|
||||
Try [switching from SVG to Canvas as the default rendering back-end](http://leafletjs.com/reference.html#global),
|
||||
it may help considerably (depends on the app and the data).
|
||||
|
||||
If you still have too much data to render, you'll have to use some help of a server-side service
|
||||
like [MapBox](https://www.mapbox.com/),
|
||||
[CartoDB](http://cartodb.com/)
|
||||
and [GIS Cloud](http://www.giscloud.com/)
|
||||
(they all work great with Leaflet).
|
||||
What they do under the hood is serving rendered data as image tiles,
|
||||
along with additional data to enable interactivity like hovering shapes
|
||||
(e.g. done using [UTFGrid](https://www.mapbox.com/developers/utfgrid/) —
|
||||
Leaflet [has a nice plugin](https://github.com/danzel/Leaflet.utfgrid) for it).
|
||||
|
||||
|
||||
## Misc
|
||||
|
||||
#### I downloaded the Leaflet source but didn't find `leaflet.js` there. Why is that?
|
||||
|
||||
You can download the built versions using links from the [download page](http://leafletjs.com/download.html).
|
||||
It even includes the latest build of the development version (`master` branch),
|
||||
updated automatically on each commit to the repo.
|
||||
|
||||
We removed the built versions from the repository because it's a chore to build and commit them manually on each change,
|
||||
and it often complicates merging branches and managing contributions.
|
||||
|
||||
There's a common complaint that Leaflet can't be used with [Bower](http://bower.io/) because of that, but we'll resolve the issue soon.
|
28
Jakefile.js
28
Jakefile.js
@ -14,13 +14,33 @@ For a custom build, open build/build.html in the browser and follow the instruct
|
||||
|
||||
var build = require('./build/build.js');
|
||||
|
||||
function hint(msg, paths) {
|
||||
return function () {
|
||||
console.log(msg);
|
||||
jake.exec('node node_modules/jshint/bin/jshint -c ' + paths,
|
||||
{printStdout: true}, function () {
|
||||
console.log('\tCheck passed.\n');
|
||||
complete();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
desc('Check Leaflet source for errors with JSHint');
|
||||
task('lint', build.lint);
|
||||
task('lint', {async: true}, hint('Checking for JS errors...', 'build/hintrc.js src'));
|
||||
|
||||
desc('Check Leaflet specs source for errors with JSHint');
|
||||
task('lintspec', {async: true}, hint('Checking for specs JS errors...', 'spec/spec.hintrc.js spec/suites'));
|
||||
|
||||
desc('Combine and compress Leaflet source files');
|
||||
task('build', ['lint'], build.build);
|
||||
task('build', build.build);
|
||||
|
||||
desc('Run PhantomJS tests');
|
||||
task('test', ['lint'], build.test);
|
||||
task('test', ['lint', 'lintspec'], {async: true}, function () {
|
||||
build.test(complete);
|
||||
});
|
||||
|
||||
task('default', ['build']);
|
||||
task('default', ['test', 'build']);
|
||||
|
||||
jake.addListener('complete', function () {
|
||||
process.exit();
|
||||
});
|
||||
|
18
README.md
18
README.md
@ -1,24 +1,23 @@
|
||||
<img src="http://leafletjs.com/docs/images/logo.png" alt="Leaflet" />
|
||||
|
||||
Leaflet is a modern open-source JavaScript library for **mobile-friendly interactive maps**.
|
||||
It is developed by [Vladimir Agafonkin][] with a team of dedicated [contributors][].
|
||||
Leaflet is an open source JavaScript library for **mobile-friendly interactive maps**.
|
||||
It is developed by [Vladimir Agafonkin][] of [MapBox][] with a team of dedicated [contributors][].
|
||||
Weighing just about 30 KB of gzipped JS code, it has all the [features][] most developers ever need for online maps.
|
||||
|
||||
Leaflet is designed with *simplicity*, *performance* and *usability* in mind.
|
||||
It works efficiently across all major desktop and mobile platforms out of the box,
|
||||
taking advantage of HTML5 and CSS3 on modern browsers while being accessible on older ones too.
|
||||
It can also be extended with many [plugins][],
|
||||
It can be extended with a huge amount of [plugins][],
|
||||
has a beautiful, easy to use and [well-documented][] API
|
||||
and a simple, readable [source code][] that is a joy to [contribute][] to.
|
||||
|
||||
For more information, check out the [official website][].
|
||||
For more info, docs and tutorials, check out the [official website][].<br>
|
||||
For **Leaflet downloads** (including the built master version), check out the [download page][].
|
||||
|
||||
We're happy to meet new contributors.
|
||||
If you want to **get involved** with Leaflet development, check out the [contribution guide][contribute].
|
||||
Let's make the best open-source library for maps that can possibly exist!
|
||||
|
||||
P.S. If you're looking for **Leaflet downloads** (including the built master version),
|
||||
check out the [Leaflet Download Page][].
|
||||
Let's make the best mapping library that will ever exist,
|
||||
and push the limits of what's possible with online maps!
|
||||
|
||||
[![Build Status](https://travis-ci.org/Leaflet/Leaflet.png?branch=master)](https://travis-ci.org/Leaflet/Leaflet)
|
||||
|
||||
@ -31,4 +30,5 @@ check out the [Leaflet Download Page][].
|
||||
[hosted on GitHub]: http://github.com/Leaflet/Leaflet
|
||||
[contribute]: https://github.com/Leaflet/Leaflet/blob/master/CONTRIBUTING.md "A guide to contributing to Leaflet"
|
||||
[official website]: http://leafletjs.com
|
||||
[Leaflet Download Page]: http://leafletjs.com/download.html
|
||||
[download page]: http://leafletjs.com/download.html
|
||||
[MapBox]: https://mapbox.com
|
||||
|
@ -86,21 +86,14 @@
|
||||
<li><a href="http://nodejs.org/#download">Download and install Node</a></li>
|
||||
<li>Run this in the command line:<br />
|
||||
<pre><code>npm install -g jake
|
||||
npm install jshint
|
||||
npm install uglify-js</code></pre></li>
|
||||
npm install</code></pre></li>
|
||||
<li>Run this command inside the Leaflet directory: <br /><input type="text" id="command2" />
|
||||
</ol>
|
||||
<h2>Building using Closure Compiler</h2>
|
||||
<ol>
|
||||
<li><a href="http://closure-compiler.googlecode.com/files/compiler-latest.zip">Download Closure Compiler</a>, extract it into <code>closure-compiler</code> directory</li>
|
||||
<li>Run this command in the root Leaflet directory: <br /><input type="text" id="command" /></li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var deplist = document.getElementById('deplist'),
|
||||
commandInput = document.getElementById('command'),
|
||||
commandInput2 = document.getElementById('command2');
|
||||
commandInput = document.getElementById('command2');
|
||||
|
||||
document.getElementById('select-all').onclick = function() {
|
||||
var checks = deplist.getElementsByTagName('input');
|
||||
@ -139,15 +132,7 @@ npm install uglify-js</code></pre></li>
|
||||
}
|
||||
}
|
||||
|
||||
var command = 'java -jar closure-compiler/compiler.jar ';
|
||||
for (var src in files) {
|
||||
command += '--js src/' + src + ' ';
|
||||
}
|
||||
command += '--js_output_file dist/leaflet-custom.js';
|
||||
|
||||
commandInput.value = command;
|
||||
|
||||
commandInput2.value = 'jake build[' + parseInt(compsStr, 2).toString(32) + ',custom]';
|
||||
commandInput.value = 'jake build[' + parseInt(compsStr, 2).toString(32) + ',custom]';
|
||||
}
|
||||
|
||||
function inputSelect() {
|
||||
@ -156,7 +141,6 @@ npm install uglify-js</code></pre></li>
|
||||
};
|
||||
|
||||
commandInput.onclick = inputSelect;
|
||||
commandInput2.onclick = inputSelect;
|
||||
|
||||
function onCheckboxChange() {
|
||||
if (this.checked) {
|
||||
|
@ -2,29 +2,7 @@ var fs = require('fs'),
|
||||
jshint = require('jshint'),
|
||||
UglifyJS = require('uglify-js'),
|
||||
|
||||
deps = require('./deps.js').deps,
|
||||
hintrc = require('./hintrc.js').config;
|
||||
|
||||
function lintFiles(files) {
|
||||
|
||||
var errorsFound = 0,
|
||||
i, j, len, len2, src, errors, e;
|
||||
|
||||
for (i = 0, len = files.length; i < len; i++) {
|
||||
|
||||
jshint.JSHINT(fs.readFileSync(files[i], 'utf8'), hintrc, i ? {L: true} : null);
|
||||
errors = jshint.JSHINT.errors;
|
||||
|
||||
for (j = 0, len2 = errors.length; j < len2; j++) {
|
||||
e = errors[j];
|
||||
console.log(files[i] + '\tline ' + e.line + '\tcol ' + e.character + '\t ' + e.reason);
|
||||
}
|
||||
|
||||
errorsFound += len2;
|
||||
}
|
||||
|
||||
return errorsFound;
|
||||
}
|
||||
deps = require('./deps.js').deps;
|
||||
|
||||
function getFiles(compsBase32) {
|
||||
var memo = {},
|
||||
@ -44,16 +22,18 @@ function getFiles(compsBase32) {
|
||||
for (var i in deps) {
|
||||
if (comps) {
|
||||
if (parseInt(comps.pop(), 2) === 1) {
|
||||
console.log('\t* ' + i);
|
||||
console.log(' * ' + i);
|
||||
addFiles(deps[i].src);
|
||||
} else {
|
||||
console.log('\t ' + i);
|
||||
console.log(' ' + i);
|
||||
}
|
||||
} else {
|
||||
addFiles(deps[i].src);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('');
|
||||
|
||||
var files = [];
|
||||
|
||||
for (var src in memo) {
|
||||
@ -65,23 +45,6 @@ function getFiles(compsBase32) {
|
||||
|
||||
exports.getFiles = getFiles;
|
||||
|
||||
exports.lint = function () {
|
||||
|
||||
var files = getFiles();
|
||||
|
||||
console.log('Checking for JS errors...');
|
||||
|
||||
var errorsFound = lintFiles(files);
|
||||
|
||||
if (errorsFound > 0) {
|
||||
console.log(errorsFound + ' error(s) found.\n');
|
||||
fail();
|
||||
} else {
|
||||
console.log('\tCheck passed');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function getSizeDelta(newContent, oldContent) {
|
||||
if (!oldContent) {
|
||||
return 'new';
|
||||
@ -129,10 +92,10 @@ exports.build = function (compsBase32, buildName) {
|
||||
console.log('\tUncompressed size: ' + newSrc.length + ' bytes (' + srcDelta + ')');
|
||||
|
||||
if (newSrc === oldSrc) {
|
||||
console.log('\tNo changes');
|
||||
console.log('\tNo changes\n');
|
||||
} else {
|
||||
fs.writeFileSync(srcPath, newSrc);
|
||||
console.log('\tSaved to ' + srcPath);
|
||||
console.log('\tSaved to ' + srcPath + '\n');
|
||||
}
|
||||
|
||||
console.log('Compressing...');
|
||||
@ -148,19 +111,23 @@ exports.build = function (compsBase32, buildName) {
|
||||
console.log('\tCompressed size: ' + newCompressed.length + ' bytes (' + delta + ')');
|
||||
|
||||
if (newCompressed === oldCompressed) {
|
||||
console.log('\tNo changes');
|
||||
console.log('\tNo changes\n');
|
||||
} else {
|
||||
fs.writeFileSync(path, newCompressed);
|
||||
console.log('\tSaved to ' + path);
|
||||
console.log('\tSaved to ' + path + '\n');
|
||||
}
|
||||
};
|
||||
|
||||
exports.test = function() {
|
||||
exports.test = function(callback) {
|
||||
var karma = require('karma'),
|
||||
testConfig = {configFile : __dirname + '/../spec/karma.conf.js'};
|
||||
|
||||
testConfig.browsers = ['PhantomJS'];
|
||||
|
||||
function isArgv(optName) {
|
||||
return process.argv.indexOf(optName) !== -1;
|
||||
}
|
||||
|
||||
if (isArgv('--chrome')) {
|
||||
testConfig.browsers.push('Chrome');
|
||||
}
|
||||
@ -185,9 +152,12 @@ exports.test = function() {
|
||||
testConfig.reporters = ['coverage'];
|
||||
}
|
||||
|
||||
karma.server.start(testConfig);
|
||||
console.log('Running tests...');
|
||||
|
||||
function isArgv(optName) {
|
||||
return process.argv.indexOf(optName) !== -1;
|
||||
}
|
||||
karma.server.start(testConfig, function(exitCode) {
|
||||
if (!exitCode) {
|
||||
console.log('\tTests ran successfully.\n');
|
||||
}
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
@ -151,7 +151,7 @@ var deps = {
|
||||
|
||||
GeoJSON: {
|
||||
src: ['layer/GeoJSON.js'],
|
||||
deps: ['Marker', 'MultiPoly', 'FeatureGroup'],
|
||||
deps: ['CircleMarker', 'Marker', 'MultiPoly', 'FeatureGroup'],
|
||||
desc: 'GeoJSON layer, parses the data and adds corresponding layers above.'
|
||||
},
|
||||
|
||||
@ -176,7 +176,7 @@ var deps = {
|
||||
TouchZoom: {
|
||||
src: ['dom/DomEvent.js',
|
||||
'dom/DomEvent.DoubleTap.js',
|
||||
'dom/DomEvent.MsTouch.js',
|
||||
'dom/DomEvent.Pointer.js',
|
||||
'core/Handler.js',
|
||||
'map/handler/Map.TouchZoom.js',
|
||||
'map/handler/Map.Tap.js'],
|
||||
@ -231,6 +231,7 @@ var deps = {
|
||||
'dom/PosAnimation.js',
|
||||
'map/anim/Map.PanAnimation.js'
|
||||
],
|
||||
heading: 'Animation',
|
||||
desc: 'Core panning animation support.'
|
||||
},
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
exports.config = {
|
||||
|
||||
{
|
||||
// environment
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"predef": ['define'],
|
||||
"globals": {
|
||||
"L": true,
|
||||
"define": true
|
||||
},
|
||||
"strict": false,
|
||||
|
||||
// code style
|
||||
@ -34,4 +36,4 @@ exports.config = {
|
||||
// "maxcomplexity": 5
|
||||
// "maxparams": 4,
|
||||
// "maxdepth": 4
|
||||
};
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1 maximum-scale=1.0 user-scalable=0">
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
@ -4,10 +4,9 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
<script src="../leaflet-include.js"></script>
|
||||
</head>
|
||||
@ -18,18 +17,18 @@
|
||||
<script type="text/javascript">
|
||||
|
||||
var tiles = new L.TileLayer.Canvas();
|
||||
|
||||
|
||||
tiles.drawTile = function(canvas, tile, zoom) {
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillRect(0, 0, 255, 255);
|
||||
|
||||
|
||||
|
||||
|
||||
ctx.fillStyle = 'black';
|
||||
ctx.fillText('x: ' + tile.x + ', y: ' + tile.y + ', zoom:' + zoom, 20, 20);
|
||||
|
||||
|
||||
|
||||
|
||||
ctx.strokeStyle = 'red';
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, 0);
|
||||
@ -39,9 +38,9 @@
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
|
||||
var map = new L.Map('map', {center: new L.LatLng(50.5, 30.51), zoom: 15, layers: [tiles]});
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet geolocation debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/mobile.css" />
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
@ -22,7 +21,7 @@
|
||||
|
||||
var cloudmade = L.tileLayer('http://{s}.tile.cloudmade.com/{key}/997/256/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade',
|
||||
attribution: 'Map data © 2011 <a href="#">OpenStreetMap</a> contributors, Imagery © 2011 <a href="#">CloudMade</a>',
|
||||
key: 'd4fc77ea4a63471cab2423e66626cbb6'
|
||||
});
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/mobile.css" />
|
||||
|
||||
@ -31,6 +30,8 @@
|
||||
maxBounds: bounds
|
||||
});
|
||||
|
||||
var latlngs = L.rectangle(bounds).getLatLngs();
|
||||
L.polyline(latlngs.concat([latlngs[0]])).addTo(map);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
@ -4,10 +4,9 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
<script src="../leaflet-include.js"></script>
|
||||
</head>
|
||||
@ -17,7 +16,7 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
var map = new L.Map('map', {crs: L.CRS.EPSG4326});
|
||||
|
||||
|
||||
var bluemarble = new L.TileLayer.WMS("http://maps.opengeo.org/geowebcache/service/wms", {
|
||||
layers: 'bluemarble',
|
||||
attribution: "Data © NASA Blue Marble, image service by OpenGeo",
|
||||
@ -28,4 +27,4 @@
|
||||
map.addLayer(bluemarble).fitWorld();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.0.js'></script>
|
||||
@ -32,7 +31,7 @@
|
||||
map.addLayer(osm);
|
||||
map.fitBounds(new L.LatLngBounds([51,7],[51,7]));
|
||||
drawTestLine();
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
@ -46,19 +45,19 @@
|
||||
function (e) {
|
||||
popup = new L.Popup();
|
||||
popup.setLatLng(this.getLatLng());
|
||||
|
||||
|
||||
var popuptxt = "Hello!";
|
||||
alert("I am the click function");
|
||||
popup.setContent(popuptxt);
|
||||
|
||||
map.openPopup(popup);
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
myLayerGroup.addLayer(myCircle);
|
||||
lat = lat + 0.0001;
|
||||
long = long + 0.0001;
|
||||
|
||||
|
||||
}
|
||||
|
||||
map.addLayer(myLayerGroup);
|
||||
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
|
@ -1,7 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
<script>
|
||||
L_PREFER_CANVAS = true;
|
||||
</script>
|
||||
@ -45,4 +44,4 @@
|
||||
<script src="../leaflet-include.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.0.js'></script>
|
||||
|
61
debug/tests/dragging_and_copyworldjump.html
Normal file
61
debug/tests/dragging_and_copyworldjump.html
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
<script src="../leaflet-include.js"></script>
|
||||
<script type='text/javascript' src='http://code.jquery.com/jquery-1.8.0.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
On the left Map dragging and worldCopyJump are enabled during initialisation.<br>
|
||||
On the right Map worldCopyJump is enabled. Dragging is enabled by clicking the button.
|
||||
</p>
|
||||
<button id="foo">
|
||||
Click to enable dragging on the right map, then dragging around and watch copying
|
||||
</button><br>
|
||||
<div id="map1" style="height: 300px;width: 400px; float:left;"></div>
|
||||
<div id="map2" style="height: 300px;width: 400px; float:left; margin-left: 10px;"></div>
|
||||
<div style="clear:both"></div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
function addLayerAndMarker(map) {
|
||||
var layer = new L.TileLayer('http://{s}.tile.cloudmade.com/d4fc77ea4a63471cab2423e66626cbb6/997/256/{z}/{x}/{y}.png', {
|
||||
maxZoom : 18
|
||||
}).addTo(map);
|
||||
|
||||
var marker = L.marker([50.5, 30.5]).addTo(map);
|
||||
|
||||
}
|
||||
var map1 = new L.Map('map1', {
|
||||
center : new L.LatLng(45.50144, -122.67599),
|
||||
zoom : 0,
|
||||
dragging : true,
|
||||
worldCopyJump : true
|
||||
});
|
||||
var map2 = new L.Map('map2', {
|
||||
center : new L.LatLng(45.50144, -122.67599),
|
||||
zoom : 0,
|
||||
dragging : false,
|
||||
worldCopyJump : true
|
||||
});
|
||||
$("#foo").click(function() {
|
||||
map2.dragging.enable();
|
||||
});
|
||||
|
||||
|
||||
|
||||
addLayerAndMarker(map1);
|
||||
addLayerAndMarker(map2);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/mobile.css" />
|
||||
<style>
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
|
@ -4,10 +4,9 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
<script src="../leaflet-include.js"></script>
|
||||
</head>
|
||||
@ -23,7 +22,7 @@
|
||||
setTimeout(function() {
|
||||
map.removeLayer(marker);
|
||||
}, 3000);
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
|
42
debug/tests/rtl.html
Normal file
42
debug/tests/rtl.html
Normal file
@ -0,0 +1,42 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
<script src="../leaflet-include.js"></script>
|
||||
<style>
|
||||
body {
|
||||
direction: rtl;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>Click the map to place a popup at the mouse location</p>
|
||||
<div id="map"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var cloudmade = L.tileLayer('http://{s}.tile.cloudmade.com/{key}/997/256/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade',
|
||||
key: 'd4fc77ea4a63471cab2423e66626cbb6'
|
||||
});
|
||||
|
||||
var map = L.map('map')
|
||||
.setView([50.5, 30.51], 15)
|
||||
.addLayer(cloudmade);
|
||||
|
||||
map.on('click', function(e) {
|
||||
L.popup().setLatLng(e.latlng).setContent('Hello').openOn(map);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
27
debug/tests/rtl2.html
Normal file
27
debug/tests/rtl2.html
Normal file
@ -0,0 +1,27 @@
|
||||
<html dir="rtl">
|
||||
<head>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<link rel="stylesheet" href="../css/mobile.css" />
|
||||
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
<script src="../leaflet-include.js"></script>
|
||||
<style>
|
||||
#map { height: 100%; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<script>
|
||||
var map = L.map('map').setView([51.505, -0.09], 13);
|
||||
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
|
||||
map.on('click', function(e) {
|
||||
L.popup().setLatLng(e.latlng).setContent('Hello').openOn(map);
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -2,18 +2,17 @@
|
||||
<head>
|
||||
<title>Test for preservation of Icon DOM element</title>
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
<script src="../leaflet-include.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map" style="width: 600px; height: 600px; border: 1px solid #ccc"></div>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
var blueIcon = new L.Icon({iconUrl: 'http://www.webatlas.no/webatlasapi/v/071009/media/interface/default/markers/flag_blue.gif'});
|
||||
var redIcon = new L.Icon({iconUrl: 'http://www.webatlas.no/webatlasapi/v/071009/media/interface/default/markers/flag_red.gif'});
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
@ -33,7 +32,7 @@
|
||||
var osm = new L.TileLayer(osmUrl, { minZoom: 1, maxZoom: 17 });
|
||||
map.addLayer(osm);
|
||||
map.fitBounds(new L.LatLngBounds([51,7],[51,7]));
|
||||
|
||||
|
||||
var route = L.polyline([
|
||||
[51, 7.000],
|
||||
[51.002, 7.004],
|
||||
@ -45,8 +44,8 @@
|
||||
[51.002, 7.004]
|
||||
],
|
||||
{ clickable:false,color:'#f00' }
|
||||
).addTo(map);
|
||||
|
||||
).addTo(map);
|
||||
|
||||
// when the mouse hovers over the red route2, you cannot click through the blue route1 beneath
|
||||
};
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
<script src="../leaflet-include.js"></script>
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
@ -24,7 +23,7 @@
|
||||
//console.log = function (text) {
|
||||
// buffer += text + "\r\n";
|
||||
//}
|
||||
|
||||
|
||||
var cloudmadeUrl = 'http://{s}.tile.cloudmade.com/d4fc77ea4a63471cab2423e66626cbb6/997/256/{z}/{x}/{y}.png',
|
||||
cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18}),
|
||||
map = new L.Map('map', {layers: [cloudmade], center: new L.LatLng(51.505, -0.04), zoom: 13});
|
||||
@ -157,7 +156,7 @@
|
||||
}
|
||||
_timerAt++;
|
||||
}
|
||||
|
||||
|
||||
function Hack4() {
|
||||
_timerAt = 0;
|
||||
clearInterval(_timer);
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/mobile.css" />
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/mobile.css" />
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Leaflet debug page</title>
|
||||
|
||||
<link rel="stylesheet" href="../../dist/leaflet.css" />
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="../../dist/leaflet.ie.css" /><![endif]-->
|
||||
|
||||
<link rel="stylesheet" href="../css/screen.css" />
|
||||
<script type="text/javascript" src="../../build/deps.js"></script>
|
||||
|
129
dist/leaflet.css
vendored
129
dist/leaflet.css
vendored
@ -65,6 +65,16 @@
|
||||
.leaflet-marker-pane { z-index: 6; }
|
||||
.leaflet-popup-pane { z-index: 7; }
|
||||
|
||||
.leaflet-vml-shape {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.lvml {
|
||||
behavior: url(#default#VML);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
||||
/* control positioning */
|
||||
|
||||
@ -160,9 +170,8 @@
|
||||
.leaflet-control {
|
||||
cursor: auto;
|
||||
}
|
||||
.leaflet-dragging,
|
||||
.leaflet-dragging .leaflet-clickable,
|
||||
.leaflet-dragging .leaflet-container {
|
||||
.leaflet-dragging .leaflet-container,
|
||||
.leaflet-dragging .leaflet-clickable {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
@ -182,9 +191,8 @@
|
||||
outline: 2px solid orange;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
border: 2px dotted #05f;
|
||||
background: white;
|
||||
opacity: 0.5;
|
||||
border: 2px dotted #38f;
|
||||
background: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
|
||||
@ -197,11 +205,11 @@
|
||||
/* general toolbar styles */
|
||||
|
||||
.leaflet-bar {
|
||||
box-shadow: 0 1px 7px rgba(0,0,0,0.65);
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a, .leaflet-bar a:hover {
|
||||
.leaflet-bar a,
|
||||
.leaflet-bar a:hover {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ccc;
|
||||
width: 26px;
|
||||
@ -222,16 +230,12 @@
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.leaflet-bar a:first-child {
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a:last-child {
|
||||
-webkit-border-bottom-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
-webkit-border-bottom-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom: none;
|
||||
}
|
||||
.leaflet-bar a.leaflet-disabled {
|
||||
@ -240,55 +244,38 @@
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-bar {
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:first-child {
|
||||
-webkit-border-top-left-radius: 7px;
|
||||
border-top-left-radius: 7px;
|
||||
-webkit-border-top-right-radius: 7px;
|
||||
border-top-right-radius: 7px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:last-child {
|
||||
-webkit-border-bottom-left-radius: 7px;
|
||||
border-bottom-left-radius: 7px;
|
||||
-webkit-border-bottom-right-radius: 7px;
|
||||
border-bottom-right-radius: 7px;
|
||||
border-bottom: none;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
|
||||
/* zoom control */
|
||||
|
||||
.leaflet-control-zoom-in {
|
||||
.leaflet-control-zoom-in,
|
||||
.leaflet-control-zoom-out {
|
||||
font: bold 18px 'Lucida Console', Monaco, monospace;
|
||||
text-indent: 1px;
|
||||
}
|
||||
.leaflet-control-zoom-out {
|
||||
font: bold 22px 'Lucida Console', Monaco, monospace;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-zoom-in {
|
||||
font-size: 22px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-zoom-out {
|
||||
font-size: 28px;
|
||||
line-height: 30px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
|
||||
/* layers control */
|
||||
|
||||
.leaflet-control-layers {
|
||||
box-shadow: 0 1px 7px rgba(0,0,0,0.4);
|
||||
background: #f8f8f9;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers.png);
|
||||
@ -334,8 +321,8 @@
|
||||
/* attribution and scale controls */
|
||||
|
||||
.leaflet-container .leaflet-control-attribution {
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
box-shadow: 0 0 5px #bbb;
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
margin: 0;
|
||||
}
|
||||
.leaflet-control-attribution,
|
||||
@ -343,6 +330,12 @@
|
||||
padding: 0 5px;
|
||||
color: #333;
|
||||
}
|
||||
.leaflet-control-attribution a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.leaflet-control-attribution a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.leaflet-container .leaflet-control-attribution,
|
||||
.leaflet-container .leaflet-control-scale {
|
||||
font-size: 11px;
|
||||
@ -356,21 +349,21 @@
|
||||
.leaflet-control-scale-line {
|
||||
border: 2px solid #777;
|
||||
border-top: none;
|
||||
color: black;
|
||||
line-height: 1.1;
|
||||
padding: 2px 5px 1px;
|
||||
font-size: 11px;
|
||||
text-shadow: 1px 1px 1px #fff;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.2);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child) {
|
||||
border-top: 2px solid #777;
|
||||
border-bottom: none;
|
||||
margin-top: -2px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
||||
border-bottom: 2px solid #777;
|
||||
@ -383,7 +376,8 @@
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
border: 4px solid rgba(0,0,0,0.3);
|
||||
border: 2px solid rgba(0,0,0,0.2);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
|
||||
@ -396,8 +390,7 @@
|
||||
.leaflet-popup-content-wrapper {
|
||||
padding: 1px;
|
||||
text-align: left;
|
||||
-webkit-border-radius: 12px;
|
||||
border-radius: 12px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.leaflet-popup-content {
|
||||
margin: 13px 19px;
|
||||
@ -426,7 +419,8 @@
|
||||
-o-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
|
||||
.leaflet-popup-content-wrapper,
|
||||
.leaflet-popup-tip {
|
||||
background: white;
|
||||
|
||||
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
||||
@ -454,6 +448,27 @@
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper {
|
||||
zoom: 1;
|
||||
}
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
width: 24px;
|
||||
margin: 0 auto;
|
||||
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
||||
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
||||
}
|
||||
.leaflet-oldie .leaflet-popup-tip-container {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-control-zoom,
|
||||
.leaflet-oldie .leaflet-control-layers,
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper,
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
|
||||
/* div icon */
|
||||
|
||||
@ -461,7 +476,3 @@
|
||||
background: #fff;
|
||||
border: 1px solid #666;
|
||||
}
|
||||
.leaflet-editing-icon {
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
51
dist/leaflet.ie.css
vendored
51
dist/leaflet.ie.css
vendored
@ -1,51 +0,0 @@
|
||||
.leaflet-vml-shape {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.lvml {
|
||||
behavior: url(#default#VML);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.leaflet-control {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.leaflet-popup-tip {
|
||||
width: 21px;
|
||||
_width: 27px;
|
||||
margin: 0 auto;
|
||||
_margin-top: -3px;
|
||||
|
||||
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
||||
}
|
||||
.leaflet-popup-tip-container {
|
||||
margin-top: -1px;
|
||||
}
|
||||
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
|
||||
border: 1px solid #999;
|
||||
}
|
||||
.leaflet-popup-content-wrapper {
|
||||
zoom: 1;
|
||||
}
|
||||
|
||||
.leaflet-control-zoom,
|
||||
.leaflet-control-layers {
|
||||
border: 3px solid #999;
|
||||
}
|
||||
.leaflet-control-layers-toggle {
|
||||
}
|
||||
.leaflet-control-attribution,
|
||||
.leaflet-control-layers,
|
||||
.leaflet-control-scale-line {
|
||||
background: white;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
filter: alpha(opacity=50);
|
||||
}
|
||||
.leaflet-control-attribution {
|
||||
border-top: 1px solid #bbb;
|
||||
border-left: 1px solid #bbb;
|
||||
}
|
46
package.json
46
package.json
@ -1,23 +1,27 @@
|
||||
{
|
||||
"name": "leaflet",
|
||||
"version": "0.6.4",
|
||||
"description": "JavaScript library for mobile-friendly interactive maps",
|
||||
"devDependencies": {
|
||||
"jshint": "~2.1.4",
|
||||
"mocha": "~1.10.0",
|
||||
"happen": "~0.1.2",
|
||||
"karma": "~0.8.6",
|
||||
"uglify-js": "~2.3.6",
|
||||
"jake": "~0.5.16"
|
||||
},
|
||||
"main": "dist/leaflet.js",
|
||||
"scripts": {
|
||||
"test": "jake test",
|
||||
"prepublish": "jake"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/Leaflet/Leaflet.git"
|
||||
},
|
||||
"keywords": ["gis", "map"]
|
||||
"name": "leaflet",
|
||||
"version": "0.7.0",
|
||||
"description": "JavaScript library for mobile-friendly interactive maps",
|
||||
"devDependencies": {
|
||||
"jake": "~0.7.4",
|
||||
"jshint": "~2.3.0",
|
||||
"uglify-js": "~2.4.3",
|
||||
"mocha": "~1.14.0",
|
||||
"happen": "~0.1.3",
|
||||
"karma": "~0.10.4",
|
||||
"karma-mocha": "~0.1.0"
|
||||
},
|
||||
"main": "dist/leaflet-src.js",
|
||||
"scripts": {
|
||||
"test": "jake test",
|
||||
"prepublish": "jake build"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/Leaflet/Leaflet.git"
|
||||
},
|
||||
"keywords": [
|
||||
"gis",
|
||||
"map"
|
||||
]
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
// put after Leaflet files as imagePath can't be detected in a PhantomJS env
|
||||
L.Icon.Default.imagePath = "../dist/images";
|
||||
L.Icon.Default.imagePath = "/base/dist/images";
|
||||
|
@ -1,15 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Spec Runner</title>
|
||||
<meta charset="utf-8">
|
||||
<title>Leaflet Spec Runner</title>
|
||||
<link rel="stylesheet" type="text/css" href="../node_modules/mocha/mocha.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script src="expect.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/mocha/mocha.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/happen/src/happen.js"></script>
|
||||
<div id="mocha"></div>
|
||||
<script src="expect.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/mocha/mocha.js"></script>
|
||||
<script type="text/javascript" src="../node_modules/happen/happen.js"></script>
|
||||
<script type="text/javascript" src="sinon.js"></script>
|
||||
|
||||
<!-- source files -->
|
||||
@ -18,10 +18,12 @@
|
||||
|
||||
<script type="text/javascript" src="../debug/leaflet-include.js"></script>
|
||||
|
||||
<script>
|
||||
mocha.setup('bdd');
|
||||
mocha.ignoreLeaks();
|
||||
</script>
|
||||
<script>
|
||||
mocha.setup({
|
||||
ui: 'bdd',
|
||||
ignoreLeaks: true
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- spec files -->
|
||||
|
||||
@ -74,8 +76,11 @@
|
||||
<!-- /map -->
|
||||
<script type="text/javascript" src="suites/map/MapSpec.js"></script>
|
||||
|
||||
<script>
|
||||
(window.mochaPhantomJS || window.mocha).run();
|
||||
</script>
|
||||
<!-- /map/handler -->
|
||||
<script type="text/javascript" src="suites/map/handler/Map.DragSpec.js"></script>
|
||||
|
||||
<script>
|
||||
(window.mochaPhantomJS || window.mocha).run();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,64 +1,65 @@
|
||||
// Karma configuration
|
||||
var libSources = require(__dirname+'/../build/build.js').getFiles();
|
||||
module.exports = function (config) {
|
||||
|
||||
// base path, that will be used to resolve files and exclude
|
||||
basePath = '';
|
||||
var libSources = require(__dirname+'/../build/build.js').getFiles();
|
||||
|
||||
for (var i=0; i < libSources.length; i++) {
|
||||
libSources[i] = "../" + libSources[i];
|
||||
}
|
||||
var files = [
|
||||
"spec/before.js",
|
||||
"spec/sinon.js",
|
||||
"spec/expect.js"
|
||||
].concat(libSources, [
|
||||
"spec/after.js",
|
||||
"node_modules/happen/happen.js",
|
||||
"spec/suites/SpecHelper.js",
|
||||
"spec/suites/**/*.js",
|
||||
{pattern: "dist/images/*.png", included: false}
|
||||
]);
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files = [].concat([
|
||||
"../node_modules/mocha/mocha.js",
|
||||
MOCHA_ADAPTER,
|
||||
"before.js",
|
||||
"sinon.js",
|
||||
"expect.js"
|
||||
], libSources, [
|
||||
"after.js",
|
||||
"../node_modules/happen/src/happen.js",
|
||||
"suites/SpecHelper.js",
|
||||
"suites/**/*.js"
|
||||
]);
|
||||
config.set({
|
||||
// base path, that will be used to resolve files and exclude
|
||||
basePath: '../',
|
||||
|
||||
// list of files to exclude
|
||||
exclude = [
|
||||
];
|
||||
plugins: ['karma-mocha', 'karma-phantomjs-launcher', 'karma-chrome-launcher'],
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress', 'junit'
|
||||
reporters = ['dots'];
|
||||
// frameworks to use
|
||||
frameworks: ['mocha'],
|
||||
|
||||
// web server port
|
||||
port = 8080;
|
||||
// list of files / patterns to load in the browser
|
||||
files: files,
|
||||
exclude: [],
|
||||
|
||||
// cli runner port
|
||||
runnerPort = 9100;
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
|
||||
reporters: ['dots'],
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors = true;
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
// level of logging
|
||||
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
|
||||
logLevel = LOG_WARN;
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_WARN,
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch = false;
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
// Start these browsers, currently available:
|
||||
// - Chrome
|
||||
// - ChromeCanary
|
||||
// - Firefox
|
||||
// - Opera
|
||||
// - Safari (only Mac)
|
||||
// - PhantomJS
|
||||
// - IE (only Windows)
|
||||
browsers = ['PhantomJS'];
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: false,
|
||||
|
||||
// If browser does not capture in given timeout [ms], kill it
|
||||
captureTimeout = 5000;
|
||||
// Start these browsers, currently available:
|
||||
// - Chrome
|
||||
// - ChromeCanary
|
||||
// - Firefox
|
||||
// - Opera
|
||||
// - Safari (only Mac)
|
||||
// - PhantomJS
|
||||
// - IE (only Windows)
|
||||
browsers: ['PhantomJS'],
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, it capture browsers, run tests and exit
|
||||
singleRun = true;
|
||||
// If browser does not capture in given timeout [ms], kill it
|
||||
captureTimeout: 5000,
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, it capture browsers, run tests and exit
|
||||
singleRun: true
|
||||
});
|
||||
};
|
||||
|
25
spec/spec.hintrc.js
Normal file
25
spec/spec.hintrc.js
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"predef": ["define", "L", "expect", "describe", "it", "sinon", "happen", "beforeEach", "afterEach"],
|
||||
"strict": false,
|
||||
"bitwise": true,
|
||||
"camelcase": true,
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"forin": false,
|
||||
"immed": true,
|
||||
"latedef": true,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"noempty": true,
|
||||
"nonew": true,
|
||||
"undef": true,
|
||||
// "unused": true,
|
||||
// "quotmark": "single",
|
||||
"indent": 4,
|
||||
"trailing": true,
|
||||
"white": true,
|
||||
"smarttabs": true
|
||||
// "maxlen": 120
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
describe('L#noConflict', function() {
|
||||
it('restores the previous L value and returns Leaflet namespace', function(){
|
||||
describe('L#noConflict', function () {
|
||||
it('restores the previous L value and returns Leaflet namespace', function () {
|
||||
|
||||
expect(L.version).to.be.ok();
|
||||
|
||||
|
@ -1,26 +1,42 @@
|
||||
function noSpecs() {
|
||||
xit('has no specs');
|
||||
if (!Array.prototype.map) {
|
||||
Array.prototype.map = function (fun /*, thisp */) {
|
||||
"use strict";
|
||||
|
||||
if (this === void 0 || this === null) {
|
||||
throw new TypeError();
|
||||
}
|
||||
|
||||
var t = Object(this);
|
||||
// jshint bitwise: false
|
||||
var len = t.length >>> 0;
|
||||
if (typeof fun !== "function") {
|
||||
throw new TypeError();
|
||||
}
|
||||
|
||||
var res = new Array(len);
|
||||
var thisp = arguments[1];
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (i in t) {
|
||||
res[i] = fun.call(thisp, t[i], i, t);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
if (!Array.prototype.map) {
|
||||
Array.prototype.map = function(fun /*, thisp */) {
|
||||
"use strict";
|
||||
expect.Assertion.prototype.near = function (expected, delta) {
|
||||
delta = delta || 1;
|
||||
expect(this.obj.x).to
|
||||
.be.within(expected.x - delta, expected.x + delta);
|
||||
expect(this.obj.y).to
|
||||
.be.within(expected.y - delta, expected.y + delta);
|
||||
};
|
||||
|
||||
if (this === void 0 || this === null)
|
||||
throw new TypeError();
|
||||
|
||||
var t = Object(this);
|
||||
var len = t.length >>> 0;
|
||||
if (typeof fun !== "function")
|
||||
throw new TypeError();
|
||||
|
||||
var res = new Array(len);
|
||||
var thisp = arguments[1];
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (i in t)
|
||||
res[i] = fun.call(thisp, t[i], i, t);
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
}
|
||||
expect.Assertion.prototype.nearLatLng = function (expected, delta) {
|
||||
delta = delta || 1e-4;
|
||||
expect(this.obj.lat).to
|
||||
.be.within(expected.lat - delta, expected.lat + delta);
|
||||
expect(this.obj.lng).to
|
||||
.be.within(expected.lng - delta, expected.lng + delta);
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ describe("Control.Layers", function () {
|
||||
spy = sinon.spy();
|
||||
|
||||
map.on('baselayerchange', spy)
|
||||
.whenReady(function() {
|
||||
.whenReady(function () {
|
||||
happen.click(layers._baseLayersList.getElementsByTagName("input")[0]);
|
||||
|
||||
expect(spy.called).to.be.ok();
|
||||
|
@ -1,11 +1,11 @@
|
||||
describe("Class", function() {
|
||||
describe("Class", function () {
|
||||
|
||||
describe("#extend", function() {
|
||||
describe("#extend", function () {
|
||||
var Klass,
|
||||
constructor,
|
||||
method;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
constructor = sinon.spy();
|
||||
method = sinon.spy();
|
||||
|
||||
@ -19,7 +19,7 @@ describe("Class", function() {
|
||||
});
|
||||
});
|
||||
|
||||
it("creates a class with the given constructor & properties", function() {
|
||||
it("creates a class with the given constructor & properties", function () {
|
||||
var a = new Klass();
|
||||
|
||||
expect(constructor.called).to.be.ok();
|
||||
@ -30,7 +30,7 @@ describe("Class", function() {
|
||||
expect(method.called).to.be.ok();
|
||||
});
|
||||
|
||||
it("inherits parent classes' constructor & properties", function() {
|
||||
it("inherits parent classes' constructor & properties", function () {
|
||||
var Klass2 = Klass.extend({baz: 2});
|
||||
|
||||
var b = new Klass2();
|
||||
@ -46,28 +46,28 @@ describe("Class", function() {
|
||||
expect(method.called).to.be.ok();
|
||||
});
|
||||
|
||||
it("supports static properties", function() {
|
||||
it("supports static properties", function () {
|
||||
expect(Klass.bla).to.eql(1);
|
||||
});
|
||||
|
||||
it("inherits parent static properties", function() {
|
||||
it("inherits parent static properties", function () {
|
||||
var Klass2 = Klass.extend({});
|
||||
|
||||
expect(Klass2.bla).to.eql(1);
|
||||
});
|
||||
|
||||
it("overrides parent static properties", function() {
|
||||
it("overrides parent static properties", function () {
|
||||
var Klass2 = Klass.extend({statics: {bla: 2}});
|
||||
|
||||
expect(Klass2.bla).to.eql(2);
|
||||
});
|
||||
|
||||
it("includes the given mixin", function() {
|
||||
it("includes the given mixin", function () {
|
||||
var a = new Klass();
|
||||
expect(a.mixin).to.be.ok();
|
||||
});
|
||||
|
||||
it("includes multiple mixins", function() {
|
||||
it("includes multiple mixins", function () {
|
||||
var Klass2 = L.Class.extend({
|
||||
includes: [{mixin: true}, {mixin2: true}]
|
||||
});
|
||||
@ -77,14 +77,14 @@ describe("Class", function() {
|
||||
expect(a.mixin2).to.be.ok();
|
||||
});
|
||||
|
||||
it("grants the ability to include the given mixin", function() {
|
||||
it("grants the ability to include the given mixin", function () {
|
||||
Klass.include({mixin2: true});
|
||||
|
||||
var a = new Klass();
|
||||
expect(a.mixin2).to.be.ok();
|
||||
});
|
||||
|
||||
it("merges options instead of replacing them", function() {
|
||||
it("merges options instead of replacing them", function () {
|
||||
var KlassWithOptions1 = L.Class.extend({
|
||||
options: {
|
||||
foo1: 1,
|
||||
|
@ -1,21 +1,21 @@
|
||||
describe('Events', function() {
|
||||
describe('Events', function () {
|
||||
var Klass;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
Klass = L.Class.extend({
|
||||
includes: L.Mixin.Events
|
||||
});
|
||||
});
|
||||
|
||||
describe('#fireEvent', function() {
|
||||
describe('#fireEvent', function () {
|
||||
|
||||
it('fires all listeners added through #addEventListener', function() {
|
||||
it('fires all listeners added through #addEventListener', function () {
|
||||
var obj = new Klass(),
|
||||
spy1 = sinon.spy(),
|
||||
spy2 = sinon.spy(),
|
||||
spy3 = sinon.spy(),
|
||||
spy4 = sinon.spy(),
|
||||
spy5 = sinon.spy();
|
||||
spy5 = sinon.spy(),
|
||||
spy6 = sinon.spy();
|
||||
|
||||
obj.addEventListener('test', spy1);
|
||||
@ -42,7 +42,7 @@ describe('Events', function() {
|
||||
expect(spy6.callCount).to.be(1);
|
||||
});
|
||||
|
||||
it('provides event object to listeners and executes them in the right context', function() {
|
||||
it('provides event object to listeners and executes them in the right context', function () {
|
||||
var obj = new Klass(),
|
||||
obj2 = new Klass(),
|
||||
obj3 = new Klass(),
|
||||
@ -88,7 +88,7 @@ describe('Events', function() {
|
||||
obj4.fireEvent('test', {baz: 4});
|
||||
});
|
||||
|
||||
it('calls no listeners removed through #removeEventListener', function() {
|
||||
it('calls no listeners removed through #removeEventListener', function () {
|
||||
var obj = new Klass(),
|
||||
spy = sinon.spy(),
|
||||
spy2 = sinon.spy(),
|
||||
@ -171,7 +171,7 @@ describe('Events', function() {
|
||||
expect(spy2.called).to.be(true);
|
||||
});
|
||||
|
||||
it('removes listeners with a stamp originally added without one', function() {
|
||||
it('removes listeners with a stamp originally added without one', function () {
|
||||
var obj = new Klass(),
|
||||
spy1 = sinon.spy(),
|
||||
spy2 = sinon.spy(),
|
||||
@ -190,6 +190,29 @@ describe('Events', function() {
|
||||
expect(spy2.called).to.be(false);
|
||||
});
|
||||
|
||||
it('removes listeners with context == this and a stamp originally added without one', function () {
|
||||
var obj = new Klass(),
|
||||
obj2 = new Klass(),
|
||||
spy1 = sinon.spy(),
|
||||
spy2 = sinon.spy(),
|
||||
spy3 = sinon.spy();
|
||||
|
||||
obj.addEventListener('test', spy1, obj);
|
||||
L.Util.stamp(obj);
|
||||
obj.addEventListener('test', spy2, obj);
|
||||
obj.addEventListener('test', spy3, obj2); // So that there is a contextId based listener, otherwise removeEventListener will do correct behaviour anyway
|
||||
|
||||
obj.removeEventListener('test', spy1, obj);
|
||||
obj.removeEventListener('test', spy2, obj);
|
||||
obj.removeEventListener('test', spy3, obj2);
|
||||
|
||||
obj.fireEvent('test');
|
||||
|
||||
expect(spy1.called).to.be(false);
|
||||
expect(spy2.called).to.be(false);
|
||||
expect(spy3.called).to.be(false);
|
||||
});
|
||||
|
||||
it('doesnt lose track of listeners when removing non existent ones', function () {
|
||||
var obj = new Klass(),
|
||||
spy = sinon.spy(),
|
||||
@ -212,20 +235,42 @@ describe('Events', function() {
|
||||
expect(spy.called).to.be(false);
|
||||
});
|
||||
|
||||
it('makes sure an event is not triggered if a listener is removed during dispatch',function() {
|
||||
it('correctly removes all listeners if given no fn', function () {
|
||||
var obj = new Klass(),
|
||||
spy = sinon.spy(),
|
||||
foo = {},
|
||||
foo2 = {},
|
||||
foo3 = {};
|
||||
|
||||
obj.addEventListener('test', spy, foo2);
|
||||
obj.addEventListener('test', spy, foo3);
|
||||
|
||||
obj.removeEventListener('test'); // Removes both of the above listeners
|
||||
|
||||
expect(obj.hasEventListeners('test')).to.be(false);
|
||||
|
||||
//Add and remove a listener
|
||||
obj.addEventListener('test', spy, foo2);
|
||||
obj.removeEventListener('test', spy, foo2);
|
||||
|
||||
expect(obj.hasEventListeners('test')).to.be(false);
|
||||
});
|
||||
|
||||
it('makes sure an event is not triggered if a listener is removed during dispatch', function () {
|
||||
var obj = new Klass(),
|
||||
spy = sinon.spy();
|
||||
obj.addEventListener('test', function() { obj.removeEventListener('test',spy); });
|
||||
obj.addEventListener('test', spy);
|
||||
obj.fireEvent('test');
|
||||
|
||||
obj.addEventListener('test', function () { obj.removeEventListener('test', spy); });
|
||||
obj.addEventListener('test', spy);
|
||||
obj.fireEvent('test');
|
||||
|
||||
expect(spy.called).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#on, #off & #fire', function() {
|
||||
describe('#on, #off & #fire', function () {
|
||||
|
||||
it('works like #addEventListener && #removeEventListener', function() {
|
||||
it('works like #addEventListener && #removeEventListener', function () {
|
||||
var obj = new Klass(),
|
||||
spy = sinon.spy();
|
||||
|
||||
@ -240,7 +285,7 @@ describe('Events', function() {
|
||||
expect(spy.callCount).to.be.lessThan(2);
|
||||
});
|
||||
|
||||
it('does not override existing methods with the same name', function() {
|
||||
it('does not override existing methods with the same name', function () {
|
||||
var spy1 = sinon.spy(),
|
||||
spy2 = sinon.spy(),
|
||||
spy3 = sinon.spy();
|
||||
@ -265,10 +310,10 @@ describe('Events', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#clearEventListeners", function() {
|
||||
it("clears all registered listeners on an object", function() {
|
||||
describe("#clearEventListeners", function () {
|
||||
it("clears all registered listeners on an object", function () {
|
||||
var spy = sinon.spy(),
|
||||
obj = new Klass()
|
||||
obj = new Klass(),
|
||||
otherObj = new Klass();
|
||||
|
||||
obj.on('test', spy, obj);
|
||||
@ -282,8 +327,8 @@ describe('Events', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#once', function() {
|
||||
it('removes event listeners after first trigger', function() {
|
||||
describe('#once', function () {
|
||||
it('removes event listeners after first trigger', function () {
|
||||
var obj = new Klass(),
|
||||
spy = sinon.spy();
|
||||
|
||||
@ -297,7 +342,7 @@ describe('Events', function() {
|
||||
expect(spy.callCount).to.be.lessThan(2);
|
||||
});
|
||||
|
||||
it('works with an object hash', function() {
|
||||
it('works with an object hash', function () {
|
||||
var obj = new Klass(),
|
||||
spy = sinon.spy(),
|
||||
otherSpy = sinon.spy();
|
||||
@ -332,7 +377,7 @@ describe('Events', function() {
|
||||
expect(spy.called).to.be(false);
|
||||
});
|
||||
|
||||
it('works if called from a context that doesnt implement #Events', function() {
|
||||
it('works if called from a context that doesnt implement #Events', function () {
|
||||
var obj = new Klass(),
|
||||
spy = sinon.spy(),
|
||||
foo = {};
|
||||
|
@ -1,16 +1,16 @@
|
||||
describe('Util', function() {
|
||||
describe('Util', function () {
|
||||
|
||||
describe('#extend', function() {
|
||||
describe('#extend', function () {
|
||||
var a;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
a = {
|
||||
foo: 5,
|
||||
bar: 'asd'
|
||||
};
|
||||
});
|
||||
|
||||
it('extends the first argument with the properties of the second', function() {
|
||||
it('extends the first argument with the properties of the second', function () {
|
||||
L.Util.extend(a, {
|
||||
bar: 7,
|
||||
baz: 3
|
||||
@ -23,7 +23,7 @@ describe('Util', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('accepts more than 2 arguments', function() {
|
||||
it('accepts more than 2 arguments', function () {
|
||||
L.Util.extend(a, {bar: 7}, {baz: 3});
|
||||
|
||||
expect(a).to.eql({
|
||||
@ -34,9 +34,9 @@ describe('Util', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#bind', function() {
|
||||
it('returns the given function with the given context', function() {
|
||||
var fn = function() {
|
||||
describe('#bind', function () {
|
||||
it('returns the given function with the given context', function () {
|
||||
var fn = function () {
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -59,8 +59,8 @@ describe('Util', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#stamp', function() {
|
||||
it('sets a unique id on the given object and returns it', function() {
|
||||
describe('#stamp', function () {
|
||||
it('sets a unique id on the given object and returns it', function () {
|
||||
var a = {},
|
||||
id = L.Util.stamp(a);
|
||||
|
||||
@ -115,38 +115,37 @@ describe('Util', function() {
|
||||
});
|
||||
|
||||
|
||||
describe('#getParamString', function() {
|
||||
it('creates a valid query string for appending depending on url input', function() {
|
||||
describe('#getParamString', function () {
|
||||
it('creates a valid query string for appending depending on url input', function () {
|
||||
var a = {
|
||||
url: "http://example.com/get",
|
||||
url: 'http://example.com/get',
|
||||
obj: {bar: 7, baz: 3},
|
||||
result: "?bar=7&baz=3"
|
||||
result: '?bar=7&baz=3'
|
||||
};
|
||||
|
||||
expect(L.Util.getParamString(a.obj,a.url)).to.eql(a.result);
|
||||
expect(L.Util.getParamString(a.obj, a.url)).to.eql(a.result);
|
||||
|
||||
var b = {
|
||||
url: "http://example.com/get?justone=qs",
|
||||
url: 'http://example.com/get?justone=qs',
|
||||
obj: {bar: 7, baz: 3},
|
||||
result: "&bar=7&baz=3"
|
||||
result: '&bar=7&baz=3'
|
||||
};
|
||||
|
||||
expect(L.Util.getParamString(b.obj,b.url)).to.eql(b.result);
|
||||
expect(L.Util.getParamString(b.obj, b.url)).to.eql(b.result);
|
||||
|
||||
var c = {
|
||||
url: undefined,
|
||||
obj: {bar: 7, baz: 3},
|
||||
result: "?bar=7&baz=3"
|
||||
result: '?bar=7&baz=3'
|
||||
};
|
||||
|
||||
expect(L.Util.getParamString(c.obj,c.url)).to.eql(c.result);
|
||||
expect(L.Util.getParamString(c.obj, c.url)).to.eql(c.result);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#requestAnimFrame', function () {
|
||||
it('calles a function on next frame, unless canceled', function (done) {
|
||||
var spy = sinon.spy(),
|
||||
spy2 = sinon.spy(),
|
||||
foo = {};
|
||||
|
||||
L.Util.requestAnimFrame(spy);
|
||||
@ -160,7 +159,7 @@ describe('Util', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#limitExecByInterval', function() {
|
||||
describe('#limitExecByInterval', function () {
|
||||
it('limits execution to not more often than specified time interval', function (done) {
|
||||
var spy = sinon.spy();
|
||||
|
||||
@ -189,24 +188,69 @@ describe('Util', function() {
|
||||
|
||||
describe('#template', function () {
|
||||
it('evaluates templates with a given data object', function () {
|
||||
var tpl = 'Hello {foo} and {bar}!';
|
||||
var tpl = 'Hello {foo} and {baz }!';
|
||||
|
||||
var str = L.Util.template(tpl, {
|
||||
foo: 'Vlad',
|
||||
bar: 'Dave'
|
||||
bar: 'Dave',
|
||||
baz: function (o) {
|
||||
return o.bar;
|
||||
}
|
||||
});
|
||||
|
||||
expect(str).to.eql('Hello Vlad and Dave!');
|
||||
});
|
||||
|
||||
it('check the cache', function () {
|
||||
var tpl = 'Hello {foo} and {baz }!';
|
||||
|
||||
var str = L.Util._templateCache[tpl]({
|
||||
foo: 'ladies',
|
||||
baz: function () {
|
||||
return 'gentlemen';
|
||||
}
|
||||
});
|
||||
|
||||
expect(str).to.eql('Hello ladies and gentlemen!');
|
||||
});
|
||||
|
||||
it('evaluates templates with a function', function () {
|
||||
var tpl = L.Util.compileTemplate('Hello { foo } and { bar}!', {});
|
||||
|
||||
var str1 = tpl({
|
||||
foo: 'Vlad',
|
||||
bar: 'Dave'
|
||||
});
|
||||
var str2 = tpl({
|
||||
foo: '{Calvin}',
|
||||
bar: '{Simon}'
|
||||
});
|
||||
|
||||
expect(str1).to.eql('Hello Vlad and Dave!');
|
||||
expect(str2).to.eql('Hello {Calvin} and {Simon}!');
|
||||
});
|
||||
|
||||
it('does not modify text without a token variable', function () {
|
||||
expect(L.Util.template('foo', {})).to.eql('foo');
|
||||
});
|
||||
|
||||
it('supports templates with double quotes', function () {
|
||||
expect(L.Util.template('He said: "{foo}"!', {
|
||||
foo: 'Hello'
|
||||
})).to.eql('He said: "Hello"!');
|
||||
});
|
||||
|
||||
it('throws when a template token is not given', function () {
|
||||
expect(function () {
|
||||
L.Util.template(tpl, {foo: 'bar'});
|
||||
L.Util.template(undefined, {foo: 'bar'});
|
||||
}).to.throwError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isArray', function () {
|
||||
expect(L.Util.isArray([1, 2, 3])).to.be(true);
|
||||
expect(L.Util.isArray(new Array(1, 2, 3))).to.be(true);
|
||||
expect(L.Util.isArray('blabla')).to.be(false);
|
||||
expect(L.Util.isArray({0: 1, 1: 2})).to.be(false);
|
||||
});
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
describe('DomEvent', function() {
|
||||
describe('DomEvent', function () {
|
||||
var el;
|
||||
|
||||
function simulateClick(el) {
|
||||
if (document.createEvent) {
|
||||
var e = document.createEvent('MouseEvents');
|
||||
e.initMouseEvent('click', true, true, window,
|
||||
e.initMouseEvent('click', true, true, window,
|
||||
0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
return el.dispatchEvent(e);
|
||||
} else if (el.fireEvent) {
|
||||
@ -12,19 +12,19 @@ describe('DomEvent', function() {
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
el = document.createElement('div');
|
||||
el.style.position = 'absolute';
|
||||
el.style.top = el.style.left = '-10000px';
|
||||
document.body.appendChild(el);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
afterEach(function () {
|
||||
document.body.removeChild(el);
|
||||
});
|
||||
|
||||
describe('#addListener', function() {
|
||||
it('adds a listener and calls it on event', function() {
|
||||
describe('#addListener', function () {
|
||||
it('adds a listener and calls it on event', function () {
|
||||
var listener1 = sinon.spy(),
|
||||
listener2 = sinon.spy();
|
||||
|
||||
@ -37,11 +37,11 @@ describe('DomEvent', function() {
|
||||
expect(listener2.called).to.be.ok();
|
||||
});
|
||||
|
||||
it('binds "this" to the given context', function() {
|
||||
it('binds "this" to the given context', function () {
|
||||
var obj = {foo: 'bar'},
|
||||
result;
|
||||
|
||||
L.DomEvent.addListener(el, 'click', function() {
|
||||
L.DomEvent.addListener(el, 'click', function () {
|
||||
result = this;
|
||||
}, obj);
|
||||
|
||||
@ -50,10 +50,10 @@ describe('DomEvent', function() {
|
||||
expect(result).to.eql(obj);
|
||||
});
|
||||
|
||||
it('passes an event object to the listener', function() {
|
||||
it('passes an event object to the listener', function () {
|
||||
var type;
|
||||
|
||||
L.DomEvent.addListener(el, 'click', function(e) {
|
||||
L.DomEvent.addListener(el, 'click', function (e) {
|
||||
type = e && e.type;
|
||||
});
|
||||
simulateClick(el);
|
||||
@ -62,8 +62,8 @@ describe('DomEvent', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeListener', function() {
|
||||
it('removes a previously added listener', function() {
|
||||
describe('#removeListener', function () {
|
||||
it('removes a previously added listener', function () {
|
||||
var listener = sinon.spy();
|
||||
|
||||
L.DomEvent.addListener(el, 'click', listener);
|
||||
@ -75,8 +75,8 @@ describe('DomEvent', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#stopPropagation', function() {
|
||||
it('stops propagation of the given event', function() {
|
||||
describe('#stopPropagation', function () {
|
||||
it('stops propagation of the given event', function () {
|
||||
var child = document.createElement('div'),
|
||||
listener = sinon.spy();
|
||||
|
||||
@ -92,8 +92,8 @@ describe('DomEvent', function() {
|
||||
el.removeChild(child);
|
||||
});
|
||||
});
|
||||
describe('#preventDefault', function() {
|
||||
it('prevents the default action of event', function() {
|
||||
describe('#preventDefault', function () {
|
||||
it('prevents the default action of event', function () {
|
||||
L.DomEvent.addListener(el, 'click', L.DomEvent.preventDefault);
|
||||
|
||||
expect(simulateClick(el)).to.be(false);
|
||||
|
@ -1,30 +1,30 @@
|
||||
describe('DomUtil', function() {
|
||||
describe('DomUtil', function () {
|
||||
var el;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
el = document.createElement('div');
|
||||
el.style.position = 'absolute';
|
||||
el.style.top = el.style.left = '-10000px';
|
||||
document.body.appendChild(el);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
afterEach(function () {
|
||||
document.body.removeChild(el);
|
||||
});
|
||||
|
||||
describe('#get', function() {
|
||||
it('gets element by id if the given argument is string', function() {
|
||||
describe('#get', function () {
|
||||
it('gets element by id if the given argument is string', function () {
|
||||
el.id = 'testId';
|
||||
expect(L.DomUtil.get(el.id)).to.eql(el);
|
||||
});
|
||||
|
||||
it('returns the element if it is given as an argument', function() {
|
||||
it('returns the element if it is given as an argument', function () {
|
||||
expect(L.DomUtil.get(el)).to.eql(el);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#addClass, #removeClass, #hasClass', function() {
|
||||
it('has defined class for test element', function() {
|
||||
describe('#addClass, #removeClass, #hasClass', function () {
|
||||
it('has defined class for test element', function () {
|
||||
el.className = 'bar foo baz ';
|
||||
expect(L.DomUtil.hasClass(el, 'foo')).to.be.ok();
|
||||
expect(L.DomUtil.hasClass(el, 'bar')).to.be.ok();
|
||||
@ -32,7 +32,7 @@ describe('DomUtil', function() {
|
||||
expect(L.DomUtil.hasClass(el, 'boo')).to.not.be.ok();
|
||||
});
|
||||
|
||||
it('adds or removes the class', function() {
|
||||
it('adds or removes the class', function () {
|
||||
el.className = '';
|
||||
L.DomUtil.addClass(el, 'foo');
|
||||
|
||||
@ -53,13 +53,6 @@ describe('DomUtil', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#documentIsLtr', function () {
|
||||
it('returns true if doc direction is ltr', function () {
|
||||
expect(L.DomUtil.documentIsLtr()).to.eql(true);
|
||||
expect(L.DomUtil.documentIsLtr()).to.eql(true); // cached
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getViewportOffset', function () {
|
||||
it('calculates the viewport offset of an element', function () {
|
||||
var div = document.createElement('div');
|
||||
|
@ -1,23 +1,23 @@
|
||||
describe('PosAnimation', function() {
|
||||
describe('PosAnimation', function () {
|
||||
var el;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
el = document.createElement('div');
|
||||
this.subject = new L.PosAnimation();
|
||||
this.subject._el = el;
|
||||
});
|
||||
|
||||
describe('#_onStep', function() {
|
||||
it("sets element position and fires step event if it is able to get current position", function() {
|
||||
describe('#_onStep', function () {
|
||||
it("sets element position and fires step event if it is able to get current position", function () {
|
||||
var point = new L.Point(5, 5, true);
|
||||
sinon.stub(this.subject, '_getPos').returns(point);
|
||||
this.subject.fire = sinon.stub();
|
||||
this.subject._onStep();
|
||||
expect(this.subject.fire.withArgs('step').calledOnce).to.be(true);
|
||||
expect(this.subject._el._leaflet_pos).to.be(point);
|
||||
expect(L.DomUtil.getPosition(this.subject._el)).to.be(point);
|
||||
});
|
||||
|
||||
it('stops transition if a position returned', function() {
|
||||
it('stops transition if a position returned', function () {
|
||||
sinon.stub(this.subject, '_onTransitionEnd');
|
||||
sinon.stub(this.subject, '_getPos').returns(undefined);
|
||||
this.subject._onStep();
|
||||
|
47
spec/suites/geo/CRSSpec.js
Normal file
47
spec/suites/geo/CRSSpec.js
Normal file
@ -0,0 +1,47 @@
|
||||
describe("CRS.EPSG3395", function () {
|
||||
var crs = L.CRS.EPSG3395;
|
||||
|
||||
describe("#latLngToPoint", function () {
|
||||
it("projects a center point", function () {
|
||||
expect(crs.latLngToPoint(L.latLng(0, 0), 0)).near(new L.Point(128, 128), 0.01);
|
||||
});
|
||||
|
||||
it("projects the northeast corner of the world", function () {
|
||||
expect(crs.latLngToPoint(L.latLng(85.0840591556, 180), 0)).near(new L.Point(256, 0));
|
||||
});
|
||||
});
|
||||
|
||||
describe("#pointToLatLng", function () {
|
||||
it("reprojects a center point", function () {
|
||||
expect(crs.pointToLatLng(new L.Point(128, 128), 0)).nearLatLng(L.latLng(0, 0), 0.01);
|
||||
});
|
||||
|
||||
it("reprojects the northeast corner of the world", function () {
|
||||
expect(crs.pointToLatLng(new L.Point(256, 0), 0)).nearLatLng(L.latLng(85.0840591556, 180));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("CRS.EPSG3857", function () {
|
||||
var crs = L.CRS.EPSG3857;
|
||||
|
||||
describe("#latLngToPoint", function () {
|
||||
it("projects a center point", function () {
|
||||
expect(crs.latLngToPoint(L.latLng(0, 0), 0)).near(new L.Point(128, 128), 0.01);
|
||||
});
|
||||
|
||||
it("projects the northeast corner of the world", function () {
|
||||
expect(crs.latLngToPoint(L.latLng(85.0511287798, 180), 0)).near(new L.Point(256, 0));
|
||||
});
|
||||
});
|
||||
|
||||
describe("#pointToLatLng", function () {
|
||||
it("reprojects a center point", function () {
|
||||
expect(crs.pointToLatLng(new L.Point(128, 128), 0)).nearLatLng(L.latLng(0, 0), 0.01);
|
||||
});
|
||||
|
||||
it("reprojects the northeast corner of the world", function () {
|
||||
expect(crs.pointToLatLng(new L.Point(256, 0), 0)).nearLatLng(L.latLng(85.0511287798, 180));
|
||||
});
|
||||
});
|
||||
});
|
@ -1,7 +1,7 @@
|
||||
describe('LatLngBounds', function() {
|
||||
describe('LatLngBounds', function () {
|
||||
var a, c;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
a = new L.LatLngBounds(
|
||||
new L.LatLng(14, 12),
|
||||
new L.LatLng(30, 40));
|
||||
@ -27,13 +27,17 @@ describe('LatLngBounds', function() {
|
||||
|
||||
it('extends the bounds by given bounds', function () {
|
||||
a.extend([[20, 50], [8, 40]]);
|
||||
|
||||
expect(a.getSouthEast()).to.eql(new L.LatLng(8, 50));
|
||||
});
|
||||
|
||||
it('extends the bounds by undefined', function () {
|
||||
expect(a.extend()).to.eql(a);
|
||||
});
|
||||
|
||||
it('extends the bounds by raw object', function () {
|
||||
a.extend({lat: 20, lng: 50});
|
||||
expect(a.getNorthEast()).to.eql(new L.LatLng(30, 50));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCenter', function () {
|
||||
@ -58,62 +62,62 @@ describe('LatLngBounds', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isValid', function() {
|
||||
it('returns true if properly set up', function() {
|
||||
describe('#isValid', function () {
|
||||
it('returns true if properly set up', function () {
|
||||
expect(a.isValid()).to.be.ok();
|
||||
});
|
||||
it('returns false if is invalid', function() {
|
||||
it('returns false if is invalid', function () {
|
||||
expect(c.isValid()).to.not.be.ok();
|
||||
});
|
||||
it('returns true if extended', function() {
|
||||
it('returns true if extended', function () {
|
||||
c.extend([0, 0]);
|
||||
expect(c.isValid()).to.be.ok();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getWest', function () {
|
||||
it('returns a proper bbox west value', function() {
|
||||
it('returns a proper bbox west value', function () {
|
||||
expect(a.getWest()).to.eql(12);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getSouth', function () {
|
||||
it('returns a proper bbox south value', function() {
|
||||
it('returns a proper bbox south value', function () {
|
||||
expect(a.getSouth()).to.eql(14);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#getEast', function () {
|
||||
it('returns a proper bbox east value', function() {
|
||||
it('returns a proper bbox east value', function () {
|
||||
expect(a.getEast()).to.eql(40);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#getNorth', function () {
|
||||
it('returns a proper bbox north value', function() {
|
||||
it('returns a proper bbox north value', function () {
|
||||
expect(a.getNorth()).to.eql(30);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#toBBoxString', function () {
|
||||
it('returns a proper left,bottom,right,top bbox', function() {
|
||||
it('returns a proper left,bottom,right,top bbox', function () {
|
||||
expect(a.toBBoxString()).to.eql("12,14,40,30");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#getNorthWest', function () {
|
||||
it('returns a proper north-west LatLng', function() {
|
||||
it('returns a proper north-west LatLng', function () {
|
||||
expect(a.getNorthWest()).to.eql(new L.LatLng(a.getNorth(), a.getWest()));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#getSouthEast', function () {
|
||||
it('returns a proper south-east LatLng', function() {
|
||||
it('returns a proper south-east LatLng', function () {
|
||||
expect(a.getSouthEast()).to.eql(new L.LatLng(a.getSouth(), a.getEast()));
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
describe('LatLng', function() {
|
||||
describe('constructor', function() {
|
||||
it("sets lat and lng", function() {
|
||||
describe('LatLng', function () {
|
||||
describe('constructor', function () {
|
||||
it("sets lat and lng", function () {
|
||||
var a = new L.LatLng(25, 74);
|
||||
expect(a.lat).to.eql(25);
|
||||
expect(a.lng).to.eql(74);
|
||||
@ -15,16 +15,30 @@ describe('LatLng', function() {
|
||||
var a = new L.LatLng(NaN, NaN);
|
||||
}).to.throwError();
|
||||
});
|
||||
|
||||
it('does not set altitude if undefined', function () {
|
||||
var a = new L.LatLng(25, 74);
|
||||
expect(typeof a.alt).to.eql('undefined');
|
||||
});
|
||||
|
||||
it('sets altitude', function () {
|
||||
var a = new L.LatLng(25, 74, 50);
|
||||
expect(a.alt).to.eql(50);
|
||||
|
||||
var b = new L.LatLng(-25, -74, -50);
|
||||
expect(b.alt).to.eql(-50);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('#equals', function() {
|
||||
it("returns true if compared objects are equal within a certain margin", function() {
|
||||
describe('#equals', function () {
|
||||
it("returns true if compared objects are equal within a certain margin", function () {
|
||||
var a = new L.LatLng(10, 20);
|
||||
var b = new L.LatLng(10 + 1.0E-10, 20 - 1.0E-10);
|
||||
expect(a.equals(b)).to.eql(true);
|
||||
});
|
||||
|
||||
it("returns false if compared objects are not equal within a certain margin", function() {
|
||||
it("returns false if compared objects are not equal within a certain margin", function () {
|
||||
var a = new L.LatLng(10, 20);
|
||||
var b = new L.LatLng(10, 23.3);
|
||||
expect(a.equals(b)).to.eql(false);
|
||||
@ -37,7 +51,7 @@ describe('LatLng', function() {
|
||||
});
|
||||
|
||||
describe('#wrap', function () {
|
||||
it("wraps longitude to lie between -180 and 180 by default", function() {
|
||||
it("wraps longitude to lie between -180 and 180 by default", function () {
|
||||
var a = new L.LatLng(0, 190).wrap().lng;
|
||||
expect(a).to.eql(-170);
|
||||
|
||||
@ -63,7 +77,7 @@ describe('LatLng', function() {
|
||||
expect(h).to.eql(180);
|
||||
});
|
||||
|
||||
it("wraps longitude within the given range", function() {
|
||||
it("wraps longitude within the given range", function () {
|
||||
var a = new L.LatLng(0, 190).wrap(-100, 100).lng;
|
||||
expect(a).to.eql(-10);
|
||||
});
|
||||
|
@ -1,47 +1,39 @@
|
||||
describe("Projection.Mercator", function() {
|
||||
describe("Projection.Mercator", function () {
|
||||
var p = L.Projection.Mercator;
|
||||
|
||||
expect.Assertion.prototype.near = function(expected, delta) {
|
||||
delta = delta || 1;
|
||||
expect(this.obj.x).to
|
||||
.be.within(expected.x - delta, expected.x + delta);
|
||||
expect(this.obj.y).to
|
||||
.be.within(expected.y - delta, expected.y + delta);
|
||||
};
|
||||
|
||||
describe("#project", function() {
|
||||
it("projects a center point", function() {
|
||||
describe("#project", function () {
|
||||
it("projects a center point", function () {
|
||||
//edge cases
|
||||
expect(p.project(new L.LatLng(0, 0))).near(new L.Point(0, 0));
|
||||
});
|
||||
|
||||
it("projects the northeast corner of the world", function() {
|
||||
it("projects the northeast corner of the world", function () {
|
||||
expect(p.project(new L.LatLng(90, 180))).near(new L.Point(20037508, 20037508));
|
||||
});
|
||||
|
||||
it("projects the southwest corner of the world", function() {
|
||||
it("projects the southwest corner of the world", function () {
|
||||
expect(p.project(new L.LatLng(-90, -180))).near(new L.Point(-20037508, -20037508));
|
||||
});
|
||||
|
||||
it("projects other points", function() {
|
||||
expect(p.project(new L.LatLng(50, 30))).near(new L.Point(3339584, 6413524));
|
||||
it("projects other points", function () {
|
||||
expect(p.project(new L.LatLng(50, 30))).near(new L.Point(3339584, 6413524));
|
||||
|
||||
// from https://github.com/Leaflet/Leaflet/issues/1578
|
||||
expect(p.project(new L.LatLng(51.9371170300465, 80.11230468750001)))
|
||||
.near(new L.Point(8918060.964088084, 6755099.410887127));
|
||||
// from https://github.com/Leaflet/Leaflet/issues/1578
|
||||
expect(p.project(new L.LatLng(51.9371170300465, 80.11230468750001)))
|
||||
.near(new L.Point(8918060.964088084, 6755099.410887127));
|
||||
});
|
||||
});
|
||||
|
||||
describe("#unproject", function() {
|
||||
describe("#unproject", function () {
|
||||
function pr(point) {
|
||||
return p.project(p.unproject(point));
|
||||
}
|
||||
|
||||
it("unprojects a center point", function() {
|
||||
it("unprojects a center point", function () {
|
||||
expect(pr(new L.Point(0, 0))).near(new L.Point(0, 0));
|
||||
});
|
||||
|
||||
it("unprojects pi points", function() {
|
||||
it("unprojects pi points", function () {
|
||||
expect(pr(new L.Point(-Math.PI, Math.PI))).near(new L.Point(-Math.PI, Math.PI));
|
||||
expect(pr(new L.Point(-Math.PI, -Math.PI))).near(new L.Point(-Math.PI, -Math.PI));
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
describe('Bounds', function() {
|
||||
describe('Bounds', function () {
|
||||
var a, b, c;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
a = new L.Bounds(
|
||||
new L.Point(14, 12),
|
||||
new L.Point(30, 40));
|
||||
@ -13,19 +13,19 @@ describe('Bounds', function() {
|
||||
c = new L.Bounds();
|
||||
});
|
||||
|
||||
describe('constructor', function() {
|
||||
it('creates bounds with proper min & max on (Point, Point)', function() {
|
||||
describe('constructor', function () {
|
||||
it('creates bounds with proper min & max on (Point, Point)', function () {
|
||||
expect(a.min).to.eql(new L.Point(14, 12));
|
||||
expect(a.max).to.eql(new L.Point(30, 40));
|
||||
});
|
||||
it('creates bounds with proper min & max on (Point[])', function() {
|
||||
it('creates bounds with proper min & max on (Point[])', function () {
|
||||
expect(b.min).to.eql(new L.Point(14, 12));
|
||||
expect(b.max).to.eql(new L.Point(30, 40));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#extend', function() {
|
||||
it('extends the bounds to contain the given point', function() {
|
||||
describe('#extend', function () {
|
||||
it('extends the bounds to contain the given point', function () {
|
||||
a.extend(new L.Point(50, 20));
|
||||
expect(a.min).to.eql(new L.Point(14, 12));
|
||||
expect(a.max).to.eql(new L.Point(50, 40));
|
||||
@ -36,14 +36,14 @@ describe('Bounds', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCenter', function() {
|
||||
it('returns the center point', function() {
|
||||
describe('#getCenter', function () {
|
||||
it('returns the center point', function () {
|
||||
expect(a.getCenter()).to.eql(new L.Point(22, 26));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#contains', function() {
|
||||
it('contains other bounds or point', function() {
|
||||
describe('#contains', function () {
|
||||
it('contains other bounds or point', function () {
|
||||
a.extend(new L.Point(50, 10));
|
||||
expect(a.contains(b)).to.be.ok();
|
||||
expect(b.contains(a)).to.not.be.ok();
|
||||
@ -52,14 +52,14 @@ describe('Bounds', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isValid', function() {
|
||||
it('returns true if properly set up', function() {
|
||||
describe('#isValid', function () {
|
||||
it('returns true if properly set up', function () {
|
||||
expect(a.isValid()).to.be.ok();
|
||||
});
|
||||
it('returns false if is invalid', function() {
|
||||
it('returns false if is invalid', function () {
|
||||
expect(c.isValid()).to.not.be.ok();
|
||||
});
|
||||
it('returns true if extended', function() {
|
||||
it('returns true if extended', function () {
|
||||
c.extend([0, 0]);
|
||||
expect(c.isValid()).to.be.ok();
|
||||
});
|
||||
|
@ -1,42 +1,42 @@
|
||||
describe("Point", function() {
|
||||
describe("Point", function () {
|
||||
|
||||
describe('constructor', function() {
|
||||
describe('constructor', function () {
|
||||
|
||||
it("creates a point with the given x and y", function() {
|
||||
it("creates a point with the given x and y", function () {
|
||||
var p = new L.Point(1.5, 2.5);
|
||||
expect(p.x).to.eql(1.5);
|
||||
expect(p.y).to.eql(2.5);
|
||||
});
|
||||
|
||||
it("rounds the given x and y if the third argument is true", function() {
|
||||
it("rounds the given x and y if the third argument is true", function () {
|
||||
var p = new L.Point(1.3, 2.7, true);
|
||||
expect(p.x).to.eql(1);
|
||||
expect(p.y).to.eql(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#subtract', function() {
|
||||
it('subtracts the given point from this one', function() {
|
||||
describe('#subtract', function () {
|
||||
it('subtracts the given point from this one', function () {
|
||||
var a = new L.Point(50, 30),
|
||||
b = new L.Point(20, 10);
|
||||
expect(a.subtract(b)).to.eql(new L.Point(30, 20));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#add', function() {
|
||||
it('adds given point to this one', function() {
|
||||
describe('#add', function () {
|
||||
it('adds given point to this one', function () {
|
||||
expect(new L.Point(50, 30).add(new L.Point(20, 10))).to.eql(new L.Point(70, 40));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#divideBy', function() {
|
||||
it('divides this point by the given amount', function() {
|
||||
describe('#divideBy', function () {
|
||||
it('divides this point by the given amount', function () {
|
||||
expect(new L.Point(50, 30).divideBy(5)).to.eql(new L.Point(10, 6));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#multiplyBy', function() {
|
||||
it('multiplies this point by the given amount', function() {
|
||||
describe('#multiplyBy', function () {
|
||||
it('multiplies this point by the given amount', function () {
|
||||
expect(new L.Point(50, 30).multiplyBy(2)).to.eql(new L.Point(100, 60));
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,13 @@
|
||||
describe("Transformation", function() {
|
||||
describe("Transformation", function () {
|
||||
var t, p;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
t = new L.Transformation(1, 2, 3, 4);
|
||||
p = new L.Point(10, 20);
|
||||
});
|
||||
|
||||
describe('#transform', function () {
|
||||
it("performs a transformation", function() {
|
||||
it("performs a transformation", function () {
|
||||
var p2 = t.transform(p, 2);
|
||||
expect(p2).to.eql(new L.Point(24, 128));
|
||||
});
|
||||
@ -18,7 +18,7 @@ describe("Transformation", function() {
|
||||
});
|
||||
|
||||
describe('#untransform', function () {
|
||||
it("performs a reverse transformation", function() {
|
||||
it("performs a reverse transformation", function () {
|
||||
var p2 = t.transform(p, 2);
|
||||
var p3 = t.untransform(p2, 2);
|
||||
expect(p3).to.eql(p);
|
||||
|
@ -17,22 +17,25 @@
|
||||
fg1.addLayer(marker);
|
||||
fg2.addLayer(marker);
|
||||
|
||||
var wasClicked = 0;
|
||||
fg2.on('click', function(e) {
|
||||
var wasClicked1,
|
||||
wasClicked2;
|
||||
|
||||
fg2.on('click', function (e) {
|
||||
expect(e.layer).to.be(marker);
|
||||
expect(e.target).to.be(fg2);
|
||||
wasClicked |= 1;
|
||||
wasClicked2 = true;
|
||||
});
|
||||
|
||||
fg1.on('click', function (e) {
|
||||
expect(e.layer).to.be(marker);
|
||||
expect(e.target).to.be(fg1);
|
||||
wasClicked |= 2;
|
||||
wasClicked1 = true;
|
||||
});
|
||||
|
||||
marker.fire('click', { type: 'click' });
|
||||
|
||||
expect(wasClicked).to.be(3);
|
||||
expect(wasClicked1).to.be(true);
|
||||
expect(wasClicked2).to.be(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -47,6 +50,16 @@
|
||||
|
||||
expect(fg.hasLayer(marker)).to.be(true);
|
||||
});
|
||||
it('supports non-evented layers', function () {
|
||||
var fg = L.featureGroup(),
|
||||
g = L.layerGroup();
|
||||
|
||||
expect(fg.hasLayer(g)).to.be(false);
|
||||
|
||||
fg.addLayer(g);
|
||||
|
||||
expect(fg.hasLayer(g)).to.be(true);
|
||||
});
|
||||
});
|
||||
describe('removeLayer', function () {
|
||||
it('removes the layer passed to it', function () {
|
||||
@ -66,7 +79,7 @@
|
||||
fg.addLayer(marker);
|
||||
expect(fg.hasLayer(marker)).to.be(true);
|
||||
|
||||
fg.removeLayer(marker._leaflet_id);
|
||||
fg.removeLayer(L.stamp(marker));
|
||||
expect(fg.hasLayer(marker)).to.be(false);
|
||||
});
|
||||
});
|
||||
|
@ -5,7 +5,7 @@ describe("L.GeoJSON", function () {
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [20, 10]
|
||||
coordinates: [20, 10, 5]
|
||||
}
|
||||
};
|
||||
|
||||
@ -24,47 +24,79 @@ describe("L.GeoJSON", function () {
|
||||
});
|
||||
|
||||
describe("L.Marker#toGeoJSON", function () {
|
||||
it("returns a Point object", function () {
|
||||
it("returns a 2D Point object", function () {
|
||||
var marker = new L.Marker([10, 20]);
|
||||
expect(marker.toGeoJSON().geometry).to.eql({
|
||||
type: 'Point',
|
||||
coordinates: [20, 10]
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a 3D Point object", function () {
|
||||
var marker = new L.Marker([10, 20, 30]);
|
||||
expect(marker.toGeoJSON().geometry).to.eql({
|
||||
type: 'Point',
|
||||
coordinates: [20, 10, 30]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("L.Circle#toGeoJSON", function () {
|
||||
it("returns a Point object", function () {
|
||||
it("returns a 2D Point object", function () {
|
||||
var circle = new L.Circle([10, 20], 100);
|
||||
expect(circle.toGeoJSON().geometry).to.eql({
|
||||
type: 'Point',
|
||||
coordinates: [20, 10]
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a 3D Point object", function () {
|
||||
var circle = new L.Circle([10, 20, 30], 100);
|
||||
expect(circle.toGeoJSON().geometry).to.eql({
|
||||
type: 'Point',
|
||||
coordinates: [20, 10, 30]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("L.CircleMarker#toGeoJSON", function () {
|
||||
it("returns a Point object", function () {
|
||||
it("returns a 2D Point object", function () {
|
||||
var marker = new L.CircleMarker([10, 20]);
|
||||
expect(marker.toGeoJSON().geometry).to.eql({
|
||||
type: 'Point',
|
||||
coordinates: [20, 10]
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a 3D Point object", function () {
|
||||
var marker = new L.CircleMarker([10, 20, 30]);
|
||||
expect(marker.toGeoJSON().geometry).to.eql({
|
||||
type: 'Point',
|
||||
coordinates: [20, 10, 30]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("L.Polyline#toGeoJSON", function () {
|
||||
it("returns a LineString object", function () {
|
||||
it("returns a 2D LineString object", function () {
|
||||
var polyline = new L.Polyline([[10, 20], [2, 5]]);
|
||||
expect(polyline.toGeoJSON().geometry).to.eql({
|
||||
type: 'LineString',
|
||||
coordinates: [[20, 10], [5, 2]]
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a 3D LineString object", function () {
|
||||
var polyline = new L.Polyline([[10, 20, 30], [2, 5, 10]]);
|
||||
expect(polyline.toGeoJSON().geometry).to.eql({
|
||||
type: 'LineString',
|
||||
coordinates: [[20, 10, 30], [5, 2, 10]]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("L.MultiPolyline#toGeoJSON", function () {
|
||||
it("returns a MultiLineString object", function () {
|
||||
it("returns a 2D MultiLineString object", function () {
|
||||
var multiPolyline = new L.MultiPolyline([[[10, 20], [2, 5]], [[1, 2], [3, 4]]]);
|
||||
expect(multiPolyline.toGeoJSON().geometry).to.eql({
|
||||
type: 'MultiLineString',
|
||||
@ -74,10 +106,21 @@ describe("L.MultiPolyline#toGeoJSON", function () {
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a 3D MultiLineString object", function () {
|
||||
var multiPolyline = new L.MultiPolyline([[[10, 20, 30], [2, 5, 10]], [[1, 2, 3], [4, 5, 6]]]);
|
||||
expect(multiPolyline.toGeoJSON().geometry).to.eql({
|
||||
type: 'MultiLineString',
|
||||
coordinates: [
|
||||
[[20, 10, 30], [5, 2, 10]],
|
||||
[[2, 1, 3], [5, 4, 6]]
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("L.Polygon#toGeoJSON", function () {
|
||||
it("returns a Polygon object (no holes)", function () {
|
||||
it("returns a 2D Polygon object (no holes)", function () {
|
||||
var polygon = new L.Polygon([[1, 2], [3, 4], [5, 6]]);
|
||||
expect(polygon.toGeoJSON().geometry).to.eql({
|
||||
type: 'Polygon',
|
||||
@ -85,7 +128,15 @@ describe("L.Polygon#toGeoJSON", function () {
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a Polygon object (with holes)", function () {
|
||||
it("returns a 3D Polygon object (no holes)", function () {
|
||||
var polygon = new L.Polygon([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
|
||||
expect(polygon.toGeoJSON().geometry).to.eql({
|
||||
type: 'Polygon',
|
||||
coordinates: [[[2, 1, 3], [5, 4, 6], [8, 7, 9], [2, 1, 3]]]
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a 2D Polygon object (with holes)", function () {
|
||||
var polygon = new L.Polygon([[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]]);
|
||||
expect(polygon.toGeoJSON().geometry).to.eql({
|
||||
type: 'Polygon',
|
||||
@ -95,10 +146,21 @@ describe("L.Polygon#toGeoJSON", function () {
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a 3D Polygon object (with holes)", function () {
|
||||
var polygon = new L.Polygon([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]]]);
|
||||
expect(polygon.toGeoJSON().geometry).to.eql({
|
||||
type: 'Polygon',
|
||||
coordinates: [
|
||||
[[2, 1, 3], [5, 4, 6], [8, 7, 9], [2, 1, 3]],
|
||||
[[11, 10, 12], [14, 13, 15], [17, 16, 18], [11, 10, 12]]
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("L.MultiPolygon#toGeoJSON", function () {
|
||||
it("returns a MultiPolygon object", function () {
|
||||
it("returns a 2D MultiPolygon object", function () {
|
||||
var multiPolygon = new L.MultiPolygon([[[1, 2], [3, 4], [5, 6]]]);
|
||||
expect(multiPolygon.toGeoJSON().geometry).to.eql({
|
||||
type: 'MultiPolygon',
|
||||
@ -107,10 +169,20 @@ describe("L.MultiPolygon#toGeoJSON", function () {
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a 3D MultiPolygon object", function () {
|
||||
var multiPolygon = new L.MultiPolygon([[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]);
|
||||
expect(multiPolygon.toGeoJSON().geometry).to.eql({
|
||||
type: 'MultiPolygon',
|
||||
coordinates: [
|
||||
[[[2, 1, 3], [5, 4, 6], [8, 7, 9], [2, 1, 3]]]
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("L.LayerGroup#toGeoJSON", function () {
|
||||
it("returns a FeatureCollection object", function () {
|
||||
it("returns a 2D FeatureCollection object", function () {
|
||||
var marker = new L.Marker([10, 20]),
|
||||
polyline = new L.Polyline([[10, 20], [2, 5]]),
|
||||
layerGroup = new L.LayerGroup([marker, polyline]);
|
||||
@ -120,6 +192,16 @@ describe("L.LayerGroup#toGeoJSON", function () {
|
||||
});
|
||||
});
|
||||
|
||||
it("returns a 3D FeatureCollection object", function () {
|
||||
var marker = new L.Marker([10, 20, 30]),
|
||||
polyline = new L.Polyline([[10, 20, 30], [2, 5, 10]]),
|
||||
layerGroup = new L.LayerGroup([marker, polyline]);
|
||||
expect(layerGroup.toGeoJSON()).to.eql({
|
||||
type: 'FeatureCollection',
|
||||
features: [marker.toGeoJSON(), polyline.toGeoJSON()]
|
||||
});
|
||||
});
|
||||
|
||||
it("ensures that every member is a Feature", function () {
|
||||
var tileLayer = new L.TileLayer(),
|
||||
layerGroup = new L.LayerGroup([tileLayer]);
|
||||
@ -128,7 +210,7 @@ describe("L.LayerGroup#toGeoJSON", function () {
|
||||
return {
|
||||
type: 'Point',
|
||||
coordinates: [20, 10]
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
expect(layerGroup.toGeoJSON()).to.eql({
|
||||
@ -144,6 +226,51 @@ describe("L.LayerGroup#toGeoJSON", function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('roundtrips GeometryCollection features', function () {
|
||||
var json = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "GeometryCollection",
|
||||
"geometries": [{
|
||||
"type": "LineString",
|
||||
"coordinates": [[-122.4425587930444, 37.80666418607323], [-122.4428379594768, 37.80663578323093]]
|
||||
}, {
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[-122.4425509770566, 37.80662588061205],
|
||||
[-122.4428340530617, 37.8065999493009]
|
||||
]
|
||||
}]
|
||||
},
|
||||
"properties": {
|
||||
"name": "SF Marina Harbor Master"
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
expect(L.geoJson(json).toGeoJSON()).to.eql(json);
|
||||
});
|
||||
|
||||
it('roundtrips MiltiPoint features', function () {
|
||||
var json = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "MultiPoint",
|
||||
"coordinates": [[-122.4425587930444, 37.80666418607323], [-122.4428379594768, 37.80663578323093]]
|
||||
},
|
||||
"properties": {
|
||||
"name": "Test MultiPoints"
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
expect(L.geoJson(json).toGeoJSON()).to.eql(json);
|
||||
});
|
||||
|
||||
it("omits layers which do not implement toGeoJSON", function () {
|
||||
var tileLayer = new L.TileLayer(),
|
||||
layerGroup = new L.LayerGroup([tileLayer]);
|
||||
|
@ -1,6 +1,6 @@
|
||||
describe('LayerGroup', function () {
|
||||
describe("#addLayer", function () {
|
||||
it('adds a layer', function() {
|
||||
it('adds a layer', function () {
|
||||
var lg = L.layerGroup(),
|
||||
marker = L.marker([0, 0]);
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
});
|
||||
});
|
||||
describe("#removeLayer", function () {
|
||||
it('removes a layer', function() {
|
||||
it('removes a layer', function () {
|
||||
var lg = L.layerGroup(),
|
||||
marker = L.marker([0, 0]);
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
});
|
||||
});
|
||||
describe("#clearLayers", function () {
|
||||
it('removes all layers', function() {
|
||||
it('removes all layers', function () {
|
||||
var lg = L.layerGroup(),
|
||||
marker = L.marker([0, 0]);
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
});
|
||||
});
|
||||
describe("#getLayers", function () {
|
||||
it('gets all layers', function() {
|
||||
it('gets all layers', function () {
|
||||
var lg = L.layerGroup(),
|
||||
marker = L.marker([0, 0]);
|
||||
|
||||
@ -42,14 +42,14 @@
|
||||
});
|
||||
});
|
||||
describe("#eachLayer", function () {
|
||||
it('iterates over all layers', function() {
|
||||
it('iterates over all layers', function () {
|
||||
var lg = L.layerGroup(),
|
||||
marker = L.marker([0, 0]),
|
||||
ctx = { foo: 'bar' };
|
||||
|
||||
lg.addLayer(marker);
|
||||
|
||||
lg.eachLayer(function(layer) {
|
||||
lg.eachLayer(function (layer) {
|
||||
expect(layer).to.eql(marker);
|
||||
expect(this).to.eql(ctx);
|
||||
}, ctx);
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('Popup', function() {
|
||||
describe('Popup', function () {
|
||||
|
||||
var c, map;
|
||||
|
||||
@ -10,7 +10,7 @@ describe('Popup', function() {
|
||||
map.setView(new L.LatLng(55.8, 37.6), 6);
|
||||
});
|
||||
|
||||
it("closes on map click when map has closePopupOnClick option", function() {
|
||||
it("closes on map click when map has closePopupOnClick option", function () {
|
||||
map.options.closePopupOnClick = true;
|
||||
|
||||
var popup = new L.Popup()
|
||||
@ -22,7 +22,7 @@ describe('Popup', function() {
|
||||
expect(map.hasLayer(popup)).to.be(false);
|
||||
});
|
||||
|
||||
it("closes on map click when popup has closeOnClick option", function() {
|
||||
it("closes on map click when popup has closeOnClick option", function () {
|
||||
map.options.closePopupOnClick = false;
|
||||
|
||||
var popup = new L.Popup({closeOnClick: true})
|
||||
@ -34,7 +34,7 @@ describe('Popup', function() {
|
||||
expect(map.hasLayer(popup)).to.be(false);
|
||||
});
|
||||
|
||||
it("does not close on map click when popup has closeOnClick: false option", function() {
|
||||
it("does not close on map click when popup has closeOnClick: false option", function () {
|
||||
map.options.closePopupOnClick = true;
|
||||
|
||||
var popup = new L.Popup({closeOnClick: false})
|
||||
@ -46,7 +46,7 @@ describe('Popup', function() {
|
||||
expect(map.hasLayer(popup)).to.be(true);
|
||||
});
|
||||
|
||||
it("toggles its visibility when marker is clicked", function() {
|
||||
it("toggles its visibility when marker is clicked", function () {
|
||||
var marker = new L.Marker(new L.LatLng(55.8, 37.6));
|
||||
map.addLayer(marker);
|
||||
|
||||
@ -70,7 +70,7 @@ describe('Popup', function() {
|
||||
marker.closePopup.restore();
|
||||
});
|
||||
|
||||
it("should trigger popupopen on marker when popup opens", function() {
|
||||
it("should trigger popupopen on marker when popup opens", function () {
|
||||
var marker1 = new L.Marker(new L.LatLng(55.8, 37.6));
|
||||
var marker2 = new L.Marker(new L.LatLng(57.123076977278, 44.861962891635));
|
||||
|
||||
@ -91,7 +91,7 @@ describe('Popup', function() {
|
||||
expect(spy.called).to.be(true);
|
||||
});
|
||||
|
||||
it("should trigger popupclose on marker when popup closes", function() {
|
||||
it("should trigger popupclose on marker when popup closes", function () {
|
||||
var marker1 = new L.Marker(new L.LatLng(55.8, 37.6));
|
||||
var marker2 = new L.Marker(new L.LatLng(57.123076977278, 44.861962891635));
|
||||
|
||||
|
@ -11,7 +11,8 @@ describe('TileLayer', function () {
|
||||
it("has the same zoomlevels as the tilelayer", function () {
|
||||
var maxZoom = 10,
|
||||
minZoom = 5;
|
||||
map.setView([0, 0], 1);
|
||||
|
||||
map.setView([0, 0], 1);
|
||||
|
||||
L.tileLayer(tileUrl, {
|
||||
maxZoom: maxZoom,
|
||||
@ -36,33 +37,32 @@ describe('TileLayer', function () {
|
||||
it("has its zoomlevels updated to fit the new layer", function () {
|
||||
map.setView([0, 0], 1);
|
||||
|
||||
L.tileLayer(tileUrl, { minZoom:10, maxZoom: 15 }).addTo(map);
|
||||
L.tileLayer(tileUrl, {minZoom: 10, maxZoom: 15}).addTo(map);
|
||||
expect(map.getMinZoom()).to.be(10);
|
||||
expect(map.getMaxZoom()).to.be(15);
|
||||
|
||||
L.tileLayer(tileUrl, { minZoom:5, maxZoom: 10 }).addTo(map);
|
||||
L.tileLayer(tileUrl, {minZoom: 5, maxZoom: 10}).addTo(map);
|
||||
expect(map.getMinZoom()).to.be(5); // changed
|
||||
expect(map.getMaxZoom()).to.be(15); // unchanged
|
||||
|
||||
|
||||
L.tileLayer(tileUrl,{ minZoom:10, maxZoom: 20 }).addTo(map);
|
||||
L.tileLayer(tileUrl, {minZoom: 10, maxZoom: 20}).addTo(map);
|
||||
expect(map.getMinZoom()).to.be(5); // unchanged
|
||||
expect(map.getMaxZoom()).to.be(20); // changed
|
||||
|
||||
|
||||
L.tileLayer(tileUrl, { minZoom:0, maxZoom: 25 }).addTo(map);
|
||||
L.tileLayer(tileUrl, {minZoom: 0, maxZoom: 25}).addTo(map);
|
||||
expect(map.getMinZoom()).to.be(0); // changed
|
||||
expect(map.getMaxZoom()).to.be(25); // changed
|
||||
});
|
||||
});
|
||||
describe("when a tilelayer is removed from a map", function () {
|
||||
it("has its zoomlevels updated to only fit the layers it currently has", function () {
|
||||
var tiles = [ L.tileLayer(tileUrl, { minZoom:10, maxZoom: 15 }).addTo(map),
|
||||
L.tileLayer(tileUrl, { minZoom:5, maxZoom: 10 }).addTo(map),
|
||||
L.tileLayer(tileUrl, { minZoom:10, maxZoom: 20 }).addTo(map),
|
||||
L.tileLayer(tileUrl, { minZoom:0, maxZoom: 25 }).addTo(map)
|
||||
var tiles = [ L.tileLayer(tileUrl, {minZoom: 10, maxZoom: 15}).addTo(map),
|
||||
L.tileLayer(tileUrl, {minZoom: 5, maxZoom: 10}).addTo(map),
|
||||
L.tileLayer(tileUrl, {minZoom: 10, maxZoom: 20}).addTo(map),
|
||||
L.tileLayer(tileUrl, {minZoom: 0, maxZoom: 25}).addTo(map)
|
||||
];
|
||||
map.whenReady(function() {
|
||||
map.whenReady(function () {
|
||||
expect(map.getMinZoom()).to.be(0);
|
||||
expect(map.getMaxZoom()).to.be(25);
|
||||
|
||||
|
@ -1,31 +1,39 @@
|
||||
describe("Marker", function () {
|
||||
var map,
|
||||
spy;
|
||||
spy,
|
||||
icon1,
|
||||
icon2;
|
||||
|
||||
beforeEach(function () {
|
||||
map = L.map(document.createElement('div')).setView([0, 0], 0);
|
||||
icon1 = new L.Icon.Default();
|
||||
icon2 = new L.Icon.Default({
|
||||
iconUrl: icon1._getIconUrl('icon') + '?2',
|
||||
shadowUrl: icon1._getIconUrl('shadow') + '?2'
|
||||
});
|
||||
});
|
||||
|
||||
describe("#setIcon", function () {
|
||||
it("changes the icon to another image", function () {
|
||||
var marker = new L.Marker([0, 0], {icon: new L.Icon({iconUrl: 'icon1.png' }) });
|
||||
var marker = new L.Marker([0, 0], {icon: icon1});
|
||||
map.addLayer(marker);
|
||||
|
||||
|
||||
var beforeIcon = marker._icon;
|
||||
marker.setIcon(new L.Icon({iconUrl: 'icon2.png' }));
|
||||
marker.setIcon(icon2);
|
||||
var afterIcon = marker._icon;
|
||||
|
||||
|
||||
expect(beforeIcon).to.be(afterIcon);
|
||||
expect(afterIcon.src).to.contain('icon2.png');
|
||||
expect(afterIcon.src).to.contain(icon2._getIconUrl('icon'));
|
||||
});
|
||||
|
||||
it("changes the icon to another DivIcon", function () {
|
||||
var marker = new L.Marker([0, 0], {icon: new L.DivIcon({html: 'Inner1Text' }) });
|
||||
map.addLayer(marker);
|
||||
|
||||
|
||||
var beforeIcon = marker._icon;
|
||||
marker.setIcon(new L.DivIcon({html: 'Inner2Text' }));
|
||||
var afterIcon = marker._icon;
|
||||
|
||||
|
||||
expect(beforeIcon).to.be(afterIcon);
|
||||
expect(afterIcon.innerHTML).to.contain('Inner2Text');
|
||||
});
|
||||
@ -33,10 +41,10 @@ describe("Marker", function () {
|
||||
it("removes text when changing to a blank DivIcon", function () {
|
||||
var marker = new L.Marker([0, 0], {icon: new L.DivIcon({html: 'Inner1Text' }) });
|
||||
map.addLayer(marker);
|
||||
|
||||
|
||||
marker.setIcon(new L.DivIcon());
|
||||
var afterIcon = marker._icon;
|
||||
|
||||
|
||||
expect(marker._icon.innerHTML).to.not.contain('Inner1Text');
|
||||
});
|
||||
|
||||
@ -44,37 +52,37 @@ describe("Marker", function () {
|
||||
var marker = new L.Marker([0, 0], {icon: new L.DivIcon({html: 'Inner1Text' }) });
|
||||
map.addLayer(marker);
|
||||
var oldIcon = marker._icon;
|
||||
|
||||
marker.setIcon(new L.Icon({iconUrl: 'icon1.png' }));
|
||||
|
||||
|
||||
marker.setIcon(icon1);
|
||||
|
||||
expect(oldIcon).to.not.be(marker._icon);
|
||||
expect(oldIcon.parentNode).to.be(null);
|
||||
|
||||
expect(marker._icon.src).to.contain('icon1.png');
|
||||
|
||||
expect(marker._icon.src).to.contain('marker-icon.png');
|
||||
expect(marker._icon.parentNode).to.be(map._panes.markerPane);
|
||||
});
|
||||
|
||||
it("changes an image to a DivIcon", function () {
|
||||
var marker = new L.Marker([0, 0], {icon: new L.Icon({iconUrl: 'icon1.png' }) });
|
||||
var marker = new L.Marker([0, 0], {icon: icon1});
|
||||
map.addLayer(marker);
|
||||
var oldIcon = marker._icon;
|
||||
|
||||
marker.setIcon(new L.DivIcon({html: 'Inner1Text' }));
|
||||
|
||||
|
||||
expect(oldIcon).to.not.be(marker._icon);
|
||||
expect(oldIcon.parentNode).to.be(null);
|
||||
|
||||
|
||||
expect(marker._icon.innerHTML).to.contain('Inner1Text');
|
||||
expect(marker._icon.parentNode).to.be(map._panes.markerPane);
|
||||
});
|
||||
|
||||
it("reuses the icon/shadow when changing icon", function () {
|
||||
var marker = new L.Marker([0, 0], { icon: new L.Icon({ iconUrl: 'icon1.png', shadowUrl: 'shadow1.png', }) });
|
||||
var marker = new L.Marker([0, 0], { icon: icon1});
|
||||
map.addLayer(marker);
|
||||
var oldIcon = marker._icon;
|
||||
var oldShadow = marker._shadow;
|
||||
|
||||
marker.setIcon(new L.Icon({ iconUrl: 'icon2.png', shadowUrl: 'shadow2.png', }));
|
||||
marker.setIcon(icon2);
|
||||
|
||||
expect(oldIcon).to.be(marker._icon);
|
||||
expect(oldShadow).to.be(marker._shadow);
|
||||
@ -83,4 +91,4 @@ describe("Marker", function () {
|
||||
expect(marker._shadow.parentNode).to.be(map._panes.shadowPane);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,13 @@
|
||||
describe('CircleMarker', function() {
|
||||
describe("#_radius", function() {
|
||||
describe('CircleMarker', function () {
|
||||
describe("#_radius", function () {
|
||||
var map;
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
map = L.map(document.createElement('div'));
|
||||
map.setView([0, 0], 1);
|
||||
});
|
||||
describe("when a CircleMarker is added to the map ", function() {
|
||||
describe("with a radius set as an option", function() {
|
||||
it("takes that radius", function() {
|
||||
describe("when a CircleMarker is added to the map ", function () {
|
||||
describe("with a radius set as an option", function () {
|
||||
it("takes that radius", function () {
|
||||
var marker = L.circleMarker([0, 0], { radius: 20 }).addTo(map);
|
||||
|
||||
expect(marker._radius).to.be(20);
|
||||
@ -33,7 +33,7 @@
|
||||
});
|
||||
|
||||
describe("and setStyle is used to change the radius after adding", function () {
|
||||
it("takes the given radius", function() {
|
||||
it("takes the given radius", function () {
|
||||
var marker = L.circleMarker([0, 0], { radius: 20 });
|
||||
marker.addTo(map);
|
||||
marker.setStyle({ radius: 15 });
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('Polygon', function() {
|
||||
describe('Polygon', function () {
|
||||
|
||||
var c = document.createElement('div');
|
||||
c.style.width = '400px';
|
||||
@ -6,7 +6,7 @@ describe('Polygon', function() {
|
||||
var map = new L.Map(c);
|
||||
map.setView(new L.LatLng(55.8, 37.6), 6);
|
||||
|
||||
describe("#initialize", function() {
|
||||
describe("#initialize", function () {
|
||||
it("doesn't overwrite the given latlng array", function () {
|
||||
var originalLatLngs = [
|
||||
[1, 2],
|
||||
@ -24,6 +24,21 @@ describe('Polygon', function() {
|
||||
var polygon = new L.Polygon([]);
|
||||
expect(polygon.getLatLngs()).to.eql([]);
|
||||
});
|
||||
|
||||
it("can be initialized with holes", function () {
|
||||
var originalLatLngs = [
|
||||
[ //external rink
|
||||
[0, 10], [10, 10], [10, 0]
|
||||
], [ //hole
|
||||
[2, 3], [2, 4], [3, 4]
|
||||
]
|
||||
];
|
||||
|
||||
var polygon = new L.Polygon(originalLatLngs);
|
||||
|
||||
//getLatLngs() returns only external ring
|
||||
expect(polygon.getLatLngs()).to.eql([L.latLng([0, 10]), L.latLng([10, 10]), L.latLng([10, 0])]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#setLatLngs", function () {
|
||||
@ -40,6 +55,22 @@ describe('Polygon', function() {
|
||||
|
||||
expect(sourceLatLngs).to.eql(originalLatLngs);
|
||||
});
|
||||
|
||||
it("can be set external ring and holes", function () {
|
||||
var latLngs = [
|
||||
[ //external rink
|
||||
[0, 10], [10, 10], [10, 0]
|
||||
], [ //hole
|
||||
[2, 3], [2, 4], [3, 4]
|
||||
]
|
||||
];
|
||||
|
||||
var polygon = new L.Polygon([]);
|
||||
polygon.setLatLngs(latLngs);
|
||||
|
||||
//getLatLngs() returns only external ring
|
||||
expect(polygon.getLatLngs()).to.eql([L.latLng([0, 10]), L.latLng([10, 10]), L.latLng([10, 0])]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#spliceLatLngs", function () {
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('PolylineGeometry', function() {
|
||||
describe('PolylineGeometry', function () {
|
||||
|
||||
var c = document.createElement('div');
|
||||
c.style.width = '400px';
|
||||
@ -6,12 +6,12 @@ describe('PolylineGeometry', function() {
|
||||
var map = new L.Map(c);
|
||||
map.setView(new L.LatLng(55.8, 37.6), 6);
|
||||
|
||||
describe("#distanceTo", function() {
|
||||
it("calculates distances to points", function() {
|
||||
describe("#distanceTo", function () {
|
||||
it("calculates distances to points", function () {
|
||||
var p1 = map.latLngToLayerPoint(new L.LatLng(55.8, 37.6));
|
||||
var p2 = map.latLngToLayerPoint(new L.LatLng(57.123076977278, 44.861962891635));
|
||||
var latlngs = [[56.485503424111, 35.545556640339], [55.972522915346, 36.116845702918], [55.502459116923, 34.930322265253], [55.31534617509, 38.973291015816]]
|
||||
.map(function(ll) {
|
||||
.map(function (ll) {
|
||||
return new L.LatLng(ll[0], ll[1]);
|
||||
});
|
||||
var polyline = new L.Polyline([], {
|
||||
|
@ -1,4 +1,4 @@
|
||||
describe('Polyline', function() {
|
||||
describe('Polyline', function () {
|
||||
|
||||
var c = document.createElement('div');
|
||||
c.style.width = '400px';
|
||||
@ -6,7 +6,7 @@ describe('Polyline', function() {
|
||||
var map = new L.Map(c);
|
||||
map.setView(new L.LatLng(55.8, 37.6), 6);
|
||||
|
||||
describe("#initialize", function() {
|
||||
describe("#initialize", function () {
|
||||
it("doesn't overwrite the given latlng array", function () {
|
||||
var originalLatLngs = [
|
||||
[1, 2],
|
||||
|
@ -29,8 +29,8 @@ describe("Map", function () {
|
||||
var container = document.createElement('div'),
|
||||
map = new L.Map(container);
|
||||
expect(function () {
|
||||
new L.Map(container);
|
||||
}).to.throwException(function(e) {
|
||||
L.map(container);
|
||||
}).to.throwException(function (e) {
|
||||
expect(e.message).to.eql("Map container is already initialized.");
|
||||
});
|
||||
map.remove();
|
||||
@ -38,8 +38,8 @@ describe("Map", function () {
|
||||
|
||||
it("throws an exception if a container is not found", function () {
|
||||
expect(function () {
|
||||
new L.Map('nonexistentdivelement');
|
||||
}).to.throwException(function(e) {
|
||||
L.map('nonexistentdivelement');
|
||||
}).to.throwException(function (e) {
|
||||
expect(e.message).to.eql("Map container not found.");
|
||||
});
|
||||
map.remove();
|
||||
@ -72,11 +72,24 @@ describe("Map", function () {
|
||||
});
|
||||
|
||||
describe('#getCenter', function () {
|
||||
it ('throws if not set before', function () {
|
||||
it('throws if not set before', function () {
|
||||
expect(function () {
|
||||
map.getCenter();
|
||||
}).to.throwError();
|
||||
});
|
||||
|
||||
it('returns a precise center when zoomed in after being set (#426)', function () {
|
||||
var center = L.latLng(10, 10);
|
||||
map.setView(center, 1);
|
||||
map.setZoom(19);
|
||||
expect(map.getCenter()).to.eql(center);
|
||||
});
|
||||
|
||||
it('returns correct center after invalidateSize (#1919)', function () {
|
||||
map.setView(L.latLng(10, 10), 1);
|
||||
map.invalidateSize();
|
||||
expect(map.getCenter()).not.to.eql(L.latLng(10, 10));
|
||||
});
|
||||
});
|
||||
|
||||
describe("#whenReady", function () {
|
||||
@ -108,6 +121,12 @@ describe("Map", function () {
|
||||
expect(map.getZoom()).to.be(13);
|
||||
expect(map.getCenter().distanceTo([51.505, -0.09])).to.be.lessThan(5);
|
||||
});
|
||||
it("can be passed without a zoom specified", function () {
|
||||
map.setZoom(13);
|
||||
expect(map.setView([51.605, -0.11])).to.be(map);
|
||||
expect(map.getZoom()).to.be(13);
|
||||
expect(map.getCenter().distanceTo([51.605, -0.11])).to.be.lessThan(5);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#getBounds", function () {
|
||||
@ -120,7 +139,53 @@ describe("Map", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setMaxBounds', function () {
|
||||
it("aligns pixel-wise map view center with maxBounds center if it cannot move view bounds inside maxBounds (#1908)", function () {
|
||||
var container = map.getContainer();
|
||||
// large view, cannot fit within maxBounds
|
||||
container.style.width = container.style.height = "1000px";
|
||||
document.body.appendChild(container);
|
||||
// maxBounds
|
||||
var bounds = L.latLngBounds([51.5, -0.05], [51.55, 0.05]);
|
||||
map.setMaxBounds(bounds, {animate: false});
|
||||
// set view outside
|
||||
map.setView(L.latLng([53.0, 0.15]), 12, {animate: false});
|
||||
// get center of bounds in pixels
|
||||
var boundsCenter = map.project(bounds.getCenter()).round();
|
||||
expect(map.project(map.getCenter()).round()).to.eql(boundsCenter);
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
it("moves map view within maxBounds by changing one coordinate", function () {
|
||||
var container = map.getContainer();
|
||||
// small view, can fit within maxBounds
|
||||
container.style.width = container.style.height = "200px";
|
||||
document.body.appendChild(container);
|
||||
// maxBounds
|
||||
var bounds = L.latLngBounds([51, -0.2], [52, 0.2]);
|
||||
map.setMaxBounds(bounds, {animate: false});
|
||||
// set view outside maxBounds on one direction only
|
||||
// leaves untouched the other coordinate (that is not already centered)
|
||||
var initCenter = [53.0, 0.1];
|
||||
map.setView(L.latLng(initCenter), 16, {animate: false});
|
||||
// one pixel coordinate hasn't changed, the other has
|
||||
var pixelCenter = map.project(map.getCenter()).round();
|
||||
var pixelInit = map.project(initCenter).round();
|
||||
expect(pixelCenter.x).to.eql(pixelInit.x);
|
||||
expect(pixelCenter.y).not.to.eql(pixelInit.y);
|
||||
// the view is inside the bounds
|
||||
expect(bounds.contains(map.getBounds())).to.be(true);
|
||||
document.body.removeChild(container);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#getMinZoom and #getMaxZoom", function () {
|
||||
describe('#getMinZoom', function () {
|
||||
it('returns 0 if not set by Map options or TileLayer options', function () {
|
||||
var map = L.map(document.createElement('div'));
|
||||
expect(map.getMinZoom()).to.be(0);
|
||||
});
|
||||
});
|
||||
|
||||
it("minZoom and maxZoom options overrides any minZoom and maxZoom set on layers", function () {
|
||||
|
||||
var map = L.map(document.createElement('div'), {minZoom: 2, maxZoom: 20});
|
||||
@ -189,7 +254,7 @@ describe("Map", function () {
|
||||
|
||||
it("adds the layer before firing layeradd", function (done) {
|
||||
var layer = { onAdd: sinon.spy(), onRemove: sinon.spy() };
|
||||
map.on('layeradd', function() {
|
||||
map.on('layeradd', function () {
|
||||
expect(map.hasLayer(layer)).to.be.ok();
|
||||
done();
|
||||
});
|
||||
@ -202,7 +267,7 @@ describe("Map", function () {
|
||||
var spy = sinon.spy();
|
||||
map.on("zoomlevelschange", spy);
|
||||
expect(spy.called).not.to.be.ok();
|
||||
L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 10 }).addTo(map);
|
||||
L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map);
|
||||
expect(spy.called).to.be.ok();
|
||||
});
|
||||
});
|
||||
@ -210,10 +275,10 @@ describe("Map", function () {
|
||||
describe("when a new layer with greater zoomlevel coverage than the current layer is added to a map", function () {
|
||||
it("fires a zoomlevelschange event", function () {
|
||||
var spy = sinon.spy();
|
||||
L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 10 }).addTo(map);
|
||||
L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map);
|
||||
map.on("zoomlevelschange", spy);
|
||||
expect(spy.called).not.to.be.ok();
|
||||
L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 15 }).addTo(map);
|
||||
L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 15}).addTo(map);
|
||||
expect(spy.called).to.be.ok();
|
||||
});
|
||||
});
|
||||
@ -221,12 +286,12 @@ describe("Map", function () {
|
||||
describe("when a new layer with the same or lower zoomlevel coverage as the current layer is added to a map", function () {
|
||||
it("fires no zoomlevelschange event", function () {
|
||||
var spy = sinon.spy();
|
||||
L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 10 }).addTo(map);
|
||||
L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map);
|
||||
map.on("zoomlevelschange", spy);
|
||||
expect(spy.called).not.to.be.ok();
|
||||
L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 10 }).addTo(map);
|
||||
L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map);
|
||||
expect(spy.called).not.to.be.ok();
|
||||
L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 5 }).addTo(map);
|
||||
L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 5}).addTo(map);
|
||||
expect(spy.called).not.to.be.ok();
|
||||
});
|
||||
});
|
||||
@ -285,7 +350,7 @@ describe("Map", function () {
|
||||
|
||||
it("removes the layer before firing layerremove", function (done) {
|
||||
var layer = { onAdd: sinon.spy(), onRemove: sinon.spy() };
|
||||
map.on('layerremove', function() {
|
||||
map.on('layerremove', function () {
|
||||
expect(map.hasLayer(layer)).not.to.be.ok();
|
||||
done();
|
||||
});
|
||||
@ -296,9 +361,9 @@ describe("Map", function () {
|
||||
|
||||
describe("when the last tile layer on a map is removed", function () {
|
||||
it("fires a zoomlevelschange event", function () {
|
||||
map.whenReady(function(){
|
||||
map.whenReady(function () {
|
||||
var spy = sinon.spy();
|
||||
var tl = L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 10 }).addTo(map);
|
||||
var tl = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map);
|
||||
|
||||
map.on("zoomlevelschange", spy);
|
||||
expect(spy.called).not.to.be.ok();
|
||||
@ -310,10 +375,10 @@ describe("Map", function () {
|
||||
|
||||
describe("when a tile layer is removed from a map and it had greater zoom level coverage than the remainding layer", function () {
|
||||
it("fires a zoomlevelschange event", function () {
|
||||
map.whenReady(function(){
|
||||
map.whenReady(function () {
|
||||
var spy = sinon.spy(),
|
||||
tl = L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 10 }).addTo(map),
|
||||
t2 = L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 15 }).addTo(map);
|
||||
tl = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map),
|
||||
t2 = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 15}).addTo(map);
|
||||
|
||||
map.on("zoomlevelschange", spy);
|
||||
expect(spy.called).to.not.be.ok();
|
||||
@ -325,10 +390,10 @@ describe("Map", function () {
|
||||
|
||||
describe("when a tile layer is removed from a map it and it had lesser or the sa,e zoom level coverage as the remainding layer(s)", function () {
|
||||
it("fires no zoomlevelschange event", function () {
|
||||
map.whenReady(function(){
|
||||
var tl = L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 10 }).addTo(map),
|
||||
t2 = L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 10 }).addTo(map),
|
||||
t3 = L.tileLayer("{z}{x}{y}", { minZoom:0, maxZoom: 5 }).addTo(map);
|
||||
map.whenReady(function () {
|
||||
var tl = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map),
|
||||
t2 = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map),
|
||||
t3 = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 5}).addTo(map);
|
||||
|
||||
map.on("zoomlevelschange", spy);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
@ -367,4 +432,105 @@ describe("Map", function () {
|
||||
expect(spy.thisValues[0]).to.eql(map);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#invalidateSize", function () {
|
||||
var container,
|
||||
origWidth = 100,
|
||||
clock;
|
||||
|
||||
beforeEach(function () {
|
||||
container = map.getContainer();
|
||||
container.style.width = origWidth + "px";
|
||||
document.body.appendChild(container);
|
||||
map.setView([0, 0], 0);
|
||||
map.invalidateSize({pan: false});
|
||||
clock = sinon.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
document.body.removeChild(container);
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
it("pans by the right amount when growing in 1px increments", function () {
|
||||
container.style.width = (origWidth + 1) + "px";
|
||||
map.invalidateSize();
|
||||
expect(map._getMapPanePos().x).to.be(1);
|
||||
|
||||
container.style.width = (origWidth + 2) + "px";
|
||||
map.invalidateSize();
|
||||
expect(map._getMapPanePos().x).to.be(1);
|
||||
|
||||
container.style.width = (origWidth + 3) + "px";
|
||||
map.invalidateSize();
|
||||
expect(map._getMapPanePos().x).to.be(2);
|
||||
});
|
||||
|
||||
it("pans by the right amount when shrinking in 1px increments", function () {
|
||||
container.style.width = (origWidth - 1) + "px";
|
||||
map.invalidateSize();
|
||||
expect(map._getMapPanePos().x).to.be(0);
|
||||
|
||||
container.style.width = (origWidth - 2) + "px";
|
||||
map.invalidateSize();
|
||||
expect(map._getMapPanePos().x).to.be(-1);
|
||||
|
||||
container.style.width = (origWidth - 3) + "px";
|
||||
map.invalidateSize();
|
||||
expect(map._getMapPanePos().x).to.be(-1);
|
||||
});
|
||||
|
||||
it("pans back to the original position after growing by an odd size and back", function () {
|
||||
container.style.width = (origWidth + 5) + "px";
|
||||
map.invalidateSize();
|
||||
|
||||
container.style.width = origWidth + "px";
|
||||
map.invalidateSize();
|
||||
|
||||
expect(map._getMapPanePos().x).to.be(0);
|
||||
});
|
||||
|
||||
it("emits no move event if the size has not changed", function () {
|
||||
var spy = sinon.spy();
|
||||
map.on("move", spy);
|
||||
|
||||
map.invalidateSize();
|
||||
|
||||
expect(spy.called).not.to.be.ok();
|
||||
});
|
||||
|
||||
it("emits a move event if the size has changed", function () {
|
||||
var spy = sinon.spy();
|
||||
map.on("move", spy);
|
||||
|
||||
container.style.width = (origWidth + 5) + "px";
|
||||
map.invalidateSize();
|
||||
|
||||
expect(spy.called).to.be.ok();
|
||||
});
|
||||
|
||||
it("emits a moveend event if the size has changed", function () {
|
||||
var spy = sinon.spy();
|
||||
map.on("moveend", spy);
|
||||
|
||||
container.style.width = (origWidth + 5) + "px";
|
||||
map.invalidateSize();
|
||||
|
||||
expect(spy.called).to.be.ok();
|
||||
});
|
||||
|
||||
it("debounces the moveend event if the debounceMoveend option is given", function () {
|
||||
var spy = sinon.spy();
|
||||
map.on("moveend", spy);
|
||||
|
||||
container.style.width = (origWidth + 5) + "px";
|
||||
map.invalidateSize({debounceMoveend: true});
|
||||
|
||||
expect(spy.called).not.to.be.ok();
|
||||
|
||||
clock.tick(200);
|
||||
|
||||
expect(spy.called).to.be.ok();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
38
spec/suites/map/handler/Map.DragSpec.js
Normal file
38
spec/suites/map/handler/Map.DragSpec.js
Normal file
@ -0,0 +1,38 @@
|
||||
describe("Map.Drag", function () {
|
||||
describe("#addHook", function () {
|
||||
it("calls the map with dragging enabled", function () {
|
||||
var container = document.createElement('div'),
|
||||
map = new L.Map(container, {
|
||||
dragging: true
|
||||
});
|
||||
|
||||
expect(map.dragging.enabled()).to.be(true);
|
||||
map.setView([0, 0], 0);
|
||||
expect(map.dragging.enabled()).to.be(true);
|
||||
});
|
||||
it("calls the map with dragging and worldCopyJump enabled", function () {
|
||||
var container = document.createElement('div'),
|
||||
map = new L.Map(container, {
|
||||
dragging: true,
|
||||
worldCopyJump: true
|
||||
});
|
||||
|
||||
expect(map.dragging.enabled()).to.be(true);
|
||||
map.setView([0, 0], 0);
|
||||
expect(map.dragging.enabled()).to.be(true);
|
||||
});
|
||||
it("calls the map with dragging disabled and worldCopyJump enabled; " +
|
||||
"enables dragging after setting center and zoom", function () {
|
||||
var container = document.createElement('div'),
|
||||
map = new L.Map(container, {
|
||||
dragging: false,
|
||||
worldCopyJump: true
|
||||
});
|
||||
|
||||
expect(map.dragging.enabled()).to.be(false);
|
||||
map.setView([0, 0], 0);
|
||||
map.dragging.enable();
|
||||
expect(map.dragging.enabled()).to.be(true);
|
||||
});
|
||||
});
|
||||
});
|
@ -2,7 +2,7 @@
|
||||
var oldL = window.L,
|
||||
L = {};
|
||||
|
||||
L.version = '0.6.4';
|
||||
L.version = '0.7';
|
||||
|
||||
// define Leaflet for Node module pattern loaders, including Browserify
|
||||
if (typeof module === 'object' && typeof module.exports === 'object') {
|
||||
|
@ -18,6 +18,12 @@ L.Control.Attribution = L.Control.extend({
|
||||
this._container = L.DomUtil.create('div', 'leaflet-control-attribution');
|
||||
L.DomEvent.disableClickPropagation(this._container);
|
||||
|
||||
for (var i in map._layers) {
|
||||
if (map._layers[i].getAttribution) {
|
||||
this.addAttribution(map._layers[i].getAttribution());
|
||||
}
|
||||
}
|
||||
|
||||
map
|
||||
.on('layeradd', this._onLayerAdd, this)
|
||||
.on('layerremove', this._onLayerRemove, this);
|
||||
|
@ -69,8 +69,9 @@ L.Control.Layers = L.Control.extend({
|
||||
container.setAttribute('aria-haspopup', true);
|
||||
|
||||
if (!L.Browser.touch) {
|
||||
L.DomEvent.disableClickPropagation(container);
|
||||
L.DomEvent.on(container, 'mousewheel', L.DomEvent.stopPropagation);
|
||||
L.DomEvent
|
||||
.disableClickPropagation(container)
|
||||
.disableScrollPropagation(container);
|
||||
} else {
|
||||
L.DomEvent.on(container, 'click', L.DomEvent.stopPropagation);
|
||||
}
|
||||
@ -95,6 +96,10 @@ L.Control.Layers = L.Control.extend({
|
||||
else {
|
||||
L.DomEvent.on(link, 'focus', this._expand, this);
|
||||
}
|
||||
//Work around for Firefox android issue https://github.com/Leaflet/Leaflet/issues/2033
|
||||
L.DomEvent.on(form, 'click', function () {
|
||||
setTimeout(L.bind(this._onInputClick, this), 0);
|
||||
}, this);
|
||||
|
||||
this._map.on('click', this._collapse, this);
|
||||
// TODO keyboard accessibility
|
||||
@ -229,6 +234,8 @@ L.Control.Layers = L.Control.extend({
|
||||
}
|
||||
|
||||
this._handlingClick = false;
|
||||
|
||||
this._refocusOnMap();
|
||||
},
|
||||
|
||||
_expand: function () {
|
||||
|
@ -4,7 +4,11 @@
|
||||
|
||||
L.Control.Zoom = L.Control.extend({
|
||||
options: {
|
||||
position: 'topleft'
|
||||
position: 'topleft',
|
||||
zoomInText: '+',
|
||||
zoomInTitle: 'Zoom in',
|
||||
zoomOutText: '-',
|
||||
zoomOutTitle: 'Zoom out'
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
@ -14,10 +18,13 @@ L.Control.Zoom = L.Control.extend({
|
||||
this._map = map;
|
||||
|
||||
this._zoomInButton = this._createButton(
|
||||
'+', 'Zoom in', zoomName + '-in', container, this._zoomIn, this);
|
||||
this.options.zoomInText, this.options.zoomInTitle,
|
||||
zoomName + '-in', container, this._zoomIn, this);
|
||||
this._zoomOutButton = this._createButton(
|
||||
'-', 'Zoom out', zoomName + '-out', container, this._zoomOut, this);
|
||||
this.options.zoomOutText, this.options.zoomOutTitle,
|
||||
zoomName + '-out', container, this._zoomOut, this);
|
||||
|
||||
this._updateDisabled();
|
||||
map.on('zoomend zoomlevelschange', this._updateDisabled, this);
|
||||
|
||||
return container;
|
||||
@ -48,7 +55,8 @@ L.Control.Zoom = L.Control.extend({
|
||||
.on(link, 'mousedown', stop)
|
||||
.on(link, 'dblclick', stop)
|
||||
.on(link, 'click', L.DomEvent.preventDefault)
|
||||
.on(link, 'click', fn, context);
|
||||
.on(link, 'click', fn, context)
|
||||
.on(link, 'click', this._refocusOnMap, context);
|
||||
|
||||
return link;
|
||||
},
|
||||
|
@ -66,6 +66,12 @@ L.Control = L.Class.extend({
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_refocusOnMap: function () {
|
||||
if (this._map) {
|
||||
this._map.getContainer().focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -4,9 +4,7 @@
|
||||
|
||||
(function () {
|
||||
|
||||
var ie = !!window.ActiveXObject,
|
||||
ie6 = ie && !window.XMLHttpRequest,
|
||||
ie7 = ie && !document.querySelector,
|
||||
var ie = 'ActiveXObject' in window,
|
||||
ielt9 = ie && !document.addEventListener,
|
||||
|
||||
// terrible browser detection to work around Safari / iOS / Android browser bugs
|
||||
@ -16,10 +14,13 @@
|
||||
phantomjs = ua.indexOf('phantom') !== -1,
|
||||
android = ua.indexOf('android') !== -1,
|
||||
android23 = ua.search('android [23]') !== -1,
|
||||
gecko = ua.indexOf('gecko') !== -1,
|
||||
|
||||
mobile = typeof orientation !== undefined + '',
|
||||
msTouch = window.navigator && window.navigator.msPointerEnabled &&
|
||||
window.navigator.msMaxTouchPoints,
|
||||
msPointer = window.navigator && window.navigator.msPointerEnabled &&
|
||||
window.navigator.msMaxTouchPoints && !window.PointerEvent,
|
||||
pointer = (window.PointerEvent && window.navigator.pointerEnabled && window.navigator.maxTouchPoints) ||
|
||||
msPointer,
|
||||
retina = ('devicePixelRatio' in window && window.devicePixelRatio > 1) ||
|
||||
('matchMedia' in window && window.matchMedia('(min-resolution:144dpi)') &&
|
||||
window.matchMedia('(min-resolution:144dpi)').matches),
|
||||
@ -39,8 +40,8 @@
|
||||
|
||||
var startName = 'ontouchstart';
|
||||
|
||||
// IE10+ (We simulate these into touch* events in L.DomEvent and L.DomEvent.MsTouch) or WebKit, etc.
|
||||
if (msTouch || (startName in doc)) {
|
||||
// IE10+ (We simulate these into touch* events in L.DomEvent and L.DomEvent.Pointer) or WebKit, etc.
|
||||
if (pointer || (startName in doc)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -66,10 +67,9 @@
|
||||
|
||||
L.Browser = {
|
||||
ie: ie,
|
||||
ie6: ie6,
|
||||
ie7: ie7,
|
||||
ielt9: ielt9,
|
||||
webkit: webkit,
|
||||
gecko: gecko && !webkit && !window.opera && !ie,
|
||||
|
||||
android: android,
|
||||
android23: android23,
|
||||
@ -88,7 +88,8 @@
|
||||
mobileOpera: mobile && window.opera,
|
||||
|
||||
touch: touch,
|
||||
msTouch: msTouch,
|
||||
msPointer: msPointer,
|
||||
pointer: pointer,
|
||||
|
||||
retina: retina
|
||||
};
|
||||
|
@ -14,7 +14,7 @@ L.Mixin.Events = {
|
||||
if (L.Util.invokeEach(types, this.addEventListener, this, fn, context)) { return this; }
|
||||
|
||||
var events = this[eventsKey] = this[eventsKey] || {},
|
||||
contextId = context && L.stamp(context),
|
||||
contextId = context && context !== this && L.stamp(context),
|
||||
i, len, event, type, indexKey, indexLenKey, typeIndex;
|
||||
|
||||
// types can be a string of space-separated words
|
||||
@ -27,7 +27,7 @@ L.Mixin.Events = {
|
||||
};
|
||||
type = types[i];
|
||||
|
||||
if (context) {
|
||||
if (contextId) {
|
||||
// store listeners of a particular context in a separate hash (if it has an id)
|
||||
// gives a major performance boost when removing thousands of map layers
|
||||
|
||||
@ -74,7 +74,7 @@ L.Mixin.Events = {
|
||||
if (L.Util.invokeEach(types, this.removeEventListener, this, fn, context)) { return this; }
|
||||
|
||||
var events = this[eventsKey],
|
||||
contextId = context && L.stamp(context),
|
||||
contextId = context && context !== this && L.stamp(context),
|
||||
i, len, type, listeners, j, indexKey, indexLenKey, typeIndex, removed;
|
||||
|
||||
types = L.Util.splitWords(types);
|
||||
@ -90,9 +90,10 @@ L.Mixin.Events = {
|
||||
// clear all listeners for a type if function isn't specified
|
||||
delete events[type];
|
||||
delete events[indexKey];
|
||||
delete events[indexLenKey];
|
||||
|
||||
} else {
|
||||
listeners = context && typeIndex ? typeIndex[contextId] : events[type];
|
||||
listeners = contextId && typeIndex ? typeIndex[contextId] : events[type];
|
||||
|
||||
if (listeners) {
|
||||
for (j = listeners.length - 1; j >= 0; j--) {
|
||||
@ -135,7 +136,7 @@ L.Mixin.Events = {
|
||||
listeners = events[type].slice();
|
||||
|
||||
for (i = 0, len = listeners.length; i < len; i++) {
|
||||
listeners[i].action.call(listeners[i].context || this, event);
|
||||
listeners[i].action.call(listeners[i].context, event);
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,7 +148,7 @@ L.Mixin.Events = {
|
||||
|
||||
if (listeners) {
|
||||
for (i = 0, len = listeners.length; i < len; i++) {
|
||||
listeners[i].action.call(listeners[i].context || this, event);
|
||||
listeners[i].action.call(listeners[i].context, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,19 +105,23 @@ L.Util = {
|
||||
return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');
|
||||
},
|
||||
|
||||
template: function (str, data) {
|
||||
return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) {
|
||||
var value = data[key];
|
||||
if (value === undefined) {
|
||||
throw new Error('No value provided for variable ' + str);
|
||||
} else if (typeof value === 'function') {
|
||||
value = value(data);
|
||||
}
|
||||
return value;
|
||||
compileTemplate: function (str, data) {
|
||||
// based on https://gist.github.com/padolsey/6008842
|
||||
str = str.replace(/"/g, '\\\"');
|
||||
str = str.replace(/\{ *([\w_]+) *\}/g, function (str, key) {
|
||||
return '" + o["' + key + '"]' + (typeof data[key] === 'function' ? '(o)' : '') + ' + "';
|
||||
});
|
||||
// jshint evil: true
|
||||
return new Function('o', 'return "' + str + '";');
|
||||
},
|
||||
|
||||
isArray: function (obj) {
|
||||
template: function (str, data) {
|
||||
var cache = L.Util._templateCache = L.Util._templateCache || {};
|
||||
cache[str] = cache[str] || L.Util.compileTemplate(str, data);
|
||||
return cache[str](data);
|
||||
},
|
||||
|
||||
isArray: Array.isArray || function (obj) {
|
||||
return (Object.prototype.toString.call(obj) === '[object Array]');
|
||||
},
|
||||
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
L.extend(L.DomEvent, {
|
||||
|
||||
_touchstart: L.Browser.msTouch ? 'MSPointerDown' : 'touchstart',
|
||||
_touchend: L.Browser.msTouch ? 'MSPointerUp' : 'touchend',
|
||||
_touchstart: L.Browser.msPointer ? 'MSPointerDown' : L.Browser.pointer ? 'pointerdown' : 'touchstart',
|
||||
_touchend: L.Browser.msPointer ? 'MSPointerUp' : L.Browser.pointer ? 'pointerup' : 'touchend',
|
||||
|
||||
// inspired by Zepto touch code by Thomas Fuchs
|
||||
addDoubleTapListener: function (obj, handler, id) {
|
||||
@ -21,7 +21,7 @@ L.extend(L.DomEvent, {
|
||||
function onTouchStart(e) {
|
||||
var count;
|
||||
|
||||
if (L.Browser.msTouch) {
|
||||
if (L.Browser.pointer) {
|
||||
trackedTouches.push(e.pointerId);
|
||||
count = trackedTouches.length;
|
||||
} else {
|
||||
@ -40,7 +40,7 @@ L.extend(L.DomEvent, {
|
||||
}
|
||||
|
||||
function onTouchEnd(e) {
|
||||
if (L.Browser.msTouch) {
|
||||
if (L.Browser.pointer) {
|
||||
var idx = trackedTouches.indexOf(e.pointerId);
|
||||
if (idx === -1) {
|
||||
return;
|
||||
@ -49,7 +49,7 @@ L.extend(L.DomEvent, {
|
||||
}
|
||||
|
||||
if (doubleTap) {
|
||||
if (L.Browser.msTouch) {
|
||||
if (L.Browser.pointer) {
|
||||
// work around .type being readonly with MSPointer* events
|
||||
var newTouch = { },
|
||||
prop;
|
||||
@ -73,15 +73,15 @@ L.extend(L.DomEvent, {
|
||||
obj[pre + touchstart + id] = onTouchStart;
|
||||
obj[pre + touchend + id] = onTouchEnd;
|
||||
|
||||
// on msTouch we need to listen on the document, otherwise a drag starting on the map and moving off screen
|
||||
// on pointer we need to listen on the document, otherwise a drag starting on the map and moving off screen
|
||||
// will not come through to us, so we will lose track of how many touches are ongoing
|
||||
var endElement = L.Browser.msTouch ? document.documentElement : obj;
|
||||
var endElement = L.Browser.pointer ? document.documentElement : obj;
|
||||
|
||||
obj.addEventListener(touchstart, onTouchStart, false);
|
||||
endElement.addEventListener(touchend, onTouchEnd, false);
|
||||
|
||||
if (L.Browser.msTouch) {
|
||||
endElement.addEventListener('MSPointerCancel', onTouchEnd, false);
|
||||
if (L.Browser.pointer) {
|
||||
endElement.addEventListener(L.DomEvent.POINTER_CANCEL, onTouchEnd, false);
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -91,11 +91,12 @@ L.extend(L.DomEvent, {
|
||||
var pre = '_leaflet_';
|
||||
|
||||
obj.removeEventListener(this._touchstart, obj[pre + this._touchstart + id], false);
|
||||
(L.Browser.msTouch ? document.documentElement : obj).removeEventListener(
|
||||
(L.Browser.pointer ? document.documentElement : obj).removeEventListener(
|
||||
this._touchend, obj[pre + this._touchend + id], false);
|
||||
|
||||
if (L.Browser.msTouch) {
|
||||
document.documentElement.removeEventListener('MSPointerCancel', obj[pre + this._touchend + id], false);
|
||||
if (L.Browser.pointer) {
|
||||
document.documentElement.removeEventListener(L.DomEvent.POINTER_CANCEL, obj[pre + this._touchend + id],
|
||||
false);
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
|
||||
*/
|
||||
|
||||
L.extend(L.DomEvent, {
|
||||
|
||||
_msTouches: [],
|
||||
_msDocumentListener: false,
|
||||
|
||||
// Provides a touch events wrapper for msPointer events.
|
||||
// Based on changes by veproza https://github.com/CloudMade/Leaflet/pull/1019
|
||||
|
||||
addMsTouchListener: function (obj, type, handler, id) {
|
||||
|
||||
switch (type) {
|
||||
case 'touchstart':
|
||||
return this.addMsTouchListenerStart(obj, type, handler, id);
|
||||
case 'touchend':
|
||||
return this.addMsTouchListenerEnd(obj, type, handler, id);
|
||||
case 'touchmove':
|
||||
return this.addMsTouchListenerMove(obj, type, handler, id);
|
||||
default:
|
||||
throw 'Unknown touch event type';
|
||||
}
|
||||
},
|
||||
|
||||
addMsTouchListenerStart: function (obj, type, handler, id) {
|
||||
var pre = '_leaflet_',
|
||||
touches = this._msTouches;
|
||||
|
||||
var cb = function (e) {
|
||||
|
||||
var alreadyInArray = false;
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
if (touches[i].pointerId === e.pointerId) {
|
||||
alreadyInArray = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alreadyInArray) {
|
||||
touches.push(e);
|
||||
}
|
||||
|
||||
e.touches = touches.slice();
|
||||
e.changedTouches = [e];
|
||||
|
||||
handler(e);
|
||||
};
|
||||
|
||||
obj[pre + 'touchstart' + id] = cb;
|
||||
obj.addEventListener('MSPointerDown', cb, false);
|
||||
|
||||
// need to also listen for end events to keep the _msTouches list accurate
|
||||
// this needs to be on the body and never go away
|
||||
if (!this._msDocumentListener) {
|
||||
var internalCb = function (e) {
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
if (touches[i].pointerId === e.pointerId) {
|
||||
touches.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
//We listen on the documentElement as any drags that end by moving the touch off the screen get fired there
|
||||
document.documentElement.addEventListener('MSPointerUp', internalCb, false);
|
||||
document.documentElement.addEventListener('MSPointerCancel', internalCb, false);
|
||||
|
||||
this._msDocumentListener = true;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
addMsTouchListenerMove: function (obj, type, handler, id) {
|
||||
var pre = '_leaflet_',
|
||||
touches = this._msTouches;
|
||||
|
||||
function cb(e) {
|
||||
|
||||
// don't fire touch moves when mouse isn't down
|
||||
if (e.pointerType === e.MSPOINTER_TYPE_MOUSE && e.buttons === 0) { return; }
|
||||
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
if (touches[i].pointerId === e.pointerId) {
|
||||
touches[i] = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
e.touches = touches.slice();
|
||||
e.changedTouches = [e];
|
||||
|
||||
handler(e);
|
||||
}
|
||||
|
||||
obj[pre + 'touchmove' + id] = cb;
|
||||
obj.addEventListener('MSPointerMove', cb, false);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
addMsTouchListenerEnd: function (obj, type, handler, id) {
|
||||
var pre = '_leaflet_',
|
||||
touches = this._msTouches;
|
||||
|
||||
var cb = function (e) {
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
if (touches[i].pointerId === e.pointerId) {
|
||||
touches.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
e.touches = touches.slice();
|
||||
e.changedTouches = [e];
|
||||
|
||||
handler(e);
|
||||
};
|
||||
|
||||
obj[pre + 'touchend' + id] = cb;
|
||||
obj.addEventListener('MSPointerUp', cb, false);
|
||||
obj.addEventListener('MSPointerCancel', cb, false);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
removeMsTouchListener: function (obj, type, id) {
|
||||
var pre = '_leaflet_',
|
||||
cb = obj[pre + type + id];
|
||||
|
||||
switch (type) {
|
||||
case 'touchstart':
|
||||
obj.removeEventListener('MSPointerDown', cb, false);
|
||||
break;
|
||||
case 'touchmove':
|
||||
obj.removeEventListener('MSPointerMove', cb, false);
|
||||
break;
|
||||
case 'touchend':
|
||||
obj.removeEventListener('MSPointerUp', cb, false);
|
||||
obj.removeEventListener('MSPointerCancel', cb, false);
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
155
src/dom/DomEvent.Pointer.js
Normal file
155
src/dom/DomEvent.Pointer.js
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.
|
||||
*/
|
||||
|
||||
L.extend(L.DomEvent, {
|
||||
|
||||
//static
|
||||
POINTER_DOWN: L.Browser.msPointer ? 'MSPointerDown' : 'pointerdown',
|
||||
POINTER_MOVE: L.Browser.msPointer ? 'MSPointerMove' : 'pointermove',
|
||||
POINTER_UP: L.Browser.msPointer ? 'MSPointerUp' : 'pointerup',
|
||||
POINTER_CANCEL: L.Browser.msPointer ? 'MSPointerCancel' : 'pointercancel',
|
||||
|
||||
_pointers: [],
|
||||
_pointerDocumentListener: false,
|
||||
|
||||
// Provides a touch events wrapper for (ms)pointer events.
|
||||
// Based on changes by veproza https://github.com/CloudMade/Leaflet/pull/1019
|
||||
//ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890
|
||||
|
||||
addPointerListener: function (obj, type, handler, id) {
|
||||
|
||||
switch (type) {
|
||||
case 'touchstart':
|
||||
return this.addPointerListenerStart(obj, type, handler, id);
|
||||
case 'touchend':
|
||||
return this.addPointerListenerEnd(obj, type, handler, id);
|
||||
case 'touchmove':
|
||||
return this.addPointerListenerMove(obj, type, handler, id);
|
||||
default:
|
||||
throw 'Unknown touch event type';
|
||||
}
|
||||
},
|
||||
|
||||
addPointerListenerStart: function (obj, type, handler, id) {
|
||||
var pre = '_leaflet_',
|
||||
pointers = this._pointers;
|
||||
|
||||
var cb = function (e) {
|
||||
|
||||
L.DomEvent.preventDefault(e);
|
||||
|
||||
var alreadyInArray = false;
|
||||
for (var i = 0; i < pointers.length; i++) {
|
||||
if (pointers[i].pointerId === e.pointerId) {
|
||||
alreadyInArray = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alreadyInArray) {
|
||||
pointers.push(e);
|
||||
}
|
||||
|
||||
e.touches = pointers.slice();
|
||||
e.changedTouches = [e];
|
||||
|
||||
handler(e);
|
||||
};
|
||||
|
||||
obj[pre + 'touchstart' + id] = cb;
|
||||
obj.addEventListener(this.POINTER_DOWN, cb, false);
|
||||
|
||||
// need to also listen for end events to keep the _pointers list accurate
|
||||
// this needs to be on the body and never go away
|
||||
if (!this._pointerDocumentListener) {
|
||||
var internalCb = function (e) {
|
||||
for (var i = 0; i < pointers.length; i++) {
|
||||
if (pointers[i].pointerId === e.pointerId) {
|
||||
pointers.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
//We listen on the documentElement as any drags that end by moving the touch off the screen get fired there
|
||||
document.documentElement.addEventListener(this.POINTER_UP, internalCb, false);
|
||||
document.documentElement.addEventListener(this.POINTER_CANCEL, internalCb, false);
|
||||
|
||||
this._pointerDocumentListener = true;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
addPointerListenerMove: function (obj, type, handler, id) {
|
||||
var pre = '_leaflet_',
|
||||
touches = this._pointers;
|
||||
|
||||
function cb(e) {
|
||||
|
||||
// don't fire touch moves when mouse isn't down
|
||||
if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; }
|
||||
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
if (touches[i].pointerId === e.pointerId) {
|
||||
touches[i] = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
e.touches = touches.slice();
|
||||
e.changedTouches = [e];
|
||||
|
||||
handler(e);
|
||||
}
|
||||
|
||||
obj[pre + 'touchmove' + id] = cb;
|
||||
obj.addEventListener(this.POINTER_MOVE, cb, false);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
addPointerListenerEnd: function (obj, type, handler, id) {
|
||||
var pre = '_leaflet_',
|
||||
touches = this._pointers;
|
||||
|
||||
var cb = function (e) {
|
||||
for (var i = 0; i < touches.length; i++) {
|
||||
if (touches[i].pointerId === e.pointerId) {
|
||||
touches.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
e.touches = touches.slice();
|
||||
e.changedTouches = [e];
|
||||
|
||||
handler(e);
|
||||
};
|
||||
|
||||
obj[pre + 'touchend' + id] = cb;
|
||||
obj.addEventListener(this.POINTER_UP, cb, false);
|
||||
obj.addEventListener(this.POINTER_CANCEL, cb, false);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
removePointerListener: function (obj, type, id) {
|
||||
var pre = '_leaflet_',
|
||||
cb = obj[pre + type + id];
|
||||
|
||||
switch (type) {
|
||||
case 'touchstart':
|
||||
obj.removeEventListener(this.POINTER_DOWN, cb, false);
|
||||
break;
|
||||
case 'touchmove':
|
||||
obj.removeEventListener(this.POINTER_MOVE, cb, false);
|
||||
break;
|
||||
case 'touchend':
|
||||
obj.removeEventListener(this.POINTER_UP, cb, false);
|
||||
obj.removeEventListener(this.POINTER_CANCEL, cb, false);
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
@ -16,8 +16,8 @@ L.DomEvent = {
|
||||
return fn.call(context || obj, e || L.DomEvent._getEvent());
|
||||
};
|
||||
|
||||
if (L.Browser.msTouch && type.indexOf('touch') === 0) {
|
||||
return this.addMsTouchListener(obj, type, handler, id);
|
||||
if (L.Browser.pointer && type.indexOf('touch') === 0) {
|
||||
return this.addPointerListener(obj, type, handler, id);
|
||||
}
|
||||
if (L.Browser.touch && (type === 'dblclick') && this.addDoubleTapListener) {
|
||||
this.addDoubleTapListener(obj, handler, id);
|
||||
@ -69,8 +69,8 @@ L.DomEvent = {
|
||||
|
||||
if (!handler) { return this; }
|
||||
|
||||
if (L.Browser.msTouch && type.indexOf('touch') === 0) {
|
||||
this.removeMsTouchListener(obj, type, id);
|
||||
if (L.Browser.pointer && type.indexOf('touch') === 0) {
|
||||
this.removePointerListener(obj, type, id);
|
||||
} else if (L.Browser.touch && (type === 'dblclick') && this.removeDoubleTapListener) {
|
||||
this.removeDoubleTapListener(obj, id);
|
||||
|
||||
@ -101,19 +101,29 @@ L.DomEvent = {
|
||||
} else {
|
||||
e.cancelBubble = true;
|
||||
}
|
||||
L.DomEvent._skipped(e);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
disableScrollPropagation: function (el) {
|
||||
var stop = L.DomEvent.stopPropagation;
|
||||
|
||||
return L.DomEvent
|
||||
.on(el, 'mousewheel', stop)
|
||||
.on(el, 'MozMousePixelScroll', stop);
|
||||
},
|
||||
|
||||
disableClickPropagation: function (el) {
|
||||
var stop = L.DomEvent.stopPropagation;
|
||||
|
||||
for (var i = L.Draggable.START.length - 1; i >= 0; i--) {
|
||||
L.DomEvent.addListener(el, L.Draggable.START[i], stop);
|
||||
L.DomEvent.on(el, L.Draggable.START[i], stop);
|
||||
}
|
||||
|
||||
return L.DomEvent
|
||||
.addListener(el, 'click', L.DomEvent._fakeStop)
|
||||
.addListener(el, 'dblclick', stop);
|
||||
.on(el, 'click', L.DomEvent._fakeStop)
|
||||
.on(el, 'dblclick', stop);
|
||||
},
|
||||
|
||||
preventDefault: function (e) {
|
||||
@ -127,34 +137,31 @@ L.DomEvent = {
|
||||
},
|
||||
|
||||
stop: function (e) {
|
||||
return L.DomEvent.preventDefault(e).stopPropagation(e);
|
||||
return L.DomEvent
|
||||
.preventDefault(e)
|
||||
.stopPropagation(e);
|
||||
},
|
||||
|
||||
getMousePosition: function (e, container) {
|
||||
|
||||
var ie7 = L.Browser.ie7,
|
||||
body = document.body,
|
||||
var body = document.body,
|
||||
docEl = document.documentElement,
|
||||
x = e.pageX ? e.pageX - body.scrollLeft - docEl.scrollLeft: e.clientX,
|
||||
//gecko makes scrollLeft more negative as you scroll in rtl, other browsers don't
|
||||
//ref: https://code.google.com/p/closure-library/source/browse/closure/goog/style/bidi.js
|
||||
x = L.DomUtil.documentIsLtr() ?
|
||||
(e.pageX ? e.pageX - body.scrollLeft - docEl.scrollLeft : e.clientX) :
|
||||
(L.Browser.gecko ? e.pageX - body.scrollLeft - docEl.scrollLeft :
|
||||
e.pageX ? e.pageX - body.scrollLeft + docEl.scrollLeft : e.clientX),
|
||||
y = e.pageY ? e.pageY - body.scrollTop - docEl.scrollTop: e.clientY,
|
||||
pos = new L.Point(x, y),
|
||||
rect = container.getBoundingClientRect(),
|
||||
pos = new L.Point(x, y);
|
||||
|
||||
if (!container) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
var rect = container.getBoundingClientRect(),
|
||||
left = rect.left - container.clientLeft,
|
||||
top = rect.top - container.clientTop;
|
||||
|
||||
// webkit (and ie <= 7) handles RTL scrollLeft different to everyone else
|
||||
// https://code.google.com/p/closure-library/source/browse/trunk/closure/goog/style/bidi.js
|
||||
if (!L.DomUtil.documentIsLtr() && (L.Browser.webkit || ie7)) {
|
||||
left += container.scrollWidth - container.clientWidth;
|
||||
|
||||
// ie7 shows the scrollbar by default and provides clientWidth counting it, so we
|
||||
// need to add it back in if it is visible; scrollbar is on the left as we are RTL
|
||||
if (ie7 && L.DomUtil.getStyle(container, 'overflow-y') !== 'hidden' &&
|
||||
L.DomUtil.getStyle(container, 'overflow') !== 'hidden') {
|
||||
left += 17;
|
||||
}
|
||||
}
|
||||
|
||||
return pos._subtract(new L.Point(left, top));
|
||||
},
|
||||
|
||||
|
@ -30,8 +30,7 @@ L.DomUtil = {
|
||||
el = element,
|
||||
docBody = document.body,
|
||||
docEl = document.documentElement,
|
||||
pos,
|
||||
ie7 = L.Browser.ie7;
|
||||
pos;
|
||||
|
||||
do {
|
||||
top += el.offsetTop || 0;
|
||||
@ -78,19 +77,6 @@ L.DomUtil = {
|
||||
top -= el.scrollTop || 0;
|
||||
left -= el.scrollLeft || 0;
|
||||
|
||||
// webkit (and ie <= 7) handles RTL scrollLeft different to everyone else
|
||||
// https://code.google.com/p/closure-library/source/browse/trunk/closure/goog/style/bidi.js
|
||||
if (!L.DomUtil.documentIsLtr() && (L.Browser.webkit || ie7)) {
|
||||
left += el.scrollWidth - el.clientWidth;
|
||||
|
||||
// ie7 shows the scrollbar by default and provides clientWidth counting it, so we
|
||||
// need to add it back in if it is visible; scrollbar is on the left as we are RTL
|
||||
if (ie7 && L.DomUtil.getStyle(el, 'overflow-y') !== 'hidden' &&
|
||||
L.DomUtil.getStyle(el, 'overflow') !== 'hidden') {
|
||||
left += 17;
|
||||
}
|
||||
}
|
||||
|
||||
el = el.parentNode;
|
||||
} while (el);
|
||||
|
||||
@ -118,18 +104,44 @@ L.DomUtil = {
|
||||
},
|
||||
|
||||
hasClass: function (el, name) {
|
||||
return (el.className.length > 0) &&
|
||||
new RegExp('(^|\\s)' + name + '(\\s|$)').test(el.className);
|
||||
if (el.classList !== undefined) {
|
||||
return el.classList.contains(name);
|
||||
}
|
||||
var className = L.DomUtil._getClass(el);
|
||||
return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className);
|
||||
},
|
||||
|
||||
addClass: function (el, name) {
|
||||
if (!L.DomUtil.hasClass(el, name)) {
|
||||
el.className += (el.className ? ' ' : '') + name;
|
||||
if (el.classList !== undefined) {
|
||||
var classes = L.Util.splitWords(name);
|
||||
for (var i = 0, len = classes.length; i < len; i++) {
|
||||
el.classList.add(classes[i]);
|
||||
}
|
||||
} else if (!L.DomUtil.hasClass(el, name)) {
|
||||
var className = L.DomUtil._getClass(el);
|
||||
L.DomUtil._setClass(el, (className ? className + ' ' : '') + name);
|
||||
}
|
||||
},
|
||||
|
||||
removeClass: function (el, name) {
|
||||
el.className = L.Util.trim((' ' + el.className + ' ').replace(' ' + name + ' ', ' '));
|
||||
if (el.classList !== undefined) {
|
||||
el.classList.remove(name);
|
||||
} else {
|
||||
L.DomUtil._setClass(el, L.Util.trim((' ' + L.DomUtil._getClass(el) + ' ').replace(' ' + name + ' ', ' ')));
|
||||
}
|
||||
},
|
||||
|
||||
_setClass: function (el, name) {
|
||||
if (el.className.baseVal === undefined) {
|
||||
el.className = name;
|
||||
} else {
|
||||
// in case of SVG element
|
||||
el.className.baseVal = name;
|
||||
}
|
||||
},
|
||||
|
||||
_getClass: function (el) {
|
||||
return el.className.baseVal === undefined ? el.className : el.className.baseVal;
|
||||
},
|
||||
|
||||
setOpacity: function (el, value) {
|
||||
@ -238,27 +250,39 @@ L.DomUtil.TRANSITION_END =
|
||||
L.DomUtil.TRANSITION + 'End' : 'transitionend';
|
||||
|
||||
(function () {
|
||||
var userSelectProperty = L.DomUtil.testProp(
|
||||
['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);
|
||||
if ('onselectstart' in document) {
|
||||
L.extend(L.DomUtil, {
|
||||
disableTextSelection: function () {
|
||||
L.DomEvent.on(window, 'selectstart', L.DomEvent.preventDefault);
|
||||
},
|
||||
|
||||
enableTextSelection: function () {
|
||||
L.DomEvent.off(window, 'selectstart', L.DomEvent.preventDefault);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var userSelectProperty = L.DomUtil.testProp(
|
||||
['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);
|
||||
|
||||
L.extend(L.DomUtil, {
|
||||
disableTextSelection: function () {
|
||||
if (userSelectProperty) {
|
||||
var style = document.documentElement.style;
|
||||
this._userSelect = style[userSelectProperty];
|
||||
style[userSelectProperty] = 'none';
|
||||
}
|
||||
},
|
||||
|
||||
enableTextSelection: function () {
|
||||
if (userSelectProperty) {
|
||||
document.documentElement.style[userSelectProperty] = this._userSelect;
|
||||
delete this._userSelect;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
L.extend(L.DomUtil, {
|
||||
disableTextSelection: function () {
|
||||
L.DomEvent.on(window, 'selectstart', L.DomEvent.preventDefault);
|
||||
if (userSelectProperty) {
|
||||
var style = document.documentElement.style;
|
||||
this._userSelect = style[userSelectProperty];
|
||||
style[userSelectProperty] = 'none';
|
||||
}
|
||||
},
|
||||
|
||||
enableTextSelection: function () {
|
||||
L.DomEvent.off(window, 'selectstart', L.DomEvent.preventDefault);
|
||||
if (userSelectProperty) {
|
||||
document.documentElement.style[userSelectProperty] = this._userSelect;
|
||||
delete this._userSelect;
|
||||
}
|
||||
},
|
||||
|
||||
disableImageDrag: function () {
|
||||
L.DomEvent.on(window, 'dragstart', L.DomEvent.preventDefault);
|
||||
},
|
||||
|
@ -10,11 +10,13 @@ L.Draggable = L.Class.extend({
|
||||
END: {
|
||||
mousedown: 'mouseup',
|
||||
touchstart: 'touchend',
|
||||
pointerdown: 'touchend',
|
||||
MSPointerDown: 'touchend'
|
||||
},
|
||||
MOVE: {
|
||||
mousedown: 'mousemove',
|
||||
touchstart: 'touchmove',
|
||||
pointerdown: 'touchmove',
|
||||
MSPointerDown: 'touchmove'
|
||||
}
|
||||
},
|
||||
@ -46,28 +48,21 @@ L.Draggable = L.Class.extend({
|
||||
},
|
||||
|
||||
_onDown: function (e) {
|
||||
this._moved = false;
|
||||
|
||||
if (e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; }
|
||||
|
||||
L.DomEvent
|
||||
.stopPropagation(e);
|
||||
L.DomEvent.stopPropagation(e);
|
||||
|
||||
if (L.Draggable._disabled) { return; }
|
||||
|
||||
L.DomUtil.disableImageDrag();
|
||||
L.DomUtil.disableTextSelection();
|
||||
|
||||
var first = e.touches ? e.touches[0] : e,
|
||||
el = first.target;
|
||||
|
||||
// if touching a link, highlight it
|
||||
if (L.Browser.touch && el.tagName.toLowerCase() === 'a') {
|
||||
L.DomUtil.addClass(el, 'leaflet-active');
|
||||
}
|
||||
|
||||
this._moved = false;
|
||||
|
||||
if (this._moving) { return; }
|
||||
|
||||
var first = e.touches ? e.touches[0] : e;
|
||||
|
||||
this._startPoint = new L.Point(first.clientX, first.clientY);
|
||||
this._startPos = this._newPos = L.DomUtil.getPosition(this._element);
|
||||
|
||||
@ -77,7 +72,10 @@ L.Draggable = L.Class.extend({
|
||||
},
|
||||
|
||||
_onMove: function (e) {
|
||||
if (e.touches && e.touches.length > 1) { return; }
|
||||
if (e.touches && e.touches.length > 1) {
|
||||
this._moved = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),
|
||||
newPoint = new L.Point(first.clientX, first.clientY),
|
||||
@ -93,9 +91,8 @@ L.Draggable = L.Class.extend({
|
||||
this._moved = true;
|
||||
this._startPos = L.DomUtil.getPosition(this._element).subtract(offset);
|
||||
|
||||
if (!L.Browser.touch) {
|
||||
L.DomUtil.addClass(document.body, 'leaflet-dragging');
|
||||
}
|
||||
L.DomUtil.addClass(document.body, 'leaflet-dragging');
|
||||
L.DomUtil.addClass((e.target || e.srcElement), 'leaflet-drag-target');
|
||||
}
|
||||
|
||||
this._newPos = this._startPos.add(offset);
|
||||
@ -111,10 +108,9 @@ L.Draggable = L.Class.extend({
|
||||
this.fire('drag');
|
||||
},
|
||||
|
||||
_onUp: function () {
|
||||
if (!L.Browser.touch) {
|
||||
L.DomUtil.removeClass(document.body, 'leaflet-dragging');
|
||||
}
|
||||
_onUp: function (e) {
|
||||
L.DomUtil.removeClass(document.body, 'leaflet-dragging');
|
||||
L.DomUtil.removeClass((e.target || e.srcElement), 'leaflet-drag-target');
|
||||
|
||||
for (var i in L.Draggable.MOVE) {
|
||||
L.DomEvent
|
||||
@ -129,7 +125,9 @@ L.Draggable = L.Class.extend({
|
||||
// ensure drag is not fired after dragend
|
||||
L.Util.cancelAnimFrame(this._animRequest);
|
||||
|
||||
this.fire('dragend');
|
||||
this.fire('dragend', {
|
||||
distance: this._newPos.distanceTo(this._startPos)
|
||||
});
|
||||
}
|
||||
|
||||
this._moving = false;
|
||||
|
@ -2,16 +2,20 @@
|
||||
* L.LatLng represents a geographical point with latitude and longitude coordinates.
|
||||
*/
|
||||
|
||||
L.LatLng = function (rawLat, rawLng) { // (Number, Number)
|
||||
var lat = parseFloat(rawLat),
|
||||
lng = parseFloat(rawLng);
|
||||
L.LatLng = function (lat, lng, alt) { // (Number, Number, Number)
|
||||
lat = parseFloat(lat);
|
||||
lng = parseFloat(lng);
|
||||
|
||||
if (isNaN(lat) || isNaN(lng)) {
|
||||
throw new Error('Invalid LatLng object: (' + rawLat + ', ' + rawLng + ')');
|
||||
throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');
|
||||
}
|
||||
|
||||
this.lat = lat;
|
||||
this.lng = lng;
|
||||
|
||||
if (alt !== undefined) {
|
||||
this.alt = parseFloat(alt);
|
||||
}
|
||||
};
|
||||
|
||||
L.extend(L.LatLng, {
|
||||
@ -75,7 +79,11 @@ L.latLng = function (a, b) { // (LatLng) or ([Number, Number]) or (Number, Numbe
|
||||
return a;
|
||||
}
|
||||
if (L.Util.isArray(a)) {
|
||||
return new L.LatLng(a[0], a[1]);
|
||||
if (typeof a[0] === 'number' || typeof a[0] === 'string') {
|
||||
return new L.LatLng(a[0], a[1], a[2]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (a === undefined || a === null) {
|
||||
return a;
|
||||
@ -83,6 +91,9 @@ L.latLng = function (a, b) { // (LatLng) or ([Number, Number]) or (Number, Numbe
|
||||
if (typeof a === 'object' && 'lat' in a) {
|
||||
return new L.LatLng(a.lat, 'lng' in a ? a.lng : a.lon);
|
||||
}
|
||||
if (b === undefined) {
|
||||
return null;
|
||||
}
|
||||
return new L.LatLng(a, b);
|
||||
};
|
||||
|
||||
|
@ -17,8 +17,9 @@ L.LatLngBounds.prototype = {
|
||||
extend: function (obj) { // (LatLng) or (LatLngBounds)
|
||||
if (!obj) { return this; }
|
||||
|
||||
if (typeof obj[0] === 'number' || typeof obj[0] === 'string' || obj instanceof L.LatLng) {
|
||||
obj = L.latLng(obj);
|
||||
var latLng = L.latLng(obj);
|
||||
if (latLng !== null) {
|
||||
obj = latLng;
|
||||
} else {
|
||||
obj = L.latLngBounds(obj);
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ L.CRS.EPSG3395 = L.extend({}, L.CRS, {
|
||||
transformation: (function () {
|
||||
var m = L.Projection.Mercator,
|
||||
r = m.R_MAJOR,
|
||||
r2 = m.R_MINOR;
|
||||
scale = 0.5 / (Math.PI * r);
|
||||
|
||||
return new L.Transformation(0.5 / (Math.PI * r), 0.5, -0.5 / (Math.PI * r2), 0.5);
|
||||
return new L.Transformation(scale, 0.5, -scale, 0.5);
|
||||
}())
|
||||
});
|
||||
|
@ -23,5 +23,10 @@ L.CRS = {
|
||||
|
||||
scale: function (zoom) {
|
||||
return 256 * Math.pow(2, zoom);
|
||||
},
|
||||
|
||||
getSize: function (zoom) {
|
||||
var s = this.scale(zoom);
|
||||
return L.point(s, s);
|
||||
}
|
||||
};
|
||||
|
@ -15,7 +15,9 @@ L.FeatureGroup = L.LayerGroup.extend({
|
||||
return this;
|
||||
}
|
||||
|
||||
layer.on(L.FeatureGroup.EVENTS, this._propagateEvent, this);
|
||||
if ('on' in layer) {
|
||||
layer.on(L.FeatureGroup.EVENTS, this._propagateEvent, this);
|
||||
}
|
||||
|
||||
L.LayerGroup.prototype.addLayer.call(this, layer);
|
||||
|
||||
@ -51,6 +53,15 @@ L.FeatureGroup = L.LayerGroup.extend({
|
||||
return this.invoke('bindPopup', content, options);
|
||||
},
|
||||
|
||||
openPopup: function (latlng) {
|
||||
// open popup on the first layer
|
||||
for (var id in this._layers) {
|
||||
this._layers[id].openPopup(latlng);
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
setStyle: function (style) {
|
||||
return this.invoke('setStyle', style);
|
||||
},
|
||||
@ -74,11 +85,10 @@ L.FeatureGroup = L.LayerGroup.extend({
|
||||
},
|
||||
|
||||
_propagateEvent: function (e) {
|
||||
if (!e.layer) {
|
||||
e.layer = e.target;
|
||||
}
|
||||
e.target = this;
|
||||
|
||||
e = L.extend({}, e, {
|
||||
layer: e.target,
|
||||
target: this
|
||||
});
|
||||
this.fire(e.type, e);
|
||||
}
|
||||
});
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user