View file rusnet-interactive-map/assets/js/frontend/map-init.js

File size: 18.78Kb
(function() {
    if ( typeof window.RusnetimWP !== 'object' ) window.RusnetimWP = {};

    window.RusnetimWP.initMap = function( index ) {
        try {
            var data = window['rusnetim_map_' + index];
            if ( ! data ) return;

            if ( data.center && !Array.isArray(data.center) ) {
                data.center = [parseFloat(data.center[0]), parseFloat(data.center[1])];
            }
            if ( data.controls && !Array.isArray(data.controls) ) {
                data.controls = Object.values(data.controls);
            }
            if ( data.markers && !Array.isArray(data.markers) ) {
                data.markers = Object.values(data.markers);
            }
            if ( data.markers ) {
                for ( var i = 0; i < data.markers.length; i++ ) {
                    var m = data.markers[i];
                    if ( m.iconSize && !Array.isArray(m.iconSize) ) {
                        m.iconSize = Object.values(m.iconSize);
                    }
                }
            }

            var mapKey = 'myMap' + index;
            window.RusnetimWP[mapKey] = window.RusnetimWP[mapKey] || {};
            window.RusnetimWP[mapKey].places = {};
            window.RusnetimWP[mapKey].markersData = data.markers || [];

            var container = document.getElementById( data.container );
            if ( ! container ) {
                console.warn( 'Rusnetim: контейнер #' + data.container + ' не найден для карты ' + index );
                return;
            }

            var myMap = new ymaps.Map( container, {
                center: data.center,
                zoom: data.zoom,
                type: data.type,
                controls: data.controls
            }, { suppressMapOpenBlock: false } );

            window.RusnetimWP[mapKey].map = myMap;

            function isMobileDevice() {
                return /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
            }

            if ( data.scrollzoom === '0' ) myMap.behaviors.disable('scrollZoom');

            if ( isMobileDevice() ) {
                if ( data.mobiledrag === '0' ) {
                    myMap.behaviors.disable('drag');
                } else {
                    myMap.behaviors.enable('drag');
                }
            } else {
                myMap.behaviors.enable('drag');
            }

            window.RusnetimWP[mapKey].showInfoPanel = function( placeData ) {
                try {
                    var infoPanel = document.getElementById( data.info_panel_id );
                    if ( ! infoPanel ) return;
            
                    var titlepos = data.titleposition || 'below';
                    var titleTag = data.title_tag || 'h3';
                    var titleFontSize = data.title_font_size || '';
                    var titleColor = data.title_color || '';
            
                    var titleStyle = '';
                    if ( titleFontSize ) titleStyle += 'font-size:' + titleFontSize + ';';
                    if ( titleColor ) titleStyle += 'color:' + titleColor + ';';
            
                    var displayName = placeData.name || 'Без названия';
            
                    infoPanel.innerHTML = '';
            
                    var html = '<button type="button" class="rusnetim-info-close" style="position: absolute; top: 10px; right: 10px; background: rgba(255,255,255,0.9); border: 1px solid #ccc; font-size: 24px; font-weight: bold; cursor: pointer; z-index: 2000; color: #333; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 50%; box-shadow: 0 2px 4px rgba(0,0,0,0.2); padding: 0; box-sizing: border-box;">&times;</button>';
            
                    if ( titlepos === 'above' ) {
                        html += '<' + titleTag + ' style="' + titleStyle + '">' + displayName + '</' + titleTag + '>';
                    }
            
                    if ( placeData.gallery && Array.isArray(placeData.gallery) && placeData.gallery.length > 0 ) {
                        html += '<div class="rusnetim-gallery" style="margin-bottom: 15px;">';
                        html += '<div class="rusnetim-gallery-main" style="margin-bottom: 10px;">' +
                                '<a href="' + placeData.gallery[0] + '" target="_blank" style="display: block; cursor: pointer;">' +
                                '<img src="' + placeData.gallery[0] + '" style="max-width: 100%; height: auto; border-radius: 4px;" class="main-gallery-image">' +
                                '</a>' +
                                '</div>';
                        if ( placeData.gallery.length > 1 ) {
                            html += '<div class="rusnetim-gallery-thumbs" style="display: flex; flex-wrap: wrap; gap: 8px;">';
                            for ( var i = 0; i < placeData.gallery.length; i++ ) {
                                html += '<img src="' + placeData.gallery[i] + '" data-index="' + i + '" style="width: 60px; height: 60px; object-fit: cover; border: 2px solid ' + (i === 0 ? '#1e98ff' : '#ddd') + '; border-radius: 4px; cursor: pointer;" class="gallery-thumb" />';
                            }
                            html += '</div>';
                        }
                        html += '</div>';
                    } else if ( placeData.image ) {
                        html += '<div style="margin-bottom: 15px;">' +
                                '<a href="' + placeData.image + '" target="_blank" style="display: block; cursor: pointer;">' +
                                '<img src="' + placeData.image + '" style="max-width: 100%; height: auto; border-radius: 4px;">' +
                                '</a>' +
                                '</div>';
                    }
            
                    if ( titlepos !== 'above' ) {
                        html += '<' + titleTag + ' style="' + titleStyle + '">' + displayName + '</' + titleTag + '>';
                    }
            
                    if ( placeData.description ) {
                        html += '<div style="font-size: 14px; line-height: 1.5;">' + placeData.description + '</div>';
                    }
            
                    html += '</div>';
            
                    infoPanel.innerHTML = html;
                    infoPanel.style.display = 'block';
                    var closeBtn = infoPanel.querySelector('.rusnetim-info-close');
                    if (closeBtn) {
                        closeBtn.addEventListener('click', function(e) {
                            e.stopPropagation();
                            infoPanel.style.display = 'none';
                        });
                    }
            
                    var mainImage = infoPanel.querySelector('.main-gallery-image');
                    var thumbs = infoPanel.querySelectorAll('.gallery-thumb');
                    if ( mainImage && thumbs.length ) {
                        thumbs.forEach(function(thumb) {
                            thumb.addEventListener('click', function() {
                                var index = this.dataset.index;
                                mainImage.src = placeData.gallery[index];
                                var parentLink = mainImage.closest('a');
                                if (parentLink) parentLink.href = placeData.gallery[index];
                                thumbs.forEach(function(t) {
                                    t.style.borderColor = '#ddd';
                                });
                                this.style.borderColor = '#1e98ff';
                            });
                        });
                    }
                } catch ( e ) {
                    console.error( 'Rusnetim: ошибка в showInfoPanel', e );
                }
            };

            myMap.events.add('click', function(e) {
                var target = e.get('target');
                var isCluster = target && typeof target.getGeoObjects === 'function';
                if ( ! ( target instanceof ymaps.Placemark ) && !isCluster ) {
                    var infoPanel = document.getElementById( data.info_panel_id );
                    if ( infoPanel ) infoPanel.style.display = 'none';
                }
            });

            var handleClusterClick = function(e) {
                try {
                    var cluster = e.get('target');
                    if (!cluster || typeof cluster.getGeoObjects !== 'function') return;
                    var geoObjects = cluster.getGeoObjects();
                    if (geoObjects.length === 0) return;
                    var placesData = window.RusnetimWP[mapKey].places;
                    var listHtml = '<div class="rusnetim-cluster-list"><h3>' + data.cluster_list_title + '</h3><ul>';
                    geoObjects.forEach(function (geoObject) {
                        var id = geoObject.properties.get('id');
                        var placeData = placesData[id];
                        if (placeData) {
                            listHtml += '<li class="rusnetim-cluster-item" data-id="' + id + '">' +
                                        '<span class="rusnetim-cluster-item-name">' + (placeData.name || data.unnamed) + '</span>' +
                                        '</li>';
                        }
                    });
                    listHtml += '</ul></div>';
                    var infoPanel = document.getElementById( data.info_panel_id );
                    if (infoPanel) {
                        infoPanel.innerHTML = listHtml;
                        infoPanel.style.display = 'block';
                        var clusterListHandler = function(evt) {
                            var item = evt.target.closest('.rusnetim-cluster-item');
                            if (!item) return;
                            evt.stopPropagation();
                            var id = item.getAttribute('data-id');
                            var placeData = placesData[id];
                            if (placeData && typeof window.RusnetimWP[mapKey].showInfoPanel === 'function') {
                                window.RusnetimWP[mapKey].showInfoPanel(placeData);
                            }
                        };
                        infoPanel.removeEventListener('click', clusterListHandler);
                        infoPanel.addEventListener('click', clusterListHandler);
                    }
                    e.stopPropagation();
                } catch ( e ) {
                    console.error( 'Rusnetim: ошибка в handleClusterClick', e );
                }
            };

            function createPlacemarkFromData(markerData, originalIdx) {
                try {
                    var placemarkId = 'map' + index + '_placemark' + originalIdx;
                    var placemarkOptions = {
                        draggable: false,
                        zIndex: 1
                    };

                    if ( markerData.iconUrl ) {
                        placemarkOptions.iconLayout = 'default#image';
                        placemarkOptions.iconImageHref = markerData.iconUrl;
                        if ( markerData.iconSize && markerData.iconSize.length === 2 ) {
                            placemarkOptions.iconImageSize = markerData.iconSize;
                        }
                    } else {
                        placemarkOptions.preset = markerData.iconPreset || 'islands#dotIcon';
                        placemarkOptions.iconColor = markerData.iconColor;
                    }

                    var coords = markerData.coord.split(',').map(parseFloat);
                    if ( coords.length !== 2 || isNaN(coords[0]) || isNaN(coords[1]) ) {
                        console.warn( 'Rusnetim: некорректные координаты маркера', markerData.coord );
                        return null;
                    }

                    var placemark = new ymaps.Placemark(
                        coords,
                        {
                            hintContent: markerData.hint || '',
                            iconContent: markerData.content || '',
                            id: placemarkId
                        },
                        placemarkOptions
                    );

                    if ( ! window.RusnetimWP[mapKey].places[ placemarkId ] ) {
                        window.RusnetimWP[mapKey].places[ placemarkId ] = {
                            coord: markerData.coord,
                            name: markerData.name,
                            icon: markerData.iconPreset || markerData.iconUrl,
                            color: markerData.iconColor,
                            url: markerData.url,
                            category: markerData.category,
                            image: markerData.image,
                            description: markerData.description,
                            gallery: markerData.gallery || []
                        };
                    }

                    placemark.events.add('click', function(e) {
                        var placeData = window.RusnetimWP[mapKey].places[ placemarkId ];
                        if ( placeData && typeof window.RusnetimWP[mapKey].showInfoPanel === 'function' ) {
                            window.RusnetimWP[mapKey].showInfoPanel( placeData );
                        }
                        if ( markerData.url ) {
                            setTimeout(function() {
                                window.location.href = markerData.url;
                            }, 100);
                        }
                    });

                    placemark.events.add('mouseenter', function(e) {
                        e.get('target').options.set('zIndex', 1000);
                    });

                    placemark.events.add('mouseleave', function(e) {
                        e.get('target').options.set('zIndex', 0);
                    });

                    return placemark;
                } catch (e) {
                    console.warn('Rusnetim: ошибка создания маркера', e, markerData);
                    return null;
                }
            }

            var placemarks = [];
            if ( data.markers && Array.isArray(data.markers) ) {
                data.markers.forEach( function( markerData, idx ) {
                    var placemark = createPlacemarkFromData(markerData, idx);
                    if (placemark) placemarks.push(placemark);
                });
            }

            placemarks = placemarks.filter(function(p) {
                return p && typeof p.geometry !== 'undefined';
            });

            window.RusnetimWP[mapKey].placemarks = placemarks;

            function addMarkersToMap(marks, useCluster) {
                if (!marks.length) return;

                if (useCluster) {
                    var clusterer = new ymaps.Clusterer( {
                        groupByCoordinates: false,
                        clusterDisableClickZoom: false,
                        clusterHideIconOnBalloonOpen: false,
                        clusterOpenBalloonOnClick: false,
                        geoObjectHideIconOnBalloonOpen: false,
                        gridSize: parseInt(data.clustergrid, 10) || 64,
                        clusterIconColor: data.clustercolor
                    } );

                    try {
                        clusterer.add(marks);
                        myMap.geoObjects.add(clusterer);
                        clusterer.events.add('click', handleClusterClick);
                        window.RusnetimWP[mapKey].clusterer = clusterer;
                    } catch (e) {
                        console.warn('Rusnetim: ошибка кластеризации, добавляем маркеры напрямую', e);
                        for (var i = 0; i < marks.length; i++) {
                            try {
                                myMap.geoObjects.add(marks[i]);
                            } catch (e2) {}
                        }
                    }
                } else {
                    for (var i = 0; i < marks.length; i++) {
                        try {
                            myMap.geoObjects.add(marks[i]);
                        } catch (e) {
                            console.warn('Rusnetim: ошибка добавления отдельного маркера', e);
                        }
                    }
                }
            }

            addMarkersToMap(placemarks, data.cluster === '1');

            var filterButtons = document.querySelectorAll( '.rusnetim-cat-btn[data-map="' + index + '"]' );
            if ( filterButtons.length ) {
                filterButtons.forEach( function( btn ) {
                    btn.addEventListener( 'click', function() {
                        try {
                            var cat = this.getAttribute( 'data-cat' ).toLowerCase();
                            var myMap = window.RusnetimWP[mapKey].map;
                            var markersData = window.RusnetimWP[mapKey].markersData || [];

                            if ( ! myMap ) return;

                            filterButtons.forEach( function( b ) { b.classList.remove( 'active' ); } );
                            this.classList.add( 'active' );

                            myMap.geoObjects.removeAll();

                            var newPlacemarks = [];
                            markersData.forEach( function(markerData, originalIdx) {
                                var placeCategory = ( markerData.category ) ? markerData.category.toLowerCase() : 'all';
                                if ( cat === 'all' || placeCategory === cat ) {
                                    var placemark = createPlacemarkFromData(markerData, originalIdx);
                                    if (placemark) newPlacemarks.push(placemark);
                                }
                            });

                            newPlacemarks = newPlacemarks.filter(function(p) {
                                return p && typeof p.geometry !== 'undefined';
                            });

                            addMarkersToMap(newPlacemarks, data.cluster === '1');
                            window.RusnetimWP[mapKey].placemarks = newPlacemarks;

                        } catch ( e ) {
                            console.error( 'Rusnetim: ошибка в фильтре категорий', e );
                        }
                    } );
                } );
            }
        } catch ( e ) {
            console.error( 'Rusnetim: ошибка инициализации карты ' + index, e );
        }
    };

    ymaps.ready(function() {
        for ( var key in window ) {
            if ( key.indexOf('rusnetim_map_') === 0 ) {
                var index = key.replace('rusnetim_map_', '');
                if ( window.RusnetimWP.initMap ) {
                    window.RusnetimWP.initMap( index );
                }
            }
        }
    });
})();