Browse Source

version 4.42.0 : GIS passe en Leaflet 1.0 !

maj des libsn et comme les choses sont bien faites, ça ne "devrait" rien casser chez les personnes qui utilisent le plugin
svn/root/tags/v4.47.18
brunobergot@gmail.com 6 years ago
parent
commit
9b968b8dd2
  1. 2
      .gitattributes
  2. 6
      gis_options.php
  3. 4
      javascript/gis.js.html
  4. 2
      lib/leaflet/LICENSE
  5. 8
      lib/leaflet/README.md
  6. 13184
      lib/leaflet/dist/leaflet-src.js
  7. 217
      lib/leaflet/dist/leaflet.css
  8. 14
      lib/leaflet/dist/leaflet.js
  9. 10
      lib/leaflet/plugins/Control.MiniMap.js
  10. 228
      lib/leaflet/plugins/Google.js
  11. 391
      lib/leaflet/plugins/Leaflet.GoogleMutant.js
  12. 3
      lib/leaflet/plugins/Marker.Rotate.js
  13. 12
      lib/leaflet/plugins/leaflet-providers.js
  14. 355
      lib/leaflet/plugins/leaflet.markercluster-src.js
  15. 2
      lib/leaflet/plugins/leaflet.markercluster.css
  16. 3
      paquet.xml

2
.gitattributes vendored

@ -83,8 +83,8 @@ lib/leaflet/plugins/Control.FullScreen.js -text
lib/leaflet/plugins/Control.MiniMap.js -text
lib/leaflet/plugins/GPX.Speed.js -text
lib/leaflet/plugins/GPX.js -text
lib/leaflet/plugins/Google.js -text
lib/leaflet/plugins/KML.js -text
lib/leaflet/plugins/Leaflet.GoogleMutant.js -text
lib/leaflet/plugins/Marker.Rotate.js -text
lib/leaflet/plugins/TOPOJSON.js -text
lib/leaflet/plugins/images/icon-fullscreen-2x.png -text

6
gis_options.php

