wikipoints/public/js/map.js

477 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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 &copy; <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 &copy; <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('quest');
initCategories(); // getPoints внутри
myMap.on('click', function(e) {
if (!myMap._popup) {
if (status == statusHunting)
{
$('#addPointId').remove();
$('#addPointForm input').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();
myMap.on('moveend', function(e) {
if (!myMap._popup && $('#boxRoute').css('display') == 'none')
{
history.pushState({}, document.title, "/?lat=" + myMap.getCenter().lat + "&lng=" + myMap.getCenter().lng + "&zoom=" + myMap.getZoom());
document.title = pointsCount+' или даже больше поводов не сидеть дома';
}
});
$('.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')
{
roundIndex = Math.floor(Math.random()*points.length);
runner = 0;
for(var key in points)
{
if(runner++ >= roundIndex)
return showInfo(key);
}
}
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;
description = '<div class="infoCard">' +
'<h3>' + data.name + '</h3>' +
'<img src="' + data.img + '" onclick="showImage(\''+ data.img +'\',\''+ data.name +'\')" />' +
'<button type="button" class="btn btn-default btn-xs" onclick="addToRoute(' + id + ')">' +
'<span class="glyphicon glyphicon-plus"></span> Добавить в маршрут' +
'</button><br/>';
if (isAdmin == '1')
{
description = description + '<button type="button" class="btn btn-default btn-xs" onclick="editPoint(' + id + ')">' +
'<span class="glyphicon glyphicon-pencil"></span> Редактировать' +
'</button><br/>';
}
description = description + data.descriptionHtml;
if (data.source.length > 11)
{
//description = description + ' <a href="/page/point/id/' + id + '" target="blank">Подробнее...</a>';
description = description + ' <a href="' + data.source + '" target="blank">Подробнее...</a>';
}
description = description + '</div><div class="clear"></div>';
marker.options.description = description;
marker.bindPopup(marker.options.description, {maxWidth: 500, maxHeight: 300});
markers.zoomToShowLayer(marker,function() {
marker.openPopup();
history.pushState({}, document.title, "/?point=" + id);
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({}, 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({}, document.title, "/?point=" + id);
document.title = points[id].options.title;
}
}
/**
* Загружает с сервера список категорий точек.
* @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'))
{
$('#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;
$.ajax({
type: "POST",
url: "/json/addpoint/",
data: {
name: $('#addPointName').val(),
img: $('#addPointImg').val(),
description: $('#addPointDescription').val(),
categoryId: $('#addPointCategoryId').val(),
source: $('#addPointSource').val(),
lat: $('#addPointLat').val(),
lng: $('#addPointLng').val(),
id: id
},
success: function(data) {
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)
$('#addPointImg').parent().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);
$('#addPointImg').val(pointsSources[id].img);
$('#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);
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');
}
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]);
}
}
}