Version Description
Download this release
Release Info
Developer | webaware |
Plugin | Flexible Map |
Version | 1.17.0 |
Comparing to | |
See all releases |
Code changes from version 1.16.0 to 1.17.0
- changelog.md +9 -0
- flexible-map.php +2 -2
- includes/class.FlxMapPlugin.php +6 -3
- js/flexible-map.js +981 -988
- js/flexible-map.min.js +1 -1
- readme.txt +10 -9
changelog.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2 |
|
3 |
## Changelog
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
### 1.16.0
|
6 |
|
7 |
Released 2018-09-07
|
2 |
|
3 |
## Changelog
|
4 |
|
5 |
+
### 1.17.0
|
6 |
+
|
7 |
+
Released 2018-11-19
|
8 |
+
|
9 |
+
* fixed: map tiles don't redraw for KML maps with zoom when hidden in a tab / accordion
|
10 |
+
* changed: use the [current quarterly (stable) version of the Google Maps API](https://developers.google.com/maps/documentation/javascript/versions)
|
11 |
+
* changed: remove support for ancient browsers (Opera 12, IE < 11)
|
12 |
+
* tested: WordPress 5.0 (no Gutenberg block yet; maybe next release!)
|
13 |
+
|
14 |
### 1.16.0
|
15 |
|
16 |
Released 2018-09-07
|
flexible-map.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Flexible Map
|
4 |
Plugin URI: https://flexible-map.webaware.net.au/
|
5 |
Description: Embed Google Maps shortcodes in pages and posts, either by centre coordinates or street address, or by URL to a Google Earth KML file. <a href="https://flexible-map.webaware.net.au/manual/getting-started/">Get started</a> with a simple shortcode. See the <a href="https://flexible-map.webaware.net.au/manual/attribute-reference/">complete attribute reference</a> for more details.
|
6 |
-
Version: 1.
|
7 |
Author: WebAware
|
8 |
Author URI: https://shop.webaware.com.au/
|
9 |
Text Domain: wp-flexible-map
|
@@ -37,7 +37,7 @@ define('FLXMAP_PLUGIN_FILE', __FILE__);
|
|
37 |
define('FLXMAP_PLUGIN_ROOT', dirname(__FILE__) . '/');
|
38 |
define('FLXMAP_PLUGIN_NAME', basename(dirname(__FILE__)) . '/' . basename(__FILE__));
|
39 |
define('FLXMAP_PLUGIN_OPTIONS', 'flexible_map');
|
40 |
-
define('FLXMAP_PLUGIN_VERSION', '1.
|
41 |
|
42 |
// shortcode tags
|
43 |
define('FLXMAP_PLUGIN_TAG_MAP', 'flexiblemap');
|
3 |
Plugin Name: Flexible Map
|
4 |
Plugin URI: https://flexible-map.webaware.net.au/
|
5 |
Description: Embed Google Maps shortcodes in pages and posts, either by centre coordinates or street address, or by URL to a Google Earth KML file. <a href="https://flexible-map.webaware.net.au/manual/getting-started/">Get started</a> with a simple shortcode. See the <a href="https://flexible-map.webaware.net.au/manual/attribute-reference/">complete attribute reference</a> for more details.
|
6 |
+
Version: 1.17.0
|
7 |
Author: WebAware
|
8 |
Author URI: https://shop.webaware.com.au/
|
9 |
Text Domain: wp-flexible-map
|
37 |
define('FLXMAP_PLUGIN_ROOT', dirname(__FILE__) . '/');
|
38 |
define('FLXMAP_PLUGIN_NAME', basename(dirname(__FILE__)) . '/' . basename(__FILE__));
|
39 |
define('FLXMAP_PLUGIN_OPTIONS', 'flexible_map');
|
40 |
+
define('FLXMAP_PLUGIN_VERSION', '1.17.0');
|
41 |
|
42 |
// shortcode tags
|
43 |
define('FLXMAP_PLUGIN_TAG_MAP', 'flexiblemap');
|
includes/class.FlxMapPlugin.php
CHANGED
@@ -87,7 +87,7 @@ class FlxMapPlugin {
|
|
87 |
$options = get_option(FLXMAP_PLUGIN_OPTIONS, array());
|
88 |
|
89 |
if (empty($options['noAPI'])) {
|
90 |
-
$args = array('v' => '
|
91 |
if (!empty($options['apiKey'])) {
|
92 |
$args['key'] = $options['apiKey'];
|
93 |
}
|
@@ -573,8 +573,11 @@ HTML;
|
|
573 |
throw new Exception("error decoding JSON\n" . $response['body']);
|
574 |
}
|
575 |
|
576 |
-
if ($result->status
|
577 |
-
|
|
|
|
|
|
|
578 |
}
|
579 |
|
580 |
// success, return array with latitude and longitude
|
87 |
$options = get_option(FLXMAP_PLUGIN_OPTIONS, array());
|
88 |
|
89 |
if (empty($options['noAPI'])) {
|
90 |
+
$args = array('v' => 'quarterly');
|
91 |
if (!empty($options['apiKey'])) {
|
92 |
$args['key'] = $options['apiKey'];
|
93 |
}
|
573 |
throw new Exception("error decoding JSON\n" . $response['body']);
|
574 |
}
|
575 |
|
576 |
+
if ($result->status !== 'OK') {
|
577 |
+
if (!empty($result->error_message)) {
|
578 |
+
throw new Exception(sprintf("error retrieving address: %s; %s", $result->status, $result->error_message));
|
579 |
+
}
|
580 |
+
throw new Exception(sprintf("error retrieving address: %s", $result->status));
|
581 |
}
|
582 |
|
583 |
// success, return array with latitude and longitude
|
js/flexible-map.js
CHANGED
@@ -1,993 +1,986 @@
|
|
|
|
|
|
1 |
/*
|
2 |
JavaScript for the WordPress plugin wp-flexible-map
|
3 |
https://flexible-map.webaware.net.au/
|
4 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
addEventListener(mapDiv, "click", function(event) {
|
585 |
-
if (event.target.getAttribute("data-flxmap-fix-opera")) {
|
586 |
-
stopEvent(event);
|
587 |
-
}
|
588 |
-
});
|
589 |
-
}
|
590 |
-
|
591 |
-
},
|
592 |
-
|
593 |
-
/**
|
594 |
-
* show a map centred at latitude / longitude and with marker at latitude / longitude
|
595 |
-
* @param {String} divID the ID of the div that will contain the map
|
596 |
-
* @param {Array} centre an array of two integers: [ latitude, longitude ]
|
597 |
-
* @param {Array} marker an array of two integers: [ latitude, longitude ]
|
598 |
-
*/
|
599 |
-
showMarker: function(divID, centre, marker) {
|
600 |
-
var map = this.showMap(divID, centre);
|
601 |
-
var markerLocation = new google.maps.LatLng(marker[0], marker[1]);
|
602 |
-
var options = {
|
603 |
-
map: map,
|
604 |
-
position: markerLocation,
|
605 |
-
icon: this.markerIcon
|
606 |
-
};
|
607 |
-
var Animation = google.maps.Animation;
|
608 |
-
|
609 |
-
switch (this.markerAnimation) {
|
610 |
-
|
611 |
-
case "drop":
|
612 |
-
options.animation = Animation.DROP;
|
613 |
-
break;
|
614 |
-
|
615 |
-
case "bounce":
|
616 |
-
options.animation = Animation.BOUNCE;
|
617 |
-
break;
|
618 |
-
|
619 |
-
}
|
620 |
-
|
621 |
-
var point = new google.maps.Marker(options);
|
622 |
-
|
623 |
-
this.setMarkerPoint(point);
|
624 |
-
this.setMarkerLocation(markerLocation);
|
625 |
-
|
626 |
-
handleHiddenMap(this, divID);
|
627 |
-
|
628 |
-
if (!this.markerTitle) {
|
629 |
-
this.markerTitle = this.markerAddress;
|
630 |
-
}
|
631 |
-
|
632 |
-
if (this.markerTitle || this.markerHTML || this.markerDescription || this.markerLink || this.markerDirections) {
|
633 |
-
var i, len, lines, infowin, element, a,
|
634 |
-
self = this,
|
635 |
-
container = document.createElement("DIV");
|
636 |
-
|
637 |
-
container.className = "flxmap-infowin";
|
638 |
-
|
639 |
-
// heading for info window
|
640 |
-
element = document.createElement("DIV");
|
641 |
-
element.className = "flxmap-marker-title";
|
642 |
-
if (this.markerTitle) {
|
643 |
-
element.appendChild(document.createTextNode(this.markerTitle));
|
644 |
-
|
645 |
-
// add tooltip title for marker
|
646 |
-
point.setTitle(this.markerTitle);
|
647 |
-
}
|
648 |
-
container.appendChild(element);
|
649 |
-
|
650 |
-
// add precomposed HTML for infowindow
|
651 |
-
if (this.markerHTML) {
|
652 |
-
element = document.createElement("DIV");
|
653 |
-
element.innerHTML = this.markerHTML;
|
654 |
-
container.appendChild(element);
|
655 |
-
}
|
656 |
-
|
657 |
-
// body of info window, with link
|
658 |
-
if (this.markerDescription || this.markerLink) {
|
659 |
-
element = document.createElement("DIV");
|
660 |
-
element.className = "flxmap-marker-link";
|
661 |
-
if (this.markerDescription) {
|
662 |
-
lines = this.markerDescription.split("\n");
|
663 |
-
for (i = 0, len = lines.length; i < len; i++) {
|
664 |
-
if (i > 0)
|
665 |
-
element.appendChild(document.createElement("BR"));
|
666 |
-
element.appendChild(document.createTextNode(lines[i]));
|
667 |
-
}
|
668 |
-
if (this.markerLink) {
|
669 |
-
element.appendChild(document.createElement("BR"));
|
670 |
-
}
|
671 |
-
}
|
672 |
-
if (this.markerLink) {
|
673 |
-
a = document.createElement("A");
|
674 |
-
a.href = this.markerLink;
|
675 |
-
if (this.markerLinkTarget) {
|
676 |
-
a.target = this.markerLinkTarget;
|
677 |
-
}
|
678 |
-
a.appendChild(document.createTextNode(this.markerLinkText || this.gettext("Click for details")));
|
679 |
-
element.appendChild(a);
|
680 |
-
}
|
681 |
-
container.appendChild(element);
|
682 |
-
}
|
683 |
-
|
684 |
-
// add a link for directions if wanted
|
685 |
-
if (this.markerDirections) {
|
686 |
-
element = document.createElement("DIV");
|
687 |
-
element.className = "flxmap-directions-link";
|
688 |
-
a = document.createElement("A");
|
689 |
-
a.href = "#";
|
690 |
-
a.dataLatitude = marker[0];
|
691 |
-
a.dataLongitude = marker[1];
|
692 |
-
addEventListener(a, "click", function(event) {
|
693 |
-
stopEvent(event);
|
694 |
-
self.showDirections(this.dataLatitude, this.dataLongitude, true);
|
695 |
-
});
|
696 |
-
a.appendChild(document.createTextNode(this.gettext("Directions")));
|
697 |
-
element.appendChild(a);
|
698 |
-
container.appendChild(element);
|
699 |
-
}
|
700 |
-
|
701 |
-
infowin = new google.maps.InfoWindow({content: container});
|
702 |
-
this.setMarkerInfowin(infowin);
|
703 |
-
|
704 |
-
if (this.markerShowInfo) {
|
705 |
-
// open after map is loaded, so that infowindow will auto-pan and won't be cropped at top
|
706 |
-
google.maps.event.addListenerOnce(map, "tilesloaded", function() {
|
707 |
-
infowin.open(map, point);
|
708 |
-
});
|
709 |
-
}
|
710 |
-
|
711 |
-
google.maps.event.addListener(point, "click", function() {
|
712 |
-
infowin.open(map, point);
|
713 |
-
});
|
714 |
-
|
715 |
-
// find Google link and append marker info, modern browsers only!
|
716 |
-
// NB: Google link is set before initial map idle event, and reset each time the map centre changes
|
717 |
-
var googleLink = function() { self.updateGoogleLink(); };
|
718 |
-
google.maps.event.addListener(map, "idle", googleLink);
|
719 |
-
google.maps.event.addListener(map, "center_changed", googleLink);
|
720 |
-
google.maps.event.addListenerOnce(map, "tilesloaded", googleLink);
|
721 |
-
}
|
722 |
-
|
723 |
-
// add a directions service if needed
|
724 |
-
if (this.markerDirections || this.markerDirectionsShow) {
|
725 |
-
this.startDirService(map);
|
726 |
-
|
727 |
-
// show directions immediately if required
|
728 |
-
if (this.markerDirectionsShow) {
|
729 |
-
this.showDirections(marker[0], marker[1], false);
|
730 |
-
}
|
731 |
-
}
|
732 |
-
|
733 |
-
},
|
734 |
-
|
735 |
-
/**
|
736 |
-
* show a map centred at address
|
737 |
-
* @param {String} divID the ID of the div that will contain the map
|
738 |
-
* @param {String} address the address (should return a unique location in Google Maps!)
|
739 |
-
*/
|
740 |
-
showAddress: function(divID, address) {
|
741 |
-
var self = this,
|
742 |
-
geocoder = new google.maps.Geocoder();
|
743 |
-
|
744 |
-
this.markerAddress = address;
|
745 |
-
|
746 |
-
if (this.markerTitle === "") {
|
747 |
-
this.markerTitle = address;
|
748 |
-
}
|
749 |
-
|
750 |
-
geocoder.geocode({address: address, region: this.region}, function(results, status) {
|
751 |
-
if (status === google.maps.GeocoderStatus.OK) {
|
752 |
-
var location = results[0].geometry.location,
|
753 |
-
centre = [ location.lat(), location.lng() ];
|
754 |
-
self.showMarker(divID, centre, centre);
|
755 |
-
}
|
756 |
-
else {
|
757 |
-
window.alert("Map address returns error: " + status);
|
758 |
-
}
|
759 |
-
});
|
760 |
-
},
|
761 |
-
|
762 |
-
/**
|
763 |
-
* set query parameters on Google link to maps -- modern browsers only
|
764 |
-
* NB: will only set the query parameters when Google link doesn't have them already;
|
765 |
-
* Google link is set before initial map idle event, and reset each time the map centre changes
|
766 |
-
*/
|
767 |
-
updateGoogleLink: function() {
|
768 |
-
if ("querySelectorAll" in document) {
|
769 |
-
try {
|
770 |
-
var flxmap = this.getMap().getDiv(),
|
771 |
-
location = this.getMarkerLocation(),
|
772 |
-
googleLinks = flxmap.querySelectorAll("a[href*='maps.google.com/maps']:not([href*='mps_dialog']):not([href*='&q='])"),
|
773 |
-
i = 0, len = googleLinks.length,
|
774 |
-
query = encodeURIComponent((this.markerAddress ? this.markerAddress : this.markerTitle) +
|
775 |
-
" @" + location.lat() + "," + location.lng());
|
776 |
-
|
777 |
-
for (; i < len; i++) {
|
778 |
-
googleLinks[i].href += "&mrt=loc&iwloc=A&q=" + query;
|
779 |
-
}
|
780 |
-
}
|
781 |
-
catch (e) {
|
782 |
-
// we don't care about IE8 and earlier...
|
783 |
-
}
|
784 |
-
}
|
785 |
-
},
|
786 |
-
|
787 |
-
/**
|
788 |
-
* tell Google Maps to redraw the map, and centre it back where it started with default zoom
|
789 |
-
*/
|
790 |
-
redraw: function() {
|
791 |
-
var map = this.getMap(),
|
792 |
-
kmlLayer = this.getKmlLayer();
|
793 |
-
|
794 |
-
google.maps.event.trigger(map, "resize");
|
795 |
-
|
796 |
-
// if map is KML, must refit to computed bounds, else use centre and zoom setting
|
797 |
-
if (kmlLayer) {
|
798 |
-
map.fitBounds(kmlLayer.getDefaultViewport());
|
799 |
-
}
|
800 |
-
else {
|
801 |
-
map.setCenter(this.getCenter());
|
802 |
-
map.setZoom(this.zoom);
|
803 |
-
|
804 |
-
// redraw the marker's infowindow if it has one
|
805 |
-
var infowin = this.getMarkerInfowin();
|
806 |
-
if (infowin) {
|
807 |
-
infowin.open(map, this.getMarkerPoint());
|
808 |
-
}
|
809 |
-
}
|
810 |
-
},
|
811 |
-
|
812 |
-
/**
|
813 |
-
* create directions service
|
814 |
-
*/
|
815 |
-
startDirService: function(map) {
|
816 |
-
// make sure we have a directions service
|
817 |
-
if (!this.dirService) {
|
818 |
-
this.dirService = new google.maps.DirectionsService();
|
819 |
-
}
|
820 |
-
|
821 |
-
// make sure we have a directions renderer
|
822 |
-
if (!this.dirRenderer) {
|
823 |
-
this.dirRenderer = new google.maps.DirectionsRenderer({
|
824 |
-
map: map,
|
825 |
-
draggable: this.dirDraggable,
|
826 |
-
suppressMarkers: this.dirSuppressMarkers,
|
827 |
-
panel: this.dirShowSteps ? document.getElementById(this.markerDirectionsDiv) : null
|
828 |
-
});
|
829 |
-
}
|
830 |
-
},
|
831 |
-
|
832 |
-
/**
|
833 |
-
* show directions for specified latitude / longitude and title
|
834 |
-
* @param {Number} latitude
|
835 |
-
* @param {Number} longitude
|
836 |
-
* @param {bool} focus [optional]
|
837 |
-
*/
|
838 |
-
showDirections: function(latitude, longitude, focus) {
|
839 |
-
var self = this;
|
840 |
-
|
841 |
-
/**
|
842 |
-
* show the directions form to allow directions searches
|
843 |
-
*/
|
844 |
-
function showDirectionsForm() {
|
845 |
-
var panel = document.getElementById(self.markerDirectionsDiv),
|
846 |
-
form = document.createElement("form"),
|
847 |
-
input, p, from;
|
848 |
-
|
849 |
-
// remove all from panel
|
850 |
-
for (p = panel.lastChild; p; p = panel.lastChild) {
|
851 |
-
panel.removeChild(p);
|
852 |
-
}
|
853 |
-
|
854 |
-
// populate form and add to panel
|
855 |
-
p = document.createElement("p");
|
856 |
-
p.appendChild(document.createTextNode(self.gettext("From") + ": "));
|
857 |
-
from = document.createElement("input");
|
858 |
-
from.type = "text";
|
859 |
-
from.name = "from";
|
860 |
-
from.value = self.markerDirectionsDefault;
|
861 |
-
p.appendChild(from);
|
862 |
-
input = document.createElement("input");
|
863 |
-
input.type = "submit";
|
864 |
-
input.value = self.gettext("Get directions");
|
865 |
-
p.appendChild(input);
|
866 |
-
form.appendChild(p);
|
867 |
-
panel.appendChild(form);
|
868 |
-
|
869 |
-
// hack to fix IE<=7 name weirdness for dynamically created form elements;
|
870 |
-
// see https://msdn.microsoft.com/en-us/library/ms534184.aspx but have a hanky ready
|
871 |
-
if (typeof form.elements.from == "undefined") {
|
872 |
-
form.elements.from = from;
|
873 |
-
}
|
874 |
-
|
875 |
-
// only focus when asked, to prevent problems autofocusing on elements and scrolling the page!
|
876 |
-
if (focus) {
|
877 |
-
from.focus();
|
878 |
-
}
|
879 |
-
|
880 |
-
// handle the form submit
|
881 |
-
addEventListener(form, "submit", function(event) {
|
882 |
-
stopEvent(event);
|
883 |
-
|
884 |
-
var from = this.elements.from.value;
|
885 |
-
|
886 |
-
// only process if something was entered to search on
|
887 |
-
if (/\S/.test(from)) {
|
888 |
-
requestDirections(from);
|
889 |
-
}
|
890 |
-
|
891 |
-
});
|
892 |
-
}
|
893 |
-
|
894 |
-
/**
|
895 |
-
* request directions
|
896 |
-
* @param {String} from
|
897 |
-
*/
|
898 |
-
function requestDirections(from) {
|
899 |
-
var dest = (self.markerAddress === "") ? new google.maps.LatLng(latitude, longitude) : self.markerAddress,
|
900 |
-
request = {
|
901 |
-
origin: from,
|
902 |
-
destination: dest
|
903 |
-
};
|
904 |
-
|
905 |
-
if (self.region) {
|
906 |
-
request.region = self.region;
|
907 |
-
}
|
908 |
-
|
909 |
-
switch (self.dirTravelMode) {
|
910 |
-
case "bicycling":
|
911 |
-
request.travelMode = google.maps.TravelMode.BICYCLING;
|
912 |
-
break;
|
913 |
-
|
914 |
-
case "driving":
|
915 |
-
request.travelMode = google.maps.TravelMode.DRIVING;
|
916 |
-
break;
|
917 |
-
|
918 |
-
case "transit":
|
919 |
-
request.travelMode = google.maps.TravelMode.TRANSIT;
|
920 |
-
break;
|
921 |
-
|
922 |
-
case "walking":
|
923 |
-
request.travelMode = google.maps.TravelMode.WALKING;
|
924 |
-
break;
|
925 |
-
}
|
926 |
-
|
927 |
-
switch (self.dirUnitSystem) {
|
928 |
-
case "imperial":
|
929 |
-
request.unitSystem = google.maps.UnitSystem.IMPERIAL;
|
930 |
-
break;
|
931 |
-
|
932 |
-
case "metric":
|
933 |
-
request.unitSystem = google.maps.UnitSystem.METRIC;
|
934 |
-
break;
|
935 |
-
}
|
936 |
-
|
937 |
-
self.dirService.route(request, dirResponseHander);
|
938 |
-
}
|
939 |
-
|
940 |
-
/**
|
941 |
-
* handle the response for Google directions service
|
942 |
-
* @param {google.maps.DirectionsResult} response
|
943 |
-
* @param {Number} status
|
944 |
-
*/
|
945 |
-
function dirResponseHander(response, status) {
|
946 |
-
var DirectionsStatus = google.maps.DirectionsStatus;
|
947 |
-
|
948 |
-
switch (status) {
|
949 |
-
case DirectionsStatus.OK:
|
950 |
-
self.dirRenderer.setDirections(response);
|
951 |
-
break;
|
952 |
-
|
953 |
-
case DirectionsStatus.ZERO_RESULTS:
|
954 |
-
window.alert("No route could be found between the origin and destination.");
|
955 |
-
break;
|
956 |
-
|
957 |
-
case DirectionsStatus.OVER_QUERY_LIMIT:
|
958 |
-
window.alert("The webpage has gone over the requests limit in too short a period of time.");
|
959 |
-
break;
|
960 |
-
|
961 |
-
case DirectionsStatus.REQUEST_DENIED:
|
962 |
-
window.alert("The webpage is not allowed to use the directions service.");
|
963 |
-
break;
|
964 |
-
|
965 |
-
case DirectionsStatus.INVALID_REQUEST:
|
966 |
-
window.alert("Invalid directions request.");
|
967 |
-
break;
|
968 |
-
|
969 |
-
case DirectionsStatus.NOT_FOUND:
|
970 |
-
window.alert("Origin or destination was not found.");
|
971 |
-
break;
|
972 |
-
|
973 |
-
default:
|
974 |
-
window.alert("A directions request could not be processed due to a server error. The request may succeed if you try again.");
|
975 |
-
break;
|
976 |
-
}
|
977 |
-
}
|
978 |
-
|
979 |
-
// if we have a directions div, show the form for searching it
|
980 |
-
if (this.markerDirectionsDiv && this.dirShowSearch) {
|
981 |
-
showDirectionsForm();
|
982 |
-
}
|
983 |
-
|
984 |
-
// if the from: location is already set, trigger the directions query
|
985 |
-
if (this.markerDirectionsDefault) {
|
986 |
-
requestDirections(this.markerDirectionsDefault);
|
987 |
-
}
|
988 |
-
|
989 |
-
}
|
990 |
-
|
991 |
-
};
|
992 |
-
|
993 |
-
})();
|
1 |
+
"use strict";
|
2 |
+
|
3 |
/*
|
4 |
JavaScript for the WordPress plugin wp-flexible-map
|
5 |
https://flexible-map.webaware.net.au/
|
6 |
*/
|
7 |
+
window.FlexibleMap = function () {
|
8 |
+
"use strict"; // instance-private members with accessors
|
9 |
+
|
10 |
+
var map; // google.maps.Map object
|
11 |
+
|
12 |
+
var centre; // google.maps.LatLng object for map centre
|
13 |
+
|
14 |
+
var markerLocation; // google.maps.LatLng object for single marker, when using showMarker()
|
15 |
+
|
16 |
+
var markerPoint; // google.maps.Marker object for single marker, when using showMarker()
|
17 |
+
|
18 |
+
var markerInfowin; // google.maps.InfoWindow object for single marker, when using showMarker()
|
19 |
+
|
20 |
+
var kmlLayer; // if map has a KML layer, this is the layer object
|
21 |
+
|
22 |
+
var hasRedrawn = false; // boolean, whether map has been asked to redrawOnce() already
|
23 |
+
|
24 |
+
/**
|
25 |
+
* set gesture handling options, with legacy support for draggable, dblclickZoom, scrollwheel
|
26 |
+
* set to "cooperative" if none of the settings are given
|
27 |
+
* @link https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.gestureHandling
|
28 |
+
* @param {Object} mapOptions
|
29 |
+
* @param {FlexibleMap} flexibleMap
|
30 |
+
* @return {Object}
|
31 |
+
*/
|
32 |
+
|
33 |
+
function getGestureHandling(mapOptions, flexibleMap) {
|
34 |
+
if (flexibleMap.gestureHandling !== undefined) {
|
35 |
+
mapOptions.gestureHandling = flexibleMap.gestureHandling;
|
36 |
+
} else if (flexibleMap.draggable === undefined && flexibleMap.dblclickZoom === undefined && flexibleMap.scrollwheel === undefined) {
|
37 |
+
mapOptions.gestureHandling = "cooperative";
|
38 |
+
} else {
|
39 |
+
// legacy support; deprecated
|
40 |
+
var draggable = flexibleMap.draggable === undefined ? true : flexibleMap.draggable; // default true, i.e. enable draggable
|
41 |
+
|
42 |
+
var disableDblclickZoom = flexibleMap.dblclickZoom === undefined ? false : !flexibleMap.draggable; // default true, i.e. enable double-click zoom
|
43 |
+
|
44 |
+
var scrollwheel = flexibleMap.scrollwheel === undefined ? false : flexibleMap.scrollwheel; // default false, i.e. dinable scrollwheel
|
45 |
+
// ----------------+-----------+------------------------+------------
|
46 |
+
// gestureHandling | draggable | disableDoubleClickZoom | scrollwheel
|
47 |
+
// ----------------+-----------+------------------------+------------
|
48 |
+
// cooperative | true | false | ctrl+ |
|
49 |
+
// greedy | true | false | true |
|
50 |
+
// auto | ???? | false | ???? |
|
51 |
+
// none | false | true | false |
|
52 |
+
// ----------------+-----------+------------------------+------------
|
53 |
+
|
54 |
+
if (!draggable && disableDblclickZoom && !scrollwheel) {
|
55 |
+
mapOptions.gestureHandling = "none";
|
56 |
+
} else if (draggable && !disableDblclickZoom && scrollwheel) {
|
57 |
+
mapOptions.gestureHandling = "greedy";
|
58 |
+
} else {
|
59 |
+
mapOptions.draggable = draggable;
|
60 |
+
mapOptions.disableDoubleClickZoom = disableDblclickZoom;
|
61 |
+
mapOptions.scrollwheel = scrollwheel;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
return mapOptions;
|
66 |
+
}
|
67 |
+
/**
|
68 |
+
* get the Google Maps API Map object
|
69 |
+
* @return {google.maps.Map}
|
70 |
+
*/
|
71 |
+
|
72 |
+
|
73 |
+
this.getMap = function () {
|
74 |
+
return map;
|
75 |
+
};
|
76 |
+
/**
|
77 |
+
* get the centrepoint of the map at creation, or via setCenter()
|
78 |
+
* @return {google.maps.LatLng}
|
79 |
+
*/
|
80 |
+
|
81 |
+
|
82 |
+
this.getCenter = function () {
|
83 |
+
return centre;
|
84 |
+
};
|
85 |
+
/**
|
86 |
+
* set the centrepoint of the map
|
87 |
+
* @param {google.maps.LatLng} latLng
|
88 |
+
*/
|
89 |
+
|
90 |
+
|
91 |
+
this.setCenter = function (latLng) {
|
92 |
+
centre = latLng;
|
93 |
+
map.setCenter(centre);
|
94 |
+
};
|
95 |
+
/**
|
96 |
+
* record the single marker location
|
97 |
+
* @param {google.maps.LatLng} latLng
|
98 |
+
*/
|
99 |
+
|
100 |
+
|
101 |
+
this.setMarkerLocation = function (latLng) {
|
102 |
+
markerLocation = latLng;
|
103 |
+
};
|
104 |
+
/**
|
105 |
+
* get the single marker location
|
106 |
+
* @return {google.maps.LatLng}
|
107 |
+
*/
|
108 |
+
|
109 |
+
|
110 |
+
this.getMarkerLocation = function () {
|
111 |
+
return markerLocation;
|
112 |
+
};
|
113 |
+
/**
|
114 |
+
* record the single marker point
|
115 |
+
* @param {google.maps.Marker} point
|
116 |
+
*/
|
117 |
+
|
118 |
+
|
119 |
+
this.setMarkerPoint = function (point) {
|
120 |
+
markerPoint = point;
|
121 |
+
};
|
122 |
+
/**
|
123 |
+
* get the single marker point
|
124 |
+
* @return {google.maps.Marker}
|
125 |
+
*/
|
126 |
+
|
127 |
+
|
128 |
+
this.getMarkerPoint = function () {
|
129 |
+
return markerPoint;
|
130 |
+
};
|
131 |
+
/**
|
132 |
+
* record the single marker infowindow
|
133 |
+
* @param {google.maps.InfoWindow} infowin
|
134 |
+
*/
|
135 |
+
|
136 |
+
|
137 |
+
this.setMarkerInfowin = function (infowin) {
|
138 |
+
markerInfowin = infowin;
|
139 |
+
};
|
140 |
+
/**
|
141 |
+
* get the single marker infowindow
|
142 |
+
* @return {google.maps.InfoWindow}
|
143 |
+
*/
|
144 |
+
|
145 |
+
|
146 |
+
this.getMarkerInfowin = function () {
|
147 |
+
return markerInfowin;
|
148 |
+
};
|
149 |
+
/**
|
150 |
+
* get the map's KML layer if set
|
151 |
+
* @return {google.maps.KmlLayer}
|
152 |
+
*/
|
153 |
+
|
154 |
+
|
155 |
+
this.getKmlLayer = function () {
|
156 |
+
return kmlLayer;
|
157 |
+
};
|
158 |
+
/**
|
159 |
+
* if map starts life hidden and needs to be redrawn when revealed, this function will perform that redraw *once*
|
160 |
+
*/
|
161 |
+
|
162 |
+
|
163 |
+
this.redrawOnce = function () {
|
164 |
+
if (!hasRedrawn) {
|
165 |
+
hasRedrawn = true;
|
166 |
+
this.redraw();
|
167 |
+
}
|
168 |
+
};
|
169 |
+
/**
|
170 |
+
* show a map at specified centre latitude / longitude
|
171 |
+
* @param {String} divID the ID of the div that will contain the map
|
172 |
+
* @param {Array} latLng the map centre, an array of two integers: [ latitude, longitude ]
|
173 |
+
* @return {google.maps.Map} the Google Maps map created
|
174 |
+
*/
|
175 |
+
|
176 |
+
|
177 |
+
this.showMap = function (divID, latLng) {
|
178 |
+
centre = new google.maps.LatLng(latLng[0], latLng[1]);
|
179 |
+
var zoomControlStyles = {
|
180 |
+
"small": google.maps.ZoomControlStyle.SMALL,
|
181 |
+
"large": google.maps.ZoomControlStyle.LARGE,
|
182 |
+
"default": google.maps.ZoomControlStyle.DEFAULT
|
183 |
+
};
|
184 |
+
var zoomControlStyle = zoomControlStyles.small; // style the zoom control
|
185 |
+
|
186 |
+
if (this.zoomControlStyle in zoomControlStyles) {
|
187 |
+
zoomControlStyle = zoomControlStyles[this.zoomControlStyle];
|
188 |
+
} // basic options
|
189 |
+
|
190 |
+
|
191 |
+
var mapOptions = {
|
192 |
+
mapTypeId: this.mapTypeId,
|
193 |
+
mapTypeControl: this.mapTypeControl,
|
194 |
+
scaleControl: this.scaleControl,
|
195 |
+
panControl: this.panControl,
|
196 |
+
streetViewControl: this.streetViewControl,
|
197 |
+
zoomControl: this.zoomControl,
|
198 |
+
zoomControlOptions: {
|
199 |
+
style: zoomControlStyle
|
200 |
+
},
|
201 |
+
fullscreenControl: this.fullscreen,
|
202 |
+
center: centre,
|
203 |
+
zoom: this.zoom
|
204 |
+
};
|
205 |
+
mapOptions = getGestureHandling(mapOptions, this); // select which map types for map type control, if specified as comma-separated list of map type IDs
|
206 |
+
|
207 |
+
if (this.mapTypeIds) {
|
208 |
+
mapOptions.mapTypeControlOptions = {
|
209 |
+
mapTypeIds: this.mapTypeIds.split(",")
|
210 |
+
};
|
211 |
+
} // create a map
|
212 |
+
|
213 |
+
|
214 |
+
map = new google.maps.Map(document.getElementById(divID), mapOptions); // set custom map type if specified
|
215 |
+
|
216 |
+
if (this.mapTypeId in this.mapTypes) {
|
217 |
+
map.mapTypes.set(this.mapTypeId, this.mapTypes[this.mapTypeId]._styled_map);
|
218 |
+
}
|
219 |
+
|
220 |
+
return map;
|
221 |
+
};
|
222 |
+
/**
|
223 |
+
* load a map from a KML file and add as a layer on the Google Maps map
|
224 |
+
* @param {String} kmlFileURL
|
225 |
+
* @return {google.maps.KmlLayer}
|
226 |
+
*/
|
227 |
+
|
228 |
+
|
229 |
+
this.loadKmlMap = function (kmlFileURL) {
|
230 |
+
// load KML file as a layer and add to map
|
231 |
+
var self = this;
|
232 |
+
var options = {
|
233 |
+
map: map,
|
234 |
+
url: kmlFileURL
|
235 |
+
};
|
236 |
+
/**
|
237 |
+
* reset the map back to the recorded centre coordinates -- only used when centre is set for map
|
238 |
+
*/
|
239 |
+
|
240 |
+
function resetCentre() {
|
241 |
+
self.setCenter(new google.maps.LatLng(self.kmlCentre[0], self.kmlCentre[1]));
|
242 |
+
}
|
243 |
+
/**
|
244 |
+
* update centre of map from bounds on KML layer -- not called when centre is set for map
|
245 |
+
*/
|
246 |
+
|
247 |
+
|
248 |
+
function recordKmlCentre() {
|
249 |
+
centre = kmlLayer.getDefaultViewport().getCenter();
|
250 |
+
} // if a centre has been set, stop the viewport from changing and add the centre to map options
|
251 |
+
|
252 |
+
|
253 |
+
if (this.kmlCentre) {
|
254 |
+
options.preserveViewport = true;
|
255 |
+
options.center = new google.maps.LatLng(this.kmlCentre[0], this.kmlCentre[1]);
|
256 |
+
}
|
257 |
+
|
258 |
+
kmlLayer = new google.maps.KmlLayer(options); // listen for KML layer loaded event
|
259 |
+
|
260 |
+
google.maps.event.addListenerOnce(kmlLayer, "defaultviewport_changed", this.kmlCentre ? resetCentre : recordKmlCentre);
|
261 |
+
return kmlLayer;
|
262 |
+
}; // load localisations if they haven't already been loaded
|
263 |
+
|
264 |
+
|
265 |
+
if (!this.localised && "flxmap" in window) {
|
266 |
+
this.localise();
|
267 |
+
} // set map defaults
|
268 |
+
|
269 |
+
|
270 |
+
this.mapTypeId = google.maps.MapTypeId.ROADMAP;
|
271 |
+
this.mapTypeControl = true; // no control for changing map type
|
272 |
+
|
273 |
+
this.scaleControl = false; // no control for changing scale
|
274 |
+
|
275 |
+
this.panControl = false; // no control for panning
|
276 |
+
|
277 |
+
this.zoomControl = true; // show control for zooming
|
278 |
+
|
279 |
+
this.zoomControlStyle = "small"; // from "small", "large", "default"
|
280 |
+
|
281 |
+
this.streetViewControl = false; // no control for street view
|
282 |
+
|
283 |
+
this.fullscreen = true; // show control for full-screen view
|
284 |
+
|
285 |
+
this.gestureHandling = undefined; // defaults to cooperative
|
286 |
+
|
287 |
+
this.scrollwheel = undefined; // deprecated; use gestureHandling instead
|
288 |
+
|
289 |
+
this.draggable = undefined; // deprecated; use gestureHandling instead
|
290 |
+
|
291 |
+
this.dblclickZoom = undefined; // deprecated; use gestureHandling instead
|
292 |
+
|
293 |
+
this.zoom = 16; // zoom level, smaller is closer
|
294 |
+
|
295 |
+
this.markerTitle = ""; // title for marker info window
|
296 |
+
|
297 |
+
this.markerDescription = ""; // description for marker info window
|
298 |
+
|
299 |
+
this.markerHTML = ""; // HTML for marker info window (overrides title and description)
|
300 |
+
|
301 |
+
this.markerLink = ""; // link for marker title
|
302 |
+
|
303 |
+
this.markerLinkTarget = ""; // link target for marker link, e.g. _blank
|
304 |
+
|
305 |
+
this.markerLinkText = false; // link text for marker link, overriding default text
|
306 |
+
|
307 |
+
this.markerIcon = ""; // link for marker icon, leave blank for default
|
308 |
+
|
309 |
+
this.markerShowInfo = true; // if have infowin for marker, show it immediately
|
310 |
+
|
311 |
+
this.markerAnimation = "drop"; // marker animation - bounce, drop, none
|
312 |
+
|
313 |
+
this.markerDirections = false; // show directions link in info window
|
314 |
+
|
315 |
+
this.markerDirectionsShow = false; // show directions as soon as page loads
|
316 |
+
|
317 |
+
this.markerDirectionsDefault = ""; // default from: location for directions
|
318 |
+
|
319 |
+
this.markerAddress = ""; // address of marker, if given
|
320 |
+
|
321 |
+
this.targetFix = true; // remove target="_blank" from links on KML map
|
322 |
+
|
323 |
+
this.dirService = false;
|
324 |
+
this.dirRenderer = false;
|
325 |
+
this.dirDraggable = false; // directions route is draggable (for alternate routing)
|
326 |
+
|
327 |
+
this.dirSuppressMarkers = false; // suppress A/B markers on directions route
|
328 |
+
|
329 |
+
this.dirShowSteps = true; // show the directions steps (turn-by-turn)
|
330 |
+
|
331 |
+
this.dirShowSearch = true; // show the directions form for searching directions
|
332 |
+
|
333 |
+
this.dirTravelMode = "driving"; // can be bicycling, driving, transit, walking
|
334 |
+
|
335 |
+
this.dirUnitSystem = undefined; // can be imperial or metric
|
336 |
+
|
337 |
+
this.region = "";
|
338 |
+
this.locale = "en";
|
339 |
+
this.localeActive = false;
|
340 |
+
this.kmlCentre = false;
|
341 |
+
this.kmlcache = "none";
|
342 |
+
};
|
343 |
+
|
344 |
+
FlexibleMap.prototype = function () {
|
345 |
+
"use strict";
|
346 |
+
|
347 |
+
function stopEvent(event) {
|
348 |
+
event.stopPropagation();
|
349 |
+
event.preventDefault();
|
350 |
+
} // handle hidden maps, trigger a resize on first display
|
351 |
+
|
352 |
+
|
353 |
+
var handleHiddenMap = function () {
|
354 |
+
if (typeof MutationObserver === "undefined") {
|
355 |
+
return function () {};
|
356 |
+
}
|
357 |
+
|
358 |
+
return function (flxmap, divID) {
|
359 |
+
var container = document.getElementById(divID).parentNode;
|
360 |
+
|
361 |
+
function isHidden(element) {
|
362 |
+
var style = window.getComputedStyle(element);
|
363 |
+
return style.display === "none" || style.visibility === "hidden";
|
364 |
+
} // only need to watch and act if the parent container is hidden from display
|
365 |
+
|
366 |
+
|
367 |
+
if (isHidden(container)) {
|
368 |
+
var observer = new MutationObserver(function (mutations, self) {
|
369 |
+
// only proceed if map is visible now
|
370 |
+
if (!isHidden(container)) {
|
371 |
+
flxmap.redrawOnce(); // stop observing, we're done
|
372 |
+
|
373 |
+
self.disconnect();
|
374 |
+
}
|
375 |
+
});
|
376 |
+
observer.observe(container, {
|
377 |
+
attributes: true,
|
378 |
+
attributeFilter: ["style"]
|
379 |
+
});
|
380 |
+
}
|
381 |
+
};
|
382 |
+
}();
|
383 |
+
/**
|
384 |
+
* encode special JavaScript characters, so text is safe when building JavaScript/HTML dynamically
|
385 |
+
* NB: conservatively assumes that HTML special characters are unsafe, and encodes them too
|
386 |
+
* @param {String} text
|
387 |
+
* @return {String}
|
388 |
+
*/
|
389 |
+
|
390 |
+
|
391 |
+
function encodeJS() {
|
392 |
+
/**
|
393 |
+
* encode character as Unicode hexadecimal escape sequence
|
394 |
+
* @param {String} ch character to encode
|
395 |
+
* @return {String}
|
396 |
+
*/
|
397 |
+
function toUnicodeHex(ch) {
|
398 |
+
var c = ch.charCodeAt(0);
|
399 |
+
var s = c.toString(16); // see if we can use 2-digit hex code
|
400 |
+
|
401 |
+
if (c < 0x100) {
|
402 |
+
return "\\x" + ("00" + s).slice(-2);
|
403 |
+
} // must use 4-digit hex code
|
404 |
+
|
405 |
+
|
406 |
+
return "\\u" + ("0000" + s).slice(-4);
|
407 |
+
}
|
408 |
|
409 |
+
return function (text) {
|
410 |
+
// search for JavaScript and HTML special characters, convert to Unicode hex
|
411 |
+
return text.replace(/[\\/"'&<>\x00-\x1f\x7f-\xa0\u2000-\u200f\u2028-\u202f]/g, toUnicodeHex); // eslint-disable-line no-control-regex
|
412 |
+
};
|
413 |
+
}
|
414 |
+
/**
|
415 |
+
* add cache buster to KML source link
|
416 |
+
* @param {String} url
|
417 |
+
* @param {String} caching
|
418 |
+
* @return {String}
|
419 |
+
*/
|
420 |
+
|
421 |
+
|
422 |
+
function kmlCacheBuster(url, caching) {
|
423 |
+
var matches = /^(\d+)\s*(minute|hour|day)s?$/.exec(caching);
|
424 |
+
var buster;
|
425 |
+
|
426 |
+
if (matches) {
|
427 |
+
var milliseconds = new Date().getTime();
|
428 |
+
var multiplier = +matches[1];
|
429 |
+
|
430 |
+
switch (matches[2]) {
|
431 |
+
case "minute":
|
432 |
+
// can't be less than 5 minutes
|
433 |
+
if (multiplier < 5) {
|
434 |
+
multiplier = 5;
|
435 |
+
}
|
436 |
+
|
437 |
+
buster = milliseconds / (60000 * multiplier);
|
438 |
+
break;
|
439 |
+
|
440 |
+
case "hour":
|
441 |
+
buster = milliseconds / (3600000 * multiplier);
|
442 |
+
break;
|
443 |
+
|
444 |
+
case "day":
|
445 |
+
buster = milliseconds / (86400000 * multiplier);
|
446 |
+
break;
|
447 |
+
|
448 |
+
default:
|
449 |
+
buster = false;
|
450 |
+
break;
|
451 |
+
}
|
452 |
+
|
453 |
+
if (buster) {
|
454 |
+
buster = Math.floor(buster);
|
455 |
+
url += (url.indexOf("?") > -1 ? "&" : "?") + "nocache=" + buster; // eslint-disable-line no-param-reassign
|
456 |
+
}
|
457 |
+
}
|
458 |
+
|
459 |
+
return url;
|
460 |
+
}
|
461 |
+
|
462 |
+
return {
|
463 |
+
constructor: FlexibleMap,
|
464 |
+
|
465 |
+
/**
|
466 |
+
* collection of locale / phrase mapping for internationalisation of messages
|
467 |
+
*/
|
468 |
+
i18n: {},
|
469 |
+
|
470 |
+
/**
|
471 |
+
* collection of custom Google Maps map types for styling maps
|
472 |
+
*/
|
473 |
+
mapTypes: {},
|
474 |
+
localised: false,
|
475 |
+
// set to true once localisations have been loaded
|
476 |
+
|
477 |
+
/**
|
478 |
+
* load localisations into class prototype
|
479 |
+
*/
|
480 |
+
localise: function localise() {
|
481 |
+
// load translations
|
482 |
+
if ("i18n" in flxmap) {
|
483 |
+
FlexibleMap.prototype.i18n = flxmap.i18n;
|
484 |
+
} // load custom map types
|
485 |
+
|
486 |
+
|
487 |
+
if ("mapTypes" in flxmap) {
|
488 |
+
var mapTypes = flxmap.mapTypes;
|
489 |
+
|
490 |
+
for (var key in mapTypes) {
|
491 |
+
mapTypes[key]._styled_map = new google.maps.StyledMapType(mapTypes[key].styles, mapTypes[key].options);
|
492 |
+
}
|
493 |
+
|
494 |
+
FlexibleMap.prototype.mapTypes = mapTypes;
|
495 |
+
}
|
496 |
+
|
497 |
+
FlexibleMap.prototype.localised = true;
|
498 |
+
},
|
499 |
+
|
500 |
+
/**
|
501 |
+
* set the locale used for i18n phrase lookup, picking the best match
|
502 |
+
* @param {String} localeWanted the locale wanted, e.g. en-AU, da-DK, sv
|
503 |
+
* @return {String} the locale that will be used (nearest match, or default if none)
|
504 |
+
*/
|
505 |
+
setlocale: function setlocale(localeWanted) {
|
506 |
+
this.locale = localeWanted; // attempt to set this locale as active
|
507 |
+
|
508 |
+
if (localeWanted in this.i18n) {
|
509 |
+
this.localeActive = localeWanted;
|
510 |
+
} else {
|
511 |
+
// not found, so try simplified locale
|
512 |
+
if (localeWanted.substr(0, 2) in this.i18n) {
|
513 |
+
this.localeActive = localeWanted;
|
514 |
+
} else {
|
515 |
+
// still not found
|
516 |
+
this.localeActive = false;
|
517 |
+
}
|
518 |
+
}
|
519 |
+
|
520 |
+
return this.localeActive;
|
521 |
+
},
|
522 |
+
|
523 |
+
/**
|
524 |
+
* get phrase from the current locale domain, or the default domain (en) if not found
|
525 |
+
* @param {String} key the key for the desired phrase
|
526 |
+
* @return {String}
|
527 |
+
*/
|
528 |
+
gettext: function gettext(key) {
|
529 |
+
var locale = this.localeActive;
|
530 |
+
|
531 |
+
if (locale && key in this.i18n[locale]) {
|
532 |
+
return this.i18n[locale][key];
|
533 |
+
}
|
534 |
+
|
535 |
+
return key;
|
536 |
+
},
|
537 |
+
|
538 |
+
/**
|
539 |
+
* show a map based on a KML file
|
540 |
+
* @param {String} divID the ID of the div that will contain the map
|
541 |
+
* @param {String} kmlFileURL path to the KML file to load
|
542 |
+
* @param {Number} zoom [optional] zoom level
|
543 |
+
*/
|
544 |
+
showKML: function showKML(divID, kmlFileURL, zoom) {
|
545 |
+
this.zoom = zoom; // will be falsey if zoom argument is undefined
|
546 |
+
|
547 |
+
var self = this;
|
548 |
+
var varName = document.getElementById(divID).getAttribute("data-flxmap");
|
549 |
+
var map = this.showMap(divID, [0, 0]);
|
550 |
+
var kmlLayer = this.loadKmlMap(kmlCacheBuster(kmlFileURL, this.kmlcache));
|
551 |
+
handleHiddenMap(this, divID); // set zoom if specified
|
552 |
+
|
553 |
+
if (typeof zoom != "undefined") {
|
554 |
+
// listen for zoom changing to fit markers on KML layer, force it back to what we asked for
|
555 |
+
google.maps.event.addListenerOnce(map, "zoom_changed", function () {
|
556 |
+
map.setZoom(zoom);
|
557 |
+
self.zoom = zoom;
|
558 |
+
});
|
559 |
+
} // add a directions service if needed
|
560 |
+
|
561 |
+
|
562 |
+
if (this.markerDirections || this.markerDirectionsShow) {
|
563 |
+
this.startDirService(map);
|
564 |
+
} // customise the infowindow as required; can do this on click event on KML layer (thanks, Stack Overflow!)
|
565 |
+
|
566 |
+
|
567 |
+
google.maps.event.addListener(kmlLayer, 'click', function (kmlEvent) {
|
568 |
+
var featureData = kmlEvent.featureData; // NB: since Google Maps API v3.9 the info window HTML is precomposed before this event occurs,
|
569 |
+
// so just changing the description won't change infowindow
|
570 |
+
|
571 |
+
if (!featureData._flxmapOnce) {
|
572 |
+
// add a flag to stop doing this on every click; once is enough
|
573 |
+
featureData._flxmapOnce = true; // stop links opening in a new window
|
574 |
+
|
575 |
+
if (self.targetFix && featureData.description) {
|
576 |
+
var reTargetFix = / target="_blank"/ig;
|
577 |
+
featureData.description = featureData.description.replace(reTargetFix, "");
|
578 |
+
featureData.infoWindowHtml = featureData.infoWindowHtml.replace(reTargetFix, "");
|
579 |
+
} // if we're showing directions, add directions link to marker description
|
580 |
+
|
581 |
+
|
582 |
+
if (self.markerDirections) {
|
583 |
+
var latLng = kmlEvent.latLng;
|
584 |
+
var params = latLng.lat() + ',' + latLng.lng() + ",'" + encodeJS(featureData.name) + "',true";
|
585 |
+
var a = '<br /><a href="#" onclick="' + varName + '.showDirections(' + params + '); return false;">' + self.gettext("Directions") + '</a>';
|
586 |
+
featureData.infoWindowHtml = featureData.infoWindowHtml.replace(/<\/div><\/div>$/i, a + "</div></div>");
|
587 |
+
}
|
588 |
+
}
|
589 |
+
});
|
590 |
+
},
|
591 |
+
|
592 |
+
/**
|
593 |
+
* show a map centred at latitude / longitude and with marker at latitude / longitude
|
594 |
+
* @param {String} divID the ID of the div that will contain the map
|
595 |
+
* @param {Array} centre an array of two integers: [ latitude, longitude ]
|
596 |
+
* @param {Array} marker an array of two integers: [ latitude, longitude ]
|
597 |
+
*/
|
598 |
+
showMarker: function showMarker(divID, centre, marker) {
|
599 |
+
var map = this.showMap(divID, centre);
|
600 |
+
var markerLocation = new google.maps.LatLng(marker[0], marker[1]);
|
601 |
+
var options = {
|
602 |
+
map: map,
|
603 |
+
position: markerLocation,
|
604 |
+
icon: this.markerIcon
|
605 |
+
};
|
606 |
+
var Animation = google.maps.Animation;
|
607 |
+
|
608 |
+
switch (this.markerAnimation) {
|
609 |
+
case "drop":
|
610 |
+
options.animation = Animation.DROP;
|
611 |
+
break;
|
612 |
+
|
613 |
+
case "bounce":
|
614 |
+
options.animation = Animation.BOUNCE;
|
615 |
+
break;
|
616 |
+
}
|
617 |
+
|
618 |
+
var point = new google.maps.Marker(options);
|
619 |
+
this.setMarkerPoint(point);
|
620 |
+
this.setMarkerLocation(markerLocation);
|
621 |
+
handleHiddenMap(this, divID);
|
622 |
+
|
623 |
+
if (!this.markerTitle) {
|
624 |
+
this.markerTitle = this.markerAddress;
|
625 |
+
}
|
626 |
+
|
627 |
+
if (this.markerTitle || this.markerHTML || this.markerDescription || this.markerLink || this.markerDirections) {
|
628 |
+
var self = this;
|
629 |
+
var container = document.createElement("DIV");
|
630 |
+
var element, a;
|
631 |
+
container.className = "flxmap-infowin"; // heading for info window
|
632 |
+
|
633 |
+
element = document.createElement("DIV");
|
634 |
+
element.className = "flxmap-marker-title";
|
635 |
+
|
636 |
+
if (this.markerTitle) {
|
637 |
+
element.appendChild(document.createTextNode(this.markerTitle)); // add tooltip title for marker
|
638 |
+
|
639 |
+
point.setTitle(this.markerTitle);
|
640 |
+
}
|
641 |
+
|
642 |
+
container.appendChild(element); // add precomposed HTML for infowindow
|
643 |
+
|
644 |
+
if (this.markerHTML) {
|
645 |
+
element = document.createElement("DIV");
|
646 |
+
element.innerHTML = this.markerHTML;
|
647 |
+
container.appendChild(element);
|
648 |
+
} // body of info window, with link
|
649 |
+
|
650 |
+
|
651 |
+
if (this.markerDescription || this.markerLink) {
|
652 |
+
element = document.createElement("DIV");
|
653 |
+
element.className = "flxmap-marker-link";
|
654 |
+
|
655 |
+
if (this.markerDescription) {
|
656 |
+
var lines = this.markerDescription.split("\n");
|
657 |
+
|
658 |
+
for (var i = 0, len = lines.length; i < len; i++) {
|
659 |
+
if (i > 0) {
|
660 |
+
element.appendChild(document.createElement("BR"));
|
661 |
+
}
|
662 |
+
|
663 |
+
element.appendChild(document.createTextNode(lines[i]));
|
664 |
+
}
|
665 |
+
|
666 |
+
if (this.markerLink) {
|
667 |
+
element.appendChild(document.createElement("BR"));
|
668 |
+
}
|
669 |
+
}
|
670 |
+
|
671 |
+
if (this.markerLink) {
|
672 |
+
a = document.createElement("A");
|
673 |
+
a.href = this.markerLink;
|
674 |
+
|
675 |
+
if (this.markerLinkTarget) {
|
676 |
+
a.target = this.markerLinkTarget;
|
677 |
+
}
|
678 |
+
|
679 |
+
a.appendChild(document.createTextNode(this.markerLinkText || this.gettext("Click for details")));
|
680 |
+
element.appendChild(a);
|
681 |
+
}
|
682 |
+
|
683 |
+
container.appendChild(element);
|
684 |
+
} // add a link for directions if wanted
|
685 |
+
|
686 |
+
|
687 |
+
if (this.markerDirections) {
|
688 |
+
element = document.createElement("DIV");
|
689 |
+
element.className = "flxmap-directions-link";
|
690 |
+
a = document.createElement("A");
|
691 |
+
a.href = "#";
|
692 |
+
a.dataLatitude = marker[0];
|
693 |
+
a.dataLongitude = marker[1];
|
694 |
+
a.addEventListener("click", function (event) {
|
695 |
+
stopEvent(event);
|
696 |
+
self.showDirections(this.dataLatitude, this.dataLongitude, true);
|
697 |
+
});
|
698 |
+
a.appendChild(document.createTextNode(this.gettext("Directions")));
|
699 |
+
element.appendChild(a);
|
700 |
+
container.appendChild(element);
|
701 |
+
}
|
702 |
+
|
703 |
+
var infowin = new google.maps.InfoWindow({
|
704 |
+
content: container
|
705 |
+
});
|
706 |
+
this.setMarkerInfowin(infowin);
|
707 |
+
|
708 |
+
if (this.markerShowInfo) {
|
709 |
+
// open after map is loaded, so that infowindow will auto-pan and won't be cropped at top
|
710 |
+
google.maps.event.addListenerOnce(map, "tilesloaded", function () {
|
711 |
+
infowin.open(map, point);
|
712 |
+
});
|
713 |
+
}
|
714 |
+
|
715 |
+
google.maps.event.addListener(point, "click", function () {
|
716 |
+
infowin.open(map, point);
|
717 |
+
}); // find Google link and append marker info, modern browsers only!
|
718 |
+
// NB: Google link is set before initial map idle event, and reset each time the map centre changes
|
719 |
+
|
720 |
+
var googleLink = function googleLink() {
|
721 |
+
self.updateGoogleLink();
|
722 |
+
};
|
723 |
+
|
724 |
+
google.maps.event.addListener(map, "idle", googleLink);
|
725 |
+
google.maps.event.addListener(map, "center_changed", googleLink);
|
726 |
+
google.maps.event.addListenerOnce(map, "tilesloaded", googleLink);
|
727 |
+
} // add a directions service if needed
|
728 |
+
|
729 |
+
|
730 |
+
if (this.markerDirections || this.markerDirectionsShow) {
|
731 |
+
this.startDirService(map); // show directions immediately if required
|
732 |
+
|
733 |
+
if (this.markerDirectionsShow) {
|
734 |
+
this.showDirections(marker[0], marker[1], false);
|
735 |
+
}
|
736 |
+
}
|
737 |
+
},
|
738 |
+
|
739 |
+
/**
|
740 |
+
* show a map centred at address
|
741 |
+
* @param {String} divID the ID of the div that will contain the map
|
742 |
+
* @param {String} address the address (should return a unique location in Google Maps!)
|
743 |
+
*/
|
744 |
+
showAddress: function showAddress(divID, address) {
|
745 |
+
var self = this;
|
746 |
+
var geocoder = new google.maps.Geocoder();
|
747 |
+
this.markerAddress = address;
|
748 |
+
|
749 |
+
if (this.markerTitle === "") {
|
750 |
+
this.markerTitle = address;
|
751 |
+
}
|
752 |
+
|
753 |
+
geocoder.geocode({
|
754 |
+
address: address,
|
755 |
+
region: this.region
|
756 |
+
}, function (results, status) {
|
757 |
+
if (status === google.maps.GeocoderStatus.OK) {
|
758 |
+
var location = results[0].geometry.location;
|
759 |
+
var centre = [location.lat(), location.lng()];
|
760 |
+
self.showMarker(divID, centre, centre);
|
761 |
+
} else {
|
762 |
+
window.alert("Map address returns error: " + status);
|
763 |
+
}
|
764 |
+
});
|
765 |
+
},
|
766 |
+
|
767 |
+
/**
|
768 |
+
* set query parameters on Google link to maps -- modern browsers only
|
769 |
+
* NB: will only set the query parameters when Google link doesn't have them already;
|
770 |
+
* Google link is set before initial map idle event, and reset each time the map centre changes
|
771 |
+
*/
|
772 |
+
updateGoogleLink: function updateGoogleLink() {
|
773 |
+
if ("querySelectorAll" in document) {
|
774 |
+
try {
|
775 |
+
var _flxmap = this.getMap().getDiv();
|
776 |
+
|
777 |
+
var location = this.getMarkerLocation();
|
778 |
+
|
779 |
+
var googleLinks = _flxmap.querySelectorAll("a[href*='maps.google.com/maps']:not([href*='mps_dialog']):not([href*='&q='])");
|
780 |
+
|
781 |
+
var query = encodeURIComponent((this.markerAddress ? this.markerAddress : this.markerTitle) + " @" + location.lat() + "," + location.lng());
|
782 |
+
|
783 |
+
for (var i = 0, len = googleLinks.length; i < len; i++) {
|
784 |
+
googleLinks[i].href += "&mrt=loc&iwloc=A&q=" + query;
|
785 |
+
}
|
786 |
+
} catch (e) {// we don't care about IE8 and earlier...
|
787 |
+
}
|
788 |
+
}
|
789 |
+
},
|
790 |
+
|
791 |
+
/**
|
792 |
+
* tell Google Maps to redraw the map, and centre it back where it started with default zoom
|
793 |
+
*/
|
794 |
+
redraw: function redraw() {
|
795 |
+
var map = this.getMap();
|
796 |
+
var kmlLayer = this.getKmlLayer();
|
797 |
+
google.maps.event.trigger(map, "resize"); // if map is KML, must refit to computed bounds, else use centre and zoom setting
|
798 |
+
|
799 |
+
if (kmlLayer) {
|
800 |
+
map.fitBounds(kmlLayer.getDefaultViewport());
|
801 |
+
|
802 |
+
if (this.zoom) {
|
803 |
+
map.setZoom(this.zoom);
|
804 |
+
}
|
805 |
+
} else {
|
806 |
+
map.setCenter(this.getCenter());
|
807 |
+
map.setZoom(this.zoom); // redraw the marker's infowindow if it has one
|
808 |
+
|
809 |
+
var infowin = this.getMarkerInfowin();
|
810 |
+
|
811 |
+
if (infowin) {
|
812 |
+
infowin.open(map, this.getMarkerPoint());
|
813 |
+
}
|
814 |
+
}
|
815 |
+
},
|
816 |
+
|
817 |
+
/**
|
818 |
+
* create directions service
|
819 |
+
*/
|
820 |
+
startDirService: function startDirService(map) {
|
821 |
+
// make sure we have a directions service
|
822 |
+
if (!this.dirService) {
|
823 |
+
this.dirService = new google.maps.DirectionsService();
|
824 |
+
} // make sure we have a directions renderer
|
825 |
+
|
826 |
+
|
827 |
+
if (!this.dirRenderer) {
|
828 |
+
this.dirRenderer = new google.maps.DirectionsRenderer({
|
829 |
+
map: map,
|
830 |
+
draggable: this.dirDraggable,
|
831 |
+
suppressMarkers: this.dirSuppressMarkers,
|
832 |
+
panel: this.dirShowSteps ? document.getElementById(this.markerDirectionsDiv) : null
|
833 |
+
});
|
834 |
+
}
|
835 |
+
},
|
836 |
+
|
837 |
+
/**
|
838 |
+
* show directions for specified latitude / longitude and title
|
839 |
+
* @param {Number} latitude
|
840 |
+
* @param {Number} longitude
|
841 |
+
* @param {bool} focus [optional]
|
842 |
+
*/
|
843 |
+
showDirections: function showDirections(latitude, longitude, focus) {
|
844 |
+
var self = this;
|
845 |
+
/**
|
846 |
+
* show the directions form to allow directions searches
|
847 |
+
*/
|
848 |
+
|
849 |
+
function showDirectionsForm() {
|
850 |
+
var panel = document.getElementById(self.markerDirectionsDiv);
|
851 |
+
var form = document.createElement("form");
|
852 |
+
var p, from; // remove all from panel
|
853 |
+
|
854 |
+
for (p = panel.lastChild; p; p = panel.lastChild) {
|
855 |
+
panel.removeChild(p);
|
856 |
+
} // populate form and add to panel
|
857 |
+
|
858 |
+
|
859 |
+
p = document.createElement("p");
|
860 |
+
p.appendChild(document.createTextNode(self.gettext("From") + ": "));
|
861 |
+
from = document.createElement("input");
|
862 |
+
from.type = "text";
|
863 |
+
from.name = "from";
|
864 |
+
from.value = self.markerDirectionsDefault;
|
865 |
+
p.appendChild(from);
|
866 |
+
var input = document.createElement("input");
|
867 |
+
input.type = "submit";
|
868 |
+
input.value = self.gettext("Get directions");
|
869 |
+
p.appendChild(input);
|
870 |
+
form.appendChild(p);
|
871 |
+
panel.appendChild(form); // only focus when asked, to prevent problems autofocusing on elements and scrolling the page!
|
872 |
+
|
873 |
+
if (focus) {
|
874 |
+
from.focus();
|
875 |
+
} // handle the form submit
|
876 |
+
|
877 |
+
|
878 |
+
form.addEventListener("submit", function (event) {
|
879 |
+
stopEvent(event);
|
880 |
+
var from = this.elements.from.value; // only process if something was entered to search on
|
881 |
+
|
882 |
+
if (/\S/.test(from)) {
|
883 |
+
requestDirections(from);
|
884 |
+
}
|
885 |
+
});
|
886 |
+
}
|
887 |
+
/**
|
888 |
+
* request directions
|
889 |
+
* @param {String} from
|
890 |
+
*/
|
891 |
+
|
892 |
+
|
893 |
+
function requestDirections(from) {
|
894 |
+
var dest = self.markerAddress === "" ? new google.maps.LatLng(latitude, longitude) : self.markerAddress;
|
895 |
+
var request = {
|
896 |
+
origin: from,
|
897 |
+
destination: dest
|
898 |
+
};
|
899 |
+
|
900 |
+
if (self.region) {
|
901 |
+
request.region = self.region;
|
902 |
+
}
|
903 |
+
|
904 |
+
switch (self.dirTravelMode) {
|
905 |
+
case "bicycling":
|
906 |
+
request.travelMode = google.maps.TravelMode.BICYCLING;
|
907 |
+
break;
|
908 |
+
|
909 |
+
case "driving":
|
910 |
+
request.travelMode = google.maps.TravelMode.DRIVING;
|
911 |
+
break;
|
912 |
+
|
913 |
+
case "transit":
|
914 |
+
request.travelMode = google.maps.TravelMode.TRANSIT;
|
915 |
+
break;
|
916 |
+
|
917 |
+
case "walking":
|
918 |
+
request.travelMode = google.maps.TravelMode.WALKING;
|
919 |
+
break;
|
920 |
+
}
|
921 |
+
|
922 |
+
switch (self.dirUnitSystem) {
|
923 |
+
case "imperial":
|
924 |
+
request.unitSystem = google.maps.UnitSystem.IMPERIAL;
|
925 |
+
break;
|
926 |
+
|
927 |
+
case "metric":
|
928 |
+
request.unitSystem = google.maps.UnitSystem.METRIC;
|
929 |
+
break;
|
930 |
+
}
|
931 |
+
|
932 |
+
self.dirService.route(request, dirResponseHander);
|
933 |
+
}
|
934 |
+
/**
|
935 |
+
* handle the response for Google directions service
|
936 |
+
* @param {google.maps.DirectionsResult} response
|
937 |
+
* @param {Number} status
|
938 |
+
*/
|
939 |
+
|
940 |
+
|
941 |
+
function dirResponseHander(response, status) {
|
942 |
+
var DirectionsStatus = google.maps.DirectionsStatus;
|
943 |
+
|
944 |
+
switch (status) {
|
945 |
+
case DirectionsStatus.OK:
|
946 |
+
self.dirRenderer.setDirections(response);
|
947 |
+
break;
|
948 |
+
|
949 |
+
case DirectionsStatus.ZERO_RESULTS:
|
950 |
+
window.alert("No route could be found between the origin and destination.");
|
951 |
+
break;
|
952 |
+
|
953 |
+
case DirectionsStatus.OVER_QUERY_LIMIT:
|
954 |
+
window.alert("The webpage has gone over the requests limit in too short a period of time.");
|
955 |
+
break;
|
956 |
+
|
957 |
+
case DirectionsStatus.REQUEST_DENIED:
|
958 |
+
window.alert("The webpage is not allowed to use the directions service.");
|
959 |
+
break;
|
960 |
+
|
961 |
+
case DirectionsStatus.INVALID_REQUEST:
|
962 |
+
window.alert("Invalid directions request.");
|
963 |
+
break;
|
964 |
+
|
965 |
+
case DirectionsStatus.NOT_FOUND:
|
966 |
+
window.alert("Origin or destination was not found.");
|
967 |
+
break;
|
968 |
+
|
969 |
+
default:
|
970 |
+
window.alert("A directions request could not be processed due to a server error. The request may succeed if you try again.");
|
971 |
+
break;
|
972 |
+
}
|
973 |
+
} // if we have a directions div, show the form for searching it
|
974 |
+
|
975 |
+
|
976 |
+
if (this.markerDirectionsDiv && this.dirShowSearch) {
|
977 |
+
showDirectionsForm();
|
978 |
+
} // if the from: location is already set, trigger the directions query
|
979 |
+
|
980 |
+
|
981 |
+
if (this.markerDirectionsDefault) {
|
982 |
+
requestDirections(this.markerDirectionsDefault);
|
983 |
+
}
|
984 |
+
}
|
985 |
+
};
|
986 |
+
}();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
js/flexible-map.min.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
// Flexible Map
|
2 |
// https://flexible-map.webaware.net.au/
|
3 |
|
4 |
-
window.FlexibleMap=function(){"use strict";var n,a,t,i,r,o,e=!1;this.getMap=function(){return n},this.getCenter=function(){return a},this.setCenter=function(e){a=e,n.setCenter(a)},this.setMarkerLocation=function(e){t=e},this.getMarkerLocation=function(){return t},this.setMarkerPoint=function(e){i=e},this.getMarkerPoint=function(){return i},this.setMarkerInfowin=function(e){r=e},this.getMarkerInfowin=function(){return r},this.getKmlLayer=function(){return o},this.redrawOnce=function(){e||(e=!0,this.redraw())},this.showMap=function(e,t){a=new google.maps.LatLng(t[0],t[1]);var i,r={small:google.maps.ZoomControlStyle.SMALL,large:google.maps.ZoomControlStyle.LARGE,default:google.maps.ZoomControlStyle.DEFAULT},o=r.small;return this.zoomControlStyle in r&&(o=r[this.zoomControlStyle]),i=function(e,t){if(void 0!==t.gestureHandling)e.gestureHandling=t.gestureHandling;else if(void 0===t.draggable&&void 0===t.dblclickZoom&&void 0===t.scrollwheel)e.gestureHandling="cooperative";else{var i=void 0===t.draggable||t.draggable,r=void 0!==t.dblclickZoom&&!t.draggable,o=void 0!==t.scrollwheel&&t.scrollwheel;i||!r||o?i&&!r&&o?e.gestureHandling="greedy":(e.draggable=i,e.disableDoubleClickZoom=r,e.scrollwheel=o):e.gestureHandling="none"}return e}(i={mapTypeId:this.mapTypeId,mapTypeControl:this.mapTypeControl,scaleControl:this.scaleControl,panControl:this.panControl,streetViewControl:this.streetViewControl,zoomControl:this.zoomControl,zoomControlOptions:{style:o},fullscreenControl:this.fullscreen,center:a,zoom:this.zoom},this),this.mapTypeIds&&(i.mapTypeControlOptions={mapTypeIds:this.mapTypeIds.split(",")}),n=new google.maps.Map(document.getElementById(e),i),this.mapTypeId in this.mapTypes&&n.mapTypes.set(this.mapTypeId,this.mapTypes[this.mapTypeId]._styled_map),n},this.loadKmlMap=function(e){var t=this,i={map:n,url:e};return this.kmlCentre&&(i.preserveViewport=!0,i.center=new google.maps.LatLng(this.kmlCentre[0],this.kmlCentre[1])),o=new google.maps.KmlLayer(i),google.maps.event.addListenerOnce(o,"defaultviewport_changed",this.kmlCentre?function(){t.setCenter(new google.maps.LatLng(t.kmlCentre[0],t.kmlCentre[1]))}:function(){a=o.getDefaultViewport().getCenter()}),o},!this.localised&&"flxmap"in window&&this.localise(),this.mapTypeId=google.maps.MapTypeId.ROADMAP,this.mapTypeControl=!0,this.scaleControl=!1,this.panControl=!1,this.zoomControl=!0,this.zoomControlStyle="small",this.streetViewControl=!1,this.fullscreen=!0,this.gestureHandling=void 0,this.scrollwheel=void 0,this.draggable=void 0,this.dblclickZoom=void 0,this.zoom=16,this.markerTitle="",this.markerDescription="",this.markerHTML="",this.markerLink="",this.markerLinkTarget="",this.markerLinkText=!1,this.markerIcon="",this.markerShowInfo=!0,this.markerAnimation="drop",this.markerDirections=!1,this.markerDirectionsShow=!1,this.markerDirectionsDefault="",this.markerAddress="",this.targetFix=!0,this.dirService=!1,this.dirRenderer=!1,this.dirDraggable=!1,this.dirSuppressMarkers=!1,this.dirShowSteps=!0,this.dirShowSearch=!0,this.dirTravelMode="driving",this.dirUnitSystem=void 0,this.region="",this.locale="en",this.localeActive=!1,this.kmlCentre=!1,this.kmlcache="none"},FlexibleMap.prototype=function(){"use strict";var k,v,w;document.addEventListener?(k=function(e,t,i){e.addEventListener(t,i,!1)},v=function(e){e.stopPropagation(),e.preventDefault()}):document.attachEvent&&(k=function(e,t,i){e.attachEvent("on"+t,function(){i.call(e,window.event)})},v=function(e){e.cancelBubble=!0,e.returnValue=0}),w="undefined"!=typeof MutationObserver?function(i,e){var r=document.getElementById(e).parentNode;function o(e){var t=window.getComputedStyle(e);return"none"===t.display||"hidden"===t.visibility}o(r)&&new MutationObserver(function(e,t){o(r)||(i.redrawOnce(),t.disconnect())}).observe(r,{attributes:!0,attributeFilter:["style"]})}:function(){};var l=function(){function t(e){var t=e.charCodeAt(0),i=t.toString(16);return t<256?"\\x"+("00"+i).slice(-2):"\\u"+("0000"+i).slice(-4)}return function(e){return e.replace(/[\\/"'&<>\x00-\x1f\x7f-\xa0\u2000-\u200f\u2028-\u202f]/g,t)}}();return{constructor:FlexibleMap,i18n:{},mapTypes:{},localised:!1,localise:function(){var e,t;if("i18n"in flxmap&&(FlexibleMap.prototype.i18n=flxmap.i18n),"mapTypes"in flxmap){for(e in t=flxmap.mapTypes)t[e]._styled_map=new google.maps.StyledMapType(t[e].styles,t[e].options);FlexibleMap.prototype.mapTypes=t}FlexibleMap.prototype.localised=!0},setlocale:function(e){return(this.locale=e)in this.i18n?this.localeActive=e:e.substr(0,2)in this.i18n?this.localeActive=e:this.localeActive=!1,this.localeActive},gettext:function(e){var t=this.localeActive;return t&&e in this.i18n[t]?this.i18n[t][e]:e},showKML:function(e,t,i){void 0!==i&&(this.zoom=i);var a=this,r=document.getElementById(e),s=r.getAttribute("data-flxmap"),o=this.showMap(e,[0,0]),n=this.loadKmlMap(function(e,t){var i,r,o,n=/^(\d+)\s*(minute|hour|day)s?$/.exec(t);if(n){switch(i=(new Date).getTime(),o=+n[1],n[2]){case"minute":o<5&&(o=5),r=i/(6e4*o);break;case"hour":r=i/(36e5*o);break;case"day":r=i/(864e5*o);break;default:r=!1}r&&(r=Math.floor(r),e+=(-1<e.indexOf("?")?"&":"?")+"nocache="+r)}return e}(t,this.kmlcache));w(this,e),void 0!==i&&google.maps.event.addListenerOnce(o,"zoom_changed",function(){o.setZoom(i),a.zoom=i}),(this.markerDirections||this.markerDirectionsShow)&&this.startDirService(o),google.maps.event.addListener(n,"click",function(e){var t=e.featureData;if(!t._flxmapOnce){if(t._flxmapOnce=!0,a.targetFix&&t.description){var i=/ target="_blank"/gi;t.description=t.description.replace(i,""),t.infoWindowHtml=t.infoWindowHtml.replace(i,"")}if(a.markerDirections){var r=e.latLng,o=r.lat()+","+r.lng()+",'"+l(t.name)+"',true",n='<br /><a href="#" data-flxmap-fix-opera="1" onclick="'+s+".showDirections("+o+'); return false;">'+a.gettext("Directions")+"</a>";t.infoWindowHtml=t.infoWindowHtml.replace(/<\/div><\/div>$/i,n+"</div></div>")}}}),window.opera&&this.markerDirections&&k(r,"click",function(e){e.target.getAttribute("data-flxmap-fix-opera")&&v(e)})},showMarker:function(e,t,i){var r=this.showMap(e,t),o=new google.maps.LatLng(i[0],i[1]),n={map:r,position:o,icon:this.markerIcon},a=google.maps.Animation;switch(this.markerAnimation){case"drop":n.animation=a.DROP;break;case"bounce":n.animation=a.BOUNCE}var s=new google.maps.Marker(n);if(this.setMarkerPoint(s),this.setMarkerLocation(o),w(this,e),this.markerTitle||(this.markerTitle=this.markerAddress),this.markerTitle||this.markerHTML||this.markerDescription||this.markerLink||this.markerDirections){var l,d,c,m,h,p,g=this,u=document.createElement("DIV");if(u.className="flxmap-infowin",(h=document.createElement("DIV")).className="flxmap-marker-title",this.markerTitle&&(h.appendChild(document.createTextNode(this.markerTitle)),s.setTitle(this.markerTitle)),u.appendChild(h),this.markerHTML&&((h=document.createElement("DIV")).innerHTML=this.markerHTML,u.appendChild(h)),this.markerDescription||this.markerLink){if((h=document.createElement("DIV")).className="flxmap-marker-link",this.markerDescription){for(l=0,d=(c=this.markerDescription.split("\n")).length;l<d;l++)0<l&&h.appendChild(document.createElement("BR")),h.appendChild(document.createTextNode(c[l]));this.markerLink&&h.appendChild(document.createElement("BR"))}this.markerLink&&((p=document.createElement("A")).href=this.markerLink,this.markerLinkTarget&&(p.target=this.markerLinkTarget),p.appendChild(document.createTextNode(this.markerLinkText||this.gettext("Click for details"))),h.appendChild(p)),u.appendChild(h)}this.markerDirections&&((h=document.createElement("DIV")).className="flxmap-directions-link",(p=document.createElement("A")).href="#",p.dataLatitude=i[0],p.dataLongitude=i[1],k(p,"click",function(e){v(e),g.showDirections(this.dataLatitude,this.dataLongitude,!0)}),p.appendChild(document.createTextNode(this.gettext("Directions"))),h.appendChild(p),u.appendChild(h)),m=new google.maps.InfoWindow({content:u}),this.setMarkerInfowin(m),this.markerShowInfo&&google.maps.event.addListenerOnce(r,"tilesloaded",function(){m.open(r,s)}),google.maps.event.addListener(s,"click",function(){m.open(r,s)});var f=function(){g.updateGoogleLink()};google.maps.event.addListener(r,"idle",f),google.maps.event.addListener(r,"center_changed",f),google.maps.event.addListenerOnce(r,"tilesloaded",f)}(this.markerDirections||this.markerDirectionsShow)&&(this.startDirService(r),this.markerDirectionsShow&&this.showDirections(i[0],i[1],!1))},showAddress:function(o,e){var n=this,t=new google.maps.Geocoder;this.markerAddress=e,""===this.markerTitle&&(this.markerTitle=e),t.geocode({address:e,region:this.region},function(e,t){if(t===google.maps.GeocoderStatus.OK){var i=e[0].geometry.location,r=[i.lat(),i.lng()];n.showMarker(o,r,r)}else window.alert("Map address returns error: "+t)})},updateGoogleLink:function(){if("querySelectorAll"in document)try{for(var e=this.getMap().getDiv(),t=this.getMarkerLocation(),i=e.querySelectorAll("a[href*='maps.google.com/maps']:not([href*='mps_dialog']):not([href*='&q='])"),r=0,o=i.length,n=encodeURIComponent((this.markerAddress?this.markerAddress:this.markerTitle)+" @"+t.lat()+","+t.lng());r<o;r++)i[r].href+="&mrt=loc&iwloc=A&q="+n}catch(e){}},redraw:function(){var e=this.getMap(),t=this.getKmlLayer();if(google.maps.event.trigger(e,"resize"),t)e.fitBounds(t.getDefaultViewport());else{e.setCenter(this.getCenter()),e.setZoom(this.zoom);var i=this.getMarkerInfowin();i&&i.open(e,this.getMarkerPoint())}},startDirService:function(e){this.dirService||(this.dirService=new google.maps.DirectionsService),this.dirRenderer||(this.dirRenderer=new google.maps.DirectionsRenderer({map:e,draggable:this.dirDraggable,suppressMarkers:this.dirSuppressMarkers,panel:this.dirShowSteps?document.getElementById(this.markerDirectionsDiv):null}))},showDirections:function(i,r,n){var a=this;function s(e){var t={origin:e,destination:""===a.markerAddress?new google.maps.LatLng(i,r):a.markerAddress};switch(a.region&&(t.region=a.region),a.dirTravelMode){case"bicycling":t.travelMode=google.maps.TravelMode.BICYCLING;break;case"driving":t.travelMode=google.maps.TravelMode.DRIVING;break;case"transit":t.travelMode=google.maps.TravelMode.TRANSIT;break;case"walking":t.travelMode=google.maps.TravelMode.WALKING}switch(a.dirUnitSystem){case"imperial":t.unitSystem=google.maps.UnitSystem.IMPERIAL;break;case"metric":t.unitSystem=google.maps.UnitSystem.METRIC}a.dirService.route(t,o)}function o(e,t){var i=google.maps.DirectionsStatus;switch(t){case i.OK:a.dirRenderer.setDirections(e);break;case i.ZERO_RESULTS:window.alert("No route could be found between the origin and destination.");break;case i.OVER_QUERY_LIMIT:window.alert("The webpage has gone over the requests limit in too short a period of time.");break;case i.REQUEST_DENIED:window.alert("The webpage is not allowed to use the directions service.");break;case i.INVALID_REQUEST:window.alert("Invalid directions request.");break;case i.NOT_FOUND:window.alert("Origin or destination was not found.");break;default:window.alert("A directions request could not be processed due to a server error. The request may succeed if you try again.")}}this.markerDirectionsDiv&&this.dirShowSearch&&function(){var e,t,i,r=document.getElementById(a.markerDirectionsDiv),o=document.createElement("form");for(t=r.lastChild;t;t=r.lastChild)r.removeChild(t);(t=document.createElement("p")).appendChild(document.createTextNode(a.gettext("From")+": ")),(i=document.createElement("input")).type="text",i.name="from",i.value=a.markerDirectionsDefault,t.appendChild(i),(e=document.createElement("input")).type="submit",e.value=a.gettext("Get directions"),t.appendChild(e),o.appendChild(t),r.appendChild(o),void 0===o.elements.from&&(o.elements.from=i),n&&i.focus(),k(o,"submit",function(e){v(e);var t=this.elements.from.value;/\S/.test(t)&&s(t)})}(),this.markerDirectionsDefault&&s(this.markerDirectionsDefault)}}}();
|
1 |
// Flexible Map
|
2 |
// https://flexible-map.webaware.net.au/
|
3 |
|
4 |
+
"use strict";window.FlexibleMap=function(){var e,t,i,r,o,n,a=!1;this.getMap=function(){return e},this.getCenter=function(){return t},this.setCenter=function(i){t=i,e.setCenter(t)},this.setMarkerLocation=function(e){i=e},this.getMarkerLocation=function(){return i},this.setMarkerPoint=function(e){r=e},this.getMarkerPoint=function(){return r},this.setMarkerInfowin=function(e){o=e},this.getMarkerInfowin=function(){return o},this.getKmlLayer=function(){return n},this.redrawOnce=function(){a||(a=!0,this.redraw())},this.showMap=function(i,r){t=new google.maps.LatLng(r[0],r[1]);var o={small:google.maps.ZoomControlStyle.SMALL,large:google.maps.ZoomControlStyle.LARGE,default:google.maps.ZoomControlStyle.DEFAULT},n=o.small;this.zoomControlStyle in o&&(n=o[this.zoomControlStyle]);var a={mapTypeId:this.mapTypeId,mapTypeControl:this.mapTypeControl,scaleControl:this.scaleControl,panControl:this.panControl,streetViewControl:this.streetViewControl,zoomControl:this.zoomControl,zoomControlOptions:{style:n},fullscreenControl:this.fullscreen,center:t,zoom:this.zoom};return a=function(e,t){if(void 0!==t.gestureHandling)e.gestureHandling=t.gestureHandling;else if(void 0===t.draggable&&void 0===t.dblclickZoom&&void 0===t.scrollwheel)e.gestureHandling="cooperative";else{var i=void 0===t.draggable||t.draggable,r=void 0!==t.dblclickZoom&&!t.draggable,o=void 0!==t.scrollwheel&&t.scrollwheel;i||!r||o?i&&!r&&o?e.gestureHandling="greedy":(e.draggable=i,e.disableDoubleClickZoom=r,e.scrollwheel=o):e.gestureHandling="none"}return e}(a,this),this.mapTypeIds&&(a.mapTypeControlOptions={mapTypeIds:this.mapTypeIds.split(",")}),e=new google.maps.Map(document.getElementById(i),a),this.mapTypeId in this.mapTypes&&e.mapTypes.set(this.mapTypeId,this.mapTypes[this.mapTypeId]._styled_map),e},this.loadKmlMap=function(i){var r=this,o={map:e,url:i};return this.kmlCentre&&(o.preserveViewport=!0,o.center=new google.maps.LatLng(this.kmlCentre[0],this.kmlCentre[1])),n=new google.maps.KmlLayer(o),google.maps.event.addListenerOnce(n,"defaultviewport_changed",this.kmlCentre?function(){r.setCenter(new google.maps.LatLng(r.kmlCentre[0],r.kmlCentre[1]))}:function(){t=n.getDefaultViewport().getCenter()}),n},!this.localised&&"flxmap"in window&&this.localise(),this.mapTypeId=google.maps.MapTypeId.ROADMAP,this.mapTypeControl=!0,this.scaleControl=!1,this.panControl=!1,this.zoomControl=!0,this.zoomControlStyle="small",this.streetViewControl=!1,this.fullscreen=!0,this.gestureHandling=void 0,this.scrollwheel=void 0,this.draggable=void 0,this.dblclickZoom=void 0,this.zoom=16,this.markerTitle="",this.markerDescription="",this.markerHTML="",this.markerLink="",this.markerLinkTarget="",this.markerLinkText=!1,this.markerIcon="",this.markerShowInfo=!0,this.markerAnimation="drop",this.markerDirections=!1,this.markerDirectionsShow=!1,this.markerDirectionsDefault="",this.markerAddress="",this.targetFix=!0,this.dirService=!1,this.dirRenderer=!1,this.dirDraggable=!1,this.dirSuppressMarkers=!1,this.dirShowSteps=!0,this.dirShowSearch=!0,this.dirTravelMode="driving",this.dirUnitSystem=void 0,this.region="",this.locale="en",this.localeActive=!1,this.kmlCentre=!1,this.kmlcache="none"},FlexibleMap.prototype=function(){function e(e){e.stopPropagation(),e.preventDefault()}var t="undefined"==typeof MutationObserver?function(){}:function(e,t){var i=document.getElementById(t).parentNode;function r(e){var t=window.getComputedStyle(e);return"none"===t.display||"hidden"===t.visibility}r(i)&&new MutationObserver(function(t,o){r(i)||(e.redrawOnce(),o.disconnect())}).observe(i,{attributes:!0,attributeFilter:["style"]})};return{constructor:FlexibleMap,i18n:{},mapTypes:{},localised:!1,localise:function(){if("i18n"in flxmap&&(FlexibleMap.prototype.i18n=flxmap.i18n),"mapTypes"in flxmap){var e=flxmap.mapTypes;for(var t in e)e[t]._styled_map=new google.maps.StyledMapType(e[t].styles,e[t].options);FlexibleMap.prototype.mapTypes=e}FlexibleMap.prototype.localised=!0},setlocale:function(e){return this.locale=e,e in this.i18n?this.localeActive=e:e.substr(0,2)in this.i18n?this.localeActive=e:this.localeActive=!1,this.localeActive},gettext:function(e){var t=this.localeActive;return t&&e in this.i18n[t]?this.i18n[t][e]:e},showKML:function(e,i,r){this.zoom=r;var o=this,n=document.getElementById(e).getAttribute("data-flxmap"),a=this.showMap(e,[0,0]),s=this.loadKmlMap(function(e,t){var i,r=/^(\d+)\s*(minute|hour|day)s?$/.exec(t);if(r){var o=(new Date).getTime(),n=+r[1];switch(r[2]){case"minute":n<5&&(n=5),i=o/(6e4*n);break;case"hour":i=o/(36e5*n);break;case"day":i=o/(864e5*n);break;default:i=!1}i&&(i=Math.floor(i),e+=(e.indexOf("?")>-1?"&":"?")+"nocache="+i)}return e}(i,this.kmlcache));t(this,e),void 0!==r&&google.maps.event.addListenerOnce(a,"zoom_changed",function(){a.setZoom(r),o.zoom=r}),(this.markerDirections||this.markerDirectionsShow)&&this.startDirService(a),google.maps.event.addListener(s,"click",function(e){var t=e.featureData;if(!t._flxmapOnce){if(t._flxmapOnce=!0,o.targetFix&&t.description){var i=/ target="_blank"/gi;t.description=t.description.replace(i,""),t.infoWindowHtml=t.infoWindowHtml.replace(i,"")}if(o.markerDirections){var r=e.latLng,a=r.lat()+","+r.lng()+",'"+function(){function e(e){var t=e.charCodeAt(0),i=t.toString(16);return t<256?"\\x"+("00"+i).slice(-2):"\\u"+("0000"+i).slice(-4)}return function(t){return t.replace(/[\\/"'&<>\x00-\x1f\x7f-\xa0\u2000-\u200f\u2028-\u202f]/g,e)}}(t.name)+"',true",s='<br /><a href="#" onclick="'+n+".showDirections("+a+'); return false;">'+o.gettext("Directions")+"</a>";t.infoWindowHtml=t.infoWindowHtml.replace(/<\/div><\/div>$/i,s+"</div></div>")}}})},showMarker:function(i,r,o){var n=this.showMap(i,r),a=new google.maps.LatLng(o[0],o[1]),s={map:n,position:a,icon:this.markerIcon},l=google.maps.Animation;switch(this.markerAnimation){case"drop":s.animation=l.DROP;break;case"bounce":s.animation=l.BOUNCE}var d=new google.maps.Marker(s);if(this.setMarkerPoint(d),this.setMarkerLocation(a),t(this,i),this.markerTitle||(this.markerTitle=this.markerAddress),this.markerTitle||this.markerHTML||this.markerDescription||this.markerLink||this.markerDirections){var c,m,h=this,p=document.createElement("DIV");if(p.className="flxmap-infowin",(c=document.createElement("DIV")).className="flxmap-marker-title",this.markerTitle&&(c.appendChild(document.createTextNode(this.markerTitle)),d.setTitle(this.markerTitle)),p.appendChild(c),this.markerHTML&&((c=document.createElement("DIV")).innerHTML=this.markerHTML,p.appendChild(c)),this.markerDescription||this.markerLink){if((c=document.createElement("DIV")).className="flxmap-marker-link",this.markerDescription){for(var g=this.markerDescription.split("\n"),u=0,f=g.length;u<f;u++)u>0&&c.appendChild(document.createElement("BR")),c.appendChild(document.createTextNode(g[u]));this.markerLink&&c.appendChild(document.createElement("BR"))}this.markerLink&&((m=document.createElement("A")).href=this.markerLink,this.markerLinkTarget&&(m.target=this.markerLinkTarget),m.appendChild(document.createTextNode(this.markerLinkText||this.gettext("Click for details"))),c.appendChild(m)),p.appendChild(c)}this.markerDirections&&((c=document.createElement("DIV")).className="flxmap-directions-link",(m=document.createElement("A")).href="#",m.dataLatitude=o[0],m.dataLongitude=o[1],m.addEventListener("click",function(t){e(t),h.showDirections(this.dataLatitude,this.dataLongitude,!0)}),m.appendChild(document.createTextNode(this.gettext("Directions"))),c.appendChild(m),p.appendChild(c));var k=new google.maps.InfoWindow({content:p});this.setMarkerInfowin(k),this.markerShowInfo&&google.maps.event.addListenerOnce(n,"tilesloaded",function(){k.open(n,d)}),google.maps.event.addListener(d,"click",function(){k.open(n,d)});var v=function(){h.updateGoogleLink()};google.maps.event.addListener(n,"idle",v),google.maps.event.addListener(n,"center_changed",v),google.maps.event.addListenerOnce(n,"tilesloaded",v)}(this.markerDirections||this.markerDirectionsShow)&&(this.startDirService(n),this.markerDirectionsShow&&this.showDirections(o[0],o[1],!1))},showAddress:function(e,t){var i=this,r=new google.maps.Geocoder;this.markerAddress=t,""===this.markerTitle&&(this.markerTitle=t),r.geocode({address:t,region:this.region},function(t,r){if(r===google.maps.GeocoderStatus.OK){var o=t[0].geometry.location,n=[o.lat(),o.lng()];i.showMarker(e,n,n)}else window.alert("Map address returns error: "+r)})},updateGoogleLink:function(){if("querySelectorAll"in document)try{for(var e=this.getMap().getDiv(),t=this.getMarkerLocation(),i=e.querySelectorAll("a[href*='maps.google.com/maps']:not([href*='mps_dialog']):not([href*='&q='])"),r=encodeURIComponent((this.markerAddress?this.markerAddress:this.markerTitle)+" @"+t.lat()+","+t.lng()),o=0,n=i.length;o<n;o++)i[o].href+="&mrt=loc&iwloc=A&q="+r}catch(e){}},redraw:function(){var e=this.getMap(),t=this.getKmlLayer();if(google.maps.event.trigger(e,"resize"),t)e.fitBounds(t.getDefaultViewport()),this.zoom&&e.setZoom(this.zoom);else{e.setCenter(this.getCenter()),e.setZoom(this.zoom);var i=this.getMarkerInfowin();i&&i.open(e,this.getMarkerPoint())}},startDirService:function(e){this.dirService||(this.dirService=new google.maps.DirectionsService),this.dirRenderer||(this.dirRenderer=new google.maps.DirectionsRenderer({map:e,draggable:this.dirDraggable,suppressMarkers:this.dirSuppressMarkers,panel:this.dirShowSteps?document.getElementById(this.markerDirectionsDiv):null}))},showDirections:function(t,i,r){var o=this;function n(e){var r={origin:e,destination:""===o.markerAddress?new google.maps.LatLng(t,i):o.markerAddress};switch(o.region&&(r.region=o.region),o.dirTravelMode){case"bicycling":r.travelMode=google.maps.TravelMode.BICYCLING;break;case"driving":r.travelMode=google.maps.TravelMode.DRIVING;break;case"transit":r.travelMode=google.maps.TravelMode.TRANSIT;break;case"walking":r.travelMode=google.maps.TravelMode.WALKING}switch(o.dirUnitSystem){case"imperial":r.unitSystem=google.maps.UnitSystem.IMPERIAL;break;case"metric":r.unitSystem=google.maps.UnitSystem.METRIC}o.dirService.route(r,a)}function a(e,t){var i=google.maps.DirectionsStatus;switch(t){case i.OK:o.dirRenderer.setDirections(e);break;case i.ZERO_RESULTS:window.alert("No route could be found between the origin and destination.");break;case i.OVER_QUERY_LIMIT:window.alert("The webpage has gone over the requests limit in too short a period of time.");break;case i.REQUEST_DENIED:window.alert("The webpage is not allowed to use the directions service.");break;case i.INVALID_REQUEST:window.alert("Invalid directions request.");break;case i.NOT_FOUND:window.alert("Origin or destination was not found.");break;default:window.alert("A directions request could not be processed due to a server error. The request may succeed if you try again.")}}this.markerDirectionsDiv&&this.dirShowSearch&&function(){var t,i,a=document.getElementById(o.markerDirectionsDiv),s=document.createElement("form");for(t=a.lastChild;t;t=a.lastChild)a.removeChild(t);(t=document.createElement("p")).appendChild(document.createTextNode(o.gettext("From")+": ")),(i=document.createElement("input")).type="text",i.name="from",i.value=o.markerDirectionsDefault,t.appendChild(i);var l=document.createElement("input");l.type="submit",l.value=o.gettext("Get directions"),t.appendChild(l),s.appendChild(t),a.appendChild(s),r&&i.focus(),s.addEventListener("submit",function(t){e(t);var i=this.elements.from.value;/\S/.test(i)&&n(i)})}(),this.markerDirectionsDefault&&n(this.markerDirectionsDefault)}}}();
|
readme.txt
CHANGED
@@ -6,8 +6,8 @@ Author URI: https://shop.webaware.com.au/
|
|
6 |
Donate link: https://shop.webaware.com.au/donations/?donation_for=Flexible+Map
|
7 |
Tags: google, map, maps, google maps, kml
|
8 |
Requires at least: 4.0
|
9 |
-
Tested up to:
|
10 |
-
Stable tag: 1.
|
11 |
Requires PHP: 5.3
|
12 |
License: GPLv2 or later
|
13 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
@@ -228,18 +228,19 @@ Either turn off CloudFlare Rocketscript :) or install the [Flxmap No Rocketscrip
|
|
228 |
|
229 |
## Upgrade Notice
|
230 |
|
231 |
-
### 1.
|
232 |
|
233 |
-
|
234 |
|
235 |
## Changelog
|
236 |
|
237 |
The full changelog can be found [on GitHub](https://github.com/webaware/flexible-map/blob/master/changelog.md). Recent entries:
|
238 |
|
239 |
-
### 1.
|
240 |
|
241 |
-
Released 2018-
|
242 |
|
243 |
-
*
|
244 |
-
*
|
245 |
-
*
|
|
6 |
Donate link: https://shop.webaware.com.au/donations/?donation_for=Flexible+Map
|
7 |
Tags: google, map, maps, google maps, kml
|
8 |
Requires at least: 4.0
|
9 |
+
Tested up to: 5.0
|
10 |
+
Stable tag: 1.17.0
|
11 |
Requires PHP: 5.3
|
12 |
License: GPLv2 or later
|
13 |
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
228 |
|
229 |
## Upgrade Notice
|
230 |
|
231 |
+
### 1.17.0
|
232 |
|
233 |
+
track the latest stable version of the Google Maps API; remove support for ancient browsers (Opera 12, IE < 11); fix KML maps with zoom when hidden in a tab
|
234 |
|
235 |
## Changelog
|
236 |
|
237 |
The full changelog can be found [on GitHub](https://github.com/webaware/flexible-map/blob/master/changelog.md). Recent entries:
|
238 |
|
239 |
+
### 1.17.0
|
240 |
|
241 |
+
Released 2018-11-19
|
242 |
|
243 |
+
* fixed: map tiles don't redraw for KML maps with zoom when hidden in a tab / accordion
|
244 |
+
* changed: use the [current quarterly (stable) version of the Google Maps API](https://developers.google.com/maps/documentation/javascript/versions)
|
245 |
+
* changed: remove support for ancient browsers (Opera 12, IE < 11)
|
246 |
+
* tested: WordPress 5.0 (no Gutenberg block yet; maybe next release!)
|