PluginProbe
Leaflet Map / trunk
Leaflet Map vtrunk
3.4.7 3.4.6 trunk 2.10.0 2.10.1 2.11.0 2.11.1 2.11.2 2.11.3 2.11.4 2.11.5 2.12.0 2.13.0 2.14.0 2.15.0 2.16.0 2.16.1 2.16.2 2.17.0 2.17.1 2.17.2 2.17.3 2.18.0 2.19.0 2.19.1 All 49 releases
leaflet-map / scripts / construct-leaflet-map.js

construct-leaflet-map.js in Leaflet Map trunk, at scripts/construct-leaflet-map.js

445 lines 10.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 // holds a function queue to call once page is loaded
3 function Main() {
4 var VERSION = '{{VERSION}}';
5 this.VERSION = VERSION;
6
7 /**
8 * Call a render function, wrapped in a try/catch
9 * @param {() => void} fnc
10 */
11 function callRenderFunction(fnc) {
12 try {
13 fnc();
14 } catch (e) {
15 console.log('-- version --', VERSION);
16 console.error(e);
17 }
18 }
19
20 var ready = false;
21 var callbacks = [];
22
23 /**
24 * this function mirrors the array appending function
25 * so that we can at least append functions to a global array
26 * before the maps are ready to be rendered
27 *
28 * All shortcodes should execute the following:
29 * window.WPLeafletMapPlugin = window.WPLeafletMapPlugin || [];
30 * window.WPLeafletMapPlugin.push(function () {
31 *
32 * Think of it as a whenReady callback
33 */
34 this.push = function (fnc) {
35 if (ready) {
36 callRenderFunction(fnc);
37 } else {
38 callbacks.push(fnc);
39 }
40 };
41
42 /**
43 * Same as above, but what if someone wants to execute a function
44 * before other functions?
45 */
46 this.unshift = function (fnc) {
47 if (ready) {
48 callRenderFunction(fnc);
49 } else {
50 callbacks.unshift(fnc);
51 }
52 };
53
54 /**
55 * execute all callbacks once page/Leaflet is loaded
56 */
57 this.init = function () {
58 ready = true;
59 for (var i = 0, len = callbacks.length; i < len; i++) {
60 callRenderFunction(callbacks[i]);
61 }
62 };
63
64 /**
65 * Create map from a div element
66 * @since 2.18.0
67 */
68 this.createMap = function (options) {
69 // gets maps by className in order
70 var elems = document.getElementsByClassName('WPLeafletMap');
71 var i = this.maps.length;
72 var container = elems[i];
73
74 var map = L.map(container, options);
75
76 // removed from PHP in 2.18.0
77 if (options.fitBounds) {
78 map._shouldFitBounds = true;
79 }
80
81 // removed from PHP in 2.18.0
82 if (options.attribution) {
83 addAttributionToMap(options.attribution, map);
84 }
85
86 this.maps.push(map);
87
88 return map;
89 };
90
91 /**
92 * Create image map from a div element
93 * @since 2.18.0
94 */
95 this.createImageMap = function (options) {
96 var map = this.createMap(options);
97
98 // moved from PHP in 2.18.0
99 map.is_image_map = true;
100
101 this.images.push(map);
102
103 return map;
104 };
105
106 /**
107 * maps are created iteratively, so the last map is the current map
108 */
109 this.getCurrentMap = function () {
110 return this.maps[this.maps.length - 1];
111 };
112
113 /**
114 * Get/Create L.FeatureGroup for ALL shapes; used for `fitbounds`
115 * @since 2.13.0
116 */
117 this.getCurrentGroup = function () {
118 // marker groups are mapid -> feature group
119 var mapid = this.maps.length;
120 if (!this.markergroups[mapid]) {
121 this.markergroups[mapid] = this.newMarkerGroup(this.maps[mapid - 1]);
122 }
123 return this.markergroups[mapid];
124 };
125
126 /**
127 * backwards-compatible getCurrentGroup
128 * @deprecated 2.13.0
129 */
130 this.getCurrentMarkerGroup = this.getCurrentGroup;
131
132 /**
133 * get FeatureGroup and add to map
134 *
135 * ! This is extracted so that it can be overwritten by plugins
136 */
137 this.getGroup = function (map) {
138 return new L.FeatureGroup().addTo(map);
139 };
140
141 /**
142 * group is created and event is added
143 */
144 this.newMarkerGroup = function (map) {
145 var mg = this.getGroup(map);
146
147 mg.timeout = null;
148
149 // custom attribute
150 if (map._shouldFitBounds) {
151 mg.on(
152 'layeradd',
153 function (event) {
154 if (event.layer instanceof L.FeatureGroup) {
155 // wait for featuregroup/ajax-geojson to be ready
156 event.layer.on('ready', function () {
157 map.fitBounds(mg.getBounds());
158 });
159 }
160
161 // needs a timeout so that it doesn't
162 // opt out of a bound change
163 window.clearTimeout(this.timeout);
164 this.timeout = window.setTimeout(function () {
165 try {
166 map.fitBounds(mg.getBounds());
167 } catch (e) {
168 // ajax-geojson might not have valid bounds yet
169 }
170 }, 100);
171 },
172 mg
173 );
174 }
175
176 return mg;
177 };
178
179 /** Adds all properties as a table-view for GeoJSON popups */
180 this.propsToTable = function (props) {
181 var prop;
182 var keys = [];
183 for (prop in props) {
184 if (Object.prototype.hasOwnProperty.call(props, prop)) {
185 keys.push(prop);
186 }
187 }
188 keys = keys.sort();
189
190 var output = '<table>';
191
192 for (var i = 0, len = keys.length; i < len; i++) {
193 var key = keys[i];
194 output += '<tr><td>' + key + '</td>';
195 output += '<td>' + props[key] + '</td></tr>';
196 }
197
198 output += '</table>';
199
200 return output;
201 };
202
203 function trim(a) {
204 return a.trim();
205 }
206
207 function addAttributionToMap(attribution, map) {
208 if (!attribution) {
209 return;
210 }
211
212 var attributions = attribution.split(';');
213 var attControl = L.control
214 .attribution({
215 prefix: false,
216 })
217 .addTo(map);
218
219 for (var i = 0, len = attributions.length; i < len; i++) {
220 var att = trim(attributions[i]);
221 attControl.addAttribution(att);
222 }
223 }
224
225 var unescape = (this.unescape = function (str) {
226 var div = document.createElement('div');
227 div.innerHTML = str;
228 return div.innerText || str;
229 });
230
231 var templateRe = /\{ *(.*?) *\}/g;
232
233 /**
234 * It interpolates variables in curly brackets (regex above)
235 *
236 * ex: "Property Value: {property_key}"
237 *
238 * @param {string} str
239 * @param {object} data e.g. feature.properties
240 */
241 this.template = function (str, data) {
242 if (data == null) {
243 return str;
244 }
245
246 return str.replace(templateRe, function (match, key) {
247 var obj = liquid(key);
248 var value = parseKey(data, obj.key);
249 if (value == null) {
250 return obj.default || match;
251 }
252 return value;
253 });
254 };
255
256 /** used in strToPath */
257 var strToPathRe = /[.‘’'“”"\[\]]+/g;
258
259 /**
260 * Converts nested object keys to array
261 *
262 * ex: `this.that['and'].theOther[4]` ->
263 * ['this', 'that', 'and', 'theOther', '4']
264 * @param {string} key
265 */
266 function strToPath(key) {
267 if (key == null) {
268 return [];
269 }
270 var input = key.split(strToPathRe);
271 var output = [];
272
273 // failsafe for all empty strings;
274 // mostly catches brackets at the end of a string
275 for (var i = 0, len = input.length; i < len; i++) {
276 if (input[i] !== '') {
277 output.push(input[i]);
278 }
279 }
280
281 return output;
282 }
283
284 /**
285 * It uses strToPath to access a possibly nested path value
286 *
287 * @param {object} obj
288 * @param {string} key
289 */
290 function parseKey(obj, key) {
291 var arr = strToPath(unescape(key));
292 var value = obj;
293
294 for (var i = 0, len = arr.length; i < len; i++) {
295 value = value[arr[i]];
296 if (!value) {
297 return undefined;
298 }
299 }
300
301 return value;
302 }
303
304 /**
305 * parses liquid tags from a string
306 *
307 * @param {string} str
308 */
309 function liquid(str) {
310 var tags = str.split(' | ');
311 var obj = {};
312
313 // removes initial variable from array
314 var key = tags.shift();
315
316 for (var i = 0, len = tags.length; i < len; i++) {
317 var tag = tags[i].split(': ');
318 var tagName = tag.shift();
319 var tagValue = tag.join(': ') || true;
320
321 obj[tagName] = tagValue;
322 }
323
324 // always preserve the original string
325 obj.key = key;
326
327 return obj;
328 }
329
330 function waitFor(prop, cb) {
331 if (typeof L !== 'undefined' && typeof L[prop] !== 'undefined') {
332 cb();
333 } else {
334 setTimeout(function () {
335 waitFor(prop, cb);
336 }, 100);
337 }
338 }
339
340 /** wait for leaflet-svg-icon (if deferred) */
341 this.waitForSVG = function (cb) {
342 waitFor('SVGIcon', cb);
343 };
344
345 /** wait for leaflet-ajax-geojson (if deferred) */
346 this.waitForAjax = function (cb) {
347 waitFor('AjaxGeoJSON', cb);
348 };
349
350 this.createScale = function (options) {
351 L.control.scale(options).addTo(this.getCurrentMap());
352 };
353
354 this.getIconOptions = function (options) {
355 var _options = options || {};
356 var iconArrays = [
357 'iconSize',
358 'iconAnchor',
359 'shadowSize',
360 'shadowAnchor',
361 'popupAnchor',
362 'tooltipAnchor',
363 ];
364 var default_icon = L.Icon.Default.prototype.options;
365 // arrays are strings, unfortunately...
366 for (var i = 0, len = iconArrays.length; i < len; i++) {
367 var option_name = iconArrays[i];
368 var option = _options[option_name];
369 // convert "1,2" to [1, 2];
370 if (option) {
371 var arr = option.split(',');
372 // array.map for ie<9
373 for (var j = 0, lenJ = arr.length; j < lenJ; j++) {
374 arr[j] = Number(arr[j]);
375 }
376 _options[option_name] = arr;
377 }
378 }
379 // default popupAnchor
380 if (!_options.popupAnchor) {
381 // set (roughly) to size of icon
382 _options.popupAnchor = (function (i_size) {
383 // copy array
384 i_size = i_size.slice();
385
386 // inverse coordinates
387 i_size[0] = 0;
388 i_size[1] *= -1;
389 // bottom position on popup is 7px
390 i_size[1] -= 3;
391 return i_size;
392 })(_options.iconSize || default_icon.iconSize);
393 }
394 if (_options.iconUrl) {
395 _options.icon = new L.Icon(_options);
396 }
397 return _options;
398 };
399
400 // these accessible properties hold map objects
401 this.maps = [];
402 this.images = [];
403 this.markergroups = {};
404 this.markers = [];
405 this.lines = [];
406 this.polygons = [];
407 this.circles = [];
408 this.geojsons = [];
409 this.overlays = [];
410 }
411
412 /**
413 * window.WPLeafletMapPlugin can be used, by saving arguments,
414 * before it is officially initialized
415 *
416 * This is used to deal with the potential for deferred scripts
417 */
418 var original = window.WPLeafletMapPlugin;
419 window.WPLeafletMapPlugin = new Main();
420
421 // check for functions to execute
422 if (!!original) {
423 for (var i = 0, len = original.length; i < len; i++) {
424 window.WPLeafletMapPlugin.push(original[i]);
425 }
426
427 // empty the array
428 original.splice(0);
429
430 // re-add any methods that may have been added to the original
431 for (var k in original) {
432 if (original.hasOwnProperty(k)) {
433 window.WPLeafletMapPlugin[k] = original[k];
434 }
435 }
436 }
437
438 // onload waits for Leaflet to load
439 if (window.addEventListener) {
440 window.addEventListener('load', window.WPLeafletMapPlugin.init, false);
441 } else if (window.attachEvent) {
442 window.attachEvent('onload', window.WPLeafletMapPlugin.init);
443 }
444 })();
445