@ -34,15 +34,15 @@ $gis_layers = array (
),
'google_roadmap' => array(
'nom' => 'Google Roadmap',
'layer' => 'L.Google("ROADMAP")'
'layer' => 'L.gridLayer.googleMutant({type:"roadmap"})'
),
'google_satellite' => array(
'nom' => 'Google Satellite',
'layer' => 'L.Google("SATELLITE")'
'layer' => 'L.gridLayer.googleMutant({type:"satellite"})'
),
'google_terrain' => array(
'nom' => 'Google Terrain',
'layer' => 'L.Google("TERRAIN")'
'layer' => 'L.gridLayer.googleMutant({type:"terrain"})'
),
'bing_aerial' => array(
'nom' => 'Bing Aerial',

4
javascript/gis.js.html

@ -2,8 +2,6 @@
[(#INCLURE{lib/leaflet/dist/[(#CONFIG{auto_compress_js}|=={oui}|?{'leaflet','leaflet-src'})].js})]
[L.Icon.Default.imagePath = '(#CHEMIN{lib/leaflet/dist/images}|url_absolue)';]
(function() {
L.gisConfig = {
@ -43,7 +41,7 @@ L.geocoderConfig = {
]
[(#LISTE{google_roadmap,google_satellite,google_terrain}|array_intersect{#GET{layers}}|count|>{0}|oui)
[(#INCLURE{lib/leaflet/plugins/Google.js})]
[(#INCLURE{lib/leaflet/plugins/Leaflet.GoogleMutant.js})]
]
[(#VAL{bing_aerial}|in_array{#GET{layers}}|oui)

2
lib/leaflet/LICENSE

@ -1,4 +1,4 @@
Copyright (c) 2010-2013, Vladimir Agafonkin
Copyright (c) 2010-2016, Vladimir Agafonkin
Copyright (c) 2010-2011, CloudMade
All rights reserved.

8
lib/leaflet/README.md

@ -9,16 +9,16 @@
* [Bing.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/tile/Bing.js)
* [Control.FullScreen.js](https://github.com/brunob/leaflet.fullscreen/blob/master/Control.FullScreen.js)
* [Control.MiniMap.js](https://github.com/Norkart/Leaflet-MiniMap/blob/master/src/Control.MiniMap.js)
* [Google.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/tile/Google.js)
* [Leaflet.GoogleMutant.js](https://gitlab.com/IvanSanchez/Leaflet.GridLayer.GoogleMutant/blob/master/Leaflet.GoogleMutant.js)
* [GPX.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/vector/GPX.js)
* [GPX.Speed.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/vector/GPX.Speed.js)
* images
* mixed from all sources
* [KML.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/vector/KML.js)
* leaflet.markercluster.css
* [MarkerCluster.css](https://github.com/Leaflet/Leaflet.markercluster/blob/leaflet-0.7/dist/MarkerCluster.css)
* [MarkerCluster.Default.css](https://github.com/Leaflet/Leaflet.markercluster/blob/leaflet-0.7/dist/MarkerCluster.Default.css)
* [leaflet.markercluster-src.js](https://github.com/Leaflet/Leaflet.markercluster/blob/leaflet-0.7/dist/leaflet.markercluster-src.js)
* [MarkerCluster.css](https://github.com/Leaflet/Leaflet.markercluster/blob/v1.0.0/dist/MarkerCluster.css)
* [MarkerCluster.Default.css](https://github.com/Leaflet/Leaflet.markercluster/blob/v1.0.0/dist/MarkerCluster.Default.css)
* [leaflet.markercluster-src.js](https://github.com/Leaflet/Leaflet.markercluster/blob/v1.0.0/dist/leaflet.markercluster-src.js)
* leaflet-plugins.css
* [Control.FullScreen.css](https://github.com/brunob/leaflet.fullscreen/blob/master/Control.FullScreen.css)
* [Control.MiniMap.css](https://github.com/Norkart/Leaflet-MiniMap/blob/master/src/Control.MiniMap.css)

13184
lib/leaflet/dist/leaflet-src.js vendored

File diff suppressed because it is too large Load Diff

217
lib/leaflet/dist/leaflet.css vendored

@ -1,16 +1,12 @@
/* required styles */
.leaflet-map-pane,
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-pane,
.leaflet-tile-container,
.leaflet-overlay-pane,
.leaflet-shadow-pane,
.leaflet-marker-pane,
.leaflet-popup-pane,
.leaflet-overlay-pane svg,
.leaflet-map-pane svg,
.leaflet-map-pane canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
@ -20,8 +16,6 @@
}
.leaflet-container {
overflow: hidden;
-ms-touch-action: none;
touch-action: none;
}
.leaflet-tile,
.leaflet-marker-icon,
@ -29,20 +23,43 @@
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
-webkit-user-drag: none;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container img {
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg,
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer {
max-width: none !important;
}
/* stupid Android 2 doesn't understand "max-width: none" properly */
.leaflet-container img.leaflet-image-layer {
max-width: 15000px !important;
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-drag {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
@ -53,18 +70,26 @@
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-tile-pane { z-index: 2; }
.leaflet-objects-pane { z-index: 3; }
.leaflet-overlay-pane { z-index: 4; }
.leaflet-shadow-pane { z-index: 5; }
.leaflet-marker-pane { z-index: 6; }
.leaflet-popup-pane { z-index: 7; }
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
@ -81,7 +106,8 @@
.leaflet-control {
position: relative;
z-index: 7;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
@ -125,7 +151,9 @@
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-tile,
.leaflet-fade-anim .leaflet-tile {
will-change: opacity;
}
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
@ -133,11 +161,17 @@
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-tile-loaded,
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
@ -145,8 +179,7 @@
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile,
.leaflet-touching .leaflet-zoom-animated {
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
@ -160,24 +193,44 @@
/* cursors */
.leaflet-clickable {
.leaflet-interactive {
cursor: pointer;
}
.leaflet-container {
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-container,
.leaflet-dragging .leaflet-clickable {
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
}
/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
pointer-events: none;
}
.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive {
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
/* visual tweaks */
@ -304,6 +357,10 @@
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
@ -318,6 +375,11 @@
margin: 5px -10px 5px -6px;
}
/* Default icon URLs */
.leaflet-default-icon-path {
background-image: url(images/marker-icon.png);
}
/* attribution and scale controls */
@ -355,8 +417,8 @@
font-size: 11px;
white-space: nowrap;
overflow: hidden;
-moz-box-sizing: content-box;
box-sizing: content-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: #fff;
background: rgba(255, 255, 255, 0.5);
@ -387,6 +449,7 @@
.leaflet-popup {
position: absolute;
text-align: center;
margin-bottom: 20px;
}
.leaflet-popup-content-wrapper {
padding: 1px;
@ -401,11 +464,13 @@
margin: 18px 0;
}
.leaflet-popup-tip-container {
margin: 0 auto;
width: 40px;
height: 20px;
position: relative;
position: absolute;
left: 50%;
margin-left: -20px;
overflow: hidden;
pointer-events: none;
}
.leaflet-popup-tip {
width: 17px;
@ -423,7 +488,7 @@
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
@ -431,6 +496,7 @@
top: 0;
right: 0;
padding: 4px 4px 0 0;
border: none;
text-align: center;
width: 18px;
height: 14px;
@ -477,3 +543,82 @@
background: #fff;
border: 1px solid #666;
}
/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
position: absolute;
padding: 6px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 3px;
color: #222;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.leaflet-tooltip.leaflet-clickable {
cursor: pointer;
pointer-events: auto;
}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
position: absolute;
pointer-events: none;
border: 6px solid transparent;
background: transparent;
content: "";
}
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
margin-left: -6px;
}
.leaflet-tooltip-top:before {
bottom: 0;
margin-bottom: -12px;
border-top-color: #fff;
}
.leaflet-tooltip-bottom:before {
top: 0;
margin-top: -12px;
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;
margin-top: -6px;
}
.leaflet-tooltip-left:before {
right: 0;
margin-right: -12px;
border-left-color: #fff;
}
.leaflet-tooltip-right:before {
left: 0;
margin-left: -12px;
border-right-color: #fff;
}

14
lib/leaflet/dist/leaflet.js vendored

File diff suppressed because one or more lines are too long

10
lib/leaflet/plugins/Control.MiniMap.js

@ -127,13 +127,21 @@
_addToggleButton: function () {
this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton(
'', this.options.strings.hideText, ('leaflet-control-minimap-toggle-display leaflet-control-minimap-toggle-display-' +
'', this._toggleButtonInitialTitleText(), ('leaflet-control-minimap-toggle-display leaflet-control-minimap-toggle-display-' +
this.options.position), this._container, this._toggleDisplayButtonClicked, this) : undefined;
this._toggleDisplayButton.style.width = this.options.collapsedWidth + 'px';
this._toggleDisplayButton.style.height = this.options.collapsedHeight + 'px';
},
_toggleButtonInitialTitleText: function () {
if (this.options.minimized) {
return this.options.strings.showText;
} else {
return this.options.strings.hideText;
}
},
_createButton: function (html, title, className, container, fn, context) {
var link = L.DomUtil.create('a', className, container);
link.innerHTML = html;

228
lib/leaflet/plugins/Google.js

@ -1,228 +0,0 @@
/*
* Google layer using Google Maps API
*/
/* global google: true */
L.Google = L.Class.extend({
includes: L.Mixin.Events,
options: {
minZoom: 0,
maxZoom: 18,
tileSize: 256,
subdomains: 'abc',
errorTileUrl: '',
attribution: '',
opacity: 1,
continuousWorld: false,
noWrap: false,
mapOptions: {
backgroundColor: '#dddddd'
}
},
// Possible types: SATELLITE, ROADMAP, HYBRID, TERRAIN
initialize: function (type, options) {
var _this = this;
this._ready = L.Google.isGoogleMapsReady();
L.Util.setOptions(this, options);
this._googleApiPromise = this._ready ? Promise.resolve(window.google) : L.Google.createGoogleApiPromise();
this._googleApiPromise
.then(function () {
_this._ready = true;
_this._initMapObject();
_this._update();
});
this._type = type || 'SATELLITE';
},
onAdd: function (map, insertAtTheBottom) {
var _this = this;
this._googleApiPromise
.then(function () {
_this._map = map;
_this._insertAtTheBottom = insertAtTheBottom;
// create a container div for tiles
_this._initContainer();
_this._initMapObject();
// set up events
map.on('viewreset', _this._reset, _this);
_this._limitedUpdate = L.Util.limitExecByInterval(_this._update, 150, _this);
map.on('move', _this._update, _this);
map.on('zoomanim', _this._handleZoomAnim, _this);
//20px instead of 1em to avoid a slight overlap with google's attribution
map._controlCorners.bottomright.style.marginBottom = '20px';
_this._reset();
_this._update();
});
},
onRemove: function (map) {
map._container.removeChild(this._container);
map.off('viewreset', this._reset, this);
map.off('move', this._update, this);
map.off('zoomanim', this._handleZoomAnim, this);
map._controlCorners.bottomright.style.marginBottom = '0em';
},
getAttribution: function () {
return this.options.attribution;
},
setOpacity: function (opacity) {
this.options.opacity = opacity;
if (opacity < 1) {
L.DomUtil.setOpacity(this._container, opacity);
}
},
setElementSize: function (e, size) {
e.style.width = size.x + 'px';
e.style.height = size.y + 'px';
},
_initContainer: function () {
var tilePane = this._map._container,
first = tilePane.firstChild;
if (!this._container) {
this._container = L.DomUtil.create('div', 'leaflet-google-layer leaflet-top leaflet-left');
this._container.id = '_GMapContainer_' + L.Util.stamp(this);
this._container.style.zIndex = 'auto';
}
tilePane.insertBefore(this._container, first);
this.setOpacity(this.options.opacity);
this.setElementSize(this._container, this._map.getSize());
},
_initMapObject: function () {
if (!this._ready || !this._container) return;
this._google_center = new google.maps.LatLng(0, 0);
var map = new google.maps.Map(this._container, {
center: this._google_center,
zoom: 0,
tilt: 0,
mapTypeId: google.maps.MapTypeId[this._type],
disableDefaultUI: true,
keyboardShortcuts: false,
draggable: false,
disableDoubleClickZoom: true,
scrollwheel: false,
streetViewControl: false,
styles: this.options.mapOptions.styles,
backgroundColor: this.options.mapOptions.backgroundColor
});
var _this = this;
this._reposition = google.maps.event.addListenerOnce(map, 'center_changed',
function () { _this.onReposition(); });
this._google = map;
google.maps.event.addListenerOnce(map, 'idle',
function () { _this._checkZoomLevels(); });
google.maps.event.addListenerOnce(map, 'tilesloaded',
function () { _this.fire('load'); });
//Reporting that map-object was initialized.
this.fire('MapObjectInitialized', {mapObject: map});
},
_checkZoomLevels: function () {
//setting the zoom level on the Google map may result in a different zoom level than the one requested
//(it won't go beyond the level for which they have data).
// verify and make sure the zoom levels on both Leaflet and Google maps are consistent
if ((this._map.getZoom() !== undefined) && (this._google.getZoom() !== this._map.getZoom())) {
//zoom levels are out of sync. Set the leaflet zoom level to match the google one
this._map.setZoom(this._google.getZoom());
}
},
_reset: function () {
this._initContainer();
},
_update: function () {
if (!this._google) return;
this._resize();
var center = this._map.getCenter();
var _center = new google.maps.LatLng(center.lat, center.lng);
this._google.setCenter(_center);
if (this._map.getZoom() !== undefined)
this._google.setZoom(Math.round(this._map.getZoom()));
this._checkZoomLevels();
},
_resize: function () {
var size = this._map.getSize();
if (this._container.style.width === size.x &&
this._container.style.height === size.y)
return;
this.setElementSize(this._container, size);
this.onReposition();
},
_handleZoomAnim: function (e) {
var center = e.center;
var _center = new google.maps.LatLng(center.lat, center.lng);
this._google.setCenter(_center);
this._google.setZoom(Math.round(e.zoom));
},
onReposition: function () {
if (!this._google) return;
google.maps.event.trigger(this._google, 'resize');
}
});
L.Google.isGoogleMapsReady = function () {
return !!window.google && !!window.google.maps && !!window.google.maps.Map;
};
// backwards compat
L.Google.asyncInitialize = L.Google.isGoogleMapsReady;
L.Google.maxApiChecks = 10;
L.Google.apiCheckIntervalMilliSecs = 500;
L.Google.createGoogleApiPromise = function () {
var checkCounter = 0;
var intervalId = null;
return new Promise(function (resolve, reject) {
intervalId = setInterval(function () {
if (checkCounter >= L.Google.maxApiChecks && !L.Google.isGoogleMapsReady()) {
clearInterval(intervalId);
return reject(new Error('window.google not found after max attempts'));
}
if (L.Google.isGoogleMapsReady()) {
clearInterval(intervalId);
return resolve(window.google);
}
checkCounter++;
}, L.Google.apiCheckIntervalMilliSecs);
});
};

391
lib/leaflet/plugins/Leaflet.GoogleMutant.js

@ -0,0 +1,391 @@
// Based on https://github.com/shramov/leaflet-plugins
// GridLayer like https://avinmathew.com/leaflet-and-google-maps/ , but using MutationObserver instead of jQuery
// 🍂class GridLayer.GoogleMutant
// 🍂extends GridLayer
L.GridLayer.GoogleMutant = L.GridLayer.extend({
includes: L.Mixin.Events,
options: {
minZoom: 0,
maxZoom: 18,
tileSize: 256,
subdomains: 'abc',
errorTileUrl: '',
attribution: '', // The mutant container will add its own attribution anyways.
opacity: 1,
continuousWorld: false,
noWrap: false,
// 🍂option type: String = 'roadmap'
// Google's map type. Valid values are 'roadmap', 'satellite' or 'terrain'. 'hybrid' is not really supported.
type: 'roadmap',
maxNativeZoom: 21
},
initialize: function (options) {
L.GridLayer.prototype.initialize.call(this, options);
this._ready = !!window.google && !!window.google.maps && !!window.google.maps.Map;
this._GAPIPromise = this._ready ? Promise.resolve(window.google) : new Promise(function (resolve, reject) {
var checkCounter = 0;
var intervalId = null;
intervalId = setInterval(function () {
if (checkCounter >= 10) {
clearInterval(intervalId);
return reject(new Error('window.google not found after 10 attempts'));
}
if (!!window.google && !!window.google.maps && !!window.google.maps.Map) {
clearInterval(intervalId);
return resolve(window.google);
}
checkCounter++;
}, 500);
});
// Couple data structures indexed by tile key
this._tileCallbacks = {}; // Callbacks for promises for tiles that are expected
this._freshTiles = {}; // Tiles from the mutant which haven't been requested yet
this._imagesPerTile = (this.options.type === 'hybrid') ? 2 : 1;
this.createTile = (this.options.type === 'hybrid') ? this._createMultiTile : this._createSingleTile;
},
onAdd: function (map) {
L.GridLayer.prototype.onAdd.call(this, map);
this._initMutantContainer();
this._GAPIPromise.then(function () {
this._ready = true;
this._map = map;
this._initMutant();
map.on('viewreset', this._reset, this);
map.on('move', this._update, this);
map.on('zoomend', this._handleZoomAnim, this);
map.on('resize', this._resize, this);
//20px instead of 1em to avoid a slight overlap with google's attribution
map._controlCorners.bottomright.style.marginBottom = '20px';
this._reset();
this._update();
}.bind(this));
},
onRemove: function (map) {
L.GridLayer.prototype.onRemove.call(this, map);
map._container.removeChild(this._mutantContainer);
this._mutantContainer = undefined;
map.off('viewreset', this._reset, this);
map.off('move', this._update, this);
map.off('zoomend', this._handleZoomAnim, this);
map.off('resize', this._resize, this);
map._controlCorners.bottomright.style.marginBottom = '0em';
},
getAttribution: function () {
return this.options.attribution;
},
setOpacity: function (opacity) {
this.options.opacity = opacity;
if (opacity < 1) {
L.DomUtil.setOpacity(this._mutantContainer, opacity);
}
},
setElementSize: function (e, size) {
e.style.width = size.x + 'px';
e.style.height = size.y + 'px';
},
_initMutantContainer: function () {
if (!this._mutantContainer) {
this._mutantContainer = L.DomUtil.create('div', 'leaflet-google-mutant leaflet-top leaflet-left');
this._mutantContainer.id = '_MutantContainer_' + L.Util.stamp(this._mutantContainer);
// this._mutantContainer.style.zIndex = 'auto';
this._mutantContainer.style.pointerEvents = 'none';
this._map.getContainer().appendChild(this._mutantContainer);
}
this.setOpacity(this.options.opacity);
this.setElementSize(this._mutantContainer, this._map.getSize());
this._attachObserver(this._mutantContainer);
},
_initMutant: function () {
if (!this._ready || !this._mutantContainer) return;
this._mutantCenter = new google.maps.LatLng(0, 0);
var map = new google.maps.Map(this._mutantContainer, {
center: this._mutantCenter,
zoom: 0,
tilt: 0,
mapTypeId: this.options.type,
disableDefaultUI: true,
keyboardShortcuts: false,
draggable: false,
disableDoubleClickZoom: true,
scrollwheel: false,
streetViewControl: false,
styles: this.options.styles || {},
backgroundColor: 'transparent'
});
this._mutant = map;
// 🍂event spawned
// Fired when the mutant has been created.
this.fire('spawned', {mapObject: map});
},
_attachObserver: function _attachObserver (node) {
// console.log('Gonna observe', node);
var observer = new MutationObserver(this._onMutations.bind(this));
// pass in the target node, as well as the observer options
observer.observe(node, { childList: true, subtree: true });
},
_onMutations: function _onMutations (mutations) {
for (var i = 0; i < mutations.length; ++i) {
var mutation = mutations[i];
for (var j = 0; j < mutation.addedNodes.length; ++j) {
var node = mutation.addedNodes[j];
if (node instanceof HTMLImageElement) {
this._onMutatedImage(node);
} else if (node instanceof HTMLElement) {
Array.prototype.forEach.call(node.querySelectorAll('img'), this._onMutatedImage.bind(this));
}
}
}
},
// Only images which 'src' attrib match this will be considered for moving around.
// Looks like some kind of string-based protobuf, maybe??
// Only the roads (and terrain, and vector-based stuff) match this pattern
_roadRegexp: /!1i(\d+)!2i(\d+)!3i(\d+)!/,
// On the other hand, raster imagery matches this other pattern
_satRegexp: /x=(\d+)&y=(\d+)&z=(\d+)/,
// On small viewports, when zooming in/out, a static image is requested
// This will not be moved around, just removed from the DOM.
_staticRegExp: /StaticMapService\.GetMapImage/,
_onMutatedImage: function _onMutatedImage (imgNode) {
// if (imgNode.src) {
// console.log('caught mutated image: ', imgNode.src);
// }
var coords;
var match = imgNode.src.match(this._roadRegexp);
var sublayer, parent;
if (match) {
coords = {
z: match[1],
x: match[2],
y: match[3]
};
if (this._imagesPerTile > 1) { imgNode.style.zIndex = 1; }
sublayer = 1;
} else {
match = imgNode.src.match(this._satRegexp);
if (match) {
coords = {
x: match[1],
y: match[2],
z: match[3]
};
}
// imgNode.style.zIndex = 0;
sublayer = 0;
}
if (coords) {
var key = this._tileCoordsToKey(coords);
if (this._imagesPerTile > 1) { key += '/' + sublayer; }
if (key in this._tileCallbacks && this._tileCallbacks[key]) {
// console.log('Fullfilling callback ', key);
this._tileCallbacks[key].pop()(imgNode);
if (!this._tileCallbacks[key].length) { delete this._tileCallbacks[key]; }
} else {
// console.log('Caching for later', key);
parent = imgNode.parentNode;
if (parent) {
parent.removeChild(imgNode);
parent.removeChild = L.Util.falseFn;
// imgNode.parentNode.replaceChild(L.DomUtil.create('img'), imgNode);
}
if (key in this._freshTiles) {
this._freshTiles[key].push(imgNode);
} else {
this._freshTiles[key] = [imgNode];
}
}
} else if (imgNode.src.match(this._staticRegExp)) {
parent = imgNode.parentNode;
if (parent) {
// Remove the image, but don't store it anywhere.
// Image needs to be replaced instead of removed, as the container
// seems to be reused.
imgNode.parentNode.replaceChild(L.DomUtil.create('img'), imgNode);
}
}
},
// This will be used as this.createTile for 'roadmap', 'sat', 'terrain'
_createSingleTile: function createTile (coords, done) {
var key = this._tileCoordsToKey(coords);
// console.log('Need:', key);
if (key in this._freshTiles) {
var tile = this._freshTiles[key].pop();
if (!this._freshTiles[key].length) { delete this._freshTiles[key]; }
L.Util.requestAnimFrame(done);
// console.log('Got ', key, ' from _freshTiles');
return tile;
} else {
var tileContainer = L.DomUtil.create('div');
this._tileCallbacks[key] = this._tileCallbacks[key] || [];
this._tileCallbacks[key].push( (function (c/*, k*/) {
return function (imgNode) {
var parent = imgNode.parentNode;
if (parent) {
parent.removeChild(imgNode);
parent.removeChild = L.Util.falseFn;
// imgNode.parentNode.replaceChild(L.DomUtil.create('img'), imgNode);
}
c.appendChild(imgNode);
done();
// console.log('Sent ', k, ' to _tileCallbacks');
}.bind(this);
}.bind(this))(tileContainer/*, key*/) );
return tileContainer;
}
},
// This will be used as this.createTile for 'hybrid'
_createMultiTile: function createTile (coords, done) {
var key = this._tileCoordsToKey(coords);
var tileContainer = L.DomUtil.create('div');
tileContainer.dataset.pending = this._imagesPerTile;
for (var i = 0; i < this._imagesPerTile; i++) {
var key2 = key + '/' + i;
if (key2 in this._freshTiles) {
tileContainer.appendChild(this._freshTiles[key2].pop());
if (!this._freshTiles[key2].length) { delete this._freshTiles[key2]; }
tileContainer.dataset.pending--;
// console.log('Got ', key2, ' from _freshTiles');
} else {
this._tileCallbacks[key2] = this._tileCallbacks[key2] || [];
this._tileCallbacks[key2].push( (function (c/*, k2*/) {
return function (imgNode) {
var parent = imgNode.parentNode;
if (parent) {
parent.removeChild(imgNode);
parent.removeChild = L.Util.falseFn;
// imgNode.parentNode.replaceChild(L.DomUtil.create('img'), imgNode);
}
c.appendChild(imgNode);
c.dataset.pending--;
if (!parseInt(c.dataset.pending)) { done(); }
// console.log('Sent ', k2, ' to _tileCallbacks, still ', c.dataset.pending, ' images to go');
}.bind(this);
}.bind(this))(tileContainer/*, key2*/) );
}
}
if (!parseInt(tileContainer.dataset.pending)) {
L.Util.requestAnimFrame(done);
}
return tileContainer;
},
_checkZoomLevels: function () {
//setting the zoom level on the Google map may result in a different zoom level than the one requested
//(it won't go beyond the level for which they have data).
// verify and make sure the zoom levels on both Leaflet and Google maps are consistent
if ((this._map.getZoom() !== undefined) && (this._mutant.getZoom() !== this._map.getZoom())) {
//zoom levels are out of sync. Set the leaflet zoom level to match the google one
this._map.setZoom(this._mutant.getZoom());
}
},
_reset: function () {
this._initContainer();
},
_update: function () {
L.GridLayer.prototype._update.call(this);
if (!this._mutant) return;
var center = this._map.getCenter();
var _center = new google.maps.LatLng(center.lat, center.lng);
this._mutant.setCenter(_center);
var zoom = this._map.getZoom();
if (zoom !== undefined) {
this._mutant.setZoom(Math.round(this._map.getZoom()));
}
},
_resize: function () {
var size = this._map.getSize();
if (this._mutantContainer.style.width === size.x &&
this._mutantContainer.style.height === size.y)
return;
this.setElementSize(this._mutantContainer, size);
if (!this._mutant) return;
google.maps.event.trigger(this._mutant, 'resize');
},
_handleZoomAnim: function () {
var center = this._map.getCenter();
var _center = new google.maps.LatLng(center.lat, center.lng);
this._mutant.setCenter(_center);
this._mutant.setZoom(Math.round(this._map.getZoom()));
},
// Agressively prune _freshtiles when a tile with the same key is removed,
// this prevents a problem where Leaflet keeps a loaded tile longer than
// GMaps, so that GMaps makes two requests but Leaflet only consumes one,
// polluting _freshTiles with stale data.
_removeTile: function (key) {
if (this._imagesPerTile > 1) {
for (var i=0; i<this._imagesPerTile; i++) {
var key2 = key + '/' + i;
if (key2 in this._freshTiles) { delete this._freshTiles[key2]; }
// console.log('Pruned spurious hybrid _freshTiles');
}
} else {
if (key in this._freshTiles) {
delete this._freshTiles[key];
// console.log('Pruned spurious _freshTiles', key);
}
}
return L.GridLayer.prototype._removeTile.call(this, key);
}
});
// 🍂factory gridLayer.googleMutant(options)
// Returns a new `GridLayer.GoogleMutant` given its options
L.gridLayer.googleMutant = function (options) {
return new L.GridLayer.GoogleMutant(options);
};

3
lib/leaflet/plugins/Marker.Rotate.js

@ -14,8 +14,9 @@
transform += ' rotate(' + this.options.iconAngle + 'deg)';
transform += ' translate(' + a.x + 'px, ' + a.y + 'px)';
i.style[L.DomUtil.TRANSFORM] += transform;
i.style[L.DomUtil.TRANSFORM + 'Origin'] = '50% 50%';
},
_getShortestEndDegree: function (startDegrees, endDegrees) {
var turnAngle = Math.abs(endDegrees - startDegrees);
var turnAnglePositive = (endDegrees - startDegrees) >= 0;

12
lib/leaflet/plugins/leaflet-providers.js

@ -144,7 +144,7 @@
}
},
Thunderforest: {
url: '//{s}.tile.thunderforest.com/{variant}/{z}/{x}/{y}.png',
url: '//{s}.tile.thunderforest.com/{variant}/{z}/{x}/{y}.png?apikey={apikey}',
options: {
attribution:
'&copy; <a href="http://www.thunderforest.com/">Thunderforest</a>, {attribution.OpenStreetMap}',
@ -528,7 +528,7 @@
}
},
BasemapAT: {
url: '//maps{s}.wien.gv.at/basemap/{variant}/normal/google3857/{z}/{y}/{x}.{format}',
url: 'https://maps{s}.wien.gv.at/basemap/{variant}/normal/google3857/{z}/{y}/{x}.{format}',
options: {
maxZoom: 19,
attribution: 'Datenquelle: <a href="www.basemap.at">basemap.at</a>',
@ -538,7 +538,12 @@
variant: 'geolandbasemap'
},
variants: {
basemap: 'geolandbasemap',
basemap: {
options: {
maxZoom: 20, // currently only in Vienna
variant: 'geolandbasemap'
}
},
grau: 'bmapgrau',
overlay: 'bmapoverlay',
highdpi: {
@ -549,6 +554,7 @@
},
orthofoto: {
options: {
maxZoom: 20, // currently only in Vienna
variant: 'bmaporthofoto30cm',
format: 'jpeg'
}

355
lib/leaflet/plugins/leaflet.markercluster-src.js

@ -56,10 +56,10 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
}
this._featureGroup = L.featureGroup();
this._featureGroup.on(L.FeatureGroup.EVENTS, this._propagateEvent, this);
this._featureGroup.addEventParent(this);
this._nonPointGroup = L.featureGroup();
this._nonPointGroup.on(L.FeatureGroup.EVENTS, this._propagateEvent, this);
this._nonPointGroup.addEventParent(this);
this._inZoomAnimation = 0;
this._needsClustering = [];
@ -79,11 +79,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
addLayer: function (layer) {
if (layer instanceof L.LayerGroup) {
var array = [];
for (var i in layer._layers) {
array.push(layer._layers[i]);
}
return this.addLayers(array);
return this.addLayers([layer]);
}
//Don't cluster non point data
@ -113,9 +109,11 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
// Refresh bounds and weighted positions.
this._topClusterLevel._recalculateBounds();
this._refreshClustersIcons();
//Work out what is visible
var visibleLayer = layer,
currentZoom = this._map.getZoom();
currentZoom = this._zoom;
if (layer.__parent) {
while (visibleLayer.__parent._zoom >= currentZoom) {
visibleLayer = visibleLayer.__parent;
@ -134,13 +132,8 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
removeLayer: function (layer) {
if (layer instanceof L.LayerGroup)
{
var array = [];
for (var i in layer._layers) {
array.push(layer._layers[i]);
}
return this.removeLayers(array);
if (layer instanceof L.LayerGroup) {
return this.removeLayers([layer]);
}
//Non point layers
@ -171,6 +164,10 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
// Refresh bounds and weighted positions.
this._topClusterLevel._recalculateBounds();
this._refreshClustersIcons();
layer.off('move', this._childMarkerMoved, this);
if (this._featureGroup.hasLayer(layer)) {
this._featureGroup.removeLayer(layer);
if (layer.clusterShow) {
@ -183,19 +180,25 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
//Takes an array of markers and adds them in bulk
addLayers: function (layersArray) {
if (!L.Util.isArray(layersArray)) {
return this.addLayer(layersArray);
}
var fg = this._featureGroup,
npg = this._nonPointGroup,
chunked = this.options.chunkedLoading,
chunkInterval = this.options.chunkInterval,
chunkProgress = this.options.chunkProgress,
newMarkers, i, l, m;
npg = this._nonPointGroup,
chunked = this.options.chunkedLoading,
chunkInterval = this.options.chunkInterval,
chunkProgress = this.options.chunkProgress,
l = layersArray.length,
offset = 0,
originalArray = true,
m;
if (this._map) {
var offset = 0,
started = (new Date()).getTime();
var started = (new Date()).getTime();
var process = L.bind(function () {
var start = (new Date()).getTime();
for (; offset < layersArray.length; offset++) {
for (; offset < l; offset++) {
if (chunked && offset % 200 === 0) {
// every couple hundred markers, instrument the time elapsed since processing started:
var elapsed = (new Date()).getTime() - start;
@ -206,6 +209,22 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
m = layersArray[offset];
// Group of layers, append children to layersArray and skip.
// Side effects:
// - Total increases, so chunkProgress ratio jumps backward.
// - Groups are not included in this group, only their non-group child layers (hasLayer).
// Changing array length while looping does not affect performance in current browsers:
// http://jsperf.com/for-loop-changing-length/6
if (m instanceof L.LayerGroup) {
if (originalArray) {
layersArray = layersArray.slice();
originalArray = false;
}
this._extractNonGroupLayers(m, layersArray);
l = layersArray.length;
continue;
}
//Not point data, can't be clustered
if (!m.getLatLng) {
npg.addLayer(m);
@ -222,7 +241,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
if (m.__parent) {
if (m.__parent.getChildCount() === 2) {
var markers = m.__parent.getAllChildMarkers(),
otherMarker = markers[0] === m ? markers[1] : markers[0];
otherMarker = markers[0] === m ? markers[1] : markers[0];
fg.removeLayer(otherMarker);
}
}
@ -230,21 +249,16 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
if (chunkProgress) {
// report progress and time elapsed:
chunkProgress(offset, layersArray.length, (new Date()).getTime() - started);
chunkProgress(offset, l, (new Date()).getTime() - started);
}
// Completed processing all markers.
if (offset === layersArray.length) {
if (offset === l) {
// Refresh bounds and weighted positions.
this._topClusterLevel._recalculateBounds();
//Update the icons of all those visible clusters that were affected
this._featureGroup.eachLayer(function (c) {
if (c instanceof L.MarkerCluster && c._iconNeedsUpdate) {
c._updateIcon();
}
});
this._refreshClustersIcons();
this._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds);
} else {
@ -254,9 +268,21 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({
process();
} else {
newMarkers = [];
for (i = 0, l = layersArray.length; i < l; i++) {
m = layersArray[i];
var needsClustering = this._needsClustering;
for (; offset < l; offset++) {
m = layersArray[offset];
// Group of layers, append children to layersArray and skip.
if (m instanceof L.LayerGroup) {
if (originalArray) {
layersArray = layersArray.slice();