@bmlt-enabled/croutonjs 3.21.0 → 3.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/crouton-map.js CHANGED
@@ -1,785 +1,3 @@
1
- function MeetingMap(inConfig) {
2
- /****************************************************************************************
3
- * CLASS VARIABLES *
4
- ****************************************************************************************/
5
-
6
- var gDelegate = new MapDelegate(inConfig);
7
- var gModalDelegate = null;
8
- var gInDiv = null;
9
- const config = inConfig;
10
- if (!config.maxZoom) config.maxZoom = 17;
11
- if (!config.minZoom) config.minZoom = 6;
12
- if (!config.marker_contents_template) config.marker_contents_template = croutonDefaultTemplates.marker_contents_template;
13
- var gAllMeetings = null;
14
- var gMeetingIdsFromCrouton = null;
15
- var loadedCallbackFunction = null;
16
- var loadedCallbackArgs = [];
17
- function preloadApiLoadedCallback(f,a) {
18
- loadedCallbackFunction = f;
19
- loadedCallbackArgs = a;
20
- }
21
- function apiLoadedCallback() {
22
- loadedCallbackFunction(...loadedCallbackArgs);
23
- }
24
-
25
- function retrieveGeolocation() {
26
- return new Promise((resolve, reject) => {
27
- if (window.storedGeolocation) {
28
- resolve(window.storedGeolocation);
29
- } else if (navigator.geolocation) {
30
- navigator.geolocation.getCurrentPosition((position) => {
31
- window.storedGeolocation = {
32
- latitude: position.coords.latitude,
33
- longitude: position.coords.longitude
34
- };
35
- resolve(window.storedGeolocation);
36
- }, (error) => {
37
- reject(new Error('Error getting geolocation: ' + error.message));
38
- });
39
- } else {
40
- reject(new Error('Geolocation is not supported by this browser.'));
41
- }
42
- });
43
- }
44
-
45
- /************************************************************************************//**
46
- * \brief Load the map and set it up. *
47
- ****************************************************************************************/
48
-
49
- function loadMap(inDiv, menuContext, handlebarMapOptions=null,cb=null,hide=false) {
50
- if (inDiv) {
51
- crouton_Handlebars.registerPartial("markerContentsTemplate", config['marker_contents_template']);
52
- gInDiv = inDiv;
53
- createThrobber(inDiv);
54
- if (!config.map_search) showThrobber();
55
- else {
56
- if (!config.map_search.width) config.map_search.width = -50;
57
- if (!config.map_search.location && !config.map_search.coordinates_search)
58
- config.map_search.auto = true;
59
- if (config.map_search.latitude || config.map_search.longitude) {
60
- config.lat = config.map_search.latitude;
61
- config.lng = config.map_search.longitude;
62
- }
63
- if (config.map_search.zoom) {
64
- config.zoom = config.map_search.zoom;
65
- }
66
- }
67
- let loc = {latitude: config.lat, longitude: config.lng, zoom: config.zoom};
68
- if (handlebarMapOptions) loc = {latitude: handlebarMapOptions.lat, longitude: handlebarMapOptions.lng};
69
- if (gDelegate.createMap(inDiv, loc, hide)) {
70
- gDelegate.addListener('zoomend', function (ev) {
71
- if (shouldRedrawMarkers() && gAllMeetings) {
72
- if (listOnlyVisible) {
73
- const oldValue = filterVisible(false);
74
- searchResponseCallback();
75
- filterVisible(oldValue);
76
- } else searchResponseCallback();
77
- }
78
- }, false);
79
- if (config.map_search) {
80
- gDelegate.addControl(createSearchButton(), 'topleft', cb);
81
- }
82
- else if (menuContext) {
83
- menuContext.imageDir = config.BMLTPlugin_images;
84
- gDelegate.addControl(createNext24Toggle(), 'topleft');
85
- gDelegate.addControl(createMenuButton(menuContext), 'topright', cb);
86
- }
87
- else {
88
- menuContext = {imageDir: config.BMLTPlugin_images, config: config, dropdownData:false};
89
- gDelegate.addControl(createMenuButton(menuContext), 'topright', cb);
90
- }
91
- }
92
- };
93
- };
94
- var gSearchModal;
95
- function createSearchButton() {
96
- const template = hbs_Crouton.templates['mapSearch'];
97
- const controlDiv = document.createElement('div');
98
- const params = {'hasClickSearch': gDelegate.hasClickSearch()}
99
- controlDiv.innerHTML = template(params);
100
- controlDiv.querySelector("#map-search-button").addEventListener('click', showBmltSearchDialog);
101
- controlDiv.querySelector("#bmltsearch-nearbyMeetings").addEventListener('click', nearMeSearch);
102
- controlDiv.querySelector("#bmltsearch-goto-text").addEventListener('keypress', function (event) {
103
- if (event.key === "Enter") {
104
- event.preventDefault();
105
- document.getElementById("bmltsearch-text-button").click();
106
- }
107
- });
108
- controlDiv.querySelector("#bmltsearch-text-button").addEventListener('click', function () {
109
- let text = document.getElementById("bmltsearch-goto-text").value.trim();
110
- if (text === "") return;
111
- showThrobber();
112
- gDelegate.callGeocoder(text, null, mapSearchGeocode);
113
- closeModalWindow(gSearchModal);
114
- });
115
- controlDiv.querySelector("#modal-seach-parameters").style.display = 'none';
116
- controlDiv.querySelector("#show-search-parameters").addEventListener('click', function (e) {
117
- const controlDiv = e.target.parentElement.parentElement;
118
- let w = config.map_search.width;
119
- let checked = '#search_radius';
120
- if (w < 0) {
121
- w = -w;
122
- checked = '#search_count';
123
- }
124
- controlDiv.querySelector(checked).checked = true;
125
- controlDiv.querySelector('#search_parameter').value = w;
126
- controlDiv.querySelector("#modal-seach-parameters").style.display = 'block';
127
- controlDiv.querySelector("#modal-search-page").style.display = 'none';
128
- controlDiv.querySelector("#search_radius_label").innerHTML = crouton.localization.getWord('Radius of search in $$').replace('$$', crouton.config.distance_units);
129
- });
130
- controlDiv.querySelector("#show-search-page").addEventListener('click', function (e) {
131
- const controlDiv = e.target.parentElement.parentElement;
132
- let w = controlDiv.querySelector('#search_parameter').value;
133
- if (controlDiv.querySelector('#search_count')) {
134
- w = -Math.round(w);
135
- if (w == 0) w = -1;
136
- }
137
- config.map_search.width = w;
138
- controlDiv.querySelector("#modal-seach-parameters").style.display = 'none';
139
- controlDiv.querySelector("#modal-search-page").style.display = 'block';
140
- });
141
-
142
-
143
- if (gDelegate.hasClickSearch()) controlDiv.querySelector("#bmltsearch-clicksearch").addEventListener('click', clickSearch);
144
- [...controlDiv.getElementsByClassName('modal-close')].forEach((elem)=>elem.addEventListener('click', (e)=>closeModalWindow(e.target)));
145
- gSearchModal = controlDiv.querySelector("#bmltsearch_modal");
146
- gSearchModal.parentElement.removeChild(gSearchModal);
147
-
148
- return controlDiv;
149
- }
150
- var next24status = false;
151
- function createNext24Toggle() {
152
- const toggleSrc = `
153
- <div id="next24_toggle" title="Next24_toggle" style="background: rgba(0, 0, 0, 0); cursor: pointer;">
154
- <div class="onoffswitch">
155
- <input type="checkbox" name="onoffswitch" class="onoffswitch-checkbox" id="next24onoffswitch"/>
156
- <label class="onoffswitch-label" for="next24onoffswitch">
157
- <span class="onoffswitch-inner"></span>
158
- <span class="onoffswitch-switch"></span>
159
- </label>
160
- </div>
161
- </div>`;
162
- rules = [`.onoffswitch-inner:before {
163
- content: "__text__";
164
- padding-left: 10px;
165
- background-color: #2d5c88; color: #FFFFFF;
166
- }`,
167
- `.onoffswitch-inner:after {
168
- content: "__text__";
169
- padding-left: 30px;
170
- background-color: #EEEEEE; color: #2d5c88;
171
- text-align: left;
172
- }`];
173
- rules[0] = rules[0].replace("__text__", crouton.localization.getWord("Upcoming Meetings"));
174
- rules[1] = rules[1].replace("__text__", crouton.localization.getWord("All Meetings"));
175
- var controlDiv = document.createElement('div');
176
- controlDiv.innerHTML = toggleSrc;
177
- controlDiv.querySelector(".onoffswitch").addEventListener('click', function (event) {
178
- if (event.pointerId < 0) return;
179
- next24status = !next24status;
180
- fitDuringFilter = false;
181
- crouton.filterNext24(next24status);
182
- fitDuringFilter = true;
183
- });
184
- document.styleSheets[0].insertRule(rules[0]);
185
- document.styleSheets[0].insertRule(rules[1]);
186
- return controlDiv;
187
- }
188
- function createMenuButton(menuContext) {
189
- var template = hbs_Crouton.templates['mapMenu'];
190
- var controlDiv = document.createElement('div');
191
- controlDiv.innerHTML = template(menuContext);
192
- controlDiv.querySelector("#nearbyMeetings").addEventListener('click', function (e) {
193
- retrieveGeolocation().then(position => {
194
- filterVisible(false);
195
- gDelegate.setViewToPosition(position, filterMeetingsAndBounds, filterVisible);
196
- }).catch(error => {
197
- console.error(error.message);
198
- jQuery('.geo').removeClass("hide").addClass("show").html(`<p>${error.message}</p>`);
199
- });
200
- dropdownContent = document.getElementById("map-menu-dropdown").style.display = "none";
201
- });
202
-
203
- controlDiv.querySelector("#lookupLocation").addEventListener('click', showGeocodingDialog);
204
- if (menuContext && menuContext.dropdownData) {
205
- controlDiv.querySelector("#filterMeetings").addEventListener('click', showFilterDialog);
206
- controlDiv.querySelector("#showAsTable").addEventListener('click', showListView);
207
- } else {
208
- controlDiv.querySelector("#filterTable").addEventListener('click', toggleVisible);
209
- }
210
- controlDiv.querySelector("#fullscreenMode").addEventListener('click', toggleFullscreen);
211
- controlDiv.querySelector("#map-menu-button").addEventListener('click', function (e) {
212
- let dropdownContent = document.getElementById("map-menu-dropdown");
213
- if (dropdownContent.style.display == "inline-block") {
214
- dropdownContent.style.display = "none";
215
- } else {
216
- jQuery("#filteringByVisibility").html(listOnlyVisible?'&#10004;':'');
217
- dropdownContent.style.display = "inline-block";
218
- }
219
- });
220
- [...controlDiv.getElementsByClassName('modal-close')].forEach((elem)=>elem.addEventListener('click', (e)=>closeModalWindow(e.target)));
221
- controlDiv.querySelector("#close_table").addEventListener('click', hideListView);
222
- controlDiv.querySelector("#goto-text").addEventListener('keydown', function (event) {
223
- if (event && event.key == "Enter") {
224
- closeModalWindow(event.target);
225
- lookupLocation(g_suspendedFullscreen);
226
- }
227
- });
228
- controlDiv.querySelector("#goto-button").addEventListener('click', function (event) {
229
- closeModalWindow(event.target);
230
- lookupLocation(g_suspendedFullscreen);
231
- });
232
-
233
- return controlDiv;
234
- }
235
- function hasMapSearch() {
236
- return 'map_search' in config;
237
- }
238
- function loadFromCrouton(inDiv_id, meetings_responseObject, menuContext = null, handlebarMapOptions = null, fitBounds = true, callback, hide) {
239
- if (!gDelegate.isApiLoaded()) {
240
- preloadApiLoadedCallback(loadFromCrouton, [inDiv_id, meetings_responseObject, menuContext, handlebarMapOptions, fitBounds, callback, hide]);
241
- gDelegate.loadApi();
242
- return;
243
- }
244
- let inDiv = document.getElementById(inDiv_id);
245
- loadMap(inDiv, menuContext, handlebarMapOptions, callback, hide);
246
- loadAllMeetings(meetings_responseObject, fitBounds, true);
247
- };
248
- function loadPopupMap(inDiv_id, meeting, handlebarMapOptions = null) {
249
- if (!gDelegate.isApiLoaded()) {
250
- preloadApiLoadedCallback(loadPopupMap, [inDiv_id, meeting, handlebarMapOptions]);
251
- gDelegate.loadApi();
252
- return;
253
- }
254
- let inDiv = document.getElementById(inDiv_id);
255
- let delegate = new MapDelegate(config);
256
- if (handlebarMapOptions) loc = {latitude: handlebarMapOptions.lat, longitude: handlebarMapOptions.lng, zoom: handlebarMapOptions.zoom};
257
- if (delegate.createMap(inDiv, loc)) {
258
- delegate.createMarker([meeting.latitude, meeting.longitude], false, null, "", [parseInt(meeting.id_bigint)]);
259
- delegate.addClusterLayer();
260
- gModalDelegate = delegate;
261
- }
262
- };
263
- var fitDuringFilter = true;
264
- function filterFromCrouton(filter) {
265
- gMeetingIdsFromCrouton = filter;
266
- if (gAllMeetings)
267
- searchResponseCallback(fitDuringFilter && !listOnlyVisible);
268
- };
269
- function nearMeSearch() {
270
- retrieveGeolocation().then(position => {
271
- showThrobber();
272
- crouton.searchByCoordinates(position.latitude, position.longitude, config.map_search.width);
273
- if (activeModal == gSearchModal) closeModalWindow(gSearchModal);
274
- }).catch(error => {
275
- console.error(error.message);
276
- if (activeModal != gSearchModal) showBmltSearchDialog();
277
- });
278
- };
279
- function clickSearch(e) {
280
- croutonMap.showMap(false,false);
281
- gDelegate.clickSearch(e, function(lat,lng) {
282
- showThrobber();
283
- crouton.searchByCoordinates(lat, lng, config.map_search.width);
284
- });
285
- closeModalWindow(gSearchModal);
286
- }
287
- function createThrobber(inDiv) {
288
- if (!inDiv.myThrobber) {
289
- inDiv.myThrobber = document.createElement("div");
290
- if (inDiv.myThrobber) {
291
- inDiv.myThrobber.id = inDiv.id + 'Throbber_div';
292
- inDiv.myThrobber.className = 'bmlt_map_throbber_div';
293
- inDiv.myThrobber.style.display = 'none';
294
- inDiv.appendChild(inDiv.myThrobber);
295
- var img = document.createElement("img");
296
-
297
- if (img) {
298
- img.src = config.BMLTPlugin_throbber_img_src;
299
- img.className = 'bmlt_mapThrobber_img';
300
- img.id = inDiv.id + 'Throbber_img';
301
- img.alt = 'AJAX Throbber';
302
- inDiv.myThrobber.appendChild(img);
303
- } else {
304
- inDiv.myThrobber = null;
305
- };
306
- };
307
- };
308
- };
309
- function showThrobber() {
310
- if (gInDiv.myThrobber) {
311
- gInDiv.myThrobber.style.display = 'block';
312
- };
313
- };
314
- function hideThrobber() {
315
- if (gInDiv.myThrobber) {
316
- gInDiv.myThrobber.style.display = 'none';
317
- };
318
- };
319
- function mapSearchGeocode(resp) {
320
- showThrobber();
321
- if (document.getElementById("bmltsearch-goto-text"))
322
- document.getElementById("bmltsearch-goto-text").value = "";
323
- let latlng = gDelegate.getGeocodeCenter(resp);
324
- if (!latlng) {
325
- hideThrobber();
326
- return;
327
- }
328
- crouton.searchByCoordinates(latlng.lat, latlng.lng, config.map_search.width);
329
- }
330
- function loadAllMeetings(meetings_responseObject, fitBounds=true, fitAll=false) {
331
- if (meetings_responseObject === null && config.map_search) {
332
- if (config.map_search.auto) nearMeSearch();
333
- else if (config.map_search.coordinates_search) {
334
- showThrobber();
335
- config.map_search.coordinates_search = false;
336
- crouton.searchByCoordinates(config.map_search.latitude, config.map_search.longitude, config.map_search.width);
337
- }
338
- else if (config.map_search.location) gDelegate.callGeocoder(config.map_search.location, null, mapSearchGeocode);
339
- else showBmltSearchDialog();
340
- return;
341
- }
342
- gAllMeetings = meetings_responseObject.filter(m => m.venue_type != 2);
343
- if (fitBounds) {
344
- const lat_lngs = gAllMeetings.reduce(function(a,m) {a.push([m.latitude, m.longitude]); return a;},[]);
345
- gDelegate.fitBounds(lat_lngs);
346
- }
347
- searchResponseCallback();
348
- hideThrobber();
349
- if (config.filter_visible || config.centerMe || config.goto) crouton.forceShowMap();
350
- if (config.centerMe) {
351
- if (navigator.geolocation) {
352
- navigator.geolocation.getCurrentPosition(
353
- function (position) {
354
- coords = {latitude: position.coords.latitude, longitude: position.coords.longitude};
355
- filterVisible(false);
356
- gDelegate.setViewToPosition(coords, filterMeetingsAndBounds, filterVisible);
357
- },
358
- showGeocodingDialog
359
- );
360
- } else if (fitAll) {
361
- showGeocodingDialog();
362
- }
363
- } else {
364
- if (!config.centerMe && !config.goto) gDelegate.afterInit(()=>filterVisible(config.filter_visible));
365
- if (config.goto) gDelegate.callGeocoder(config.goto, resetVisibleThenFilterMeetingsAndBounds);
366
- }
367
- }
368
- function createCityHash(allMeetings) {
369
- return allMeetings.reduce(function(prev, meeting) {
370
- if (prev.hasOwnProperty(meeting.location_municipality))
371
- prev[meeting.location_municipality].push(meeting);
372
- else
373
- prev[meeting.location_municipality] = [meeting];
374
- return prev;
375
- }, {});
376
- }
377
- var g_suspendedFullscreen = false;
378
- var g_overflowX;
379
- var activeModal = null;
380
- var swipableModal = false;
381
- function closeModalWindow(modal) {
382
- gDelegate.modalOff();
383
- activeModal = null;
384
- if (!modal.classList.contains("modal"))
385
- return closeModalWindow(modal.parentNode);
386
- modal.style.display = "none";
387
- if (g_suspendedFullscreen) {
388
- g_suspendedFullscreen = false;
389
- if (!isFullscreen()) {
390
- toggleFullscreen();
391
- }
392
- }
393
- if (swipableModal) {
394
- const body = document.body;
395
- const scrollY = body.style.top;
396
- body.style.overflowX = g_overflowX;
397
- body.style.position = '';
398
- body.style.top = '';
399
- window.scrollTo(0, parseInt(scrollY || '0') * -1);
400
- }
401
- }
402
- document.addEventListener("keydown", function(event) {
403
- if (activeModal && event.key == "Escape") {
404
- closeModalWindow(activeModal);
405
- }
406
- }, true);
407
- function openModalWindow(modal,swipe=false) {
408
- if (isFullscreen()) {
409
- g_suspendedFullscreen = true;
410
- toggleFullscreen();
411
- }
412
- modal.style.display = "block";
413
- swipableModal = swipe;
414
- modal.focus();
415
- activeModal = modal;
416
- dd = document.getElementById("map-menu-dropdown");
417
- if (dd) dd.style.display = "none";
418
- gDelegate.modalOn();
419
- if (swipableModal) {
420
- const body = document.body;
421
- g_overflowX = body.style.overflowX;
422
- const newTop = -window.scrollY+'px';
423
- body.style.overflowX = 'hidden';
424
- body.style.position = 'fixed';
425
- body.style.width="100%";
426
- body.style.setProperty('top', newTop, 'important');
427
- }
428
- }
429
- function showFilterDialog(e) {
430
- openModalWindow(document.getElementById('filter_modal'));
431
- }
432
- function showBmltSearchDialog(e) {
433
- if (!document.getElementById('bmltsearch_modal')) gInDiv.appendChild(gSearchModal);
434
- openModalWindow(gSearchModal);
435
- }
436
- function showSearchDialog(e) {
437
- if (!document.getElementById('bmltsearch_modal')) gInDiv.appendChild(gSearchModal);
438
- openModalWindow(gSearchModal);
439
- }
440
- function showGeocodingDialog(e=null) {
441
- openModalWindow(document.getElementById('geocoding_modal'));
442
- }
443
- function showListView(e=null) {
444
- filterVisible();
445
- jQuery("#bmlt-tabs").append(jQuery("#table_page"));
446
- jQuery("#table_page").removeClass("hide");
447
- jQuery("#bmlt-map").css("display", "none");
448
- jQuery("#table_page").css("max-height", jQuery("#bmlt-map").height());
449
- jQuery("#bmlt-maptable-div").css("height", jQuery("#bmlt-map").height()-jQuery("#bmlt-maptable-header").height());
450
- document.getElementById("map-menu-dropdown").style.display = "none";
451
- }
452
- function hideListView(e=null) {
453
- filterVisible(false);
454
- jQuery("#table_page").addClass("hide");
455
- jQuery("#bmlt-map").css("display", "block");
456
- }
457
- function resetVisibleThenFilterMeetingsAndBounds(bounds) {
458
- filterVisible(false);
459
- const ret = filterMeetingsAndBounds(bounds);
460
- filterVisible(true);
461
- return ret;
462
- }
463
- function lookupLocation(fullscreen) {
464
- if (document.getElementById('goto-text').value != '') {
465
- if (fullscreen) {
466
- gDelegate.addListener('idle', function () {
467
- gDelegate.callGeocoder(document.getElementById('goto-text').value, resetVisibleThenFilterMeetingsAndBounds);
468
- }, true);
469
- } else {
470
- gDelegate.callGeocoder(document.getElementById('goto-text').value, resetVisibleThenFilterMeetingsAndBounds);
471
- }
472
- } else {
473
- alert("");
474
- };
475
- return true;
476
- };
477
- function searchResponseCallback(expand = false) {
478
- if (!gAllMeetings) return;
479
- if (!gAllMeetings.length) {
480
- alert ( crouton.localization.getWord("no meetings found") );
481
- return;
482
- };
483
- try {
484
- drawMarkers(expand);
485
- } catch (e) {
486
- console.log(e);
487
- gDelegate.addListener('projection_changed', function (ev) {
488
- drawMarkers(expand);
489
- }, true);
490
- }
491
- };
492
- /****************************************************************************************
493
- * CREATING MARKERS *
494
- ****************************************************************************************/
495
- var prevUseMarkerCluster;
496
- function useMarkerCluster() {
497
- if (typeof gDelegate.getZoom() === 'undefined') return true;
498
- if (typeof config.clustering === 'undefined') return false;
499
- return gDelegate.getZoom() < config.clustering;
500
- }
501
- function shouldRedrawMarkers() {
502
- if (typeof prevUseMarkerCluster === 'undefined') return true;
503
- if (prevUseMarkerCluster !== useMarkerCluster()) {
504
- prevUseMarkerCluster = useMarkerCluster();
505
- return true;
506
- }
507
- if (useMarkerCluster()===false) {
508
- return true;
509
- }
510
- return false;
511
- }
512
- function drawMarkers(expand = false) {
513
- gDelegate.clearAllMarkers();
514
- gDelegate.removeClusterLayer();
515
- // This calculates which markers are the red "multi" markers.
516
- const filtered = filterMeetings(gAllMeetings);
517
-
518
- var overlap_map = (useMarkerCluster() || filtered.length == 1)
519
- ? filtered.map((m)=>[m])
520
- : mapOverlappingMarkersInCity(filtered);
521
-
522
- if (useMarkerCluster()) gDelegate.createClusterLayer();
523
- // Draw the meeting markers.
524
- overlap_map.forEach(function (marker) {
525
- createMapMarker(marker);
526
- });
527
- gDelegate.addClusterLayer();
528
- if (expand) {
529
- const lat_lngs = filtered.reduce(function(a,m) {a.push([m.latitude, m.longitude]); return a;},[]);
530
- gDelegate.fitBounds(lat_lngs);
531
- }
532
- };
533
- function mapOverlappingMarkersInCity(in_meeting_array) ///< Used to draw the markers when done.
534
- {
535
- var tolerance = 8; /* This is how many pixels we allow. */
536
-
537
- var ret = new Array;
538
- // We create this hash because we limit looking for "matches" to within one city.
539
- for (const [city, meetings] of Object.entries(createCityHash(in_meeting_array))) {
540
- // create a tmp object so we can mark which items haven't been matched yet.
541
- var tmp = meetings.map((meeting) => {
542
- item = new Object;
543
- item.matched = false;
544
- item.meeting = meeting;
545
- item.coords = gDelegate.fromLatLngToPoint(meeting.latitude, meeting.longitude);
546
- return item;
547
- });
548
- tmp.reduce(function(prev, item, index) {
549
- if (item.matched) return prev;
550
- matches = [item.meeting];
551
- var outer_coords = item.coords;
552
- for (c2 = index+1; c2<meetings.length; c2++) {
553
- if (tmp[c2].matched) continue;
554
- var inner_coords = tmp[c2].coords;
555
-
556
- var xmin = outer_coords.x - tolerance;
557
- var xmax = outer_coords.x + tolerance;
558
- var ymin = outer_coords.y - tolerance;
559
- var ymax = outer_coords.y + tolerance;
560
-
561
- /* We have an overlap. */
562
- if ((inner_coords.x >= xmin) && (inner_coords.x <= xmax) && (inner_coords.y >= ymin) && (inner_coords.y <= ymax)) {
563
- matches.push(tmp[c2].meeting);
564
- tmp[c2].matched = true;
565
- }
566
- }
567
- matches.sort(sortMeetingSearchResponseCallback)
568
- prev.push(matches);
569
- return prev;
570
- }, ret);
571
- }
572
-
573
- return ret;
574
- };
575
- function sortMeetingSearchResponseCallback(mtg_a, mtg_b) {
576
- var weekday_score_a = parseInt(mtg_a.weekday_tinyint, 10);
577
- var weekday_score_b = parseInt(mtg_b.weekday_tinyint, 10);
578
-
579
- if (weekday_score_a < config.start_week) {
580
- weekday_score_a += 7;
581
- }
582
-
583
- if (weekday_score_b < config.start_week) {
584
- weekday_score_b += 7;
585
- }
586
-
587
- if (weekday_score_a < weekday_score_b) {
588
- return -1;
589
- }
590
- else if (weekday_score_a > weekday_score_b) {
591
- return 1;
592
- };
593
- var time_a = mtg_a.start_time.toString().split(':');
594
- var time_b = mtg_b.start_time.toString().split(':');
595
- if (parseInt(time_a[0]) < parseInt(time_b[0])) {
596
- return -1;
597
- }
598
- if (parseInt(time_a[0]) > parseInt(time_b[0])) {
599
- return 1;
600
- }
601
- if (parseInt(time_a[1]) < parseInt(time_b[1])) {
602
- return -1;
603
- }
604
- if (parseInt(time_a[1]) > parseInt(time_b[1])) {
605
- return 1;
606
- }
607
- return 0;
608
- };
609
- const markerTemplateSrc = `
610
- <div class="accordion">
611
- {{#each this}}<div>
612
- <input type="radio" name="panel" id="panel-{{this.id_bigint}}" {{#unless @index}}checked{{/unless}}/>
613
- <label for="panel-{{this.id_bigint}}">{{this.formatted_day}} {{this.start_time_formatted}}</label>
614
- <div class="marker_div_meeting" id="{{this.id_bigint}}">
615
- {{> markerContentsTemplate}}
616
- </div>
617
- </div>{{/each}}
618
- </div>
619
- `;
620
-
621
- /************************************************************************************//**
622
- * \brief This creates a single meeting's marker on the map. *
623
- ****************************************************************************************/
624
- function createMapMarker(meetings) {
625
- var main_point = [meetings[0].latitude, meetings[0].longitude];
626
- let markerTemplate = crouton_Handlebars.compile(markerTemplateSrc);
627
- var marker_html = markerTemplate(meetings);
628
- gDelegate.createMarker(main_point,
629
- (meetings.length > 1),
630
- marker_html, null ,meetings.map((m)=>parseInt(m.id_bigint)));
631
- };
632
- var listOnlyVisible = false;
633
- var listener = null;
634
- function filterBounds(bounds) {
635
- return gAllMeetings.filter((meeting) => gDelegate.contains(bounds, meeting.latitude, meeting.longitude));
636
- }
637
- function showAllMeetings() {
638
- filterVisible(false);
639
- gDelegate.addListener('dragend', filterVisible, true);
640
- }
641
- function filterVisible(on=true) {
642
- if (on==listOnlyVisible) return on;
643
- let mtgs = on ? filterBounds(gDelegate.getBounds()) : gAllMeetings;
644
- let visible = mtgs.map((m)=>m.id_bigint);
645
- jQuery(".bmlt-data-row").each(function(index,row) {
646
- row.dataset.visible = (visible.includes(row.id.split('-').pop())) ? '1' : '0';
647
- });
648
- jQuery("#byday").removeClass('hide');
649
- jQuery("#filter-dropdown-visibile").val(on?'a-1':'');
650
- fitDuringFilter = false;
651
- crouton.simulateFilterDropdown();
652
- fitDuringFilter = true;
653
- jQuery("#filteringByVisibility").html(on?'&#10004;':'');
654
- listOnlyVisible = on;
655
- if (on) listener = gDelegate.addListener('dragstart', showAllMeetings, true);
656
- else if (listener) {
657
- gDelegate.removeListener(listener);
658
- listener = null;
659
- }
660
- return !on;
661
- }
662
- function toggleVisible() {
663
- filterVisible(!listOnlyVisible);
664
- }
665
- function filterBounds(bounds) {
666
- var ret = gAllMeetings.filter((meeting) =>
667
- gDelegate.contains(bounds, meeting.latitude, meeting.longitude));
668
- return ret;
669
- }
670
- function focusOnMeeting(meetingId) {
671
- let meeting = gAllMeetings.find((meeting) => meeting.id_bigint == meetingId);
672
- if (!meeting) return;
673
- if ((gDelegate.getZoom()>=14) && gDelegate.contains(gDelegate.getBounds(), meeting.latitude, meeting.longitude)) {
674
- gDelegate.openMarker(meetingId);
675
- } else {
676
- gDelegate.setViewToPosition({latitude: meeting.latitude, longitude: meeting.longitude}, filterMeetingsAndBounds, function() {gDelegate.openMarker(meetingId);});
677
- }
678
- }
679
- function filterMeetingsAndBounds(bounds) {
680
- return filterMeetings(filterBounds(bounds));
681
- }
682
- function filterMeetings(in_meetings_array) {
683
- var ret = in_meetings_array.filter(m => m.venue_type != 2);
684
- if (gMeetingIdsFromCrouton != null) {
685
- return ret.filter((m) => gMeetingIdsFromCrouton.includes(m.id_bigint));
686
- }
687
- return ret;
688
- }
689
- var _isPseudoFullscreen = false;
690
- function isFullscreen() {
691
- var fullscreenElement =
692
- document.fullscreenElement ||
693
- document.mozFullScreenElement ||
694
- document.webkitFullscreenElement ||
695
- document.msFullscreenElement;
696
-
697
- return (fullscreenElement === gInDiv) || _isPseudoFullscreen;
698
- }
699
- function toggleFullscreen(options) {
700
- var container = gInDiv;
701
- if (isFullscreen()) {
702
- if (options && options.pseudoFullscreen) {
703
- _setFullscreen(false);
704
- } else if (document.exitFullscreen) {
705
- document.exitFullscreen();
706
- } else if (document.mozCancelFullScreen) {
707
- document.mozCancelFullScreen();
708
- } else if (document.webkitCancelFullScreen) {
709
- document.webkitCancelFullScreen();
710
- } else if (document.msExitFullscreen) {
711
- document.msExitFullscreen();
712
- } else {
713
- _disablePseudoFullscreen(container);
714
- }
715
- } else {
716
- if (options && options.pseudoFullscreen) {
717
- _setFullscreen(true);
718
- } else if (container.requestFullscreen) {
719
- container.requestFullscreen();
720
- } else if (container.mozRequestFullScreen) {
721
- container.mozRequestFullScreen();
722
- } else if (container.webkitRequestFullscreen) {
723
- container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
724
- } else if (container.msRequestFullscreen) {
725
- container.msRequestFullscreen();
726
- } else {
727
- _enablePseudoFullscreen(container);
728
- }
729
- }
730
- }
731
- var _isPseudoFullscreen = false;
732
- function _setFullscreen(fullscreen) {
733
- _isPseudoFullscreen = fullscreen;
734
- var container = gInDiv;
735
- if (fullscreen) {
736
- L.DomUtil.addClass(container, 'leaflet-pseudo-fullscreen');
737
- } else {
738
- L.DomUtil.removeClass(container, 'leaflet-pseudo-fullscreen');
739
- }
740
- gDelegate.invalidateSize();
741
- }
742
- function showMap(isModal=false, fitBounds=true) {
743
- if (isModal && gModalDelegate) {
744
- gModalDelegate.invalidateSize();
745
- return;
746
- }
747
- gDelegate.invalidateSize();
748
- if (!gAllMeetings) return;
749
- if (fitBounds) gDelegate.fitBounds(
750
- ((gMeetingIdsFromCrouton) ? gAllMeetings.filter((m) => gMeetingIdsFromCrouton.includes(m.id_bigint)) : gAllMeetings)
751
- .reduce(function(a,m) {a.push([m.latitude, m.longitude]); return a;},[])
752
- );
753
- }
754
- /****************************************************************************************
755
- * MAIN FUNCTIONAL INTERFACE *
756
- ****************************************************************************************/
757
- this.initialize = loadFromCrouton;
758
- this.showMap = showMap;
759
- this.fillMap = filterFromCrouton;
760
- this.rowClick = focusOnMeeting;
761
- this.apiLoadedCallback = apiLoadedCallback;
762
- this.refreshMeetings = loadAllMeetings;
763
-
764
- this.openModalWindow = openModalWindow;
765
- this.closeModalWindow = closeModalWindow;
766
- this.loadPopupMap = loadPopupMap;
767
- this.filterVisible = filterVisible;
768
- this.hasMapSearch = hasMapSearch;
769
- };
770
- MeetingMap.prototype.initialize = null;
771
- MeetingMap.prototype.showMap = null;
772
- MeetingMap.prototype.fillMap = null;
773
- MeetingMap.prototype.rowClick = null;
774
- MeetingMap.prototype.apiLoadedCallback = null;
775
- MeetingMap.prototype.refreshMeetings = null;
776
-
777
- MeetingMap.prototype.openModalWindow = null;
778
- MeetingMap.prototype.closeModalWindow = null;
779
- MeetingMap.prototype.loadPopupMap = null;
780
- MeetingMap.prototype.filterVisible = null;
781
- MeetingMap.prototype.hasMapSearch = null;
782
-
783
1
  function MapDelegate(config) {
784
2
  var g_icon_image_single = L.icon({
785
3
  iconUrl: config.BMLTPlugin_images+"/NAMarker.png",