PageSourceSearch

https://memoriaparatodos.pt/scripts/OSM/functionOSM.js?t=639260251402555211

js memoriaparatodos.pt collected 2026-09-26 12:13:22 UTC 48,643 bytes, 1,290 lines download raw bytes

1/*global $f:false */
2var staM = getParameterByName("taM");
3var pathimage = spathimage;
4var markers = [];
5var map;
6
7// grupo de clusters
8var markersCluster;
9let markersByCoord = new Map();
10const existingIDs = new Set();
11
12var url = window.location.href;
13if (url.indexOf("/inweb/") > -1) {
14    pathimage = '../' + pathimage;
15}
16
17/**
18 * Get Content for infowindow
19 * @param {any} marker
20 * @param {any} surl
21 * @param {any} stipo
22 */
23function getCOSM(marker, surl, stipo) {
24
25    //console.log('getCOSM', marker, surl, stipo);
26    //console.log(marker);
27    //string title, string local, string stipo, string sta
28    $.ajax({
29        type: "POST",
30        contentType: "application/json; charset=utf-8",
31        url: surl + ".aspx/getInf",
32        data: "{'title': '" + marker.title + "','markerID': '" + marker.myCustomID + "','stipo':'" + stipo + "','staM':'" + staM + "'}",
33        dataType: "json",
34        success: function (data) {
35            //console.log(marker);
36            //console.log(surl);
37            //console.log(stipo);
38            //console.log(data);
39            //marker.bindPopup('<div class="info_window"><h2>' + marker.title + "</h2>" + data.d + '</div>');
40            openMarkerAt(marker, '<div class="info_window"><h5>' + marker.title + "</h5>" + data.d + '</div>'); 
41            //let popup = L.popup().setContent('<div class="info_window"><h2>' + marker.title + "</h2>" + data.d + '</div>').openOn(map);
42        },
43        failure: function (response) {
44            console.log("failure getCOSM",response.data);
45        }
46    });
47}
48
49/**
50 * alterar o icon
51 * @param {any} iconimg
52 * @param {any} param
53 * @returns
54 */
55function getColorMarkerOSM(iconimg, param) {
56    //console.log('getColorMarkerOSM');
57    //console.log('iconimg: ' + iconimg.options.iconUrl);
58    //console.log('param: '+param);
59    var _result = '';
60
61    if (iconimg.options.iconUrl.indexOf('local_aud') >= 0) {
62        if (param == 'select' || param == 'click') {
63            _result = 'images/mapa/local_aud_clicar.png';
64        }
65        //else if (param == 'click') {
66        //    _result = 'images/mapa/local_aud_clicar.png';
67        //}
68        else {
69            _result = 'images/mapa/local_aud.png';
70        }
71    }
72    else if (iconimg.options.iconUrl.indexOf('local_imv') >= 0) {
73        if (param == 'select' || param == 'click') {
74            _result = 'images/mapa/local_imv_clicar.png';
75        }
76        //else if (param == 'click') {
77        //    _result = 'images/mapa/local_imv_clicar.png';
78        //}
79        else {
80            _result = 'images/mapa/local_imv.png';
81        }
82    }
83
84    const myIcon = L.icon({
85        title: iconimg.options.title,
86        iconUrl: _result,
87        iconSize: [40, 40],
88        iconAnchor: [20, 40],   // metade da largura, altura total);
89    });
90
91    return myIcon;
92}
93
94/** 
95Constroi os pontos no mapa
96 * @param {any} _url - endereco web
97 * @returns
98*/
99function builtmapOSM(spage)
100{
101    //console.log('builtmapOSM');
102    $('#map_canvas').height($(window).height() - 150);
103    $('#centercol_all').height($(window).height() - 150);
104
105    // Inicializa o mapa
106    map = L.map('map_canvas').setView([coordx, coordy], _zoom);
107
108    // Adiciona o tile do OpenStreetMap
109    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
110        attribution: '' /*'Sistemas do Futuro'*/
111    }).addTo(map);
112
113    markers = [];
114    //markersCluster = L.markerClusterGroup(); 
115    markersCluster = L.markerClusterGroup({
116        iconCreateFunction: function (cluster) {
117
118            const _markers = cluster.getAllChildMarkers();
119            //console.log('builtmapOSM markersCluster', _markers.length);
120            //cluster.getAllChildMarkers().forEach(m => console.log(m.myID, m));
121
122            // Obter a primeira coordenada
123            const first = _markers[0].getLatLng();
124            // Verificar se todas as coordenadas são iguais
125            //const sameCoord = _markers.every(m => {
126            //    const pos = m.getLatLng();
127            //    return pos.lat === first.lat && pos.lng === first.lng;
128            //});
129            const sameCoord = _markers.every(m => {
130                const pos = m.getLatLng();
131                return almostEqual(pos.lat, first.lat) &&
132                    almostEqual(pos.lng, first.lng);
133            });
134
135            // cor da bolinha:
136            // - azul - todos na mesma coordenada
137            // - verde - cluster normal
138            //const color = sameCoord ? "azul" : "verde";
139            const color = sameCoord ? "#477ba4" : "#8cd160";
140
141            //console.log('builtmapOSM',color);
142            return L.divIcon({
143                html: `<div class="clusterBubble" style="background:${color}">${markers.length}</div>`,
144                className: '', // não usar classes default do Leaflet
145                iconSize: L.point(40, 40)
146            });
147        }
148    });
149
150    //{    spiderfyOnMaxZoom: true,
151    //    showCoverageOnHover: false,
152    //    zoomToBoundsOnClick: true
153    //});
154
155    var nome_ficheiro = 'googlemapsxml.aspx?';
156
157    jQuery.get(nome_ficheiro, {}, function (data) {
158        jQuery(data).find('marker').each(function () {
159            var markerXML = jQuery(this);
160
161            var id_ob = markerXML.attr('id_ob'); //pontos na mesma coordenada
162            var id_mark = markerXML.attr('id_mark'); //ponto unico na cooodenada 
163            var flag = markerXML.attr('flag');
164            var tip_b = markerXML.attr('tip_b');
165            var tit = markerXML.attr('tit');
166            var stipo = markerXML.attr('stipo');
167            var icon_image = markerXML.attr('menu');
168            var __ns = markerXML.attr("ns");
169            //console.log(id_ob);
170            /*console.log(icon_image);*/
171
172            //alterar o icon do marker
173            const myIcon = L.icon({
174                title: tit,
175                iconUrl: icon_image,
176                iconSize: [40, 40],
177                iconAnchor: [20, 40],   // metade da largura, altura total
178            });
179
180            // Adiciona o marcador
181            var marker = L.marker([markerXML.attr('lat'), markerXML.attr('lng')], { icon: myIcon }).bindPopup(tit);//.addTo(map);
182            marker.type = "point";
183            marker.myID = id_ob;  //juncao de pontos na mesma coordenada
184            marker.myCustomID = id_mark;//ponto mesmo clicado
185            marker.title = tit;
186            marker.mycategory = __ns;
187            markers.push(marker);
188            // Adicionar o mesmo marcador ao cluster
189            //console.log('builtmapOSM');
190            addMarkerCluster(marker);
191
192            //region click no marker - qd abre um fecha os outros todos e muda a cor
193            marker.on('click', function (event) {
194                //console.log('click builtmapOSM');
195                marker.setIcon(getColorMarkerOSM(marker.getIcon(),'click'));
196                getCOSM(marker,spage,stipo);
197            }); //endregion click no marker
198            //endregion click no marker
199
200            //endregion click no marker
201            marker.on('popupclose', function (event) {
202                marker.setIcon(getColorMarkerOSM(marker.getIcon(), 'no_select'));
203            }); 
204            //endregion click no marker
205
206            //region mouseover no marker
207                 //marker.on('mouseover',function(event){
208                 //    var _icon= marker.getIcon();
209                 //    if(_icon==getColorMarkerOSM(marker.getIcon(),'click')) { //icon click
210                 //    }
211                 //    else { //no_select
212                 //        marker.setIcon(getColorMarkerOSM(marker.getIcon(),'select'));
213                 //    }
214                 //}); //endregion mouseover no marker
215            
216                 //region mouseout no marker
217                 //marker.on('mouseout',function(event){
218                 //    var _icon= marker.getIcon();
219                 //    //if(openedInfoWindow == null) {
220                 //    //    marker.setIcon(getColorMarkerOSM(marker.getIcon(),'no_select'));
221                 //    //}
222                 //    //else { // a janela está aberta
223                 //        if(_icon==getColorMarkerOSM(marker.getIcon(),'no_select')) { //icon n select
224                 //        }
225                 //        else if(_icon==getColorMarkerOSM(marker.getIcon(),'select')) {; //mouseover
226                 //            marker.setIcon(getColorMarkerOSM(marker.getIcon(),'no_select'));
227                 //        }
228                 //        else { //select
229                 //            marker.setIcon(getColorMarkerOSM(marker.getIcon(),'click'));
230                 //        }
231                 //    //}
232                 //});//end region mouseout no marker
233
234          
235 if ($.isFunction($('#activity_pane').hideLoading)) {
236     $('#activity_pane').hideLoading();
237 }
238 $('#activity_pane').css('visibility', 'hidden');
239 $('#activity_pane').css('display', 'none');
240
241
242        }); //find marker
243    });
244}
245
246function almostEqual(a, b, epsilon = 0.0001) {
247    return Math.abs(a - b) < epsilon;
248}
249
250/**
251 * REl_CommonFunction showgooglemaps
252 * @param {any} coords
253 * @param {any} _zoom
254 */
255function initializeOSM(spage, id_o, coordx, coordy, _zoom, smap, nome_file) {
256
257    //console.log('initializeOSM');
258    if (document.getElementById(smap) != null) {
259        map = L.map('map_canvas').setView([coordx, coordy], _zoom);
260
261        // Adiciona o tile do OpenStreetMap
262        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
263            attribution: '' /*'Sistemas do Futuro'*/
264        }).addTo(map);
265        //markersCluster = L.markerClusterGroup();
266        markersCluster = L.markerClusterGroup({
267            iconCreateFunction: function (cluster) {
268
269                const _markers = cluster.getAllChildMarkers();
270                //console.log('initializeOSM', _markers.length);
271
272                //if (_markers.length < 8) {
273                //    cluster.getAllChildMarkers().forEach(m => console.log(m.myID, m.title, m.lat, m.lng));
274                //}
275                // Obter a primeira coordenada
276                const first = _markers[0].getLatLng();
277
278                const sameCoord = _markers.every(m => {
279                    const pos = m.getLatLng();
280                    return almostEqual(pos.lat, first.lat) &&
281                        almostEqual(pos.lng, first.lng);
282                });
283
284                //// Verificar se todas as coordenadas são iguais
285                //const sameCoord = _markers.every(m => {
286                //    const pos = m.getLatLng();
287                //    //if (pos.lat == '40.4385625' || pos.lat == '40.4386121') { 
288                //    //    console.log(m.title, pos.lat, pos.lng);
289                //    //    console.log(pos.lat === first.lat && pos.lng === first.lng);
290                //    //}
291                //    return pos.lat === first.lat && pos.lng === first.lng;
292                //});
293
294                // cor da bolinha:
295                // - azul - todos na mesma coordenada
296                // - verde - cluster normal
297                //const color = sameCoord ? "azul" : "verde";
298                const color = sameCoord ? "#477ba4" : "#8cd160";
299                //if (_markers.length < 8) {
300                //    console.log('initializeOSM', color,'  azul: #477ba4; verde: #8cd160');
301                //}
302                return L.divIcon({
303                    html: `<div class="clusterBubble" style="background:${color}">${_markers.length}</div>`,
304                    className: '', // não usar classes default do Leaflet
305                    iconSize: L.point(40, 40)
306                });
307            }
308        });
309
310        map.invalidateSize();
311        jQuery.get(nome_file, {}, function (data) {
312
313            jQuery(data).find("marker").each(function () {
314                var markerXML = jQuery(this);
315                var id_ob = markerXML.attr('id_i'); //pontos agregados na mesma coordenada
316                var id_mark = markerXML.attr("id_mark");// ponto unico na mesma coordenada
317                var flag = markerXML.attr("flag");
318                var tip_b = markerXML.attr("tip_b");
319                var icon_image = markerXML.attr("image");
320                var __ns = markerXML.attr("ns");
321
322                const myIcon = L.icon({
323                    iconUrl: icon_image,
324                    title: tip_b,
325                    iconSize: [40, 40],
326                    iconAnchor: [20, 40],   // metade da largura, altura total 
327                });
328
329                // Add marker - creates the marker
330                var marker = L.marker([markerXML.attr('lat'), markerXML.attr('lng')], { icon: myIcon });//.addTo(map);
331                //attaches a popup window to the marker
332                marker.bindPopup(tip_b);
333
334                //console.log('marker');
335                //console.log(marker);
336                marker.type = "point";
337                marker.myID = id_ob;//juncao de pontos na mesma coordenada
338                marker.myCustomID = id_mark;//ponto mesmo clicado
339                marker.title = tip_b;
340                marker.lat = markerXML.attr('lat');
341                marker.lng = markerXML.attr('lng');
342                marker.mycategory = __ns;
343                markers.push(marker);
344                // Adicionar o mesmo marcador ao cluster
345                //console.log('initializeOSM');
346                addMarkerCluster(marker);
347
348                //console.log('marker lat e lng');
349                //console.log(marker.lat);
350                //console.log(marker.lng);
351
352                //qd abre um fecha os outros todos e muda a cor
353                marker.on('click', function (event) {
354                    
355                    //console.log('click initializeOSM');
356                    //console.log(marker);
357                    getCMap(map, spage, marker, 'click', marker.mycategory);
358                }); //click marker
359
360            });//marker
361            }); //googlemaps.aspx
362
363        }//document.getElementById
364
365        //        google.maps.event.addListenerOnce(map, 'idle', function () {
366        map.invalidateSize();
367        //    map.setCenter(posicaoCenter);
368        //}
369    
370        
371        //fim initialize
372    //google.maps.visualRefresh = true;
373    //google.maps.event.addDomListener(window, 'load', initialize);
374    map.invalidateSize();
375}
376
377/* inicializar para a página itinerary */
378function initializeRot(coords, izoommamp, spathimg) {
379    markers = [];
380    const myArray = coords.split(",");
381    var coordx = myArray[0];
382    var coordy = myArray[1];
383
384    var _zoom = parseInt(izoommamp);
385
386    map = L.map('map_canvas').setView([coordx, coordy], _zoom);
387
388    // Adiciona o tile do OpenStreetMap
389    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
390        attribution: '' /*'Sistemas do Futuro'*/
391    }).addTo(map);
392    //markersCluster = L.markerClusterGroup();
393    markersCluster = L.markerClusterGroup({
394        iconCreateFunction: function (cluster) {
395
396            const _markers = cluster.getAllChildMarkers();
397            //console.log('initializeRot', _markers.length);
398            //cluster.getAllChildMarkers().forEach(m => console.log(m.myID, m));
399
400            // Obter a primeira coordenada
401            const first = _markers[0].getLatLng();
402            // Verificar se todas as coordenadas são iguais
403            const sameCoord = _markers.every(m => {
404                const pos = m.getLatLng();
405                return almostEqual(pos.lat, first.lat) &&
406                    almostEqual(pos.lng, first.lng);
407            });
408           
409            //const sameCoord = _markers.every(m => {
410            //    const pos = m.getLatLng();
411            //    return pos.lat === first.lat && pos.lng === first.lng;
412            //});
413
414            // cor da bolinha:
415            // - azul - todos na mesma coordenada
416            // - verde - cluster normal
417            //const color = sameCoord ? "azul" : "verde";
418            const color = sameCoord ? "#477ba4" : "#8cd160";
419            //console.log('initializeRot', color);
420            return L.divIcon({
421                html: `<div class="clusterBubble" style="background:${color}">${markers.length}</div>`,
422                className: '', // não usar classes default do Leaflet
423                iconSize: L.point(40, 40)
424            });
425        }
426    });
427    map.invalidateSize();
428
429    //rightclick
430    map.on('contextmenu', function (event) {
431        var myLatLng = event.latlng;
432
433        // Atualizar inputs
434        $('#cGPSX').val(myLatLng.lat);
435        $('#cGPSY').val(myLatLng.lng);
436
437        // remover marcadores existentes
438        markers.forEach(function (marker) {
439            map.removeLayer(marker);
440        });
441        markers = [];
442
443        // adicionar novo marcador
444        addMarker(spathimg, myLatLng);
445    });
446
447    // Create the search box and link it to the UI element.
448    var input = document.getElementById('pac-input');
449
450    var searchBox;
451    if (document.getElementById('pac-input') != null) {
452        map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
453        searchBox = new google.maps.places.SearchBox((input));
454    }
455
456    // Criar o geocoder (equivalente ao SearchBox)
457    var geocoder = L.Control.geocoder({
458        defaultMarkGeocode: false
459    }).addTo(map);
460
461    // Evento equivalente ao 'places_changed'
462    geocoder.on('markgeocode', function (e) {
463        var place = e.geocode;
464
465        // Limpar marcadores anteriores
466        markers.forEach(function (marker) { map.removeLayer(marker); });
467        markers = [];
468
469        // Limpar coordenadas
470        $('#cGPSX').val("");
471        document.getElementById('cGPSX').innerHTML = "";
472        $('#cGPSY').val("");
473        document.getElementById('cGPSY').innerHTML = "";
474
475        // Criar marcador com ícone
476        const myIcon = L.icon({
477            title: place.name,
478            iconUrl: '../' + spathimg + '/mapa/location.png',
479            //iconSize: [25, 25],
480            //iconAnchor: [12, 25]
481            iconSize: [40, 40],
482            iconAnchor: [20, 40],   // metade da largura, altura total
483        });
484
485        // Criar marcador para o resultado da pesquisa
486        var marker = L.marker(place.center, { icon: myIcon }).addTo(map);
487
488        // Evento de clique no marcador
489        marker.on('click', function (event) {
490            var myLatLng = event.latlng;
491
492            if (myLatLng.lat !== undefined) {
493                $('#cGPSX').val(myLatLng.lat);
494                document.getElementById('cGPSX').innerHTML = myLatLng.lat;
495            }
496
497            if (myLatLng.lng !== undefined) {
498                $('#cGPSY').val(myLatLng.lng);
499                document.getElementById('cGPSY').innerHTML = myLatLng.lng;
500            }
501
502            // Remover todos os marcadores para manter só 1
503            markers.forEach(m => map.removeLayer(m));
504            markers = [];
505
506            // Criar o marcador final (equivalente ao addMarker)
507            addMarker(spathimg, myLatLng);
508        });
509
510        markers.push(marker);
511
512        // Ajustar o mapa para o local (equivalente a bounds.extend)
513        map.fitBounds(place.bbox);
514    });
515
516        google.maps.event.addListener(marker, 'click', function (event) {
517            var myLatLng = event.latLng;
518            if (myLatLng.lat() != "undefined") {
519                $('#cGPSX').val(myLatLng.lat());
520                document.getElementById('cGPSX').innerHTML = myLatLng.lat();
521            }
522            if (myLatLng.lng() != "undefined") {
523                $('#cGPSY').val(myLatLng.lng());
524                document.getElementById('cGPSY').innerHTML = myLatLng.lng();
525            }
526            for (var i = 0, marker; marker = markers[i]; i++) {
527                marker.setMap(null);
528            }
529            addMarker(spathimg, myLatLng);
530        });
531
532        markers.push(marker);
533        bounds.extend(place.geometry.location);
534
535
536    // [END region_getplaces]
537
538
539        map.on('moveend', function () {
540            var bounds = map.getBounds();
541
542            // atualizar limites do geocoder (se o plugin suportar)
543            if (searchBox.setBounds) {
544                searchBox.setBounds(bounds);
545            }
546        });
547
548}
549function getCMap(map, spage, marker, param, markercat) {
550    //console.log("getCMap",map, spage, marker, param, markercat);
551    var sfieldname = getParameterByName('fieldname');
552    var _lista = getParameterByName('lista');
553    if (_lista == null || _lista == undefined) _lista = '';
554    var _idtemas = idt;
555    if ($('#idtemas').length > 0) _idtemas = idtemas.value;
556    if (_idtemas == null || _idtemas == undefined) _idtemas = '';
557    var _museu = getParameterByName('museu');
558    if (_museu == null || _museu == undefined) _museu = '';
559    var _idpr = getParameterByName('idpr');
560    if (_idpr == null || _idpr == undefined) _idpr = '';
561    var _idfield = getParameterByName('idfields');
562    if (_idfield == null || _idfield == undefined) _idfield = '';
563
564    $.ajax({
565        type: "POST",
566        contentType: "application/json; charset=utf-8",
567        url: spage + ".aspx/GetInf",
568        data: "{'markerid':'" + marker.myCustomID + "','_nsID':'" + markercat + "','_fieldname':'" + sfieldname + "','_lista':'" + _lista + "','_idt':'" + _idtemas + "','_museu':'" + _museu + "','_projecto_id':'" + _idpr + "','_idfield':'" + _idfield + "'}",
569        dataType: "json",
570        success: function (data) {
571            //console.log(data);
572            //console.log(marker.title);
573            //console.log(marker.lat);
574            //console.log(marker.lng);
575            //var _latlng = [marker.lat, marker.lng];
576            //marker.bindPopup('<div class="info_window"><h2>' + marker.title + "</h2>" + data.d + '</div>');
577            openMarkerAt(marker, '<div class="info_window"><h5>' + marker.title + "</h5>" + data.d + '</div>'); 
578            //console.log('sucess fim');
579        },
580        failure: function (response) {
581            console.log("failure getCMap", response);
582            //console.log(response.data);
583        }
584    });
585}
586
587function getCM(spage, markerid, param, markercat) {
588    //console.log('getCM 2', spage, markerid, param, markercat);
589    var sfieldname = getParameterByName('fieldname');
590    var _lista = getParameterByName('lista');
591    if (_lista == null || _lista == undefined) _lista = '';
592    var _idtemas = idt;
593    if ($('#idtemas').length > 0) _idtemas = idtemas.value;
594    if (_idtemas == null || _idtemas == undefined) _idtemas = '';
595    var _museu = getParameterByName('museu');
596    if (_museu == null || _museu == undefined) _museu = '';
597    var _idpr = getParameterByName('idpr');
598    if (_idpr == null || _idpr == undefined) _idpr = '';
599    var _idfield = getParameterByName('idfields');
600    if (_idfield == null || _idfield == undefined) _idfield = '';
601
602    $.ajax({
603        type: "POST",
604        contentType: "application/json; charset=utf-8",
605        url: spage + ".aspx/GetInf",
606        data: "{'markerid':'" + markerid + "','_nsID':'" + markercat + "','_fieldname':'" + sfieldname + "','_lista':'" + _lista + "','_idt':'" + _idtemas + "','_museu':'" + _museu + "','_projecto_id':'" + _idpr + "','_idfield':'" + _idfield + "'}",
607        dataType: "json",
608        success: function (data) {
609            //console.log("success", data);
610            //var _latlng = [marker.lat, marker.lng];
611            //console.log(markers);
612            //console.log("marker que cliquei",markerid);
613            for (var i = 0; i < markers.length; i++) {
614                //console.log(markers[i].myCustomID,markers[i].myID,  markers[i].myID.includes(markerid + ","), markers[i].myID.includes("," + markerid));
615
616                if (markers[i].myCustomID == markerid) {
617                //if (markers[i].myCustomID == markerid || markers[i].myID == markerid || markers[i].myID.includes(markerid + ",") || markers[i].myID.includes("," + markerid)) {
618                    //console.log(markers[i].myID, markers[i].myCustomID, markers[i].title);
619
620                    //markers[i].bindPopup('<div class="info_window"><h2>' + markers[i].title + "</h2>" + data.d + '</div>').openPopup();
621                    openMarkerAt(markers[i], '<div class="info_window"><h5>' + markers[i].title + "</h5>" + data.d + '</div>');                   
622
623                    return;
624                }
625            }
626
627            //console.log('sucess fim');
628        },
629        failure: function (response) {
630            console.log("failure getCM", response);
631            //console.log(response.data);
632        }
633    });
634}
635
636/**
637 * Encontrar o marcador pela posição (lat, lng)
638 * @param {any} lat
639 * @param {any} lng
640 * @returns
641 */
642function getMarkerByPosition(lat, lng) {
643    return markers.find(m => {
644        let pos = m.getLatLng();
645        return pos.lat == lat && pos.lng == lng;
646    });
647}
648
649/*
650Abrir o marcador dentro do cluster pela posição */
651function openMarkerAt(marker, informacao) {
652
653    //const allMarkers = markersCluster.getLayers();
654    //const allMarkers = markersCluster.getLayers().filter(m => m instanceof L.Marker);
655
656    //allMarkers.forEach(m => {
657    //    console.log(m.title, m.myID, m);
658    //});
659
660    if (!marker) {
661        console.warn("Nenhum marcador encontrado nesta coordenada");
662        return;
663    }
664
665    markersCluster.zoomToShowLayer(marker, function () {
666        /* markers[i].bindPopup('<div class="info_window"><h2>' + markers[i].title + "</h2>" + informacao + '</div>').openPopup(); */
667        //marker.openPopup();
668        marker.bindPopup(informacao).openPopup();
669    });
670}
671
672
673//abrir popups de todos os marcadores na mesma coordenad
674function openAllMarkersAt(lat, lng) {
675    const arr = getMarkersByCoord(lat, lng);
676    arr.forEach(m => {
677        markersCluster.zoomToShowLayer(m, function () {
678            m.openPopup();
679        });
680    });
681}
682
683
684function getMarkerByCoord(lat, lng, tolerance = 0.000001) {
685
686    var found = null;
687
688    markersCluster.eachLayer(function (layer) {
689        if (layer instanceof L.Marker) {
690            var pos = layer.getLatLng();
691
692            if (
693                Math.abs(pos.lat - lat) < tolerance &&
694                Math.abs(pos.lng - lng) < tolerance
695            ) {
696                found = layer;
697            }
698        }
699    });
700
701    return found;
702}
703
704
705/**
706 * Atualiza o mapa, apos escolher quais os tipos para aparecer
707 * @param {any} spage
708 */
709function UpdateMap(spage) {
710    //console.log("updatemap");
711    setMapOnAll();
712    var bsearchtext = document.getElementById('botao_pesquisa_submit').value;
713    //.replace("'","''")
714    //if (bsearchtext.indexOf("'") >= 0) bsearchtext = bsearchtext.replace(/'/gi, "\\'");
715    var _idtemas = '';
716    if ($('#idtemas').length > 0) {
717        _idtemas = idtemas.value;
718    }
719
720    if (_idtemas == null || _idtemas == undefined) _idtemas = '';
721    var _lista = getParameterByName('lista');
722    if (_lista == null || _lista == undefined) _lista = '';
723    var _fieldname = getParameterByName("fieldname");
724    if (_fieldname == null || _fieldname == undefined) _lista = '';
725
726    var _idfield = $('#idfields').val();
727    if (_idfield == null || _idfield == undefined) _idfield = '';
728    //console.log('_nsID');
729    //console.log(_ns);
730    //console.log('textencode bsearchtext');
731    //console.log(bsearchtext);
732    //console.log('_idt _idtemas');
733    //console.log(_idtemas);
734    //console.log('_lista');
735    //console.log(_lista);
736    //console.log('_fieldname');
737    //console.log(_fieldname);
738
739    var slang = getParameterByName('lang') || 'PO'; //idioma
740    var idpr = getParameterByName('idpr') || '0'; // project_id
741    //insite
742    var pid = getParameterByName('pid') || '0'; //id da página do insite
743
744    //console.log(bsearchtext);
745    //console.log(_idfield);
746    if (bsearchtext != '' || _idfield != '') {
747
748        //map = L.map('map_canvas').setView([coordx, coordy], _zoom);
749        map = L.map('map_canvas');
750
751        // Adiciona o tile do OpenStreetMap
752        L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
753            attribution: '' /*'Sistemas do Futuro'*/
754        }).addTo(map);
755        //markersCluster = L.markerClusterGroup();
756        markersCluster = L.markerClusterGroup({
757            iconCreateFunction: function (cluster) {
758
759                const _markers = cluster.getAllChildMarkers();
760                //console.log('UpdateMap', _markers.length);
761                //cluster.getAllChildMarkers().forEach(m => console.log(m.myID, m));
762
763                // Obter a primeira coordenada
764                const first = _markers[0].getLatLng();
765
766                 //Verificar se todas as coordenadas são iguais
767                //const sameCoord = _markers.every(m => {
768                //    const pos = m.getLatLng();
769                //    return pos.lat === first.lat && pos.lng === first.lng;
770                //});
771                const sameCoord = _markers.every(m => {
772                    const pos = m.getLatLng();
773                    return almostEqual(pos.lat, first.lat) &&
774                        almostEqual(pos.lng, first.lng);
775                });
776
777                // cor da bolinha:
778                // - azul - todos na mesma coordenada
779                // - verde - cluster normal
780                //const color = sameCoord ? "azul" : "verde";
781                const color = sameCoord ? "#477ba4" : "#8cd160";
782                //console.log('UpdateMap', color);
783                return L.divIcon({
784                    html: `<div class="clusterBubble" style="background:${color}">${_markers.length}</div>`,
785                    className: '', // não usar classes default do Leaflet
786                    iconSize: L.point(40, 40)
787                });
788            }
789        });
790        $.ajax({
791            type: "POST",
792            contentType: "application/json; charset=utf-8",
793            url: spage + '.aspx/GetUpdateMap',
794            data: "{'_nsID':'" + _ns + "','textencode':'" + bsearchtext.replace(/'/gi, "\\'") + "','_fieldname':'" + _fieldname + "','_lista':'" + _lista + "','_idt':'" + _idtemas + "','_idfield':'" + _idfield + "'}",
795            dataType: "json",
796            timeout: 20000,
797            autoFill: true,
798
799            success: function (data) {
800                //response(data.d);
801                //$('#map_canvas').html('');
802
803                markers = [];
804                //console.log('hihii');
805                var nome_ficheiro = "googlemapsxml.aspx?ns=" + _ns + "&lang=" + slang + "&idpr=" + idpr + "&pid=" + pid;
806                jQuery.get(nome_ficheiro, {}, function (data) {
807
808                    jQuery(data).find("marker").each(function () {
809                        var markerXML = jQuery(this);
810
811                        var id_ob = markerXML.attr("id_i");// ponto agregados na mesma coordenada
812                        var id_mark = markerXML.attr("id_mark"); // ponto unico na mesma coordenada
813                        var flag = markerXML.attr("flag");
814                        var tip_b = markerXML.attr("tip_b");
815                        var icon_image = markerXML.attr("image");
816                        var __ns = markerXML.attr("ns");
817
818                        const myIcon = L.icon({
819                            title: tip_b,
820                            iconUrl: icon_image,
821                            iconSize: [40, 40],//, iconSize: [100, 39]
822                            iconAnchor: [20, 40],   // metade da largura, altura total
823                        });
824
825                        // Adiciona o marcador
826                        var marker = L.marker([markerXML.attr('lat'), markerXML.attr('lng')], { icon: myIcon }).bindPopup(tip_b);//.addTo(map);
827                        marker.type = "point";
828                        marker.myID = id_ob;//juncao de pontos na mesma coordenada
829                        marker.myCustomID = id_mark;//ponto mesmo clicado
830                        marker.title = tip_b;
831                        marker.mycategory = __ns;
832                        markers.push(marker);
833                        // Adicionar o mesmo marcador ao cluster
834                        //console.log('UpdateMap');
835                        addMarkerCluster(marker);
836                       
837                        //console.log(marker);
838                        //qd abre um fecha os outros todos e muda a cor
839                        marker.on('click', function (event) {
840                            //console.log('Click 1');
841                            getCMap(map, spage, marker, 'click', marker.mycategory);
842
843                            map.invalidateSize();
844                        }); //click marker
845
846                        //fechar a janela
847                        //marker objecto
848                        //if (id_o != null) {
849                        //    posicaoCenter = new google.maps.LatLng(parseFloat(markerXML.attr("lat")), parseFloat(markerXML.attr("lng")));
850                        //}
851
852                    });//jquery marker
853
854                    //console.log(map);
855                    //console.log(marker_tmp);
856                    //console.log(openedInfoWindow);
857                    //console.log(openedInfoWindow_tmp);
858                    //if (id_o != null) {
859                    //    if (openedInfoWindow != null) openedInfoWindow_tmp.open(map, marker_tmp);
860                    //}
861                }); //googlemaps.aspx
862                //google.maps.event.addListenerOnce(map, 'idle', function () {
863                map.invalidateSize();
864                //    map.setCenter(posicaoCenter);
865                //});
866                //end sucess
867
868                //google.maps.visualRefresh = true;
869                //google.maps.event.addDomListener(window, 'load', initialize);
870                map.invalidateSize();
871
872            },
873            error: function (result) {
874                console.log("Error: " + result.status + " " + result.statusText);
875            },
876            failure: function (result) {
877                console.log("failure: " + result.status + " " + result.statusText);
878            }
879        });
880    }
881}
882
883
884
885//Tornar escolha do marcador possível
886function getMarkersByCoord(lat, lng) {
887    const key = coordKey(lat, lng);
888    return markersByCoord.get(key) || [];
889}
890
891//Arredondar para 6 casas é o padrão usado por GIS:
892function coordKey(lat, lng) {
893    return lat.toFixed(6) + "," + lng.toFixed(6);
894}
895
896/** Adicionar marcador sem duplicar e agregando corretamente
897 * Tudo fica organizado por coordenada
898 * @param {any} lat
899 * @param {any} lng
900 * @returns
901 */
902
903//markersCluster
904function addMarkerCluster(markerXML) {
905    const pos = markerXML.getLatLng();
906    //const key = coordKey(pos.lat, pos.lng);
907    const key = pos.lat + "," + pos.lng;
908    //// Se já existe marcador nesta coordenada, adiciona à lista
909    //if (markersByCoord.has(key)) {
910    //    markersByCoord.get(key).push(markerXML);
911    //} else {
912    //    markersByCoord.set(key, [markerXML]);
913    //}
914
915    // Guardar marcadores por coordenada
916    if (!markersByCoord.has(key)) {
917        markersByCoord.set(key, []);
918    }
919    markersByCoord.get(key).push(markerXML);
920
921    //if (!markersCluster.hasLayer(markerXML)) {
922    //    markersCluster.addLayer(markerXML);
923    //}
924
925    //adicionar uma marcador unico
926    if (!existingIDs.has(markerXML.myID)) {
927        if (!markersCluster.hasLayer(markerXML)) {
928            //if (pos.lat == '40.4385625' || pos.lat =='40.4386121')
929            //    console.log("Adicionado ao cluster:", markerXML.myID, markerXML.lat, markerXML.lng);
930            markersCluster.addLayer(markerXML);
931        }
932        existingIDs.add(markerXML.myID);
933    }
934
935    // Garantir que está no mapa
936    if (!map.hasLayer(markersCluster)) {
937        map.addLayer(markersCluster);
938    }
939
940    //if (addedPoints.has(key)) {
941    //    //console.log("Ponto já existe:", key);
942    //    return;
943    //}
944
945    //addedPoints.add(key);
946    /* ao carregar no cluster, mostra os titulos dos icons.*/
947    //markersCluster.on('clusterclick', function (a) {
948    //    let markers = a.layer.getAllChildMarkers();
949
950    //    markers.forEach(m => {
951    //        markersCluster.zoomToShowLayer(m, function () {
952    //            m.openPopup();
953    //        });
954    //    });
955    //});
956
957    // ao carregar no cluster, mostra os titulos dos icons.
958    /*markersCluster.on('clusterclick', function (a) {
959        let _markers = a.layer.getAllChildMarkers();
960        //teste
961        if (_markers.length < 10) {
962            let html = '<div class="info_window">';
963
964            _markers.forEach(m => {
965                html += '<h5>' + m.getLatLng() + '</h5>';
966            });
967
968            html += '</div>';
969
970            L.popup()
971                .setLatLng(a.latlng)
972                .setContent(html)
973                .openOn(map);
974        }
975        });
976        */
977}
978
979
980// Função equivalente ao addMarker(spathimg)
981function addMarker(iconPath, latlng) {
982    const myIcon = L.icon({
983        iconUrl: iconPath,
984        //iconSize: [32, 32], // ajusta conforme necessário
985        //iconAnchor: [16, 32]
986        iconSize: [40, 40],
987        iconAnchor: [20, 40],   // metade da largura, altura total
988
989    });
990
991    var marker = L.marker(latlng, { icon: myIcon }).addTo(map);
992
993    markers.push(marker);
994}
995
996
997/* #region blog */
998/* */
999function initializeMAP(coords, _zoom) {
1000    //console.log('initializeMAP');
1001    //console.log(coords);
1002    //console.log(_zoom);
1003    const myArray = coords.split(",");
1004    var coordx = myArray[0];
1005    var coordy = myArray[1];
1006    // Inicializa o mapa
1007    map = L.map('map_canvas').setView([coordx, coordy], _zoom);
1008
1009    // Adiciona o tile do OpenStreetMap
1010    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
1011        attribution: '' /*'Sistemas do Futuro'*/
1012    }).addTo(map);
1013    //markersCluster = L.markerClusterGroup();
1014    markersCluster = L.markerClusterGroup({
1015        iconCreateFunction: function (cluster) {
1016
1017            const _markers = cluster.getAllChildMarkers();
1018            //console.log('initializeMAP', _markers.length);
1019            //cluster.getAllChildMarkers().forEach(m => console.log(m.myID, m));
1020
1021            // Obter a primeira coordenada
1022            const first = _markers[0].getLatLng();
1023
1024            // Verificar se todas as coordenadas são iguais
1025            //const sameCoord = _markers.every(m => {
1026            //    const pos = m.getLatLng();
1027            //    return pos.lat === first.lat && pos.lng === first.lng;
1028            //});
1029            const sameCoord = _markers.every(m => {
1030                const pos = m.getLatLng();
1031                return almostEqual(pos.lat, first.lat) &&
1032                    almostEqual(pos.lng, first.lng);
1033            });
1034
1035            // cor da bolinha:
1036            // - azul - todos na mesma coordenada
1037            // - verde - cluster normal
1038            //const color = sameCoord ? "azul" : "verde";
1039            const color = sameCoord ? "#477ba4" : "#8cd160";
1040            //console.log('initializeMAP', color);
1041            return L.divIcon({
1042                html: `<div class="clusterBubble" style="background:${color}">${_markers.length}</div>`,
1043                className: '', // não usar classes default do Leaflet
1044                iconSize: L.point(40, 40)
1045            });
1046        }
1047    });
1048    let currentMarker = null;
1049
1050    // Add marker on right-click
1051    //Listens for right-click events
1052    map.on('contextmenu', function (e) {
1053        // Contains the latitude and longitude of the click.
1054        const latlng = e.latlng;
1055
1056        //alterar o icon do marker
1057        const myIcon = L.icon({
1058            title: tit,
1059            iconUrl: "../" + spathimage + "/mapa/location.png",
1060            iconSize: [40, 40],
1061            iconAnchor: [20, 40],   // metade da largura, altura total
1062        });
1063
1064        if (currentMarker) {
1065            map.removeLayer(currentMarker);
1066        }
1067
1068        //Adds a new marker at the clicked position.
1069        currentMarker = L.marker(latlng, { icon: myIcon });//.addTo(map);
1070        markers.push(currentMarker);
1071        // Adicionar o mesmo marcador ao cluster
1072        //console.log('initializeMAP');
1073        addMarkerCluster(currentMarker);
1074
1075        //currentMarker.bindPopup("Loading address...").openPopup();
1076        openMarkerAt(currentMarker, "Loading address..."); 
1077        
1078        // Reverse geocode using Nominatim
1079        fetch('https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat='+latlng.lat+'&lon='+latlng.lng+'')
1080            .then(response => response.json())
1081            .then(data => {
1082                //console.log('data');
1083                //console.log(data.display_name);
1084                const displayName = data.display_name || "Unknown location";
1085                currentMarker.setPopupContent(displayName);
1086            })
1087            .catch(error => {
1088                console.error("Reverse geocoding failed:", error);
1089                currentMarker.setPopupContent("Unable to fetch address.");
1090            });
1091            
1092    });
1093   
1094    // Create the search box and link it to the UI element.
1095    //var input = document.getElementById('pac-input');
1096
1097    //var searchBox;
1098    //if (document.getElementById('pac-input') != null) {
1099    //    map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
1100    //    searchBox = new google.maps.places.SearchBox((input));
1101    //}
1102
1103    // [START region_getplaces]
1104    // Listen for the event fired when the user selects an item from the
1105    // pick list. Retrieve the matching places for that item.
1106    /*
1107    marker.on('places_changed', function (event) {
1108        var places = searchBox.getPlaces();
1109
1110        for (var i = 0, marker; marker = markers[i]; i++) {
1111            marker.setMap(null);
1112        }
1113
1114        //limpar coordenadas
1115        $('#cGPSX').val("");
1116        document.getElementById('cGPSX').innerHTML = "";
1117        $('#cGPSY').val("");
1118        document.getElementById('cGPSY').innerHTML = "";
1119
1120        // For each place, get the icon, place name, and location.
1121        markers = [];
1122        var bounds = new google.maps.LatLngBounds();
1123        var place;
1124        for (var i = 0; place = places[i]; i++) {
1125
1126            var icon_image = "../" + spathimage + "/mapa/location.png";
1127            //alterar o icon do marker
1128            let customIcon = { iconUrl: icon_image }
1129            let myIcon = L.icon(customIcon);
1130            let iconOptions = {
1131                title: tit,
1132                icon: myIcon
1133                , iconSize: [71, 71]
1134            }
1135
1136            // Create a marker for each place.
1137            var marker = L.marker([place.geometry.location.lat, place.geometry.location.lng], iconOptions).bindPopup(place.name).addTo(map);
1138            marker.title = place.name;
1139
1140            marker.on('click', function (event) {
1141                console.log('Click initializeMap');
1142                var myLatLng = event.latLng;
1143                if (myLatLng.lat() != 'undefined') {
1144                    $('#cGPSX').val(myLatLng.lat());
1145                    document.getElementById('cGPSX').innerHTML = myLatLng.lat();
1146                }
1147                if (myLatLng.lng() != "undefined") {
1148                    $('#cGPSY').val(myLatLng.lng());
1149                    document.getElementById('cGPSY').innerHTML = myLatLng.lng();
1150                }
1151                for (var i = 0, marker; marker = markers[i]; i++) {
1152                    marker.setMap(null);
1153                }
1154                addMarker(spathimage);
1155            });
1156
1157            markers.push(marker);
1158            bounds.extend(place.geometry.location);
1159        }
1160
1161        if (places.length == 1 && place != undefined) {
1162            if (place.geometry.location.lat() != undefined) {
1163                $('#cGPSX').val(place.geometry.location.lat());
1164                document.getElementById('cGPSX').innerHTML = place.geometry.location.lat();
1165            }
1166            if (place.geometry.location.lng() != undefined) {
1167                $('#cGPSY').val(place.geometry.location.lng());
1168                document.getElementById('cGPSY').innerHTML = place.geometry.location.lng();
1169            }
1170        }
1171        else {
1172            alert('Selecione um ponto');
1173        }
1174        map.fitBounds(bounds);
1175    });*/
1176
1177    // Listen for "Enter" key in the input box
1178    document.getElementById('pac-input').addEventListener('keydown', function (e) {
1179        if (e.key === 'Enter') {
1180            e.preventDefault(); // prevent form submission
1181            searchPlace();
1182        }
1183    });
1184
1185  
1186    function searchPlace() {
1187        const place = document.getElementById("pac-input").value;
1188        if (!place) return console.log("Enter a place name.");
1189
1190        const url = 'https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(place);
1191
1192        fetch(url)
1193            .then(res => res.json())
1194            .then(data => {
1195                if (data.length === 0) {
1196                    alert("Place not found.");
1197                    return;
1198                }
1199
1200                if (currentMarker) {
1201                    map.removeLayer(currentMarker);
1202                }
1203
1204                const { lat, lon, display_name } = data[0];
1205
1206                // Criar marcador com ícone
1207                const myIcon = L.icon({
1208                    title: place.name,
1209                    iconUrl: '../' + spathimg + '/mapa/location.png',
1210                    //iconSize: [25, 25],
1211                    //iconAnchor: [12, 25]
1212                    iconSize: [40, 40],
1213                    iconAnchor: [20, 40],   // metade da largura, altura total
1214                });
1215
1216                currentMarker = L.marker([lat, lon], { icon: myIcon });//.addTo(map);
1217                markers.push(currentMarker);
1218                //console.log('searchPlace');
1219                 //Adicionar o mesmo marcador ao cluster
1220                addMarkerCluster(currentMarker);
1221
1222                //currentMarker.bindPopup('<strong>' + display_name + '</strong>').openPopup();
1223                openMarkerAt(currentMarker, '<strong>' + display_name + '</strong>'); 
1224                map.setView([lat, lon], 13);
1225                
1226            })
1227            .catch(err => {
1228                console.error("Geocoding error:", err);
1229                alert("Could not find location.");
1230            });
1231    }
1232    // [END region_getplaces]
1233
1234    // Bias the SearchBox results towards places that are within the bounds of the
1235    // current map's viewport.
1236    /*
1237    marker.on('bounds_changed', function (event) {
1238        var bounds = map.getBounds();
1239        searchBox.setBounds(bounds);
1240    });
1241    */
1242}
1243
1244/* #endregion blog */
1245
1246/* #region itinerary */
1247/**
1248 * itinerary
1249 * @param {any} iconimg
1250 * @param {any} param
1251 * @returns
1252 */
1253/* utilizado no itinerary.aspx */
1254
1255function getColorMarker(iconimg, param) {
1256    var _result = '';
1257    if (iconimg.indexOf('location') >= 0) {
1258        if (param == 'click') {
1259            resetMarkers();
1260            _result = pathimage +'mapa/location_on.png';
1261        }
1262        else {
1263            _result = pathimage +'mapa/location.png';
1264        }
1265
1266    }
1267    return _result;
1268}
1269// Removes the markers from the map, but keeps them in the array.
1270function setMapOnAll() {
1271    //console.log(markers);
1272    for (let i = 0; i < markers.length; i++) {
1273        // get it out off the map
1274        markers[i].setMap(null);
1275    }
1276    //console.log('----');
1277    //console.log(markers);
1278    // Deletes all markers in the array by removing references to them.
1279
1280    markers = [];
1281}
1282
1283function resetMarkers() {
1284    for (var i = 0; i < markers.length; i++) {
1285        if (markers[i].getIcon().indexOf('location') >= 0) {
1286            markers[i].setIcon(pathimage+'mapa/location.png');
1287        }
1288    }
1289}
1290/* #endregion itinerary */

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.