PluginProbe
Leaflet Map / 3.4.5
Leaflet Map v3.4.5
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
← All changes | scripts/construct-leaflet-map.js +266 -76 2.17.23.4.5 View file →
@@ -1,11 +1,27 @@
1 -;(function () {
1 +(function () {
2 2 // holds a function queue to call once page is loaded
3 3 function Main() {
4 - var ready = false
5 - var callbacks = []
4 + var VERSION = '{{VERSION}}';
5 + this.VERSION = VERSION;
6 6
7 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 + /**
8 24 * this function mirrors the array appending function
9 25 * so that we can at least append functions to a global array
10 26 * before the maps are ready to be rendered
11 27 *
@@ -16,13 +32,13 @@
16 32 * Think of it as a whenReady callback
17 33 */
18 34 this.push = function (fnc) {
19 35 if (ready) {
20 - fnc()
36 + callRenderFunction(fnc);
21 37 } else {
22 - callbacks.push(fnc)
38 + callbacks.push(fnc);
23 39 }
24 - }
40 + };
25 41
26 42 /**
27 43 * Same as above, but what if someone wants to execute a function
28 44 * before other functions?
@@ -28,30 +44,72 @@
28 44 * before other functions?
29 45 */
30 46 this.unshift = function (fnc) {
31 47 if (ready) {
32 - fnc()
48 + callRenderFunction(fnc);
33 49 } else {
34 - callbacks.unshift(fnc)
50 + callbacks.unshift(fnc);
35 51 }
36 - }
52 + };
37 53
38 54 /**
39 55 * execute all callbacks once page/Leaflet is loaded
40 56 */
41 57 this.init = function () {
42 - ready = true
58 + ready = true;
43 59 for (var i = 0, len = callbacks.length; i < len; i++) {
44 - callbacks[i]()
60 + callRenderFunction(callbacks[i]);
45 61 }
46 - }
62 + };
47 63
48 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 + /**
49 107 * maps are created iteratively, so the last map is the current map
50 108 */
51 109 this.getCurrentMap = function () {
52 - return this.maps[this.maps.length - 1]
53 - }
110 + return this.maps[this.maps.length - 1];
111 + };
54 112
55 113 /**
56 114 * Get/Create L.FeatureGroup for ALL shapes; used for `fitbounds`
57 115 * @since 2.13.0
@@ -57,20 +115,20 @@
57 115 * @since 2.13.0
58 116 */
59 117 this.getCurrentGroup = function () {
60 118 // marker groups are mapid -> feature group
61 - var mapid = this.maps.length
119 + var mapid = this.maps.length;
62 120 if (!this.markergroups[mapid]) {
63 - this.markergroups[mapid] = this.newMarkerGroup(this.maps[mapid - 1])
121 + this.markergroups[mapid] = this.newMarkerGroup(this.maps[mapid - 1]);
64 122 }
65 - return this.markergroups[mapid]
66 - }
123 + return this.markergroups[mapid];
124 + };
67 125
68 126 /**
69 127 * backwards-compatible getCurrentGroup
70 128 * @deprecated 2.13.0
71 129 */
72 - this.getCurrentMarkerGroup = this.getCurrentGroup
130 + this.getCurrentMarkerGroup = this.getCurrentGroup;
73 131
74 132 /**
75 133 * get FeatureGroup and add to map
76 134 *
@@ -76,18 +134,18 @@
76 134 *
77 135 * ! This is extracted so that it can be overwritten by plugins
78 136 */
79 137 this.getGroup = function (map) {
80 - return new L.FeatureGroup().addTo(map)
81 - }
138 + return new L.FeatureGroup().addTo(map);
139 + };
82 140
83 141 /**
84 142 * group is created and event is added
85 143 */
86 144 this.newMarkerGroup = function (map) {
87 - var mg = this.getGroup(map)
145 + var mg = this.getGroup(map);
88 146
89 - mg.timeout = null
147 + mg.timeout = null;
90 148
91 149 // custom attribute
92 150 if (map._shouldFitBounds) {
93 151 mg.on(
@@ -92,40 +150,86 @@
92 150 if (map._shouldFitBounds) {
93 151 mg.on(
94 152 'layeradd',
95 153 function (event) {
96 - // needs a timeout so that it doesn't
97 - // opt out of a bound change
98 154 if (event.layer instanceof L.FeatureGroup) {
99 155 // wait for featuregroup/ajax-geojson to be ready
100 156 event.layer.on('ready', function () {
101 - map.fitBounds(mg.getBounds())
102 - })
157 + map.fitBounds(mg.getBounds());
158 + });
103 159 }
104 160
105 - window.clearTimeout(this.timeout)
161 + // needs a timeout so that it doesn't
162 + // opt out of a bound change
163 + window.clearTimeout(this.timeout);
106 164 this.timeout = window.setTimeout(function () {
107 165 try {
108 - map.fitBounds(mg.getBounds())
166 + map.fitBounds(mg.getBounds());
109 167 } catch (e) {
110 168 // ajax-geojson might not have valid bounds yet
111 169 }
112 - }, 100)
170 + }, 100);
113 171 },
114 172 mg
115 - )
173 + );
116 174 }
117 175
118 - return mg
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();
119 205 }
120 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 +
121 225 var unescape = (this.unescape = function (str) {
122 - var div = document.createElement('div')
123 - div.innerHTML = str
124 - return div.innerText
125 - })
226 + var div = document.createElement('div');
227 + div.innerHTML = str;
228 + return div.innerText || str;
229 + });
126 230
127 - var templateRe = /\{ *(.*?) *\}/g
231 + var templateRe = /\{ *(.*?) *\}/g;
128 232
129 233 /**
130 234 * It interpolates variables in curly brackets (regex above)
131 235 *
@@ -134,18 +238,24 @@
134 238 * @param {string} str
135 239 * @param {object} data e.g. feature.properties
136 240 */
137 241 this.template = function (str, data) {
242 + if (data == null) {
243 + return str;
244 + }
245 +
138 246 return str.replace(templateRe, function (match, key) {
139 - var value = parseKey(data, key)
140 - if (value === undefined) {
141 - return match
247 + var obj = liquid(key);
248 + var value = parseKey(data, obj.key);
249 + if (value == null) {
250 + return obj.default || match;
142 251 }
143 - return value
144 - })
145 - }
252 + return value;
253 + });
254 + };
146 255
147 - var strToPathRe = /[.‘’'“”"\[\]]+/g
256 + /** used in strToPath */
257 + var strToPathRe = /[.‘’'“”"\[\]]+/g;
148 258
149 259 /**
150 260 * Converts nested object keys to array
151 261 *
@@ -153,20 +263,23 @@
153 263 * ['this', 'that', 'and', 'theOther', '4']
154 264 * @param {string} key
155 265 */
156 266 function strToPath(key) {
157 - var input = key.split(strToPathRe)
158 - var output = []
267 + if (key == null) {
268 + return [];
269 + }
270 + var input = key.split(strToPathRe);
271 + var output = [];
159 272
160 273 // failsafe for all empty strings;
161 274 // mostly catches brackets at the end of a string
162 275 for (var i = 0, len = input.length; i < len; i++) {
163 276 if (input[i] !== '') {
164 - output.push(input[i])
277 + output.push(input[i]);
165 278 }
166 279 }
167 280
168 - return output
281 + return output;
169 282 }
170 283
171 284 /**
172 285 * It uses strToPath to access a possibly nested path value
@@ -174,50 +287,127 @@
174 287 * @param {object} obj
175 288 * @param {string} key
176 289 */
177 290 function parseKey(obj, key) {
178 - var arr = strToPath(unescape(key))
179 - var value = obj
291 + var arr = strToPath(unescape(key));
292 + var value = obj;
180 293
181 294 for (var i = 0, len = arr.length; i < len; i++) {
182 - value = value[arr[i]]
295 + value = value[arr[i]];
183 296 if (!value) {
184 - return undefined
297 + return undefined;
185 298 }
186 299 }
187 300
188 - return value
301 + return value;
189 302 }
190 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 +
191 330 function waitFor(prop, cb) {
192 331 if (typeof L !== 'undefined' && typeof L[prop] !== 'undefined') {
193 - cb()
332 + cb();
194 333 } else {
195 334 setTimeout(function () {
196 - waitFor(prop, cb)
197 - }, 100)
335 + waitFor(prop, cb);
336 + }, 100);
198 337 }
199 338 }
200 339
201 340 /** wait for leaflet-svg-icon (if deferred) */
202 341 this.waitForSVG = function (cb) {
203 - waitFor('SVGIcon', cb)
204 - }
342 + waitFor('SVGIcon', cb);
343 + };
205 344
206 345 /** wait for leaflet-ajax-geojson (if deferred) */
207 346 this.waitForAjax = function (cb) {
208 - waitFor('AjaxGeoJSON', cb)
209 - }
347 + waitFor('AjaxGeoJSON', cb);
348 + };
210 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 +
211 400 // these accessible properties hold map objects
212 - this.maps = []
213 - this.images = []
214 - this.markergroups = {}
215 - this.markers = []
216 - this.lines = []
217 - this.polygons = []
218 - this.circles = []
219 - this.geojsons = []
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 = [];
220 410 }
221 411
222 412 /**
223 413 * window.WPLeafletMapPlugin can be used, by saving arguments,
@@ -224,24 +414,24 @@
224 414 * before it is officially initialized
225 415 *
226 416 * This is used to deal with the potential for deferred scripts
227 417 */
228 - var original = window.WPLeafletMapPlugin
229 - window.WPLeafletMapPlugin = new Main()
418 + var original = window.WPLeafletMapPlugin;
419 + window.WPLeafletMapPlugin = new Main();
230 420
231 421 // check for functions to execute
232 422 if (!!original) {
233 423 for (var i = 0, len = original.length; i < len; i++) {
234 - window.WPLeafletMapPlugin.push(original[i])
424 + window.WPLeafletMapPlugin.push(original[i]);
235 425 }
236 426
237 427 // empty the array
238 - original.splice(0)
428 + original.splice(0);
239 429
240 430 // re-add any methods that may have been added to the original
241 431 for (var k in original) {
242 432 if (original.hasOwnProperty(k)) {
243 - window.WPLeafletMapPlugin[k] = original[k]
433 + window.WPLeafletMapPlugin[k] = original[k];
244 434 }
245 435 }
246 436 }
247 437
@@ -246,9 +436,9 @@
246 436 }
247 437
248 438 // onload waits for Leaflet to load
249 439 if (window.addEventListener) {
250 - window.addEventListener('load', window.WPLeafletMapPlugin.init, false)
440 + window.addEventListener('load', window.WPLeafletMapPlugin.init, false);
251 441 } else if (window.attachEvent) {
252 - window.attachEvent('onload', window.WPLeafletMapPlugin.init)
442 + window.attachEvent('onload', window.WPLeafletMapPlugin.init);
253 443 }
254 -})()
444 +})();