wikipoints/public/js/main.js

605 lines
17 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 statusReady = 0; // Обычный режим. Просмотр точек, навигация по карте и прочее.
var statusHunting = 1; // Курсор-прицел. Поиск места для добавления точки.
var statusReHunting = 2; // КУрсор прицел. Переопределение координат точки.
var statusAdd = 3; // Открыто окно добавления точки - форма.
var statusEdit = 4; // Открыто окно редактирования точки. В нём информация о существующей точке, включая ID.
var statusSendingToServer = 5; // Отправлен запрос на сервер - ждём, не даём жать кнопку повторно, отвлекаем пользователя.
var status = statusReady;
var statusPrev = statusReady;
/**
* Устанавливает новое значение статуса.
* @returns {undefined}
*/
function setStatus(value)
{
statusPrev = status;
status = value;
}
/**
* Меняет значение статуса на предыдущее.
* @returns {undefined}
*/
function resetStatus()
{
tmp = status;
status = statusPrev;
statusPrev = tmp;
}
// -----------------------------------------------------------------------------
ymaps.ready(init);
var myMap;
var categories;
var points = Array();
var pointsSources = Array();
var search;
var route = false;
var addPointInProcess = false;
// -------------------------------- Libs ---------------------------------------
function getURLParameter(name) {
return decodeURI((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1]);
}
// -----------------------------------------------------------------------------
/**
* Инициализируем переменные и подгружаем данные.
* @returns true
*/
function init() {
questLayer = function () {
return new ymaps.Layer(
'http://otile1.mqcdn.com/tiles/1.0.0/osm/%z/%x/%y.png', {projection: ymaps.projection.sphericalMercator});
};
ymaps.layer.storage.add('quest#layer', questLayer);
ymaps.mapType.storage.add('quest#type', new ymaps.MapType('MapQuest', ['quest#layer']));
osmLayer = function () {
return new ymaps.Layer(
'http://c.tile.openstreetmap.org/%z/%x/%y.png', {projection: ymaps.projection.sphericalMercator});
};
ymaps.layer.storage.add('osm#layer', osmLayer);
ymaps.mapType.storage.add('osm#type', new ymaps.MapType('OpenStreetMap', ['osm#layer']));
googleLayer = function () {
return new ymaps.Layer('http://mt0.google.com/vt/lyrs=s@176000000&hl=ru&%c', {projection: ymaps.projection.sphericalMercator,tileTransparent: true});
}
ymaps.layer.storage.add('google#layer', googleLayer);
ymaps.mapType.storage.add('google#type', new ymaps.MapType('Google Maps', ['google#layer']));
myMap = new ymaps.Map("map", {
center: [ymaps.geolocation.latitude, ymaps.geolocation.longitude],
zoom: 12,
type:'quest#type',
behaviors: ['default', 'scrollZoom']
});
myMap.controls.add('mapTools');
myMap.controls.add('smallZoomControl');
myMap.controls.add('scaleLine');
typeSelector = new ymaps.control.TypeSelector();
typeSelector.addMapType('quest#type', 0);
typeSelector.addMapType('google#type', 1);
typeSelector.addMapType('yandex#publicMap', 2);
typeSelector.addMapType('osm#type', 3);
myMap.controls.add(typeSelector);
myMap.copyrights.add('Участники <a href="http://www.openstreetmap.org/copyright" target="blank">OpenStreetMap</a>');
myMap.copyrights.add('Tiles courtesy of <a href="http://www.mapquest.com/" target="blank">MapQuest</a>');
initCategories()
getPoints();
myMap.events.add('click', function(e) {
if (!myMap.balloon.isOpen()) {
if (status == statusHunting)
{
coords = e.get('coordPosition');
$('#addPointId').remove();
$('#addPointForm input').val('');
$("#addPointCategoryId option" ).attr('selected', null);
$('#addPointLat').val(coords[0].toPrecision(11));
$('#addPointLng').val(coords[1].toPrecision(11));
$('#myModalLabel').text('Добавление новой точки');
$('#addPointModal').modal('show');
} else if (status == statusReHunting)
{
resetStatus();
coords = e.get('coordPosition');
$('#addPointLat').val(coords[0].toPrecision(11));
$('#addPointLng').val(coords[1].toPrecision(11));
$('#myModalLabel').text('Редактирование точки');
$('#addPointModal').modal('show');
}
}
else {
myMap.balloon.close();
}
});
myMap.events.add('boundschange', function(e) {
if (!myMap.balloon.isOpen() && $('#routeWindow').css('display') == 'none')
{
history.pushState({}, document.title, "/?lat=" + e.get('newCenter')[0] + "&lng=" + e.get('newCenter')[1] + "&zoom=" + e.get('newZoom'));
}
});
points.im = new ymaps.Placemark(
[ymaps.geolocation.latitude, ymaps.geolocation.longitude],
{
balloonContentHeader: 'Вы здесь',
hintContent: 'Ваше местоположение',
balloonContent:
'<button type="button" class="btn btn-default btn-xs" onclick="addToRoute(\'im\')">' +
'<span class="glyphicon glyphicon-plus"></span> Добавить в маршрут' +
'</button>'
},
{
iconImageHref: '/ico/man.png',
iconImageSize: [32, 37],
iconImageOffset: [-16, -33],
}
);
myMap.geoObjects.add(points.im);
$("#wayPoints").sortable();
$("#wayPoints").disableSelection();
return true;
}
/**
* Создаёт точку для карту - Placemark.
* @param {Array} data
* @returns {ymaps.Placemark}
*/
function constructPoint(data)
{
id = data['id'];
points[id] = new ymaps.Placemark(
[data['lat'], data['lng']], {
hintContent: data['name'],
id: id
},
{
iconImageHref: data['categoryIcon'],
iconImageSize: [32, 37],
iconImageOffset: [-16, -33],
openEmptyBalloon: true,
balloonCloseButton: true
});
points[id].events.add('click', function(e) {
showInfo(e.get('target').properties.get('id'));
});
return points[id];
}
/**
* Загружает точки с сервера.
* @returns {Boolean}
*/
function getPoints()
{
$.ajax({
url: "/json/points/",
success: function(data) {
for (var k in data) {
myMap.geoObjects.add(constructPoint(data[k]));
}
if (getURLParameter('point') != 'null')
{
showInfo(getURLParameter('point'));
} else if (getURLParameter('route') != 'null')
{
loadRouteJSON(getURLParameter('route'));
buildRoute();
} else if ((getURLParameter('lat') != 'null') && (getURLParameter('lng') != 'null') && (getURLParameter('zoom') != 'null'))
{
myMap.setCenter([getURLParameter('lat'), getURLParameter('lng')], getURLParameter('zoom'));
}
}
});
return true;
}
/**
* Показывает баллун для точки. Если данных для точки нет, то подгружает их с сервера.
* @param {type} id
* @returns {Boolean}
*/
function showInfo(id)
{
if (!(id in points) || points[id].properties.get('balloonContent') == undefined)
{
points[id].properties.set('balloonContent', 'Загрузка...');
$.ajax({
url: "/json/point/id/" + id,
success: function(data) {
pointsSources[id] = data;
description = '<div class="infoCard">' +
'<h3>' + data.name + '</h3>' +
'<img src="' + data.img + '" />' +
'<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="' + data.source + '" target="blank">Подробнее...</a>';
description = description + '</div>';
points[id].properties.set('balloonContent', description);
point = getURLParameter('point');
if (point != null && id == point)
{
points[point].balloon.open();
}
}
});
}
history.pushState({}, document.title, "/?point=" + id);
return true;
}
/**
* Загружает с сервера список категорий точек.
* @returns {Boolean}
*/
function initCategories()
{
$.ajax({
url: "/json/categories/",
success: function(data) {
categories = data;
}
});
return true;
}
/**
* Производит поиск по адресу или координатам, введённым в соответствующее поле.
* @returns {undefined}
*/
function searchAdderess()
{
var myGeocoder = ymaps.geocode($('#addressField').val());
myGeocoder.then(
function(res) {
search = new ymaps.Placemark(res.geoObjects.get(0).geometry.getCoordinates());
myMap.geoObjects.add(search);
myMap.setCenter(res.geoObjects.get(0).geometry.getCoordinates(), 10);
},
function(err) {
}
);
}
/**
* Пытается более точно определить координаты пользователя на карте и, при необходимости, обновляет положение точки "im"
* @returns {undefined}
*/
function showMeOnTheMap()
{
navigator.geolocation.getCurrentPosition(function(pos) {
points.im.geometry.setCoordinates([pos.coords.latitude, pos.coords.longitude]);
myMap.setCenter(points.im.geometry.getCoordinates());
});
myMap.setCenter(points.im.geometry.getCoordinates());
}
/**
* Активирет добавление точки - ждёт выбор координат, меняет курсор на прицел.
* @returns {Boolean}
*/
function activateAddPoint()
{
$('#addPointButton').toggleClass('btn-success').toggleClass('btn-default');
if ($('#addPointButton').hasClass('btn-success'))
{
myMap.cursors.push('crosshair');
setStatus(statusHunting)
}
else
{
myMap.cursors.push('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 )
{
myMap.geoObjects.remove(points[id]);
}
balloon = myMap.balloon.open([$('#addPointLat').val(), $('#addPointLng').val()], {content: text}, {closeButton: false});
setTimeout(function() {
balloon.close();
}, 2000);
obj = {};
obj.id = data;
obj.name = $('#addPointName').val();
obj.lat = $('#addPointLat').val();
obj.lng = $('#addPointLng').val();
obj.categoryIcon = categories[$('#addPointCategoryId').val()].icon;
setTimeout(function() {
myMap.geoObjects.add(constructPoint(obj));
}, 2000);
$('#addPointModal').modal('hide');
// Clear form
$('#addPointForm input').val('');
$('#addPointForm textarea').val('');
$('.form-group').removeClass('has-error');
$('#addPointButton').removeClass('btn-success').addClass('btn-default');
$('#addPointId').remove();
myMap.cursors.push('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 ('Точка добавляется, нужно немного подождать.');
}
}
/**
* Строит маршрут по выбранным точкам.
* @returns {undefined}
*/
function buildRoute()
{
wayPoints = Array();
if (route)
myMap.geoObjects.remove(route);
$('#wayPoints div').each(function(i, el)
{
wayPoints.push(points[$(el).attr('pointId')].geometry.getCoordinates());
});
ymaps.route(wayPoints, {
mapStateAutoApply: true
}).then(function(newRoute) {
route = newRoute;
route.options.set({
// в балуне выводим только информацию о времени движения с учетом пробок
balloonContenBodyLayout: ymaps.templateLayoutFactory.createClass('$[properties.humanJamsTime]'),
strokeColor: '9000ffff',
opacity: 0.9
});
myMap.geoObjects.add(route);
distance = Math.round(route.getLength() / 1000);
$('#routeDistance').text(distance + ' км.');
routeToURL();
});
}
/**
* Сохраняет маршрут на сервере.
* @returns {undefined}
*/
function saveRoute()
{
wayPoints = Array();
name = prompt('Как назвать маршрут?', 'Мой маршрут');
$('#wayPoints div').each(function(i, el)
{
wayPoints.push($(el).attr('pointId'));
});
if (name && name != '')
$.ajax({
type: "POST",
url: "/json/saveroute/",
data: {
name: name,
points: wayPoints
},
success: function(data) {
console.log(data);
},
error: function(data) {
console.log(data);
}
});
}
/**
* Формирует список точек маршрута из JSON.ы
* @param {JSON} data
* @returns {Boolean}
*/
function loadRouteJSON(data)
{
$('#wayPoints').text('');
response = JSON.parse(data);
for (var k in response)
{
addToRoute(response[k]);
}
return true;
}
/**
* Подгружает маршрут с заданныи ID с сервера.
* @param {Integer} id
* @returns {undefined}
*/
function loadRoute(id)
{
$('#myRoutesWindow').hide(200);
$.ajax({
url: "/json/route/id/" + id,
success: function(data)
{
loadRouteJSON(data)
buildRoute();
}
});
}
/**
* Удаляет маршрут с заданным ID с сервера.
* @param {Integer} id
* @returns {undefined}
*/
function deleteRoute(id)
{
$.ajax({
url: "/json/deleteroute/id/" + id,
success: function(data)
{
console.log('Route '+id+' was removed.');
}
});
}
/**
* Добавляет точку с маршрут (в список выбранных точек)
* @param {Integer} id
* @returns {Boolean}
*/
function addToRoute(id)
{
$('#wayPoints').append('<div pointid="' + id + '" class="wayPoint"><span onclick="$(this).parent().remove()">&times;</span> ' + points[id].properties.get('hintContent') + '</div>');
myMap.balloon.close();
$('#routeWindow').show(200);
return true;
}
/**
* Формирует URL в соответсвии с точками маршрута.
* @returns {Boolean}
*/
function routeToURL()
{
wayPoints = Array();
$('#wayPoints div').each(function(i, el)
{
wayPoints.push($(el).attr('pointId'));
});
history.pushState({}, document.title, "/?route=" + JSON.stringify(wayPoints));
return true;
}
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);
myMap.balloon.close();
$('#addPointModal').modal('show');
setStatus(statusEdit);
}
function editSetNewCoords()
{
$('#addPointModal').modal('hide');
myMap.cursors.push('crosshair');
setStatus(statusReHunting)
}