536 lines
16 KiB
JavaScript
536 lines
16 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;
|
||
|
||
categories.im = L.icon({
|
||
iconUrl: '/ico/man.png',
|
||
iconSize: [32, 37],
|
||
iconAnchor: [16, 37],
|
||
popupAnchor: [0, 1]
|
||
});
|
||
|
||
// -----------------------------------------------------------------------------
|
||
|
||
/**
|
||
* Инициализируем яндекс-карты и узнаём расположение пользователя.
|
||
*/
|
||
ymaps.ready(function () {
|
||
lat = ymaps.geolocation.latitude;
|
||
lng = ymaps.geolocation.longitude;
|
||
init(lat, lng);
|
||
|
||
points.im = L.marker([lat, lng], {icon: categories.im, title: 'Вы здесь'});
|
||
points.im.addTo(myMap);
|
||
points.im.bindPopup('<b>Ваше местоположение</b><br/><img src="/ico/man.png" /> <button type="button" class="btn btn-default btn-xs" onclick="addToRoute(\'im\')"><span class="glyphicon glyphicon-plus"></span> Добавить в маршрут</button>')
|
||
});
|
||
|
||
/**
|
||
* Инициализируем переменные и подгружаем данные.
|
||
* @returns true
|
||
*/
|
||
function init(lat, lng) {
|
||
myMap = L.map('map', {zoomControl: false}).setView([lat, lng], defaultZoom);
|
||
markers = new L.MarkerClusterGroup({showCoverageOnHover: false, maxClusterRadius: 45});
|
||
|
||
layers['quest'] = L.tileLayer('http://otile1.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>', maxZoom: 18});
|
||
layers['osm'] = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery ©</a>', maxZoom: 18});
|
||
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)
|
||
{
|
||
$('#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();
|
||
|
||
myMap.on('moveend', function (e) {
|
||
if (!myMap._popup && $('#boxRoute').css('display') == 'none' && status != statusMovingInHistory)
|
||
{
|
||
document.title = pointsCount + ' или даже больше поводов не сидеть дома';
|
||
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());
|
||
}
|
||
|
||
if (status == statusMovingInHistory)
|
||
{
|
||
resetStatus();
|
||
}
|
||
});
|
||
|
||
$('.filterSelector').bind('change', function () {
|
||
filter()
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Создаёт точку для карту - Placemark.
|
||
* @param {Array} data
|
||
* @returns {ymaps.Placemark}
|
||
*/
|
||
function constructPoint(data)
|
||
{
|
||
id = data['id'];
|
||
|
||
points[id] = L.marker(
|
||
[data['lat'], data['lng']], {icon: categories[data['categoryId']], title: data['name'], id: id, categoryId: data['categoryId']}
|
||
).on('click', function (e) {
|
||
showInfo(e.target.options.id);
|
||
});
|
||
|
||
return points[id];
|
||
}
|
||
|
||
/**
|
||
* Загружает точки с сервера.
|
||
* @returns {Boolean}
|
||
*/
|
||
function initPoints()
|
||
{
|
||
$.ajax({
|
||
url: "/json/points/",
|
||
success: function (data) {
|
||
for (var k in data) {
|
||
markers.addLayer(constructPoint(data[k]));
|
||
}
|
||
myMap.addLayer(markers);
|
||
|
||
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'));
|
||
}
|
||
}
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Показывает баллун для точки. Если данных для точки нет, то подгружает их с сервера.
|
||
* @param {type} id
|
||
* @returns {Boolean}
|
||
*/
|
||
function showInfo(id)
|
||
{
|
||
marker = points[id];
|
||
|
||
if (!(id in points) || marker.options.description == undefined)
|
||
{
|
||
marker.bindPopup("Загрузка...").openPopup();
|
||
$.ajax({
|
||
url: "/json/point/id/" + id,
|
||
success: function (data) {
|
||
pointsSources[id] = data;
|
||
if (typeof (data.images) == 'object')
|
||
{
|
||
photos = '<div style="position: relative;">';
|
||
|
||
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 + '\')" />';
|
||
}
|
||
|
||
description = '<div class="infoCard">' + '<h3>' + data.name + '</h3>' + photos;
|
||
description += data.descriptionHtml;
|
||
description += '</div><div class="clear"></div>';
|
||
description += '<div class="btn-group control">';
|
||
|
||
if (data.source.length > 11)
|
||
{
|
||
description += '<a type="button" class="btn btn-default" href="' + data.source + '" target="blank"><span class="glyphicon glyphicon-eye-open"></span> <span class="label">Подробнее</span></a>';
|
||
}
|
||
// description += '<a type="button" class="btn btn-default" href="/page/point/id/' + 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"><span class="glyphicon glyphicon-ok"></span> <span class="label">Был здесь</span></button>';
|
||
// description += '<button type="button" class="btn btn-default"><span class="glyphicon glyphicon-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>';
|
||
|
||
if (isAdmin == '1')
|
||
{
|
||
description += '<button type="button" class="btn btn-default" onclick="editPoint(' + id + ')"><span class="glyphicon glyphicon-pencil"></span> <span class="label">Редактировать</span></button>';
|
||
}
|
||
description += '</div>';
|
||
|
||
marker.options.description = description;
|
||
marker.bindPopup(marker.options.description, {maxWidth: 500, maxHeight: 300});
|
||
|
||
markers.zoomToShowLayer(marker, function () {
|
||
marker.openPopup();
|
||
|
||
bounds = myMap.getBounds();
|
||
diff = (bounds._northEast.lat - bounds._southWest.lat) / 4;
|
||
myMap.setView([points[id]._latlng.lat + diff, points[id]._latlng.lng], myMap.getZoom());
|
||
|
||
history.pushState({pointId: id}, document.title, "/?point=" + id);
|
||
document.title = data.name;
|
||
});
|
||
}
|
||
});
|
||
} else {
|
||
bounds = myMap.getBounds();
|
||
diff = (bounds._northEast.lat - bounds._southWest.lat) / 4;
|
||
myMap.setView([points[id]._latlng.lat + diff, points[id]._latlng.lng], myMap.getZoom());
|
||
|
||
history.pushState({pointId: id}, document.title, "/?point=" + id);
|
||
document.title = points[id].options.title;
|
||
}
|
||
}
|
||
|
||
function showRandomPoint()
|
||
{
|
||
roundIndex = Math.floor(Math.random() * points.length);
|
||
runner = 0;
|
||
for (var key in points)
|
||
{
|
||
if (runner++ >= roundIndex)
|
||
return showInfo(key);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Загружает с сервера список категорий точек.
|
||
* @returns {Boolean}
|
||
*/
|
||
function initCategories()
|
||
{
|
||
$.ajax({
|
||
url: "/json/categories/",
|
||
success: function (data) {
|
||
for (var k in data) {
|
||
categories[data[k]['id']] = L.icon({
|
||
iconUrl: data[k]['icon'],
|
||
iconSize: [32, 37],
|
||
iconAnchor: [16, 37],
|
||
popupAnchor: [0, 1]
|
||
});
|
||
}
|
||
|
||
initPoints();
|
||
}
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Производит поиск по адресу или координатам, введённым в соответствующее поле.
|
||
* @returns {undefined}
|
||
*/
|
||
function searchAdderess()
|
||
{
|
||
$.ajax({
|
||
url: "/json/geocoding",
|
||
data: {
|
||
search: $('#addressField').val()
|
||
},
|
||
success: function (data)
|
||
{
|
||
if (data.lat && data.lng)
|
||
{
|
||
myMap.setView([data.lat, data.lng], defaultZoom);
|
||
L.popup()
|
||
.setLatLng([data.lat, data.lng])
|
||
.setContent('Координаты: lat:' + data.lat + ' lng:' + data.lng)
|
||
.openOn(myMap);
|
||
} else
|
||
{
|
||
alert('Ничего не найдено.');
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Пытается более точно определить координаты пользователя на карте и, при необходимости, обновляет положение точки "im"
|
||
* @returns {undefined}
|
||
*/
|
||
function showMeOnTheMap()
|
||
{
|
||
navigator.geolocation.getCurrentPosition(function (pos) {
|
||
coords = [pos.coords.latitude, pos.coords.longitude];
|
||
myMap.removeLayer(points.im);
|
||
points.im.setLatLng(coords).addTo(myMap);
|
||
myMap.setView(coords, defaultZoom);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Активирет добавление точки - ждёт выбор координат, меняет курсор на прицел.
|
||
* @returns {Boolean}
|
||
*/
|
||
function activateAddPoint()
|
||
{
|
||
$('#addPointButton').toggleClass('active');
|
||
if ($('#addPointButton').hasClass('active'))
|
||
{
|
||
$('.extraImage', '#imgsContainer').remove();
|
||
addNewImage();
|
||
$('#map').css('cursor', 'crosshair');
|
||
setStatus(statusHunting)
|
||
}
|
||
else
|
||
{
|
||
$('#map').css('cursor', 'arrow');
|
||
setStatus(statusReady)
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Отправляет данные о точке на сервер.
|
||
* @returns {Boolean}
|
||
*/
|
||
function addPoint()
|
||
{
|
||
$('.form-group').removeClass('has-error');
|
||
if (status != statusSendingToServer)
|
||
{
|
||
setStatus(statusSendingToServer)
|
||
id = $('#addPointId').length ? $('#addPointId').val() : 0;
|
||
hasImages = false;
|
||
$("input[name='imgs[]']", '#addPointForm').each(function () {
|
||
if ($(this).val().length > 10)
|
||
hasImages = true;
|
||
});
|
||
$("input[name='photos[]']", '#addPointForm').each(function () {
|
||
if ($(this).val().length > 5)
|
||
hasImages = true;
|
||
})
|
||
$.ajax({
|
||
type: "POST",
|
||
url: "/json/addpoint/",
|
||
data: {
|
||
name: $('#addPointName').val(),
|
||
img: hasImages ? 1 : 0,
|
||
description: $('#addPointDescription').val(),
|
||
categoryId: $('#addPointCategoryId').val(),
|
||
source: $('#addPointSource').val(),
|
||
lat: $('#addPointLat').val(),
|
||
lng: $('#addPointLng').val(),
|
||
id: id
|
||
},
|
||
success: function (data) {
|
||
if ($("input[name='photos[]']").length > 0 || $("input[name='imgs[]']").length > 0)
|
||
{
|
||
$('<input type="hidden" id="addPointId" name="id"/>').appendTo('#addPointForm').val(data);
|
||
$('#addPointForm').submit();
|
||
}
|
||
|
||
text = id ? 'Точка успешно отредактирована!' : 'Точка успешно добавлена!';
|
||
if (id)
|
||
{
|
||
markers.removeLayer(points[id]);
|
||
}
|
||
|
||
balloon = L.popup()
|
||
.setLatLng([$('#addPointLat').val(), $('#addPointLng').val()])
|
||
.setContent(text)
|
||
.openOn(myMap);
|
||
setTimeout(function () {
|
||
balloon._close();
|
||
delete balloon;
|
||
}, 2000);
|
||
|
||
obj = {};
|
||
obj.id = data;
|
||
obj.name = $('#addPointName').val();
|
||
obj.lat = $('#addPointLat').val();
|
||
obj.lng = $('#addPointLng').val();
|
||
obj.categoryIcon = categories[$('#addPointCategoryId').val()].icon;
|
||
obj.categoryId = $('#addPointCategoryId').val();
|
||
|
||
setTimeout(function () {
|
||
markers.addLayer(constructPoint(obj));
|
||
}, 2000);
|
||
|
||
$('#addPointModal').modal('hide');
|
||
|
||
// Clear form
|
||
$('#addPointForm input').val('');
|
||
$('#addPointForm textarea').val('');
|
||
$('.form-group').removeClass('has-error');
|
||
$('#addPointButton').removeClass('active');
|
||
$('#addPointId').remove();
|
||
$('#map').css('cursor', 'arrow');
|
||
setStatus(statusReady);
|
||
|
||
return true;
|
||
},
|
||
error: function (data) {
|
||
response = data.responseJSON;
|
||
message = '';
|
||
for (var k in response) {
|
||
if (typeof response[k] !== 'function') {
|
||
if (k == 1)
|
||
$('#addPointName').parent().addClass('has-error');
|
||
else
|
||
if (k == 2)
|
||
{
|
||
$('.extraImage', '#addPointForm').addClass('has-error');
|
||
}
|
||
else
|
||
if (k == 3)
|
||
$('#addPointDescription').parent().addClass('has-error');
|
||
else
|
||
message += response[k] + '; ';
|
||
}
|
||
}
|
||
|
||
if (message != '')
|
||
alert(message);
|
||
|
||
resetStatus();
|
||
return false;
|
||
}
|
||
});
|
||
}
|
||
else
|
||
{
|
||
alert('Точка добавляется, нужно немного подождать.');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Включает режим редактирования точки.
|
||
* @param int id
|
||
* @returns {undefined}
|
||
*/
|
||
function editPoint(id)
|
||
{
|
||
$('#addPointId').remove();
|
||
$('<input type="hidden" id="addPointId" name="id"/>').appendTo('#addPointForm').val(id);
|
||
$('#addPointName').val(pointsSources[id].name);
|
||
$('#addPointDescription').val(pointsSources[id].description);
|
||
$("#addPointCategoryId option").attr('selected', null);
|
||
$("#addPointCategoryId option[value='" + pointsSources[id].categoryId + "']").attr('selected', 'selected');
|
||
$('#addPointSource').val(pointsSources[id].source);
|
||
$('#addPointLat').val(pointsSources[id].lat);
|
||
$('#addPointLng').val(pointsSources[id].lng);
|
||
|
||
$('.extraImage', '#imgsContainer').remove();
|
||
if (pointsSources[id].images != undefined && pointsSources[id].images.length > 0)
|
||
{
|
||
for (var i = 0; i < pointsSources[id].images.length; i++)
|
||
{
|
||
addNewImage(pointsSources[id].images[i]);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
addNewImage(pointsSources[id].img);
|
||
}
|
||
|
||
closePopup();
|
||
$('#addPointModal').modal('show');
|
||
setStatus(statusEdit);
|
||
}
|
||
|
||
function editSetNewCoords()
|
||
{
|
||
$('#addPointModal').modal('hide');
|
||
$('#map').css('cursor', 'crosshair');
|
||
setStatus(statusReHunting)
|
||
}
|
||
|
||
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 closePopup()
|
||
{
|
||
if (myMap._popup)
|
||
myMap._popup._close();
|
||
}
|
||
|
||
function filter()
|
||
{
|
||
var selected = new Array();
|
||
$('.filterSelector:checked').each(function (i, e) {
|
||
selected.push($(e).val());
|
||
});
|
||
|
||
for (var key in points)
|
||
{
|
||
if (selected.length == 0 || points[key].options.categoryId == undefined || selected.indexOf(points[key].options.categoryId) != -1)
|
||
{
|
||
markers.addLayer(points[key]);
|
||
}
|
||
else
|
||
{
|
||
markers.removeLayer(points[key]);
|
||
}
|
||
}
|
||
}
|