583 lines
18 KiB
JavaScript
583 lines
18 KiB
JavaScript
/*
|
||
* Let's GO!
|
||
*/
|
||
|
||
var myMap;
|
||
var categories = Array();
|
||
var points = Array();
|
||
var pointsSources = Array();
|
||
var markers; // Используется для кластеризации
|
||
var search;
|
||
var route = false;
|
||
var addPointInProcess = false;
|
||
var layer;
|
||
var layers = Array();
|
||
var defaultZoom = 13;
|
||
var rightCoords = [];
|
||
var allPointsLoaded = false;
|
||
|
||
categories.im = L.icon({
|
||
iconUrl: '/ico/man.png',
|
||
iconSize: [32, 37],
|
||
iconAnchor: [16, 37],
|
||
popupAnchor: [0, 1]
|
||
});
|
||
|
||
categories.lock = L.icon({
|
||
iconUrl: '/ico/lock.png',
|
||
iconSize: [32, 37],
|
||
iconAnchor: [16, 37],
|
||
popupAnchor: [0, 1]
|
||
});
|
||
|
||
categories.simplepoint = L.icon({
|
||
iconUrl: '/ico/simplepoint.png',
|
||
iconSize: [13, 13],
|
||
iconAnchor: [7, 7],
|
||
popupAnchor: [7, 7]
|
||
});
|
||
|
||
categories.marker = L.icon({
|
||
iconUrl: '/ico/marker.png',
|
||
iconSize: [32, 37],
|
||
iconAnchor: [16, 37],
|
||
popupAnchor: [0, 1]
|
||
});
|
||
|
||
// -----------------------------------------------------------------------------
|
||
|
||
if (pointLat == pointLng) {
|
||
init(userLat, userLng);
|
||
} else {
|
||
init(pointLat, pointLng);
|
||
}
|
||
|
||
points.im = L.marker([userLat, userLng], {icon: categories.im, title: 'Вы здесь'});
|
||
points.im.addTo(myMap);
|
||
points.im.bindPopup('<h3>Похоже, что вы здесь!</h3><img src="/ico/man.png" style="float: left; margin-right: 5px;" /> <b>Ваше местоположение</b> - это точка, которую можно добавить в маршрут. При первоначальной загрузке страницы определение координат происходит очень неточно, по вашему адресу в сети интеренет. При желании координаты можно уточнить, нажав соответствующую пиктограмму справа [ <div class="glyphicon glyphicon-screenshot _b"></div> ].<br/><br/> <button type="button" class="btn btn-default" onclick="addToRoute(\'im\')"><span class="glyphicon glyphicon-map-marker"></span> Добавить в маршрут</button>');
|
||
|
||
suggestInit('#addressField');
|
||
|
||
/**
|
||
* Инициализируем переменные и подгружаем данные.
|
||
* @returns true
|
||
*/
|
||
function init(lat, lng) {
|
||
myMap = L.map('map', {zoomControl: false}).setView([lat, lng], defaultZoom);
|
||
markers = new L.MarkerClusterGroup({showCoverageOnHover: false, maxClusterRadius: 30});
|
||
// markersPlus = new L.MarkerClusterGroup({showCoverageOnHover: false, maxClusterRadius: 25});
|
||
|
||
layers['quest'] = L.tileLayer('https://otile1-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com" target="_blank">Mapbox</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 18});
|
||
layers['osm'] = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 18});
|
||
layers['topo'] = L.tileLayer('https://topo.wikipoints.ru/?z={z}&x={x}&y={y}&ver=0216', {attribution: 'Map data © <a href="http://openstreetmap.org" target="_blank">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a>, Imagery © <a href="http://www.marshruty.ru/" target="_blank">Маршруты.ру</a> | Points data © <a href="http://wikipoints.ru" target="_blank">WIKIPOINTS.RU</a>', maxZoom: 15});
|
||
layers['google'] = new L.Google('HYBRID');
|
||
layers['yandexMap'] = new L.Yandex();
|
||
layers['yandex'] = new L.Yandex('hybrid');
|
||
|
||
setLayer($.cookie('mapLayer') ? $.cookie('mapLayer') : 'quest');
|
||
|
||
initCategories(); // getPoints внутри
|
||
|
||
myMap.on('click', function (e) {
|
||
if (!myMap._popup) {
|
||
if (status == statusHunting)
|
||
{
|
||
$('div#addHelper').hide(150);
|
||
$('#addPointId').remove();
|
||
$('#addPointForm input:text').val('');
|
||
$('#addPointForm textarea').val('');
|
||
$("#addPointCategoryId option").attr('selected', null);
|
||
$('#addPointLat').val(e.latlng.lat);
|
||
$('#addPointLng').val(e.latlng.lng);
|
||
|
||
$('#myModalLabel').text('Добавление новой точки');
|
||
$('#addPointModal').modal('show');
|
||
} else if (status == statusReHunting)
|
||
{
|
||
resetStatus();
|
||
|
||
$('#addPointLat').val(e.latlng.lat);
|
||
$('#addPointLng').val(e.latlng.lng);
|
||
|
||
$('#myModalLabel').text('Редактирование точки');
|
||
$('#addPointModal').modal('show');
|
||
}
|
||
}
|
||
else {
|
||
closePopup();
|
||
}
|
||
});
|
||
|
||
$("#wayPoints").sortable();
|
||
$("#wayPoints").disableSelection();
|
||
$("#imgsContainer").sortable();
|
||
$("#extraParamsContainer").sortable();
|
||
|
||
myMap.on('moveend', function (e) {
|
||
if (!myMap._popup && $('#boxRoute').css('display') == 'none' && status != statusMovingInHistory)
|
||
{
|
||
document.title = 'Лучшие выходные — это выходные в путешествии! – wikipoints.ru';
|
||
history.pushState({lat: myMap.getCenter().lat, lng: myMap.getCenter().lng, zoom: myMap.getZoom()}, document.title, "/?lat=" + myMap.getCenter().lat + "&lng=" + myMap.getCenter().lng + "&zoom=" + myMap.getZoom());
|
||
loadPointsInBounds();
|
||
}
|
||
|
||
if (status == statusMovingInHistory)
|
||
{
|
||
resetStatus();
|
||
}
|
||
});
|
||
|
||
myMap.on('popupclose', function(e){
|
||
$('#control').show(100);
|
||
});
|
||
|
||
$('.filterSelector').bind('change', function () {
|
||
filter()
|
||
});
|
||
|
||
// Добавление произвольной точки в маршрут по правому клику
|
||
myMap.on('contextmenu', function (e) {
|
||
if (status == statusReady)
|
||
{
|
||
rightCoords = [e.latlng.lat, e.latlng.lng];
|
||
popupContent = '<button type="button" class="btn btn-default" onclick="addToRoute(rightCoords)"><span class="glyphicon glyphicon-map-marker"></span> Добавить в маршрут</button>';
|
||
popup = L.popup();
|
||
popup.setContent(popupContent);
|
||
popup.setLatLng(e.latlng);
|
||
popup.openOn(myMap);
|
||
}
|
||
});
|
||
|
||
$(document).keyup(function (e) {
|
||
if (e.keyCode === 27) { // escape key
|
||
closePopup();
|
||
}
|
||
});
|
||
|
||
// Пользователь на карте
|
||
myMap.on('locationfound', onLocationFound);
|
||
myMap.on('locationerror', onLocationError);
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Создаёт точку для карты - Placemark.
|
||
* @param {Array} data
|
||
* @returns {Array}
|
||
*/
|
||
function constructPoint(data)
|
||
{
|
||
id = data['id'];
|
||
|
||
icon = categories[data['categoryId']];
|
||
if (data['status'] != 'published') {
|
||
icon = categories.lock;
|
||
data['name'] = 'На модерации: ' + data['name'];
|
||
}
|
||
|
||
points[id] = L.marker(
|
||
[data['lat'], data['lng']], {icon: icon, title: data['name'], id: id, categoryId: data['categoryId']}
|
||
).on('click', function (e) {
|
||
if (!(id in pointsSources)) {
|
||
showInfo(e.target.options.id, true);
|
||
} else {
|
||
history.pushState({pointId: id}, document.title, "/?point=" + e.target.options.id);
|
||
document.title = e.target.options.title;
|
||
}
|
||
});
|
||
|
||
return points[id];
|
||
}
|
||
|
||
/**
|
||
* Загружает точки с сервера.
|
||
* @returns {Boolean}
|
||
*/
|
||
function initPoints(useBounds)
|
||
{
|
||
bounds = myMap.getBounds();
|
||
if (useBounds == true && getURLParameter('route') == 'null') {
|
||
bounds = Array(bounds._northEast.lat,bounds._northEast.lng,bounds._southWest.lat,bounds._southWest.lng)
|
||
} else {
|
||
bounds = 0
|
||
}
|
||
|
||
$.ajax({
|
||
url: "/json/points/",
|
||
data: {
|
||
bounds: bounds
|
||
},
|
||
success: function (data) {
|
||
for(var i=0; i<data.length; i++) {
|
||
if (typeof points[data[i].id] == 'undefined') {
|
||
markers.addLayer(constructPoint(data[i]));
|
||
}
|
||
}
|
||
myMap.addLayer(markers);
|
||
allPointsLoaded = bounds == 0;
|
||
|
||
if (getURLParameter('point') != 'null')
|
||
{
|
||
if (getURLParameter('point') == 'random')
|
||
{
|
||
showRandomPoint();
|
||
}
|
||
else
|
||
{
|
||
showInfo(getURLParameter('point'));
|
||
}
|
||
} else if (getURLParameter('route') != 'null')
|
||
{
|
||
loadRouteJSON(getURLParameter('route'));
|
||
buildRoute(true);
|
||
} else if ((getURLParameter('lat') != 'null') && (getURLParameter('lng') != 'null') && (getURLParameter('zoom') != 'null'))
|
||
{
|
||
myMap.setView([getURLParameter('lat'), getURLParameter('lng')], getURLParameter('zoom'));
|
||
|
||
if (getURLParameter('marker') == 'true') {
|
||
L.popup()
|
||
.setLatLng([getURLParameter('lat'), getURLParameter('lng')])
|
||
.setContent('Координаты: N°' + getURLParameter('lat').substring(0,8) + ' E°' + getURLParameter('lng').substring(0,8))
|
||
.openOn(myMap);
|
||
}
|
||
} else if (getURLParameter('track') != 'null')
|
||
{
|
||
showTrack(getURLParameter('track'))
|
||
}
|
||
}
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
function loadPointsInBounds()
|
||
{
|
||
if (allPointsLoaded) {
|
||
return true;
|
||
}
|
||
|
||
bounds = myMap.getBounds();
|
||
bounds = Array(bounds._northEast.lat,bounds._northEast.lng,bounds._southWest.lat,bounds._southWest.lng)
|
||
|
||
$.ajax({
|
||
url: "/json/points/",
|
||
data: {
|
||
bounds: bounds
|
||
},
|
||
success: function (data) {
|
||
if (typeof (data) != 'undefined' && data.length > 0) {
|
||
for(var i=0; i < data.length; i++) {
|
||
if (typeof points[data[i].id] == 'undefined') {
|
||
markers.addLayer(constructPoint(data[i]));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
/**
|
||
* Показывает баллун для точки. Если данных для точки нет, то подгружает их с сервера.
|
||
* @param {type} id
|
||
* @returns {Boolean}
|
||
*/
|
||
function showInfo(id, mapClick,doNotPushToHistory)
|
||
{
|
||
if (!(id in points)) {
|
||
return false;
|
||
}
|
||
|
||
mapClick = Boolean(mapClick !== undefined && mapClick === true); // true если это клик по маркеру на карте
|
||
doNotPushToHistory = Boolean(doNotPushToHistory !== undefined && doNotPushToHistory === true); // true если НЕ добавляем в history
|
||
marker = points[id];
|
||
if (!(id in pointsSources))
|
||
{
|
||
marker.bindPopup("<h3>" + marker.options['title'] + "</h3><img src='/img/loading.gif' style='height: 16px;' /> Загрузка...").openPopup();
|
||
$.ajax({
|
||
url: "/json/point/id/" + id,
|
||
success: function (data) {
|
||
pointsSources[id] = data;
|
||
drawInfoPopup(id, true)
|
||
}
|
||
});
|
||
} else {
|
||
drawInfoPopup(id, !mapClick, doNotPushToHistory);
|
||
}
|
||
}
|
||
|
||
function drawInfoPopup(id, showPopup, doNotPushToHistory) {
|
||
data = pointsSources[id];
|
||
if (typeof (data.images) == 'object')
|
||
{
|
||
photos = '<div class="photoContainer">';
|
||
|
||
if (data.images.length > 1) {
|
||
photos += '<div class="photosCount"><span class="glyphicon glyphicon-camera"></span> <b>+' + (data.photosCount - 1) + '</b></div>';
|
||
}
|
||
|
||
photos += '<img src="/photos/small/' + data.img + '" onclick="showImage(\'' + id + '\')" />';
|
||
photos += '</div>';
|
||
}
|
||
else
|
||
{
|
||
photos = '<img src="' + data.img + '" onclick="showImage(\'' + id + '\')" />';
|
||
}
|
||
|
||
onModerate = '';
|
||
if (data.status != 'published') {
|
||
onModerate = 'На модерации: ';
|
||
}
|
||
|
||
description = '<div class="infoCard">' + '<h3>' + onModerate + data.name + '</h3>' + photos;
|
||
description += data.descriptionHtml;
|
||
description += '</div><div class="clear"></div>';
|
||
description += '<div class="btn-wrapper text-center"><div class="btn-group control">';
|
||
description += '<a type="button" class="btn btn-default" href="/point/' + id + '"><span class="glyphicon glyphicon-eye-open"></span> <span class="label">Подробнее</span></a>';
|
||
description += '<button type="button" class="btn btn-default" onclick="addToRoute(' + id + ')"><span class="glyphicon glyphicon-map-marker"></span> <span class="label">В маршрут</span></button>';
|
||
description += '<button type="button" class="btn btn-default" onclick="addRemoveLike(' + id + ')"><span id="myLikesButton" class="glyphicon glyphicon-' + (data.iLike ? 'ok' : 'thumbs-up') + '"></span> <span class="label">Нравится</span></button>';
|
||
description += '<button type="button" class="btn btn-default" onclick="addRemoveFavorite(' + id + ')"><span id="myFavoritesButton" class="glyphicon glyphicon-star' + (data.inFavorites ? '' : '-empty') + ' "></span> <span class="label">Хочу посетить</span></button>';
|
||
description += '<button type="button" class="btn btn-default" onclick="showRandomPoint();"><span class="glyphicon glyphicon-random"></span> <span class="label">Другая точка</span></button>';
|
||
|
||
if (isAdmin == '1' || data.status == "moderation")
|
||
{
|
||
description += '<button type="button" class="btn btn-default" onclick="editPoint(' + id + ')"><span class="glyphicon glyphicon-pencil"></span> <span class="label">Редактировать</span></button>';
|
||
if (getURLParameter('edit') == 'true')
|
||
{
|
||
editPoint(id);
|
||
}
|
||
}
|
||
description += '</div></div>';
|
||
|
||
maxWidth = $(window).width() < 500 ? ($(window).width() - 48) : 500;
|
||
maxHeight = $(window).height() < 300 ? $(window).height() : 300;
|
||
marker.options.description = description;
|
||
marker.bindPopup(marker.options.description, {maxWidth: maxWidth, minWidth: maxWidth, maxHeight: maxHeight});
|
||
|
||
markers.zoomToShowLayer(marker, function () {
|
||
bounds = myMap.getBounds();
|
||
diff = (bounds._northEast.lat - bounds._southWest.lat) / 4;
|
||
myMap.setView([points[id]._latlng.lat + diff, points[id]._latlng.lng], myMap.getZoom());
|
||
|
||
if (showPopup) {
|
||
marker.openPopup();
|
||
}
|
||
|
||
if (!doNotPushToHistory) {
|
||
history.pushState({pointId: id}, document.title, "/?point=" + id);
|
||
}
|
||
|
||
document.title = marker.options.title + ' – wikipoints.ru';
|
||
});
|
||
|
||
setTimeout(function(){
|
||
if (myMap._popup && $(window).width() < 665) {
|
||
$('#control').hide(200);
|
||
}
|
||
}, 200);
|
||
|
||
return true;
|
||
}
|
||
|
||
function setLayer(name)
|
||
{
|
||
if (layer)
|
||
myMap.removeLayer(layers[layer])
|
||
|
||
layer = name;
|
||
myMap.addLayer(layers[layer]);
|
||
$('.layers').removeClass('selected');
|
||
$('.' + layer + 'Layer').addClass('selected');
|
||
$.cookie('mapLayer', layer);
|
||
}
|
||
|
||
function showPointagreement()
|
||
{
|
||
$.ajax({
|
||
url: "/json/pointagreement",
|
||
success: function (data) {
|
||
$('#articleModal').modal('hide').remove();
|
||
$('body').append($(data));
|
||
$('#articleModal').modal('show');
|
||
}
|
||
});
|
||
}
|
||
|
||
// =============== ADD POINT
|
||
|
||
function addNewImage(link)
|
||
{
|
||
if ($('.extraImage', '#addPointForm').length < 10)
|
||
{
|
||
$('.extraImage', '#newIm').clone().appendTo('#imgsContainer').show(200);
|
||
if (link != undefined)
|
||
{
|
||
$('.form-control.images', '#addPointForm').last().attr('readonly', 'readonly').val(link);
|
||
$('.input-group-addon.type.button', '#addPointForm').remove();
|
||
}
|
||
}
|
||
}
|
||
|
||
function addNewExtraParam(name, value)
|
||
{
|
||
if ($('.extraParam', '#addPointForm').length < 10)
|
||
{
|
||
$('.extraParam', '#newExtraParam').clone().appendTo('#extraParamsContainer').show(200);
|
||
if (name != undefined && value != undefined)
|
||
{
|
||
$('.form-control.names', '#addPointForm').last().val(name);
|
||
$('.form-control.values', '#addPointForm').last().val(value);
|
||
}
|
||
}
|
||
}
|
||
|
||
function removeInput(el)
|
||
{
|
||
container = $(el).parent().parent();
|
||
container.hide(300, function () {
|
||
container.remove()
|
||
});
|
||
}
|
||
|
||
function switchType(el)
|
||
{
|
||
container = $(el).parent().parent();
|
||
if (container.hasClass('asLink'))
|
||
{
|
||
$('.ordering', container).val('FILE');
|
||
$('.ico span', container).removeClass('glyphicon-link').addClass('glyphicon-paperclip');
|
||
$('.form-control.images', container).attr('type', 'file').attr('name', 'photos[]');
|
||
$('.form-control.photoLinks', container).show();
|
||
container.removeClass('asLink');
|
||
el.attr('title', 'Указать ссылку на изображение');
|
||
$('.input-group-addon.type.ico', container).attr('title', 'Загрузите файл с изображением');
|
||
$('.input-group-addon.type.preview', container).hide();
|
||
}
|
||
else
|
||
{
|
||
$('.ordering', container).val('LINK');
|
||
$('.ico span', container).removeClass('glyphicon-paperclip').addClass('glyphicon-link');
|
||
$('.form-control.images', container).attr('type', 'text').attr('name', 'imgs[]');
|
||
$('.form-control.photoLinks', container).hide();
|
||
container.addClass('asLink');
|
||
el.attr('title', 'Загрузить файл');
|
||
$('.input-group-addon.type.ico', container).attr('title', 'Укажите ссылку на изображение');
|
||
$('.input-group-addon.type.preview', container).show();
|
||
}
|
||
}
|
||
|
||
function showPreview(el) {
|
||
img = $('input.images', el.parent()).val();
|
||
|
||
if ($('input.ordering', el.parent()).val() == 'FILE' || img.length < 12) {
|
||
return true;
|
||
}
|
||
|
||
if (img.toLowerCase().indexOf('http') == -1) {
|
||
img = '/photos/small/' + img;
|
||
}
|
||
|
||
$('#imgPreview').attr('src', img);
|
||
$('#imgPreview').show();
|
||
}
|
||
|
||
function hidePerview() {
|
||
$('#imgPreview').hide();
|
||
}
|
||
|
||
// ======================= VK Button
|
||
|
||
$(document).ready(function () {
|
||
if ($.cookie('doNotShowVKgroup')) {
|
||
$('#vkBigLogo').remove();
|
||
} else {
|
||
setTimeout(function () {
|
||
$('#vkBigLogo').css({'display': 'block'}).animate({'margin-left': "-225px"}, 1500);
|
||
}, 10000);
|
||
}
|
||
})
|
||
|
||
function hideBigLogo() {
|
||
$.cookie('doNotShowVKgroup', true, {expires: 100, path: '/'});
|
||
$('#vkBigLogo').animate({'margin-left': "285px"}, 1500, function () {
|
||
$('#vkBigLogo').remove();
|
||
});
|
||
}
|
||
|
||
// ======================= Swipe controll
|
||
|
||
window.addEventListener('load', function(){
|
||
var touchsurface = document.getElementById('box'),
|
||
startX,
|
||
startY,
|
||
dist,
|
||
threshold = 50,
|
||
allowedTime = 200,
|
||
elapsedTime,
|
||
startTime;
|
||
|
||
touchsurface.addEventListener('touchstart', function(e){
|
||
var touchobj = e.changedTouches[0];
|
||
dist = 0;
|
||
startX = touchobj.pageX;
|
||
startY = touchobj.pageY;
|
||
startTime = new Date().getTime();
|
||
}, false);
|
||
|
||
touchsurface.addEventListener('touchend', function(e){
|
||
var touchobj = e.changedTouches[0];
|
||
dist = touchobj.pageX - startX;
|
||
elapsedTime = new Date().getTime() - startTime;
|
||
var swiperightBol = (elapsedTime <= allowedTime && dist >= threshold && Math.abs(touchobj.pageY - startY) < dist);
|
||
|
||
if(swiperightBol) {
|
||
closeBox();
|
||
}
|
||
}, false);
|
||
|
||
}, false);
|
||
|
||
function getShortLink()
|
||
{
|
||
elements = Array();
|
||
$('#wayPoints div').each(function(i, el)
|
||
{
|
||
if ($(el).attr('pointId').length <= 10) {
|
||
elements.push({id: $(el).attr('pointId')});
|
||
} else {
|
||
coords = JSON.parse($(el).attr('pointId'));
|
||
lat = coords[0];
|
||
lng = coords[1];
|
||
elements.push({latLng: {lat: lat, lng: lng}});
|
||
}
|
||
|
||
});
|
||
|
||
$.ajax({
|
||
url: "/index/shorturlroute/",
|
||
data: {
|
||
elements: elements
|
||
},
|
||
success: function (data) {
|
||
$('#shortLink').val(data).select();
|
||
}
|
||
});
|
||
}
|
||
|
||
function onLocationFound(e) {
|
||
$.cookie('userLat', e.latlng.lat);
|
||
$.cookie('userLng', e.latlng.lng);
|
||
myMap.removeLayer(points.im);
|
||
points.im.setLatLng(e.latlng).addTo(myMap);
|
||
myMap.setView(e.latlng, myMap.getZoom());
|
||
|
||
return true;
|
||
}
|
||
|
||
function onLocationError(e) {
|
||
alert('Ошибка при определении координат: ' + e.message);
|
||
}
|