[SKEL] ~date et auteurs seulement pour les articles des rubriques avec le mot-cle...
[lhc/web/www.git] / www / plugins / gis / lib / leaflet / plugins / Google.js
1 /*
2 * Google layer using Google Maps API
3 */
4
5 /* global google: true */
6
7 L.Google = L.Class.extend({
8 includes: L.Mixin.Events,
9
10 options: {
11 minZoom: 0,
12 maxZoom: 18,
13 tileSize: 256,
14 subdomains: 'abc',
15 errorTileUrl: '',
16 attribution: '',
17 opacity: 1,
18 continuousWorld: false,
19 noWrap: false,
20 mapOptions: {
21 backgroundColor: '#dddddd'
22 }
23 },
24
25 // Possible types: SATELLITE, ROADMAP, HYBRID, TERRAIN
26 initialize: function (type, options) {
27 var _this = this;
28
29 this._ready = L.Google.isGoogleMapsReady();
30
31 L.Util.setOptions(this, options);
32
33 this._googleApiPromise = this._ready ? Promise.resolve(window.google) : L.Google.createGoogleApiPromise();
34
35 this._googleApiPromise
36 .then(function () {
37 _this._ready = true;
38 _this._initMapObject();
39 _this._update();
40 });
41
42 this._type = type || 'SATELLITE';
43 },
44
45 onAdd: function (map, insertAtTheBottom) {
46 var _this = this;
47 this._googleApiPromise
48 .then(function () {
49 _this._map = map;
50 _this._insertAtTheBottom = insertAtTheBottom;
51
52 // create a container div for tiles
53 _this._initContainer();
54 _this._initMapObject();
55
56 // set up events
57 map.on('viewreset', _this._reset, _this);
58
59 _this._limitedUpdate = L.Util.limitExecByInterval(_this._update, 150, _this);
60 map.on('move', _this._update, _this);
61
62 map.on('zoomanim', _this._handleZoomAnim, _this);
63
64 //20px instead of 1em to avoid a slight overlap with google's attribution
65 map._controlCorners.bottomright.style.marginBottom = '20px';
66
67 _this._reset();
68 _this._update();
69 });
70 },
71
72 onRemove: function (map) {
73 map._container.removeChild(this._container);
74
75 map.off('viewreset', this._reset, this);
76
77 map.off('move', this._update, this);
78
79 map.off('zoomanim', this._handleZoomAnim, this);
80
81 map._controlCorners.bottomright.style.marginBottom = '0em';
82 },
83
84 getAttribution: function () {
85 return this.options.attribution;
86 },
87
88 setOpacity: function (opacity) {
89 this.options.opacity = opacity;
90 if (opacity < 1) {
91 L.DomUtil.setOpacity(this._container, opacity);
92 }
93 },
94
95 setElementSize: function (e, size) {
96 e.style.width = size.x + 'px';
97 e.style.height = size.y + 'px';
98 },
99
100 _initContainer: function () {
101 var tilePane = this._map._container,
102 first = tilePane.firstChild;
103
104 if (!this._container) {
105 this._container = L.DomUtil.create('div', 'leaflet-google-layer leaflet-top leaflet-left');
106 this._container.id = '_GMapContainer_' + L.Util.stamp(this);
107 this._container.style.zIndex = 'auto';
108 }
109
110 tilePane.insertBefore(this._container, first);
111
112 this.setOpacity(this.options.opacity);
113 this.setElementSize(this._container, this._map.getSize());
114 },
115
116 _initMapObject: function () {
117 if (!this._ready || !this._container) return;
118 this._google_center = new google.maps.LatLng(0, 0);
119 var map = new google.maps.Map(this._container, {
120 center: this._google_center,
121 zoom: 0,
122 tilt: 0,
123 mapTypeId: google.maps.MapTypeId[this._type],
124 disableDefaultUI: true,
125 keyboardShortcuts: false,
126 draggable: false,
127 disableDoubleClickZoom: true,
128 scrollwheel: false,
129 streetViewControl: false,
130 styles: this.options.mapOptions.styles,
131 backgroundColor: this.options.mapOptions.backgroundColor
132 });
133
134 var _this = this;
135 this._reposition = google.maps.event.addListenerOnce(map, 'center_changed',
136 function () { _this.onReposition(); });
137 this._google = map;
138
139 google.maps.event.addListenerOnce(map, 'idle',
140 function () { _this._checkZoomLevels(); });
141 google.maps.event.addListenerOnce(map, 'tilesloaded',
142 function () { _this.fire('load'); });
143 //Reporting that map-object was initialized.
144 this.fire('MapObjectInitialized', {mapObject: map});
145 },
146
147 _checkZoomLevels: function () {
148 //setting the zoom level on the Google map may result in a different zoom level than the one requested
149 //(it won't go beyond the level for which they have data).
150 // verify and make sure the zoom levels on both Leaflet and Google maps are consistent
151 if ((this._map.getZoom() !== undefined) && (this._google.getZoom() !== this._map.getZoom())) {
152 //zoom levels are out of sync. Set the leaflet zoom level to match the google one
153 this._map.setZoom(this._google.getZoom());
154 }
155 },
156
157 _reset: function () {
158 this._initContainer();
159 },
160
161 _update: function () {
162 if (!this._google) return;
163 this._resize();
164
165 var center = this._map.getCenter();
166 var _center = new google.maps.LatLng(center.lat, center.lng);
167
168 this._google.setCenter(_center);
169 if (this._map.getZoom() !== undefined)
170 this._google.setZoom(Math.round(this._map.getZoom()));
171
172 this._checkZoomLevels();
173 },
174
175 _resize: function () {
176 var size = this._map.getSize();
177 if (this._container.style.width === size.x &&
178 this._container.style.height === size.y)
179 return;
180 this.setElementSize(this._container, size);
181 this.onReposition();
182 },
183
184
185 _handleZoomAnim: function (e) {
186 var center = e.center;
187 var _center = new google.maps.LatLng(center.lat, center.lng);
188
189 this._google.setCenter(_center);
190 this._google.setZoom(Math.round(e.zoom));
191 },
192
193
194 onReposition: function () {
195 if (!this._google) return;
196 google.maps.event.trigger(this._google, 'resize');
197 }
198 });
199
200 L.Google.isGoogleMapsReady = function () {
201 return !!window.google && !!window.google.maps && !!window.google.maps.Map;
202 };
203
204 // backwards compat
205 L.Google.asyncInitialize = L.Google.isGoogleMapsReady;
206
207 L.Google.maxApiChecks = 10;
208
209 L.Google.apiCheckIntervalMilliSecs = 500;
210
211 L.Google.createGoogleApiPromise = function () {
212 var checkCounter = 0;
213 var intervalId = null;
214
215 return new Promise(function (resolve, reject) {
216 intervalId = setInterval(function () {
217 if (checkCounter >= L.Google.maxApiChecks && !L.Google.isGoogleMapsReady()) {
218 clearInterval(intervalId);
219 return reject(new Error('window.google not found after max attempts'));
220 }
221 if (L.Google.isGoogleMapsReady()) {
222 clearInterval(intervalId);
223 return resolve(window.google);
224 }
225 checkCounter++;
226 }, L.Google.apiCheckIntervalMilliSecs);
227 });
228 };