PageSourceSearch

https://www.lommel.be/global/js/streetmap/leaflet/streetmap.js?v=1.2

js lommel.be collected 2026-09-24 19:51:29 UTC 66,370 bytes, 1,803 lines download raw bytes

1var LCPStreetmap = {
2    baseMaps: {
3        openstreetmap: L.tileLayer('https://tile.osm.be/osmbe-nl/{z}/{x}/{y}.png', {
4            id: 'map-openstreetmap',
5            attribution: '&copy;<a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>, Tiles generated by <a href="https://www.champs-libres.coop/" rel="nofollow">Champs-Libres</a>',
6            title: 'OpenStreetMap'
7        }),
8        hot: L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
9            id: 'osm-hot',
10            attribution: '&copy; OpenStreetMap contributors, Tiles style by Humanitarian OpenStreetMap Team hosted by OpenStreetMap France',
11            ref: 'hot',
12            title: 'OpenStreetMap HOT'
13        }),
14        grb: L.tileLayer.wms('https://geo.api.vlaanderen.be/GRB/wms?', {
15            layers: 'GRB_RPD',
16            attribution: '<a href="https://www.vlaanderen.be/digitaal-vlaanderen/onze-oplossingen/basiskaart-vlaanderen-grb">Grootschalig Referentie Bestand Vlaanderen, Digitaal Vlaanderen</a>',
17            title: 'Grootschalig Referentie Bestand Vlaanderen'
18        }),
19        ofw: L.tileLayer.wms('https://geo.api.vlaanderen.be/OFW/wms?', {
20            layers: 'ofw',
21            attribution: '<a href="https://www.vlaanderen.be/datavindplaats/catalogus/wmts-orthofotowerkbestand">Orthofotowerkbestand Vlaanderen, Digitaal Vlaanderen</a>',
22            title: 'Satelliet'
23        })
24        //https://leaflet-extras.github.io/leaflet-providers/preview/
25        /*,OPNVKarte:  L.tileLayer('https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png', {
26            id: 'opnv-karte',
27            attribution: 'Map <a href="https://memomaps.de/">memomaps.de</a> <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
28            title:'Openbaar vervoer'
29        })*/
30    },
31    map: null,
32    markerslayers: [],
33    totalLayersLoading: 0,
34    totalLayersLoaded: 0,
35    init: function () {
36        var that = this;
37        that.infoPanelTemplate = new TemplateEngine('streetmap-info-poi-detail');
38        that.poiItemsTemplate = new TemplateEngine('streetmap-poi-list-item');
39        that.setNoOfActiveFilters();
40        that.renderMap();
41        that.uiEvents();
42        that.createSelect2();
43        that.startPois();
44        that.checkMyLocationOnStartup();
45    },
46
47    startPois: function () {
48        var that = this;
49        var checkedItems = $('#streetmap-filters-form input[type="checkbox"]:checked');
50        if (checkedItems.length > 0) {
51
52            checkedItems.each(function () {
53                var input = $(this);
54                that.loadLayer(input);
55            });
56        }
57
58        if (window.location.search === '') {
59
60            var logo = $('#default-logo');
61            if (logo.length > 0) {
62                var logoPath = logo.attr('src');
63                if (logoPath !== '') {
64                    that.totalLayersLoading += 1;
65                    var streetmap = $('.streetmap');
66                    that.parseData('default-location', '', [{
67                        data: null,
68                        layers: [{
69                            logo: logoPath,
70                            icon: '/global/icons/global-line.svg#home-2'
71                        }],
72                        title: '',
73                        pointOfInterest: {
74                            lat: parseFloat(LCPStreetmap.map._container.attributes.getNamedItem('data-lat').value),
75                            lng: parseFloat(LCPStreetmap.map._container.attributes.getNamedItem('data-lng').value)
76                        }
77                    }], 'default-location', false);
78                }
79            }
80        }
81
82    },
83    checkMyLocationOnStartup: function () {
84        //@Translator.Translate("www-streetmap-my-location")
85        var that = this;
86
87        $('#chk-mylocation').closest('li').remove(); //remove old version my location filter if exists
88
89        if (!navigator.geolocation) {
90            $('#btn-mylocation').remove();
91        }
92    },
93    uiEvents: function () {
94        var that = this;
95        $(document).on('change', '#streetmap-filters-form input[type="checkbox"][data-menu="0"]', function (e) {
96            var input = $(this);
97
98            if (input.is(':checked')) {
99                that.loadLayer(input);
100            } else {
101                that.unloadLayer(input);
102            }
103            that.setNoOfActiveFilters();
104            that.setBrowserHistory();
105        }).on('click', '#btn-mylocation', function () {
106            var btn = $(this);
107
108            if (btn.hasClass('active')) {
109                that.unloadLayer('mylocation');
110            } else {
111                that.loadMyLocation(btn);
112            }
113            btn.toggleClass('active');
114        }).on('click', '#pois .item[data-poi]', function () {
115            var btn = $(this);
116
117            that.findAndShowPoidetail(btn.attr('data-poi'), btn.attr('data-module'));
118
119        }).on('click', '[data-toggle-panel]', function (e) {
120            e.preventDefault();
121            var btn = $(this);
122            btn.toggleClass('active');
123            var open = btn.hasClass('active');
124            btn.attr('aria-expanded', open ? 'true' : 'false');
125
126
127            var txt = btn.attr('data-toggle-' + (open ? 'hide' : 'show'));
128            if (txt !== undefined && txt !== '') {
129                btn.attr('data-tooltip', txt);
130                btn.find('span').html(txt);
131            }
132            var panel = $('#' + btn.attr('data-toggle-panel'));
133            panel.toggleClass('hidden').toggleClass('active');
134            panel.attr('aria-hidden', open ? 'false' : 'true');
135            panel.closest('fieldset').toggleClass('open');
136            that.updateMap();
137
138        }).on('click', 'button.btn-chklist-toggle', function (e) {
139            e.preventDefault();
140            var btn = $(this);
141            btn.toggleClass('active');
142            var open = btn.hasClass('active');
143            btn.attr('aria-expanded', open ? 'true' : 'false');
144            var txt = btn.attr('data-toggle-' + (open ? 'hide' : 'show'));
145            btn.find('span').html(txt);
146            btn.attr('data-tooltip', txt);
147            var control = btn.attr('aria-controls');
148            var panel = $('#' + control);
149            panel.toggleClass('hidden');
150            panel.attr('aria-hidden', open ? 'false' : 'true');
151        }).on('change', 'input[name="layer-option"]', function (e) {
152            that.toggleBaseLayer($(this));
153        }).on('click', '#btn-clear-all-filters', function (e) {
154            e.preventDefault();
155            var chks = $('#streetmap-filters-form input[type="checkbox"]:checked');
156
157            chks.each(function () {
158                var input = $(this);
159                input.prop('checked', false);
160                that.unloadLayer(input);
161            });
162            that.unloadLayer($('#streetmap-search'));
163            that.unloadLayer('q-null');
164            $('#streetmap-search').val('').trigger('change');
165
166            window.history.replaceState(null, null, window.location.pathname);
167        }).on('click', '#lst-pois-close-btn', function (e) {
168            $('[data-toggle-panel="lst-pois"]').trigger('click');
169        }).on('change', '.checkboxlist-item input[data-parentid]', function () {
170            var chk = $(this);
171            var id = chk.val();
172            var checked = chk.is(':checked');
173            var parentid = chk.attr('data-parentid');
174            if (parentid === '0') {
175                var chks = $('.checkboxlist-item input[data-parentid="' + id + '"]');
176                chks.prop('checked', checked);
177                chks.each(function () {
178                    var input = $(this);
179                    if (input.is(':checked')) {
180                        that.loadLayer(input);
181                    } else {
182                        that.unloadLayer(input);
183                    }
184                });
185
186
187            } else if (checked == false) {
188                $('.checkboxlist-item input[value="' + parentid + '"]').prop('checked', false);
189            }
190
191            that.setNoOfActiveFilters();
192            that.setBrowserHistory();
193        }).on('click', 'button.detail__close', function () {
194            that.closeDetail();
195        }).on('click', '[data-toggle-filter]', function (e) {
196            e.preventDefault();
197            var btn = $(this);
198            btn.toggleClass('active');
199            var open = btn.hasClass('active');
200            btn.attr('aria-expanded', open ? 'true' : 'false');
201            var filterPanel = $('.filters__content-info');
202            filterPanel.toggleClass('open');
203        }).on('mouseenter', '#pois .item', function () {
204            var id = this.id.replace('list', '');
205            var svg = $('svg[data-id="' + id + '"]');
206
207            if (svg !== undefined && svg.length > 0) {
208                svg.closest('.poi-svg__wrapper').addClass('poi-hover');
209            }
210        }).on('mouseleave', '#pois .item', function () {
211            var id = this.id.replace('list', '');
212
213            var svg = $('svg[data-id="' + id + '"]');
214            if (svg !== undefined && svg.length > 0) {
215                svg.closest('.poi-svg__wrapper').removeClass('poi-hover');
216            }
217
218        }).on('mouseenter', '.leaflet-marker-icon', function () {
219            var svg = $(this).find('svg');
220            if (svg.length > 0) {
221                $('#list' + svg.attr('data-id')).addClass('poi-hover');
222            }
223        }).on('mouseleave', '.leaflet-marker-icon', function () {
224
225
226            var svg = $(this).find('svg');
227            if (svg.length > 0) {
228                var id = svg.attr('data-id');
229
230                if ($('#poi-detail[data-id="' + id + '"]').length === 0) {
231
232                    $('#list' + id).removeClass('poi-hover');
233                }
234            }
235        });
236
237
238
239        $(window).resize(function () { that.checkBtnsAttributionIntersection(); });
240    },
241    findMarker: function (id) {
242        var that = this;
243        var marker = null;
244
245        for (var i = 0; i < that.markerslayers.length; i++) {
246            var layer = that.markerslayers[i];
247            if (layer instanceof L.MarkerClusterGroup) {
248                layer.eachLayer((l) => {
249                    if (marker == null) {
250                        if (l.options.pid !== undefined && l.options.pid === id) {
251                            marker = l;
252                        } if (typeof (l.eachLayer) !== 'undefined') {
253                            l.eachLayer((lp) => {
254                                if (marker == null &&
255                                    lp.options.pid !== undefined &&
256                                    lp.options.pid === id) {
257                                    marker = lp;
258                                }
259                            });
260                        }
261                    }
262                });
263            }
264        }
265        return marker;
266    },
267    findAndShowPoidetail: function (poiID, moduleID) {
268        var that = this;
269        var marker = that.findMarker('item-' + moduleID + '-' + poiID);
270
271        if (marker != null) {
272            $('#poi-detail:not(.hidden) button.detail__close').trigger('click');
273
274
275            marker.fire('click');
276            that.map.setView(marker.getLatLng(), 15, { animate: true, duration: 0.50 });
277
278            var tooltip = marker.getTooltip();
279            if (tooltip !== undefined) {
280                that.map.closeTooltip(tooltip);
281            }
282
283        }
284    },
285    createSelect2: function () {
286        var that = this;
287        var sel = $('#streetmap-search');
288
289        sel.select2({
290            minimumInputLength: 2,
291            placeholder: that.translateKey('www-streetmap-lbl-keyword'),
292            allowClear: true,
293            debug: true,
294            templateResult: function (item) {
295                if (!item.id) return item.text;
296                var street = item.data && item.data.street && item.text.toLowerCase().indexOf(item.data.street.toLowerCase()) == -1 ? item.data.street : '';
297                return $('<span>' + item.text + (street ? ' <span class="street" >(' + street + ')</span>' : '') + '</span>');
298            },
299            ajax: {
300                url: '/Streetmap/search',
301                dataType: 'json',
302                delay: 200,
303                language: $('html').attr('lang').split('-')[0],
304                data: function (params) {
305
306                    return {
307                        q: params.term,
308                        page: params.page || 1
309                    };
310                },
311                processResults: function (data, params) {
312
313                    return {
314                        results: $.map(data, function (item) {
315                            //var extraText = '';
316                            //if (item.layers != null && item.layers.length > 0) {
317                            //    extraText = ' (' + item.layers[0].title + ')';
318                            //}
319                            var id = item.id == 0 ? 'item-' + String(item.pointOfInterest.lat).replace('.', '') + String(item.pointOfInterest.lng).replace('.', '') : item.id;
320                            return {
321                                text: item.title,
322                                id: id,
323                                data: item
324                            };
325                        }),
326                        pagination: {
327                            more: data.length > 99
328                        }
329                    };
330
331                },
332                cache: true
333            }
334        });
335        $('.select2-container').on('click', function () {
336            $('.select2-search__field').focus()
337        })
338        sel.on('select2:unselect', function (e) {
339            that.unloadLayer('q-null');
340        }).on('select2:clear', function (e) {
341            that.unloadLayer('q-null');
342        }).on('select2:select', function () {
343            var sel = $(this);
344            that.unloadLayer('q-null');
345            if (that.markerslayers.find(x => x.id === 'default-location-') != null) {
346                that.unloadLayer('default-location-');
347            }
348            var selectedData = sel.select2('data');
349            if (selectedData.length > 0) {
350
351                var data = selectedData[0].data;
352                if (data.moduleID == 18) { // trigger layer
353                    $('#chk-kaartlaagid' + data.id + ':not(:checked)').trigger('click');
354                } else {
355
356                    that.totalLayersLoading = 1;
357                    that.totalLayersLoaded = 0;
358                    if (data.layers === null) {
359                        data.layers = [{ icon: '/global/icons/global-line.svg#map-pin-2' }];
360                    }
361                    that.parseData('q', null, [data], 'q', true);
362                    //set bounds for q- layer
363                    var bounds = L.latLngBounds();
364                    for (var i = 0; i < that.markerslayers.length; i++) {
365                        var layer = that.markerslayers[i];
366                        if (layer.id.indexOf('q-') > -1 && typeof layer.getBounds === 'function') {
367                            bounds.extend(layer.getBounds());
368                        }
369                    }
370                    if (bounds.isValid()) {
371                        that.map.fitBounds(bounds, { padding: [2, 2] });
372                    }
373                }
374            }
375
376            that.setBrowserHistory();
377        });
378        $('label[for="streetmap-search"]').on('click', function (e) {
379            e.preventDefault();
380            sel.select2('open');
381        });
382
383    },
384    renderMap: function () {
385        var that = this;
386        var mapdiv = $('.streetmap');
387       // mapdiv.attr('aria-hidden', 'true');
388        that.map = L.map(mapdiv.attr('id'), {
389            center: [parseFloat(mapdiv.attr('data-lat')), parseFloat(mapdiv.attr('data-lng'))], zoom: 12, maxZoom: 18, minZoom: 10,
390            // gestureHandling: true  //Prevents users from getting trapped on the map when scrolling a long page.
391        });   // minZoom: 16,  
392        that.defaultColor = mapdiv.attr('data-default-color');
393        _DEFAULT_POLYLINE_OPTS.color = that.defaultColor;
394        that.map.attributionControl.setPrefix('<a href="https://leafletjs.com" title="A JavaScript library for interactive maps">Leaflet</a>');
395        var defaultLayer = mapdiv.attr('data-layer');
396        that.addBaseLayers(defaultLayer).addTo(that.map);
397
398        that.map.zoomControl.setPosition('topleft');
399
400
401        $('.leaflet-control-attribution').prepend($('#footer-template').html());
402        that.checkBtnsAttributionIntersection();
403    },
404    addBaseLayers: function (defaultLayer) {
405        var that = this;
406        var basemap = that.baseMaps.openstreetmap;
407        if (defaultLayer === '') {
408            defaultLayer = 'openstreetmap';
409        }
410
411        var items = '';
412        var Template = new TemplateEngine('streetmap-layers-options-template');
413        for (const key in that.baseMaps) {
414            if (that.baseMaps.hasOwnProperty(key)) {
415                var isActive = defaultLayer === key;
416                if (isActive) {
417                    basemap = that.baseMaps[key];
418                }
419                items += Template.render({ key: key, title: that.baseMaps[key].options.title, checked: isActive ? "checked" : "" });
420            }
421        }
422        $('#streetmap-layers-options').html(items);
423
424        return basemap;
425    },
426    toggleBaseLayer: function (rbtn) {
427        var that = this;
428        $('input[name="layer-option"]:not(:checked)').each(function () {
429            var name = $(this).val();
430            var layer = that.findBaseLayerByName(name);
431            if (layer != null) {
432                that.map.removeLayer(layer);
433            }
434        });
435        var value = rbtn.val();
436        $('input[name="baselayer"]').val(value);
437        that.baseMaps[value].addTo(that.map);
438        $('.leaflet-control-attribution').prepend($('#footer-template').html());
439        that.setBrowserHistory();
440    },
441    findBaseLayerByName: function (name) {
442        var that = this;
443        var foundLayer = null;
444        that.map.eachLayer(function (layer) {
445            if (layer === that.baseMaps[name]) {
446                foundLayer = layer;
447            }
448        });
449        return foundLayer;
450    },
451    loadMyLocation: function (btn) {
452        var that = this;
453        if (!navigator.geolocation) {
454            alert('Geolocation is not supported by your browser.');
455            return;
456        }
457        btn.addClass('loading');
458        btn.prop('disabled', true);
459        navigator.geolocation.getCurrentPosition(
460            function (position) {
461                var lat = position.coords.latitude;
462                var lng = position.coords.longitude;
463
464
465                that.unloadLayer('mylocation');
466
467                var markerData = {
468                    title: that.translateKey('www-streetmap-my-location'),
469                    id: 'mylocation',
470                    moduleID: -999,
471                    pointOfInterest: { lat: lat, lng: lng },
472                    layers: [{
473                        icon: '/global/icons/line/user-3.svg#user-3',
474                        iconColor: 'rgba(239,0,0,1)'
475                    }]
476                };
477
478                // Create a new layer group for mylocation
479                var layer = L.layerGroup();
480                layer.id = 'mylocation';
481
482                // Add marker using addMarker
483                var marker = that.addMarker(markerData, layer);
484                if (marker) {
485                    layer.addLayer(marker);
486                }
487                that.markerslayers.push(layer);
488                layer.addTo(that.map);
489
490                // Center the map on the user's location
491                that.map.setView([lat, lng], 15, { animate: true });
492
493                btn.removeClass('loading');
494                btn.prop('disabled', false);
495            },
496            function (error) {
497                alert('Unable to retrieve your location.');
498            }
499        );
500    },
501    loadLayer: function (input) {
502        var that = this;
503
504        if (that.markerslayers.find(x => x.id === 'default-location-') != null) {
505            that.unloadLayer('default-location-');
506        }
507
508
509
510        $('#poi-detail:not(.hidden) button.detail__close').trigger('click');
511        var name = input.attr('name');
512        var value = name === 'q' ? '' : input.val();
513        var layerName = '';
514
515
516        that.totalLayersLoading += 1;
517        $.ajax({
518            method: 'GET',
519            async: true,
520            url: '/Streetmap/MapData?' + encodeURIComponent(name) + '=' + encodeURIComponent(value),
521            dataType: 'json'
522        }).done(function (json) {
523            if (json == null || json.length == 0) {
524                that.totalLayersLoaded += 1;
525            } else {
526
527                that.parseData(name, value, json, layerName);
528            }
529
530        }).fail(function (e) { console.log(e); });
531
532    },
533    unloadLayer: function (input) {
534        var that = this;
535        var name, value = '';
536
537        $('#poi-detail:not(.hidden) button.detail__close').trigger('click');
538        if (typeof (input) === 'string') {
539
540            name = input;
541            value = '';
542        } else {
543
544            name = input.attr('name');
545            value = input.val();
546        }
547        var layerName = name + (value !== '' ? '-' + value : '');
548
549        $('#pois [data-layer="' + layerName + '"]').remove();
550
551        var data = that.markerslayers.find(x => x.id === layerName);
552        if (data != null) {
553
554            that.updatePoiItemsCounter();
555            if (typeof (data) !== 'undefined' && data !== null) {
556                data.clearLayers();
557
558                var index = that.markerslayers.indexOf(data);
559                if (index !== -1) {
560                    that.markerslayers.splice(index, 1);
561                }
562            }
563
564
565        }
566
567        var shpData = that.markerslayers.find(x => x.id === 'shp-' + layerName);
568        if (shpData != null) {
569            that.map.removeLayer(shpData);
570            var shpIndex = that.markerslayers.indexOf(shpData);
571            if (shpIndex !== -1) {
572                that.markerslayers.splice(shpIndex, 1);
573            }
574        }
575
576    },
577    checkLoadedItems: function (source) {
578        var that = this;
579        //      console.log(source, that.totalLayersLoaded, that.totalLayersLoading);
580        if (that.totalLayersLoading > 0 && that.totalLayersLoading === that.totalLayersLoaded) {
581            that.setBoundsAllLayers();
582            that.totalLayersLoading = 0;
583            that.totalLayersLoaded = 0;
584        }
585    },
586    parseData: function (name, value, json, layerName) {
587        var that = this;
588        var layer = null;
589        var data = that.markerslayers.find(x => x.id === layerName);
590
591        if (typeof (data) !== 'undefined' && data !== null) {
592            layer = data;
593        } else {
594
595            //The maximum radius that a cluster will cover from the central marker (in pixels). Default 80.
596            //Decreasing will make more, smaller clusters.You can also use a function that accepts the current map zoom and returns the maximum cluster radius in pixels.
597            var radius = json != null && json.length === 1 && json[0].data !== null && json[0].data.indexOf('/file/gpx') > -1 ? 0 : 15;
598
599            layer = L.markerClusterGroup({
600                showCoverageOnHover: false,
601                zoomToBoundsOnClick: true,
602                removeOutsideVisibleBounds: false,
603                maxClusterRadius: radius
604            });
605
606            layer.addTo(that.map);
607            layer.id = name + '-' + value;
608            layer.isWms = name === 'default-location';
609           
610            that.markerslayers.push(layer);
611        }
612
613        var hasPois = false;
614        var poiItems = [];
615        for (var i = 0; i < json.length; i++) {
616            var data = json[i];
617            if (data.data !== null) {
618                if (data.data.indexOf('[') == 0) {
619                    that.addPolygon(data, layer, 0.4);
620
621                    that.totalLayersLoaded += 1;
622                    that.checkLoadedItems('polygon');
623
624                } else if (data.data.indexOf('/wms') > -1) {
625
626                    that.doWms(data, layer);
627                } else {
628                    onlyPOIs = false;
629                    that.dataViaAjax(data, layer);
630
631                }
632            }
633            if (typeof (data.pointOfInterest) !== 'undefined' && data.pointOfInterest !== null && data.pointOfInterest.lat !== null) {
634
635                var m = that.addMarker(data, layer);
636                if (m != null) {
637                    hasPois = true;
638                    layer.addLayer(m);
639                    if (data.title !== '') {
640                        data.layerName = layer.id;
641                        data.pid = 'item-' + data.moduleID + '-' + data.id;
642                        poiItems.push(that.poiItemsTemplate.render(data)); //render poi items
643                    }
644                }
645
646            }
647
648        }
649        that.addPoiList(poiItems);
650
651        if (hasPois) {
652
653            that.totalLayersLoaded += 1;
654            that.checkLoadedItems('parsedata ' + layerName + ' ' + name + ' value: ' + value);
655        }
656
657    },
658    addMarker: function (data, layer) {
659        var that = this;
660
661        if (data.pointOfInterest.lng > 0 && data.pointOfInterest.lat > 0) {
662
663            var settings = { title: data.title, alt: data.title };
664            if (!data.title) {
665                // No accessible name available -> keep it out of the tab order / a11y tree
666                settings.keyboard = false;
667                settings.interactive = false;
668            }
669            if (data.moduleID) {
670                settings.pid = 'item-' + data.moduleID + '-' + data.id;
671            }
672
673
674
675            if (data.layers != null && data.layers.length > 0) {
676                var item = data.layers[0];
677                var color = item.iconColor == null ? that.defaultColor : item.iconColor;
678                var logo = typeof (item.logo) !== 'undefined' ? item.logo : '';
679                //https://codepen.io/localhorst/pen/yppoKO
680
681
682                settings.icon = that.createDivIcon(logo, color, item.icon, settings.pid);
683
684            }
685
686            var marker = new L.marker([data.pointOfInterest.lat, data.pointOfInterest.lng], settings);
687
688            if (data.title !== '') {
689                marker.bindTooltip(data.title, { direction: 'bottom', opacity: 0.9, maxWidth: 100 });
690
691                that.addMarkerClick(marker, data);
692
693
694            }
695            marker.addTo(layer);
696
697            return marker;
698        }
699
700    },
701    addMarkerClick: function (markerObject, data) {
702        var that = this;
703
704        markerObject.on('click', function (marker) {
705            var hasChange = false;
706            if (marker.sourceTarget._icon !== undefined && marker.sourceTarget._icon !== null) {
707
708                var icon = marker.sourceTarget._icon.firstChild;
709                if (icon != null) {
710                    var isActive = icon.classList.contains('active');
711                    $('.poi-svg__wrapper').removeClass('active');
712                    if (isActive) {
713
714                        that.closeDetail();
715                    } else {
716                        that.showPoiDetail(data);
717                        icon.classList.add('active');
718                    }
719                    hasChange = true;
720                }
721            }
722
723            if (!hasChange) {
724
725                that.showPoiDetail(data, marker);
726            }
727        });
728
729    },
730    createDivIcon: function (logo, color, icon, id) {
731        var that = this;
732
733        if (icon === null) {
734            icon = '/global/icons/global-line.svg#map-pin-2';
735
736        }
737        if (color === null || color === '') {
738            color = that.defaultColor;
739        }
740        var poiHtml = '<div class="poi-svg__wrapper" style="--poi-background-color:' + color + ';"> <div class="poi-svg__holder" ><svg class="poi-svg__icon" ' + (id ? 'data-id="' + id + '"' : '') + '><use href="' + icon + '"  ></use></svg></div></div>';
741
742        var wrapperWidth = 64, wrapperHeight = 77, badgeCenter = 32;
743        var logoOffset = 0;
744        if (logo !== '') {
745
746            var logoDisplayWidth = 120;
747            var logoHeight = 75;
748            var img = document.querySelector('img[src="' + logo + '"]');
749            if (img != null && img.naturalWidth) {
750                logoHeight = Math.round(logoDisplayWidth * (img.naturalHeight / img.naturalWidth));
751            }
752            logoOffset = logoHeight + 20;
753            logo = '<div class="logo"><img src="' + logo + '" alt="" /></div>';
754        }
755
756        return L.divIcon({
757            className: "poi",
758            html: logo + poiHtml,
759            iconSize: [wrapperWidth, logoOffset + wrapperHeight],
760            iconAnchor: [badgeCenter, logoOffset + badgeCenter],
761            popupAnchor: [0, -28]
762        });
763    },
764    closeDetail: function () {
765        var poiDetail = $('#poi-detail');
766        poiDetail.addClass('hidden');
767        poiDetail.attr('aria-hidden', 'true');
768        poiDetail.removeAttr('data-id');
769        poiDetail.html('');
770        $('#lst-pois .item.active,.poi-svg__wrapper.active').removeClass('active');
771    },
772    doWms: function (data, layer) {
773        //more layers add
774        //https://metadata.vlaanderen.be/srv/dut/catalog.search#/search?from=1&to=30
775        //
776        var that = this;
777        that.setMessagebox(that.translateKey('loading'));
778        layer.isWms = true;
779        var url = data.data;
780        var layerspart = url.split('?layers=');
781        if (layerspart.length > 1) {
782            url = layerspart[0] + '?';
783        }
784        var wmsLayer = L.tileLayer.betterWms(url,
785            {
786                layers: layerspart.length > 1 ? layerspart[1] : '',
787                version: '1.3.0',
788                format: 'image/png',
789                transparent: true
790            }).addTo(layer);
791
792
793
794
795        wmsLayer.bringToFront();
796        wmsLayer.on('load', function (event) {
797            //  that.totalLayersLoaded += 1;
798            //    that.checkLoadedItems();
799            that.removeMessagebox();
800        });
801    },
802    dataViaAjax: function (layerData, layer) {
803        var url = layerData.data;
804        if (url !== '') {
805                  var that = this;
806             if (url.indexOf('/file/download/') > -1) {
807                that.loadShpFile(url,layer,layerData);
808                 return;
809              } 
810
811            that.setMessagebox(that.translateKey('loading'));
812            if (url.indexOf('/ogc/') > -1) {
813                layer.isWms = true;
814            }
815            console.log(url);
816            $.ajax(url, {
817                success: function (data) {
818                     if (url.indexOf('/ogc/') > -1) {
819                        that.parseOGC(data, layer, layerData);
820                    } else if (url.indexOf('/file/kml') > -1) {
821                        that.parseKml(data, layer, layerData);
822
823
824                    } else if (url.indexOf('/file/gpx') > -1) {
825                        var color = layerData.color == null ? that.defaultColor : layerData.color;
826                        if (layerData.icon === undefined || layerData.icon === null) {
827                            layerData.icon = '/global/icons/global-line.svg#map-pin-2';
828                        }
829
830                        var track = new L.GPX(data,
831                            {
832                                async: true,
833                                polyline_options: { color: color, layerData: layerData, weight: 5 },
834                                marker_options: { icon: layerData.icon, wptIconUrls: null }
835                            }
836                        ).on('loaded', function (e) {
837                            track.addTo(layer);
838                            that.totalLayersLoaded += 1;
839                            that.checkLoadedItems('gpx');
840                            that.removeMessagebox();
841                        }).on('addpoint', function (e) {
842
843                            if (e.point_type == 'start' || e.point_type == 'end') {
844                                var data = that.setGpxData(e.point.options, e.target, layerData);
845                                //     that.addGpxElevation(data, e);
846                                e.point.on('click', function (ev) {
847                                    that.showGpxPoi(data);
848                                });
849                            }
850                        }).on('addline', function (e) {
851                            var data = that.setGpxData(e.sourceTarget.options, e.target, layerData);
852                            e.line.on('click', function (ev) {
853                                that.showGpxPoi(data);
854                            });
855                        });
856
857                    }
858                }
859            });
860        }
861    },
862    showGpxPoi: function (data) {
863        var that = this;
864        if (typeof (data) !== 'undefined' && data.title !== '') {
865            if (typeof (data.description) !== 'undefined' && data.description.indexOf('https://') === 0) {
866                data.description = '<a href="' + data.description + '" target="_blank"><span>' + data.description + '</span></a>';
867            }
868            that.showPoiDetail(data);
869        }
870    },
871    setGpxData: function (data, gpxLayer, layerData) {
872        data.title = gpxLayer.get_name();
873        data.description = gpxLayer.get_desc();
874
875        if ((typeof (data.description) === 'undefined' || data.description === '') && typeof (layerData) !== 'undefined') {
876            data.description = layerData.description;
877        }
878        return data;
879    },
880    addGpxElevation: function (data, e) {
881        var that = this;
882        const xmlDoc = e.target._gpx;
883
884        const elevationData = [];
885        const trackPoints = xmlDoc.querySelectorAll('trkpt');
886        trackPoints.forEach((point, index) => {
887            const lat = parseFloat(point.getAttribute('lat'));
888            const lon = parseFloat(point.getAttribute('lon'));
889            const eleElement = point.querySelector('ele');
890            const timeElement = point.querySelector('time');
891
892            if (eleElement) {
893                elevationData.push({
894                    index: index,
895                    latitude: lat,
896                    longitude: lon,
897                    elevation: parseFloat(eleElement.textContent)
898                });
899            }
900        });
901
902        if (elevationData.length === 0) {
903            const waypoints = xmlDoc.querySelectorAll('wpt');
904            waypoints.forEach((point, index) => {
905                const lat = parseFloat(point.getAttribute('lat'));
906                const lon = parseFloat(point.getAttribute('lon'));
907                const eleElement = point.querySelector('ele');
908
909                if (eleElement) {
910                    elevationData.push({
911                        index: index,
912                        latitude: lat,
913                        longitude: lon,
914                        elevation: parseFloat(eleElement.textContent),
915
916                    });
917                }
918            });
919        }
920        if (elevationData.length == 0)
921            return;
922        data.description += that.displayResults(elevationData);
923    },
924
925    displayResults: function (elevationData, stats) {
926
927        let html = `        
928        <h3>Hoogte meters</h3>
929        <table border="1">
930            <tr>
931                <th>Punt</th>
932                <th>Lat</th>
933                <th>Lng</th>
934                <th>Hoogte (m)</th>
935            </tr>
936    `;
937
938        elevationData.slice(0, 10).forEach((point, index) => {
939            html += `
940            <tr>
941                <td>${index + 1}</td>
942                <td>${point.latitude.toFixed(6)}</td>
943                <td>${point.longitude.toFixed(6)}</td>
944                <td>${point.elevation}</td>
945            </tr>
946        `;
947        });
948
949        html += '</table>';
950        return html;
951    },
952    parseOGC: function (ogcdata, layer, layerData) {
953
954        if (ogcdata !== null && typeof (ogcdata.features) !== 'undefined') {
955
956            var that = this;
957            layerData.isWms = true;
958            layerData.iconColor = layerData.color == null ? that.defaultColor : layerData.color;
959            if (layerData.icon === undefined || layerData.icon === null) {
960                layerData.icon = '/global/icons/global-line.svg#map-pin-2';
961            }
962
963            var poiItems = [];
964            var seenOgcIds = new Set();
965            for (var i = 0; i < ogcdata.features.length; i++) {
966
967                var item = ogcdata.features[i];
968                var title = that.setOgcTitle(item.properties);
969                var ogcDetailURL = that.setOgcDeailURL(item.properties);
970                var ogcID = that.setOgcId(item.properties);
971                var geometryType = item.geometry.type;
972                var coords = item.geometry.coordinates;
973
974                switch (geometryType) {
975                    case 'Point':
976                        if (seenOgcIds.has(ogcID)) break;
977                        seenOgcIds.add(ogcID);
978                        var dataList = {
979                            title: title,
980                            id: ogcID,
981                            layerName: layer.id,
982                            moduleID: -4,
983                            pointOfInterest: { lat: coords[1], lng: coords[0] },
984                            pid: 'item--4-' + ogcID,
985                            layers: [layerData],
986                            ogcDetailURL: ogcDetailURL
987                        };
988                        var m = that.addMarker(dataList, layer);
989                        layer.addLayer(m);
990                        poiItems.push(that.poiItemsTemplate.render(dataList));
991
992                        break;
993                    case 'Polygon':
994                    case 'MultiPolygon':
995
996                        that.addPolygon({ data: coords, color: layerData.iconColor, title: title }, layer, 1);
997                        break;
998                    default:
999                        console.warn('no impl', item);
1000                        break;
1001                }
1002
1003            }
1004
1005            if (poiItems.length > 0) {
1006                that.addPoiList(poiItems);
1007            }
1008
1009            that.totalLayersLoaded += 1;
1010            that.checkLoadedItems('ogc');
1011            that.removeMessagebox();
1012        }
1013    },
1014    setOgcTitle: function (data) {
1015
1016        if (data.title != null)
1017            return data.title;
1018
1019        if (data.Title != null)
1020            return data.Title;
1021
1022        if (data.HindranceDescription != null)
1023            return data.HindranceDescription;
1024
1025        if (data.Description != null)
1026            return data.Description;
1027
1028
1029
1030        if (data.Consequence != null)
1031            return data.Consequence;
1032
1033        if (data.Consequences != null)
1034            return data.Consequences;
1035
1036        return 'POI';
1037    },
1038    setOgcId: function (data) {
1039
1040        if (data.HindranceGipodId != null)
1041            return data.HindranceGipodId;
1042
1043
1044        if (data.GipodId != null)
1045            return data.GipodId;
1046
1047        return 0;
1048    },
1049    setOgcDeailURL: function (data) {
1050
1051        if (data.HindranceGipodId != null)
1052            return 'https://geo.api.vlaanderen.be/GIPOD/ogc/features/v1/collections/HINDER/items?f=application%2Fgeo%2Bjson&filter=HindranceGipodId %3D' + data.HindranceGipodId;
1053
1054
1055        if (data.GipodId != null)
1056            return 'https://geo.api.vlaanderen.be/GIPOD/ogc/features/v1/collections/INNAME/items?f=application%2Fgeo%2Bjson&filter=GipodId %3D' + data.GipodId;
1057
1058        return null;
1059    },
1060        loadShpFile:function (url,layerToAdd,layerData) {
1061        var that =this;
1062        if(url.indexOf('.zip') === -1)
1063        url +='.zip';
1064
1065        var shpId = 'shp-' + layerToAdd.id;
1066       that.setMessagebox(that.translateKey('loading'));
1067
1068        that.unloadLayer(shpId);
1069           layerData.color == null ? that.defaultColor : layerData.color;
1070                        if (layerData.icon === undefined || layerData.icon === null) {
1071                            layerData.icon = '/global/icons/global-line.svg#map-pin-2';
1072                        }
1073         var shpfile = new L.Shapefile(url, {
1074            importUrl: '/global/js/streetmap/leaflet/shp.js',
1075            pointToLayer: function (feature, latlng) {
1076                return L.marker(latlng, {
1077                    icon: that.createDivIcon('', layerData.color, layerData.icon)
1078                });
1079            },
1080			onEachFeature: function(feature, layer) {
1081				if (feature.properties) {
1082					layer.bindPopup(Object.keys(feature.properties).map(function(k) {
1083						return k + ": " + feature.properties[k];
1084					}).join("<br />"), {
1085						maxHeight: 200
1086					});
1087				}
1088			}
1089		});
1090        shpfile.id = shpId ;
1091		shpfile.addTo(that.map); //that.markersLayer
1092        shpfile.once("data:loaded", function() {
1093
1094          that.removeMessagebox();
1095          if (shpfile.getBounds().isValid()) {
1096              that.map.fitBounds(shpfile.getBounds(), { padding: [2, 2] });
1097          }
1098		 });
1099        that.markerslayers.push(shpfile);
1100    },
1101    parseKml: function (xml, layer, layerData) {
1102        if (xml !== '') {
1103
1104            var that = this;
1105            layerData.iconColor = layerData.color == null ? that.defaultColor : layerData.color;
1106            if (layerData.icon === undefined || layerData.icon === null) {
1107                layerData.icon = '/global/icons/global-line.svg#map-pin-2';
1108            }
1109            var poiItems = [];
1110            var idx = 0;
1111            var lineColors = that.xmlAllLineColors(xml);
1112
1113            var Placemarks = xml.getElementsByTagName('Placemark');
1114            for (var p = 0; p < Placemarks.length; p++) {
1115                var placemark = Placemarks[p];
1116                var title = that.getXmlValue(placemark, 'name');
1117                var description = that.getXmlValue(placemark, 'description');
1118                var point = placemark.getElementsByTagName('Point');
1119
1120                if (point.length) {
1121                    var coords = that.getXmlValue(point[0], 'coordinates').split(',');
1122
1123                    var data = {
1124                        title: title,
1125                        description: description,
1126                        id: idx,
1127                        moduleID: -3,
1128                        pointOfInterest: { lat: coords[1], lng: coords[0] },
1129                        layerName: layer.id,
1130                        pid: 'item--3-' + idx,
1131                        layers: [layerData]
1132                    };
1133                    var m = that.addMarker(data, layer);
1134                    layer.addLayer(m);
1135                    poiItems.push(that.poiItemsTemplate.render(data));
1136                    idx++;
1137                }
1138                var lineString = placemark.getElementsByTagName('LineString');
1139                if (lineString.length) {
1140
1141                    var color = layerData.iconColor;
1142                    if (lineColors.length > 1) {
1143                        var styleID = that.getXmlValue(placemark, 'styleUrl');
1144                        if (styleID != null && styleID !== '') {
1145                            var lineColor = lineColors.find(x => x.id === styleID.replace('#', ''));
1146                            if (lineColor != null) {
1147                                color = lineColor.color;
1148                            }
1149                        }
1150                    }
1151
1152                    for (var i = 0; i < lineString.length; i++) {
1153
1154                        var latlngs = that.getXmlCoords(lineString[i].getElementsByTagName('coordinates'));
1155
1156                        that.addPolyline({ data: [latlngs], color: color, title: title, description: description }, layer, 1);
1157                    }
1158
1159
1160                }
1161                var polygon = placemark.getElementsByTagName('Polygon');
1162                if (polygon.length) {
1163
1164                    var latlngs = that.getXmlCoords(polygon[0].getElementsByTagName('coordinates'));
1165
1166                    that.addPolygon({ data: [latlngs], color: that.getKmlPolyStyle(xml, placemark, layerData), title: title, description: description }, layer, 1);
1167
1168                }
1169            }
1170
1171            if (poiItems.length > 0) {
1172                that.addPoiList(poiItems);
1173            }
1174
1175            that.totalLayersLoaded += 1;
1176            that.checkLoadedItems('kml');
1177            that.removeMessagebox();
1178
1179        }
1180    },
1181    xmlAllLineColors: function (xml) {
1182        var colors = [];
1183
1184        var that = this;
1185        var styles = xml.getElementsByTagName('Style');
1186
1187        if (styles.length) {
1188            for (var i = 0; i < styles.length; i++) {
1189                var style = styles[i];
1190                var lineColor = that.xmlLineStyleColor(style);
1191
1192                if (lineColor !== '') {
1193                    var styleName = style.getAttribute('id');
1194                    colors.push({ id: styleName, color: lineColor });
1195                }
1196            }
1197        }
1198
1199
1200        var styleMaps = xml.getElementsByTagName('StyleMap');
1201
1202        for (var i = 0; i < styleMaps.length; i++) {
1203            var styleMap = styleMaps[i];
1204            var pairs = styleMap.getElementsByTagName('Pair');
1205
1206            if (pairs.length) {
1207                for (var p = 0; p < pairs.length; p++) {
1208                    var pair = pairs[p];
1209                    var key = that.getXmlValue(pair, 'key');
1210                    if (key === 'normal') {
1211
1212                        var styleUrl = that.getXmlValue(pair, 'styleUrl');
1213                        if (styleUrl !== '') {
1214                            var style = xml.getElementById(styleUrl.replace('#', ''));
1215                            var lineColor = that.xmlLineStyleColor(style);
1216                            if (lineColor !== '') {
1217                                var styleName = styleMap.getAttribute('id');
1218
1219                                colors.push({ id: styleName, color: lineColor });
1220                            }
1221                        }
1222                    }
1223                }
1224            }
1225        }
1226        return colors;
1227    },
1228    getKmlPolyStyle: function (xml, placemark, layerData) {
1229        var that = this;
1230        var color = layerData.iconColor;
1231        var styleID = that.getXmlValue(placemark, 'styleUrl');
1232        if (styleID != null && styleID !== '') {
1233            var style = xml.getElementById(styleID.replace('#', ''));
1234            if (style != null) {
1235                var pl = style.getElementsByTagName('PolyStyle');
1236                if (pl != null) {
1237                    var color = that.parseKmlColor(that.getXmlValue(pl[0], 'color'));
1238                }
1239            }
1240        } else {
1241
1242            var LineColor = that.xmlLineStyleColor(placemark);
1243            if (LineColor !== '') {
1244                color = LineColor;
1245            }
1246
1247        }
1248
1249        if (that.isColorTooLight(color)) {
1250            color = '#000000';
1251        }
1252        return color;
1253    },
1254    xmlLineStyleColor: function (node) {
1255        if (node == null)
1256            return '';
1257
1258        var that = this;
1259        var color = '';
1260        var lineStyle = node.getElementsByTagName('LineStyle');
1261        if (lineStyle.length) {
1262            var lineColor = that.getXmlValue(lineStyle[0], 'color');
1263            if (lineColor !== '') {
1264
1265                color = that.parseKmlColor(lineColor);
1266            }
1267        }
1268        return color;
1269    },
1270    parseKmlColor: function (color) {
1271        return '#' + color.substring(6, 8) + color.substring(4, 6) + color.substring(2, 4);
1272    },
1273    getXmlCoords: function (elcoords) {
1274
1275        var latlngs = [];
1276        var coords = elcoords[0].textContent.split(/[\s\n]+/);
1277        for (var i = 0; i < coords.length; i++) {
1278            var c = coords[i].split(',');
1279            if (c.length > 1) {
1280
1281                latlngs.push([parseFloat(c[1]), parseFloat(c[0])]);
1282            }
1283        }
1284        return latlngs;
1285    },
1286    getXmlValue: function (elm, selector) {
1287        if (elm !== undefined) {
1288
1289            var tag = elm.getElementsByTagName(selector);
1290            if (tag.length) {
1291                return tag[0].textContent;
1292            }
1293        }
1294        return '';
1295    },
1296    showPoiDetail(data) {
1297        var that = this;
1298        var poiDetail = $('#poi-detail');
1299
1300        var isObject = typeof (data) === 'object';
1301        var html = '';
1302        if (isObject) {
1303            if (typeof (data.ogcDetailURL) !== 'undefined' && data.ogcDetailURL !== null && data.ogcDetailURL !== '') {
1304                that.showOGCDetailgeoJSON(data);
1305                data.description = '<div id="ogc-detail">' + LCPStreetmap.translateKey('loading') + '</div>';
1306            }
1307            html = that.infoPanelTemplate.render(data);
1308        } else {
1309            html = data;
1310        }
1311
1312        poiDetail.html(html);
1313        var infoText = $('.detail__info-text');
1314        infoText.find('a').attr('target', '_blank');
1315        if (infoText.length > 0 && (infoText.html().length > 500 && $('.detail__info > *:not(button)').length != 2)) {
1316
1317            infoText.addClass('hidden').attr('aria-hidden', 'true');
1318            $('.detail__info-leesmeer').removeClass('hidden');
1319
1320        }
1321        poiDetail.attr('data-id', data.pid);
1322        poiDetail.removeClass('hidden');
1323        poiDetail.attr('aria-hidden', 'false');
1324        $('#lst-pois .item.active,.poi-svg__wrapper.active').removeClass('active');
1325        $('#list' + data.pid).addClass('active');
1326    },
1327    showOGCDetailgeoJSON(data) {
1328        var that = this;
1329        var layer = data.layers[0];
1330        var polystyle = {
1331            fillColor: layer.color,
1332            weight: 3,
1333            opacity: 1,
1334            color: layer.color,  //Outline color
1335            fillOpacity: 0.7
1336        };
1337        $.getJSON(data.ogcDetailURL, function (json) {
1338
1339            var markersLayer = that.markerslayers.find(x => x.id === 'kaartlaagid-' + layer.id);
1340
1341            var seenOgcIds = new Set();
1342            for (var i = 0; i < json.features.length; i++) {
1343                var detail = json.features[i];
1344                var id = detail.geometry.id;
1345                if (seenOgcIds.has(id)) {
1346                    continue;
1347                }
1348                seenOgcIds.add(id);
1349
1350                var g = L.geoJSON(detail.geometry, { style: polystyle });
1351                g.addTo(markersLayer);
1351
1352            }
1353
1354
1355            that.map.fitBounds(g.getBounds(), { padding: [2, 2] });
1356            $('#ogc-detail').html(that.getOGCPropertiesASHtml(json));
1357        });
1358    },
1359    getOGCPropertiesASHtml(json) {
1360
1361        var that = this;
1362        var html = '';
1363        if (json.features === undefined || json.features.length == 0)
1364            return html;
1365
1366        var data = json.features[0].properties;
1367
1368
1369        var ingoreKeys = ['Description', 'Uri', 'HindranceDescription', 'HindranceConsequenceOf', 'HindranceURI', 'ZoneType', 'MobilityHindrances', 'GroundworkCategory', 'HindranceStatus','End'];
1370        for (let key in data) {
1371            if (data.hasOwnProperty(key) && data[key] != null) {  // To ensure the property is not inherited
1372                //check if ingoreKeys contains key
1373
1374                if (key.indexOf('Start')> -1) {
1375                    html += that.setGipodDates(data, json)   ;
1376                }
1377                else if (ingoreKeys.indexOf(key) === -1 && !key.endsWith('Id')) {
1378
1379                    var value = data[key];
1380                    if (value !== null && value !== '') {
1381
1382                        var objectType = typeof (value);
1383
1384                        var title = that.translateKey(that.mapGipodTranslateKeyToOldKeys('www-roadworks-' + key.toLowerCase()));
1385                        if (title !== '') {
1386                            html += '<strong>' + title + '</strong>';
1387                        }
1388                        value = that.formatValue(objectType, value);
1389                        if (key.toLowerCase().indexOf('email') > -1 && value.indexOf('@') > 0) {
1390                            value = '<a href="mailto:' + value + '" target="_blank">' + value + '</a>';
1391                        } else if (key.toLowerCase().indexOf('url') > -1 && value.indexOf('.') > 0) {
1392                            value = '<a href="' + value + '" target="_blank">' + value + '</a>';
1393                        }
1394                        html += '<div>' + value + '</div>';
1395                    }
1396                }
1397            }
1398        }
1399    
1400        return html;
1401    },
1402    setGipodDates: function (data, json) {
1403        var that = this;
1404        var html = '';
1405        var tot = ' ' + that.translateKey('www-to') + ' ';
1406        if (data.Start !== undefined) {
1407
1408        html += '<div><strong>' + that.translateKey('www-roadworks-startDateTime') + ' - ' + that.translateKey('www-roadworks-endDateTime') + '</strong><div>' + that.formatValue('datetime', data.Start)  + tot + that.formatValue('datetime', data.End) + '</div></div>';    
1409        }
1410
1411        if (json.features.length > 1) {
1412            html += '<details><summary class="btn-primary">' + that.translateKey('www-streetmap-other-dates') + '</summary>';
1413
1414            for (var i = 1; i < json.features.length; i++) {
1415                var data = json.features[i].properties;
1416                if (data.Start !== undefined) {
1417                    html += '<div>' + this.formatValue('datetime', data.Start) + tot + this.formatValue('datetime', data.End) + '</div>';
1418                }
1419            }
1420            html += '</details>';
1421        }
1422
1423        return html;
1424    },
1425    mapGipodTranslateKeyToOldKeys: function (key) {
1426        switch (key) {
1427            case 'www-roadworks-lastmodifiedon':
1428            case 'www-roadworks-hindrancelastmodifiedon':
1429                return 'www-roadworks-latestupdate';
1430            case 'www-roadworks-start':
1431            case 'www-roadworks-hindrancestart':
1432                return 'www-roadworks-startDateTime';
1433            case 'www-roadworks-end':
1434            case 'www-roadworks-hindranceend':
1435                return 'www-roadworks-endDateTime';
1436            case 'www-roadworks-publicdomainoccupancytypes':
1437                return 'www-roadworks-eventtype';
1438            case 'www-roadworks-contactorganisations':
1439            case 'www-roadworks-hindrancecontactorganisations':
1440                return 'www-roadworks-contactdetails';
1441            case 'www-roadworks-organisationname':
1442                return 'www-roadworks-organisation';
1443            case 'www-roadworks-telephone':
1444                return 'www-roadworks-phoneNumber1';
1445            case 'www-roadworks-hindranceowner':
1446                return 'www-roadworks-owner';
1447            case 'www-roadworks-consequences':
1448                return 'www-roadworks-effects';
1449            case 'www-roadworks-hindrancecreatedon':
1450                return 'www-roadworks-createdon';
1451            case 'www-roadworks-hindrancestatus':
1452                return 'www-roadworks-state';
1453            case 'www-roadworks-timeschedule':
1454                return 'www-roadworks-date-filter-title';
1455            case 'www-roadworks-severehindrance':
1456                return 'www-roadworks-hindrance-important';
1457            case 'www-roadworks-contactname':
1458                return '';
1459            case 'www-roadworks-contactname':
1460                return '';
1461            case 'www-roadworks-contactrole':
1462                return '';
1463            case '':
1464                return '';
1465            default:
1466                return key;
1467        }
1468    },
1469    formatValue: function (objectType, value) {
1470        var that = this;
1471        if (value == undefined || value == null || value === '')
1472            return '';
1473
1474
1475        if (objectType === 'string' && value.indexOf('[{"') === 0 && value.endsWith('"}]')) {
1476            value = JSON.parse(value);
1477            objectType = 'object';
1478        }
1479
1480        if (objectType === 'datetime') {
1481            var date = Date.parse(value);
1482            if (!isNaN(date)) {
1483                return new Date(date).toLocaleString('nl-BE', {
1484                 //   weekday: 'short',
1485                    year: 'numeric',
1486                    month: 'numeric',
1487                    day: 'numeric',
1488                    hour: '2-digit',
1489                    minute: '2-digit'
1490                });
1491            }
1492            return value;
1493        }
1494
1495        if (objectType === 'object') {
1496            var html = '';
1497
1498            if (Array.isArray(value)) {
1499                for (var i = 0; i < value.length; i++) {
1500                    html += that.getOGCPropertiesASHtml(value[i]);
1501                }
1502            } else {
1503
1504                for (const [key, v] of Object.entries(value)) {
1505                    if (v[key] != null && v[key] !== '') {
1506                        if (html != '') {
1507                            html += ' - ';
1508                        }
1509                        html += that.formatValue(v[key]);
1510                    }
1511                }
1512
1513            }
1514            return html;
1515        }
1516
1517        if (objectType == "boolean")
1518            return that.translateKey('www-roadworks-hindrance-important-' + (value ? 'yes' : 'no'));
1519
1520        if ((value.length >= 19 || value.length <= 23) && value.indexOf(':') > -1 && value.indexOf('-') > -1) {
1521            var date = Date.parse(value);
1522            if (!isNaN(date)) {
1523
1524
1525                return new Date(date).toLocaleString('nl-BE',
1526                    {
1527                        year: 'numeric',
1528                        month: 'numeric',
1529                        day: 'numeric',
1530                        hour: '2-digit',
1531                        minute: '2-digit'
1532                    });
1533            }
1534        }
1535
1536        value = value.replaceAll(';', '.<br/>');
1537
1538        return value;
1539    },
1540    addPolyline: function (obj, layer, opacity) {
1541        var that = this;
1542
1543        var polygonData = typeof (obj.data) === 'object' ? obj.data : JSON.parse(obj.data);
1544
1545        var color = obj.color;
1546        var latlngs = [];
1547        if (Array.isArray(polygonData) && polygonData.length == 2 && Array.isArray(polygonData[0]) && Array.isArray(polygonData[1])) {
1548            obj.data = polygonData[0];
1549            that.addPolygon(obj, layer, opacity);
1550            obj.data = polygonData[1];
1551            that.addPolygon(obj, layer, opacity);
1552
1553        } else if (Array.isArray(polygonData) && polygonData[0][0] < 10) {
1554            latlngs = that.invertLatLngs(polygonData);
1555        } else {
1556
1557            latlngs = polygonData;
1558        }
1559
1560        if (color == null || color === '')
1561            color = that.defaultColor;
1562
1563        if (opacity === undefined) {
1564            opacity = 0.4;
1565        }
1566
1567        var polylineOptions = { color: color, weight: 5 };
1568
1569
1570
1571        var polyline = L.polyline(latlngs, polylineOptions).addTo(layer);
1572
1573        if (obj.title != undefined && obj.title !== 'Grens' && obj.title !== 'Gemeentegrens' && obj.title !== '') {
1574            polyline.bindTooltip(obj.title, { direction: 'bottom', opacity: 0.9 });
1575
1576        }
1577        if (obj.description != undefined && obj.description !== null && obj.description !== '') {
1578
1579            polyline.on('click', function (polyline) {
1580                that.showPoiDetail(obj);
1581            });
1582        }
1583
1584        if (obj.description === undefined && obj.title === undefined) {
1585            polyline._path.classList.remove('leaflet-interactive'); //disable interactive stuff
1586        }
1587    },
1588    addPolygon: function (obj, layer, opacity) {
1589        var that = this;
1590
1591        var polygonData = typeof (obj.data) === 'object' ? obj.data : JSON.parse(obj.data);
1592
1593        var color = obj.color;
1594        var latlngs = [];
1595        if (Array.isArray(polygonData) && polygonData.length == 2 && Array.isArray(polygonData[0]) && Array.isArray(polygonData[1])) {
1596            obj.data = polygonData[0];
1597            that.addPolygon(obj, layer, opacity);
1598            obj.data = polygonData[1];
1599            that.addPolygon(obj, layer, opacity);
1600
1601        } else if (Array.isArray(polygonData) && polygonData[0][0] < 10) {
1602            latlngs = that.invertLatLngs(polygonData);
1603        } else {
1604
1605            latlngs = polygonData;
1606        }
1607
1608        if (color == null || color === '')
1609            color = that.defaultColor;
1610
1611        if (opacity === undefined) {
1612            opacity = 0.4;
1613        }
1614
1615        var polylineOptions = { color: color, weight: 4, opacity: opacity, invert: true };
1616
1617        var polygon = L.polygon(latlngs, polylineOptions).addTo(layer);
1618
1619        if (obj.title != undefined && obj.title !== 'Grens' && obj.title !== 'Gemeentegrens' && obj.title !== '') {
1620            polygon.bindTooltip(obj.title, { direction: 'bottom', opacity: 0.9 });
1621
1622        }
1623        if (obj.description != undefined && obj.description !== null && obj.description !== '') {
1624
1625            polygon.on('click', function (polygon) {
1626                that.showPoiDetail(obj);
1627            });
1628        }
1629
1630        if (obj.description === undefined && obj.title === undefined) {
1631            polygon._path.classList.remove('leaflet-interactive'); //disable interactive stuff
1632        }
1633    },
1634
1635    isColorTooLight: function (hex) {
1636
1637        if (hex === '' || hex === '#')
1638            return false;
1639
1640        hex = hex.replace(/^#/, '');
1641        if (hex.length === 3) {
1642            hex = hex.split('').map(function (h) {
1643                return h + h;
1644            }).join('');
1645        }
1646
1647        const bigint = parseInt(hex, 16);
1648        const r = (bigint >> 16) & 255;
1649        const g = (bigint >> 8) & 255;
1650        const b = bigint & 255;
1651
1652        let a = [r, g, b].map(function (v) {
1653            v /= 255;
1654            return (v <= 0.03928) ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
1655        });
1656
1657        var lum = 0.2126 * a[0] + 0.7152 * a[1] + 0.0722 * a[2];
1658
1659        return lum > 0.5;
1660    },
1661
1662    invertLatLngs: function (shape) {
1663        if (Array.isArray(shape[0][0])) {
1664            return shape.map(polygon => {
1665                return polygon.map(coords => {
1666                    return coords.map(coord => {
1667                        return [coord[1], coord[0]];
1668                    });
1669                });
1670            });
1671        } else {
1672            return shape.map(coord => {
1673                return [coord[1], coord[0]];
1674            });
1675        }
1676    },
1677    addPoiList: function (poiItems) {
1678        var that = this;
1679        if (poiItems != null && poiItems.length > 0) {
1680            $('#pois').append(poiItems.join(''));
1681            that.updatePoiItemsCounter();
1682        }
1683
1684    },
1685    updatePoiItemsCounter: function () {
1686        var noOfItems = $('#pois [data-layer]').length;
1687        var c = $('#pois-counter');
1688        var text = c.attr('data-' + (noOfItems == 1 ? 's' : 'm'));
1689        c.html(noOfItems + ' ' + text);
1690    },
1691    updateMap: function () {
1692        setTimeout(function () {
1693            LCPStreetmap.map.invalidateSize();
1694        }, 100);
1695    },
1696    setBoundsAllLayers: function () {
1697        var that = this;
1698        var bounds = L.latLngBounds();
1699        for (var i = 0; i < that.markerslayers.length; i++) {
1700            var layer = that.markerslayers[i];
1701            if (!layer.isWms) { //ignore wms layers
1702                if (typeof layer.getBounds === 'function') {
1703                    bounds.extend(layer.getBounds());
1704                }
1705            }
1706        }
1707
1708        if (bounds.isValid()) {
1709            that.map.fitBounds(bounds, { padding: [2, 2] });
1710        }
1711
1712    },
1713    reset: function () {
1714
1715        LCPStreetmap.map.remove();
1716        LCPStreetmap.markerslayers = [];
1717        LCPStreetmap.map = null;
1718        LCPStreetmap.init();
1719    },
1720    setMessagebox: function (msg) {
1721
1722        $('#streetmap-interaction-info').html(msg).attr('class', 'alertbox-loading');
1723
1724    },
1725    removeMessagebox: function () {
1726        $('#streetmap-interaction-info').attr('class', 'hidden').html('');
1727
1728
1729    },
1730    setNoOfActiveFilters: function () {
1731        $('span[filter-counter]').html($('#streetmap-filters-form input[type="checkbox"][data-menu="0"]:checked').length);
1732    },
1733    setBrowserHistory: function () {
1734        var that = this;
1735        var url = window.location.pathname;
1736        var form = $('#streetmap-filters-form');
1737        var arr = that.combineSerialisedFormData(form.serializeArray());
1738        var q = '';
1739        for (var i = 0; i < arr.length; i++) {
1740            var p = arr[i];
1741            if (p.value !== null && p.value !== '' && !p.name.endsWith('_submit') && p.value !== 'on') {
1742                if (q !== '') { q += '&'; }
1743                q += encodeURIComponent(p.name) + '=' + encodeURIComponent(p.value);
1744            }
1745        }
1746        url += (q !== '') ? '?' + q : '';
1747        window.history.replaceState(null, null, url);
1748
1749    },
1750    checkBtnsAttributionIntersection: function () {
1751        var attribution = $('.leaflet-control-attribution')[0].getBoundingClientRect();
1752        var btns = $('button[data-toggle-panel="lst-pois"],button[data-toggle-panel="lst-layers"]');
1753        btns.each(function () {
1754            var btn = $(this);
1755            var btnBoundingBox = btn[0].getBoundingClientRect();
1756
1757            if (!(attribution.right < btnBoundingBox.left ||
1758                attribution.left > btnBoundingBox.right ||
1759                attribution.bottom < btnBoundingBox.top ||
1760                attribution.top > btnBoundingBox.bottom)) {
1761                btn.css({ 'margin-bottom': (attribution.bottom - attribution.top) + 'px' });
1762            } else {
1763                btn.removeAttr('style');
1764            }
1765        });
1766    },
1767    translateKey(k) {
1768        var t = StreetmapTranslations.find(x => x.key.toLowerCase() === k.toLowerCase());
1769        if (t != null)
1770            return t.value;
1771
1772        return k;
1773
1774    },
1775    combineSerialisedFormData: function (arr) {
1776
1777        var dictCombinedKeys = {};
1778        for (var i = 0; i < arr.length; i++) {
1779            var strKey = arr[i].name;
1780            var strValue = arr[i].value;
1781
1782            if (strKey !== "" && strValue !== "") {
1783                if (typeof (dictCombinedKeys[strKey]) === "undefined") {
1784                    dictCombinedKeys[strKey] = strValue;
1785                }
1786                else {
1787                    dictCombinedKeys[strKey] += "," + strValue;
1788                }
1789            }
1790        }
1791
1792        var arrKeyValuePairs = [];
1793        for (var key in dictCombinedKeys) {
1794            if (dictCombinedKeys.hasOwnProperty(key)) {
1795                arrKeyValuePairs.push({ name: key, value: dictCombinedKeys[key] });
1796            }
1797        }
1798
1799        return arrKeyValuePairs;
1800    }
1801};
1802LCPStreetmap.init();
1803

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.