PageSourceSearch

https://montagut.com/modules/montagutstores/views/js/front.js

js montagut.com collected 2026-10-08 01:33:25 UTC 27,584 bytes, 678 lines download raw bytes

1/**
2 * Module Montagut Stores JS - Version optimisée
3 *
4 * @author    Evol.digital
5 * @copyright 2025 Montagut
6 * @license   https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
7 */
8
9// Variables globales pour la carte
10var montagutMap = null;
11var montagutMarkers = [];
12var nonOfficialMarkers = [];
13var officialMarkers = [];
14var montagutMarkerCluster = null;
15
16document.addEventListener('DOMContentLoaded', function() {
17    // Initialiser la carte si on est sur la page des magasins
18    if (document.getElementById('map')) {
19        initializeMap();
20    }
21    
22    // Code spécifique pour la page des magasins
23    if (document.querySelector('.montagut-stores')) {
24        // Gestion des erreurs de chargement des images
25        document.querySelectorAll('.store-image img').forEach(function(img) {
26            img.addEventListener('error', function() {
27                this.src = prestashop.urls.base_url + 'img/cms/stores/default.jpg';
28            });
29        });
30        
31        // Gestion du focus sur les champs de recherche
32        document.querySelectorAll('.search-form input, .search-form select').forEach(function(input) {
33            input.addEventListener('focus', function() {
34                this.parentNode.classList.add('focused');
35            });
36            
37            input.addEventListener('blur', function() {
38                this.parentNode.classList.remove('focused');
39            });
40        });
41        
42        // Empêcher que le clic sur les liens dans les cartes de magasin ne déclenche le clic sur la carte
43        document.querySelectorAll('.store-card a').forEach(function(link) {
44            link.addEventListener('click', function(e) {
45                e.stopPropagation();
46            });
47        });
48        
49        // Gestion du bouton "Voir sur la carte" pour les magasins
50        document.querySelectorAll('.map-link-button').forEach(function(button) {
51            button.addEventListener('click', function(e) {
52                e.preventDefault();
53                e.stopPropagation();
54                
55                // Récupérer les coordonnées du magasin
56                var storeLat = this.getAttribute('data-lat');
57                var storeLng = this.getAttribute('data-lng');
58                
59                if (storeLat && storeLng && montagutMap) {
60                    // Animation de scroll vers la carte
61                    document.getElementById('map').scrollIntoView({
62                        behavior: 'smooth', 
63                        block: 'center'
64                    });
65                    
66                    // Centrer la carte sur le magasin avec animation
67                    montagutMap.flyTo([storeLat, storeLng], 17, {
68                        animate: true,
69                        duration: 1.5
70                    });
71                    
72                    // Délai avant d'ouvrir le popup pour que l'animation soit fluide
73                    setTimeout(function() {
74                        // Chercher et ouvrir le popup correspondant
75                        montagutMap.eachLayer(function(layer) {
76                            if (layer instanceof L.Marker) {
77                                var markerLat = layer.getLatLng().lat.toFixed(6);
78                                var markerLng = layer.getLatLng().lng.toFixed(6);
79                                
80                                if (markerLat === parseFloat(storeLat).toFixed(6) && 
81                                    markerLng === parseFloat(storeLng).toFixed(6)) {
82                                    layer.openPopup();
83                                }
84                            }
85                        });
86                    }, 1000);
87                }
88            });
89        });
90    }
91    
92    // Gestion du formulaire de recherche
93    var searchForm = document.getElementById('store-search-form');
94    if (searchForm) {
95        searchForm.addEventListener('submit', handleStoreSearch);
96    }
97    
98    // Redimensionnement de la fenêtre - pour que la carte s'adapte
99    window.addEventListener('resize', function() {
100        if (montagutMap) {
101            montagutMap.invalidateSize();
102        }
103    });
104});
105
106/**
107 * Initialise la carte Leaflet avec animations et fonctionnalités améliorées
108 */
109function initializeMap() {
110    // Création de la carte si l'élément existe
111    var mapElement = document.getElementById('map');
112    if (!mapElement) return;
113    
114    // Création de la carte centrée sur la France
115    montagutMap = L.map('map', {
116        zoomControl: false, // Nous ajouterons les contrôles de zoom manuellement
117        scrollWheelZoom: true,
118        dragging: true,
119        tap: true
120    }
120).setView([46.603354, 1.888334], 5);
121    
122    // Ajouter les contrôles de zoom dans le coin en bas à droite
123    L.control.zoom({
124        position: 'bottomright'
125    }).addTo(montagutMap);
126    
127    // Ajout des tuiles avec style élégant monochrome
128   /* L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
129        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="https://carto.com/attributions">CARTO</a>',
130        subdomains: 'abcd',
131        maxZoom: 19
132    }).addTo(montagutMap);*/
133    L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
134            attribution: '&copy; OpenStreetMap contributors',
135            maxZoom: 19
136        }).addTo(montagutMap);
137
138    
139    // Récupérer les magasins à partir de l'élément data
140    var storesData = document.getElementById('stores-data');
141    if (storesData) {
142        try {
143            var stores = JSON.parse(storesData.textContent);
144            addStoreMarkers(stores);
145        } catch (e) {
146            console.error("Erreur lors de la récupération des données des magasins:", e);
147        }
148    }
149    
150    // Ajouter un bouton de géolocalisation élégant
151    L.control.locate({
152        position: 'bottomright',
153        drawCircle: true,
154        followMarker: true,
155        setView: 'untilPan',
156        keepCurrentZoomLevel: false,
157        strings: {
158            title: "Me localiser"
159        },
160        locateOptions: {
161            enableHighAccuracy: true,
162            maxZoom: 15
163        },
164        icon: 'fas fa-location-arrow',
165        iconLoading: 'fas fa-spinner fa-spin',
166        markerStyle: {
167            weight: 2,
168            opacity: 0.9,
169            fillOpacity: 0.4
170        },
171        compassStyle: {
172            weight: 1,
173            opacity: 0.9,
174            fillOpacity: 0.4,
175            radius: 5
176        }
177    }).addTo(montagutMap);
178    
179    // Ajouter une animation au chargement de la carte
180    mapElement.style.opacity = '0';
181    mapElement.style.transition = 'opacity 1s ease';
182    
183    setTimeout(function() {
184        mapElement.style.opacity = '1';
185    }, 300);
186}
187/**
188 * Ajoute les marqueurs des magasins à la carte avec popups améliorés et positionnement optimisé
189 */
190function addStoreMarkers(stores) {
191    if (!montagutMap || !stores || !stores.length) return;
192    
193    // Vider les marqueurs existants
194    if (montagutMarkers.length > 0) {
195        montagutMarkers.forEach(function(marker) {
196            montagutMap.removeLayer(marker);
197        });
198        montagutMarkers = [];
199        officialMarkers = [];
200        nonOfficialMarkers = [];
201    }
202    
203    if (montagutMarkerCluster) {
204        montagutMap.removeLayer(montagutMarkerCluster);
205    }
206    
207    // Créer un marqueur personnalisé pour les magasins non officiels
208    var storeIcon = L.icon({
209        iconUrl: prestashop.urls.base_url + 'modules/montagutstores/views/img/marker.png',
210        iconSize: [40, 40],
211        iconAnchor: [20, 40],
212        popupAnchor: [0, -40],
213        shadowUrl: prestashop.urls.base_url + 'modules/montagutstores/views/img/marker-shadow.svg',
214        shadowSize: [50, 50],
215        shadowAnchor: [15, 50]
216    });
217    
218    // Marqueur pour les magasins officiels avec une taille légèrement plus grande
219    var officialIcon = L.icon({
220        iconUrl: prestashop.urls.base_url + 'modules/montagutstores/views/img/marker-official.png',
221        iconSize: [48, 48],
222        iconAnchor: [24, 48],
223        popupAnchor: [0, -48],
224        shadowUrl: prestashop.urls.base_url + 'modules/montagutstores/views/img/marker-shadow.svg',
225        shadowSize: [50, 50],
226        shadowAnchor: [15, 50]
227    });
228    
229    // Ajouter un marqueur pour chaque magasin
230    stores.forEach(function(store) {
231        if (store.lat && store.lng) {
232            var marker = L.marker([store.lat, store.lng], {
233                icon: store.is_official ? officialIcon : storeIcon,
234                title: store.name,
235                alt: 'Montagut ' + store.name,
236                riseOnHover: true
237            });
238            
239            // Formater les heures d'ouverture pour le popup
240            var hoursHtml = '';
241            if (store.hours && Object.keys(store.hours).length > 0) {
242                hoursHtml = '<div class="store-popup-hours"><h5><i class="fas fa-clock"></i> Horaires d\'ouverture</h5>';
243                
244                for (var day in store.hours) {
245                    var hours = store.hours[day];
246                    var displayHours = '';
247                    
248                    // Gestion des heures au format tableau
249                    if (Array.isArray(hours)) {
250                        if (hours.length === 0 || (hours.length === 1 && !hours[0])) {
251                            displayHours = 'Fermé';
252                        } else {
253                            var timeSlots = [];
254                            // Construire les créneaux horaires
255                            hours.forEach(function(slot) {
256                                if (slot && slot.trim() !== '') {
257                                    timeSlots.push(slot);
258                                }
259                            });
260                            
261                            if (timeSlots.length > 0) {
262                                displayHours = timeSlots.join(' / ');
263                            } else {
264                                displayHours = 'Fermé';
265                            }
266                        }
267                    } else {
268                        // Format chaîne classique
269                        displayHours = hours || 'Fermé';
270                    }
271                    
272                    hoursHtml += '<p><span>' + day + '</span><span>' + displayHours + '</span></p>';
273                }
274                
275                hoursHtml += '</div>';
276            }
277            
278            // Utiliser l'image téléchargée si disponible
279            var storeImageHtml = '';
280           /* if (store.image_url) {
281                storeImageHtml = `
282                    <div class="store-popup-image">
283                        <img src="${store.image_url}" alt="${store.name}" onerror="this.src='${prestashop.urls.base_url}img/cms/stores/default.jpg'">
284                    </div>
285                `;
286            }*/
287            
288            // Contenu du popup amélioré au format paysage
289            var popupContent = `
290                <div class="store-popup landscape">
291                    <div class="popup-row">
292                        ${storeImageHtml}
293                        <div class="popup-content">
294                            <div class="store-popup-header">
295                                <h4>${store.name}</h4>
296                                <p>${store.city}, ${store.country}</p>
297                                ${store.is_official ? '<div class="store-popup-badge">Officiel</div>' : ''}
298                            </div>
299                            <div class="store-popup-info">
300                                <p><i class="fas fa-map-marker-alt"></i> ${store.address}<br/>${store.postcode} ${store.city}</p>
301                                ${store.phone ? '<p><i class="fas fa-phone"></i> <a href="tel:' + store.phone.replace(/\s/g, '') + '">' + store.phone + '</a></p>' : ''}
302                                ${store.email ? '<p><i class="fas fa-envelope"></i> <a href="mailto:' + store.email + '">' + store.email + '</a></p>' : ''}
303                            </div>
304                            ${hoursHtml}
305                            <div class="store-popup-links">
306                                <a href="https://www.google.com/maps/dir/?api=1&destination=${store.lat},${store.lng}" target="_blank">
307                                    <i class="fas fa-directions"></i> Itinéraire
308                                </a>
309                            </div>
310                        </div>
311                    </div>
312                </div>
313            `;
314            
315            // Ajouter un lien vers la page CMS si elle existe
316            if (store.id_cms) {
317                // Note: Nécessiterait d'ajouter l'URL de la page CMS dans les données du store
318                var cmsUrl = prestashop.urls.base_url + 'content/category/' + store.id_cms + '-store';
319                
320                // Utilisez une opération DOM réelle pour manipuler le HTML ici
321                var tempDiv = document.createElement('div');
322                tempDiv.innerHTML = popupContent;
323                
324                var linksDiv = tempDiv.querySelector('.store-popup-links');
325                if (linksDiv) {
326                    var pageLink = document.createElement('a');
327                    pageLink.href = cmsUrl;
328                    pageLink.innerHTML = '<i class="fas fa-info-circle"></i> Voir la page';
329                    pageLink.style.marginLeft = '10px';
330                    
331                    linksDiv.appendChild(pageLink);
332                    
333                    popupContent = tempDiv.innerHTML;
334                }
335            }
336            
337            // Créer le popup avec animation
338            var popup = L.popup({
339                closeButton: true,
340                autoClose: true,
341                className: 'store-popup-container landscape-popup',
342                minWidth: 520, // Plus large pour le format paysage
343                maxHeight: 500 // Limiter la hauteur
344            }).setContent(popupContent);
345            
346            marker.bindPopup(popup);
347            montagutMarkers.push(marker);
348            
349            // Séparer les marqueurs officiels et non officiels
350            if (store.is_official) {
351                officialMarkers.push(marker);
352            } else {
353                nonOfficialMarkers.push(marker);
354            }
355            
356            // Ajouter un événement au clic sur le marqueur pour repositionner la vue
357            marker.on('click', function() {
358                // Position du marqueur
359                var popupLocation = marker.getLatLng();
360                
361                // Décalage vertical (valeur positive pour déplacer le marqueur vers le bas de l'écran)
362                // Plus la valeur est grande, plus le marqueur sera bas dans la carte
363                var yOffset = -250;
364                
365                // Calculer une nouvelle position pour que le popup soit bien visible
366                // Déplacer le centre de la carte vers le haut, ce qui place le marker plus bas
367                var offsetPoint = montagutMap.project(popupLocation).subtract([0, -yOffset]);
368                var newCenter = montagutMap.unproject(offsetPoint);
369                
370                // Animer vers cette nouvelle position
371                setTimeout(function() {
372                    montagutMap.setView(newCenter, montagutMap.getZoom(), {
373                        animate: true,
374                        duration: 0.5
375                    });
376                }, 50);
377            });
378            
379            // Animation du marqueur au survol
380            marker.on('mouseover', function() {
381                this.setZIndexOffset(1000);
382            });
383            
384            marker.on('mouseout', function() {
385                this.setZIndexOffset(0);
386            });
387        }
388    });
389    
390    // Ajouter les marqueurs officiels directement à la carte sans clustering
391    officialMarkers.forEach(function(marker) {
392        marker.addTo(montagutMap);
393    });
394    
395    // Utiliser MarkerCluster uniquement pour les magasins non officiels
396    montagutMarkerCluster = L.markerClusterGroup({
397        showCoverageOnHover: false,
398        zoomToBoundsOnClick: true,
399        spiderfyOnMaxZoom: true,
400        animateAddingMarkers: true,
401        disableClusteringAtZoom: 16,
402        maxClusterRadius: 60,
403        iconCreateFunction: function(cluster) {
404            var childCount = cluster.getChildCount();
405            var size = 40;
406            
407            if (childCount > 50) {
408                size = 60;
409            } else if (childCount > 20) {
410                size = 50;
411            }
412            
413            return L.divIcon({
414                html: '<div><span>' + childCount + '</span></div>',
415                className: 'marker-cluster' + (childCount < 10 ? ' marker-cluster-small' : childCount < 30 ? ' marker-cluster-medium' : ' marker-cluster-large'),
416                iconSize: new L.Point(size, size)
417            });
418        }
419    });
420    
421    // Ajouter uniquement les marqueurs non officiels au cluster
422    nonOfficialMarkers.forEach(function(marker) {
423        montagutMarkerCluster.addLayer(marker);
424    });
425    
426    montagutMap.addLayer(montagutMarkerCluster);
427    
428    // Ajuster la vue pour montrer tous les marqueurs si possible
429    if (montagutMarkers.length > 0) {
430        var bounds = L.featureGroup(montagutMarkers).getBounds();
431        montagutMap.fitBounds(bounds, {
432            padding: [50, 50],
433            maxZoom: 15,
434            animate: true,
435            duration: 1
436        });
437    }
438}
439
440/**
441 * Gestion du formulaire de recherche - Version améliorée
442 */
443function handleStoreSearch(e) {
444    e.preventDefault();
445    
446    var form = e.target;
447    var country = document.getElementById('store-country').value;
448    var postcode = document.getElementById('store-postcode').value;
449    var address = document.getElementById('store-address').value;
450    
451    // URL de l'action de recherche
452    var searchUrl = form.getAttribute('data-search-url');
453    
454    if (!searchUrl) {
455        console.error("URL de recherche non définie");
456        return;
457    }
458    
459    // Afficher un indicateur de chargement élégant
460    var mapElement = document.getElementById('map');
461    var loaderOverlay = document.createElement('div');
462    loaderOverlay.className = 'map-loader-overlay';
463    loaderOverlay.innerHTML = '<div class="loader"></div><p>Recherche en cours...</p>';
464    loaderOverlay.style.position = 'absolute';
465    loaderOverlay.style.top = '0';
466    loaderOverlay.style.left = '0';
467    loaderOverlay.style.right = '0';
468    loaderOverlay.style.bottom = '0';
469    loaderOverlay.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
470    loaderOverlay.style.display = 'flex';
471    loaderOverlay.style.flexDirection = 'column';
472    loaderOverlay.style.alignItems = 'center';
473    loaderOverlay.style.justifyContent = 'center';
474    loaderOverlay.style.zIndex = '1000';
475    
476    mapElement.style.position = 'relative';
477    mapElement.appendChild(loaderOverlay);
478    
479    // Animation de scroll vers la carte
480    mapElement.scrollIntoView({
481        behavior: 'smooth', 
482        block: 'center'
483    });
484    
485    // Effectuer la requête AJAX
486    var xhr = new XMLHttpRequest();
487    xhr.open('POST', searchUrl, true);
488    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
489    
490    xhr.onreadystatechange = function() {
491        if (xhr.readyState === 4) {
492            // Supprimer le loader
493            if (loaderOverlay.parentNode) {
494                loaderOverlay.parentNode.removeChild(loaderOverlay);
495            }
496            
497            if (xhr.status === 200) {
498                try {
499                    var response = JSON.parse(xhr.responseText);
500                    
501                    if (response.success && response.stores.length > 0) {
502                        // NE PAS mettre à jour les marqueurs - garder tous les magasins visibles
503                        // Modification: au lieu de remplacer les marqueurs, nous zoomons simplement sur les résultats
504                        
505                        // Créer un groupe de marqueurs pour les résultats de recherche uniquement
506                        var searchBounds = L.latLngBounds();
507                        
508                        // Ajouter chaque magasin trouvé aux boun
508ds
509                        response.stores.forEach(function(store) {
510                            if (store.lat && store.lng) {
511                                searchBounds.extend([store.lat, store.lng]);
512                            }
513                        });
514                        
515                        // Si nous avons des magasins valides, ajuster la vue
516                        if (!searchBounds.isValid()) {
517                            // Si aucun magasin n'a de coordonnées valides, utiliser le centre par défaut
518                            if (response.center && response.zoom) {
519                                montagutMap.flyTo([response.center.lat, response.center.lng], response.zoom, {
520                                    animate: true,
521                                    duration: 1.5
522                                });
523                            }
524                        } else {
525                            // Zoomer sur les résultats avec une marge
526                            montagutMap.flyToBounds(searchBounds, {
527                                padding: [50, 50],
528                                maxZoom: 15,
529                                animate: true,
530                                duration: 1.5
531                            });
532                        }
533                        
534                        // Afficher un message de succès
535                        showMapMessage('success', 'Nous avons trouvé ' + response.count + ' magasin(s) correspondant à votre recherche.');
536                    } else {
537                        // Aucun magasin trouvé
538                        showMapMessage('warning', 'Aucun magasin trouvé pour votre recherche.');
539                    }
540                } catch (e) {
541                    console.error("Erreur lors du traitement de la réponse:", e);
542                    showMapMessage('error', 'Une erreur est survenue lors de la recherche.');
543                }
544            } else {
545                // Erreur HTTP
546                console.error("Erreur HTTP:", xhr.status);
547                showMapMessage('error', 'Une erreur est survenue lors de la recherche.');
548            }
549        }
550    };
551    
552    xhr.send('ajax=1&action=search&country=' + country + '&postcode=' + postcode + '&address=' + address);
553}
554
555/**
556 * Affiche un message sur la carte
557 */
558function showMapMessage(type, message) {
559    var mapElement = document.getElementById('map');
560    var messageOverlay = document.createElement('div');
561    messageOverlay.className = 'map-message map-message-' + type;
562    messageOverlay.innerHTML = message;
563    messageOverlay.style.position = 'absolute';
564    messageOverlay.style.top = '20px';
565    messageOverlay.style.left = '50%';
566    messageOverlay.style.transform = 'translateX(-50%)';
567    messageOverlay.style.padding = '10px 20px';
568    messageOverlay.style.borderRadius = '5px';
569    messageOverlay.style.zIndex = '1000';
570    messageOverlay.style.boxShadow = '0 5px 15px rgba(0, 0, 0, 0.1)';
571    messageOverlay.style.fontWeight = '500';
572    messageOverlay.style.opacity = '0';
573    messageOverlay.style.transition = 'opacity 0.3s ease';
574    
575    // Style selon le type
576    if (type === 'success') {
577        messageOverlay.style.backgroundColor = '#d4edda';
578        messageOverlay.style.color = '#155724';
579        messageOverlay.style.border = '1px solid #c3e6cb';
580    } else if (type === 'warning') {
581        messageOverlay.style.backgroundColor = '#fff3cd';
582        messageOverlay.style.color = '#856404';
583        messageOverlay.style.border = '1px solid #ffeeba';
584    } else if (type === 'error') {
585        messageOverlay.style.backgroundColor = '#f8d7da';
586        messageOverlay.style.color = '#721c24';
587        messageOverlay.style.border = '1px solid #f5c6cb';
588    }
589    
590    mapElement.appendChild(messageOverlay);
591    
592    // Animation d'apparition
593    setTimeout(function() {
594        messageOverlay.style.opacity = '1';
595    }, 100);
596    
597    // Disparition après 5 secondes
598    setTimeout(function() {
599        messageOverlay.style.opacity = '0';
600        
601        setTimeout(function() {
602            if (messageOverlay.parentNode) {
603                messageOverlay.parentNode.removeChild(messageOverlay);
604            }
605        }, 300);
606    }, 5000);
607}
608
609/**
610 * Ajouts spécifiques à intégrer dans le fichier front.js pour gérer le nouveau design
611 */
612
613document.addEventListener('DOMContentLoaded', function() {
614    // Gestion des erreurs de chargement des images de fond
615    document.querySelectorAll('.store-image-bg').forEach(function(bg) {
616        // Créer une image temporaire pour vérifier si l'URL de fond fonctionne
617        var tempImg = new Image();
618        
619        tempImg.onerror = function() {
620            // Si l'image ne charge pas, utiliser l'image par défaut
621            var defaultImg = bg.getAttribute('data-default');
622            if (defaultImg) {
623                bg.style.backgroundImage = 'url("' + defaultImg + '")';
624                bg.classList.add('error');
625            }
626        };
627        
628        // Extraire l'URL de l'image de fond du style inline
629        var bgUrl = window.getComputedStyle(bg).backgroundImage;
630        var urlMatch = bgUrl.match(/url\(['"]?([^'"]+)['"]?\)/);
631        
632        if (urlMatch && urlMatch[1]) {
633            tempImg.src = urlMatch[1];
634        }
635    });
636    
637    // Gestion du bouton "Voir sur la carte" pour les magasins (nouvelle version)
638    document.querySelectorAll('.map-link-button-modern').forEach(function(button) {
639        button.addEventListener('click', function(e) {
640            e.preventDefault();
641            e.stopPropagation();
642            
643            // Récupérer les coordonnées du magasin
644            var storeLat = this.getAttribute('data-lat');
645            var storeLng = this.getAttribute('data-lng');
646            
647            if (storeLat && storeLng && montagutMap) {
648                // Animation de scroll vers la carte
649                document.getElementById('map').scrollIntoView({
650                    behavior: 'smooth', 
651                    block: 'center'
652                });
653                
654                // Centrer la carte sur le magasin avec animation
655                montagutMap.flyTo([storeLat, storeLng], 17, {
656                    animate: true,
657                    duration: 1.5
658                });
659                
660                // Délai avant d'ouvrir le popup pour que l'animation soit fluide
661                setTimeout(function() {
662                    // Chercher et ouvrir le popup correspondant
663                    montagutMap.eachLayer(function(layer) {
664                        if (layer instanceof L.Marker) {
665                            var markerLat = layer.getLatLng().lat.toFixed(6);
666                            var markerLng = layer.getLatLng().lng.toFixed(6);
667                            
668                            if (markerLat === parseFloat(storeLat).toFixed(6) && 
669                                markerLng === parseFloat(storeLng).toFixed(6)) {
670                                layer.openPopup();
671                            }
672                        }
673                    });
674                }, 1000);
675            }
676        });
677    });
678});

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.