(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;">×</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 );
}
}
}
});
})();