351 lines
9.8 KiB
PHP
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.

<div id="map" style="position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;"></div>
{{-- Верхняя панель поиска --}}
<div id="search-bar"
class="container-fluid py-3"
style="position:fixed;top:0;left:0;right:0;z-index:100;">
<div class="row">
<div class="col-md-6 mx-auto position-relative">
{{-- Поле ввода --}}
<input type="text"
id="address-input"
class="form-control form-control-lg shadow-lg"
style="border-radius:50px;font-size:28px;padding:20px 60px 20px 28px;"
placeholder="Введите адрес (дом, улица)…"
autocomplete="off">
{{-- Кнопка очистки --}}
<div id="clear-input-btn"
style="
position:absolute;
right:28px;
top:50%;
transform:translateY(-50%);
font-size:38px;
line-height:32px;
cursor:pointer;
display:none;
color:#666;
z-index:300;
">
&times;
</div>
{{-- Подсказки --}}
<div id="suggest-box"
class="list-group shadow position-absolute w-100"
style="z-index:200; display:none; max-height:300px; overflow-y:auto;
top:70px;border-radius:16px;">
</div>
{{-- Статус ожидания --}}
<div id="typing-status"
class="mt-2 text-center text-light"
style="display:none;text-shadow:0 0 3px black;">
Поиск ближайших адресов…
</div>
</div>
</div>
</div>
{{-- Модальное окно результата --}}
<div id="result-modal"
class="modal fade"
tabindex="-1"
role="dialog">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content shadow-lg" style="border-radius:20px;">
<div class="modal-body" id="modal-content-area" style="font-size:20px;"></div>
<div class="modal-footer text-center">
<button class="btn btn-primary btn-lg px-5" data-dismiss="modal">
Закрыть
</button>
</div>
</div>
</div>
</div>
<script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&apikey={{ $apikey }}"></script>
<script>
/* -----------------------------------------------------------
КОНСТАНТЫ
----------------------------------------------------------- */
const SUGGEST_KEY = "{{ $suggest_apikey }}";
const API_SUGGEST = "https://suggest-maps.yandex.ru/v1/suggest";
const SEARCH_CENTER = [59.859605, 30.340733];
const API_URL = "?cat={{$cat->cat}}&act=getInfo";
const SUGGEST_DELAY = 500;
const BBOX = "30.25163,59.81455~30.42983,59.90465";
let map, marker;
let typingTimer = null;
let lastTypedText = "";
let polygons = {}; // хранилище
/* -----------------------------------------------------------
КАРТА
----------------------------------------------------------- */
ymaps.ready(function () {
map = new ymaps.Map('map', {
center: SEARCH_CENTER,
zoom: 13,
controls: ['zoomControl'],
behaviors: ['drag', 'scrollZoom']
});
// Рендер существующих участков
@if (!empty($rows))
@foreach($rows as $row)
addPolygon(
{!! $row['coords'] !!},
{{ (int)$row['id'] }},
'{{ $row['color'] }}' // hex
);
@endforeach
@endif
});
function addPolygon(coords, id, color) {
if (!coords || !coords.length) return;
var polygon = new ymaps.Polygon(
coords,
{ polygon_id: id }, // ← сохраняем id внутри объекта
{
fillColor: color || '#00AAFF55',
strokeColor: '#0000FF',
strokeWidth: 2,
opacity: 0.6
}
);
// КЛИК ПО ПОЛИГОНУ
polygon.events.add('click', function (e) {
var pid = polygon.properties.get('polygon_id');
openPolygonInfo(pid);
});
map.geoObjects.add(polygon);
polygons[id] = polygon;
}
/* -----------------------------------------------------------
ЭЛЕМЕНТЫ
----------------------------------------------------------- */
var $input = $("#address-input");
var $suggest = $("#suggest-box");
var $typingStatus = $("#typing-status");
var $clearBtn = $("#clear-input-btn");
/* -----------------------------------------------------------
ФОКУС → ОЧИСТКА ПОЛЯ
----------------------------------------------------------- */
$input.on("focus", function () {
if ($(this).val().length > 0) {
$(this).val("");
$suggest.hide();
$typingStatus.hide();
$clearBtn.hide();
}
});
/* -----------------------------------------------------------
ПОКАЗ/СКРЫТИЕ КРЕСТИКА
----------------------------------------------------------- */
$input.on("input", function () {
if ($(this).val().length > 0) {
$clearBtn.show();
} else {
$clearBtn.hide();
$suggest.hide();
$typingStatus.hide();
}
});
/* Клик по крестику */
$clearBtn.on("click", function () {
$input.val("");
$input.focus();
$suggest.hide();
$typingStatus.hide();
$clearBtn.hide();
});
/* -----------------------------------------------------------
ОБРАБОТКА ВВОДА + ЗАДЕРЖКА ПЕРЕД ЗАПРОСОМ
----------------------------------------------------------- */
$input.on("input", function () {
var text = $(this).val().trim();
if (text.length < 4) {
$suggest.hide();
$typingStatus.hide();
return;
}
$typingStatus.show();
$suggest.hide();
lastTypedText = text;
clearTimeout(typingTimer);
typingTimer = setTimeout(function () {
loadSuggest(lastTypedText);
}, SUGGEST_DELAY);
});
/* -----------------------------------------------------------
ЗАГРУЗКА ПОДСКАЗОК
----------------------------------------------------------- */
function loadSuggest(query) {
$.getJSON(API_SUGGEST, {
"apikey": SUGGEST_KEY,
"text": query,
"lang": "ru_RU",
"types": "house",
"bbox": BBOX,
"ll": SEARCH_CENTER[1] + "," + SEARCH_CENTER[0],
"strict_bounds": 1
}, function (data) {
$typingStatus.hide();
renderSuggest(data.results || []);
}).fail(function(){
$typingStatus.hide();
renderSuggestError("Сервис подсказок недоступен");
});
}
/* -----------------------------------------------------------
СПИСОК ПОДСКАЗОК
----------------------------------------------------------- */
function renderSuggest(list) {
$suggest.empty();
if (!list.length) {
$suggest.html(
'<div class="list-group-item py-3 text-muted text-center">Адресов не найдено</div>'
).show();
return;
}
list.forEach(function (item) {
var title = item.title && item.title.text ? item.title.text : "";
var subtitle = item.subtitle && item.subtitle.text ? item.subtitle.text : "";
var full = title + (subtitle ? ", " + subtitle : "");
var html =
'<a href="#" class="list-group-item list-group-item-action py-3" data-address="' + full + '">' +
'<div class="font-weight-bold">' + title + '</div>' +
'<div class="small text-muted">' + subtitle + '</div>' +
'</a>';
$suggest.append(html);
});
$suggest.show();
}
function renderSuggestError(msg) {
$suggest.empty().html(
'<div class="list-group-item py-3 text-danger text-center">' + msg + '</div>'
).show();
}
/* -----------------------------------------------------------
ВЫБОР ПОДСКАЗКИ → ГЕОКОДЕР
----------------------------------------------------------- */
$(document).on("click", "#suggest-box a", function (e) {
e.preventDefault();
var addr = $(this).attr("data-address");
$input.val(addr);
$suggest.hide();
ymaps.geocode(addr, { results: 1 }).then(function (res) {
var obj = res.geoObjects.get(0);
if (!obj) {
showModal("<div class='text-danger'>Не удалось определить координаты</div>");
return;
}
var coords = obj.geometry.getCoordinates();
placeMarker(coords, addr);
sendToServer(coords);
}).catch(function(){
showModal("<div class='text-danger'>Ошибка геокодирования</div>");
});
});
/* -----------------------------------------------------------
МАРКЕР
----------------------------------------------------------- */
function placeMarker(coords, caption) {
if (marker) map.geoObjects.remove(marker);
marker = new ymaps.Placemark(coords, {
iconCaption: caption
}, { preset: 'islands#redIcon' });
map.geoObjects.add(marker);
map.panTo(coords, { flying:true });
}
/* -----------------------------------------------------------
ОТПРАВКА НА СЕРВЕР
----------------------------------------------------------- */
function sendToServer(coords) {
$.post(API_URL, { coords: coords }, function (html) {
showModal(html);
}).fail(function(){
showModal("<p class='text-danger'>Нет связи с сервером</p>");
});
}
/* -----------------------------------------------------------
ОТКРЫТИЕ ИНФО ПО ПОЛИГОНУ
----------------------------------------------------------- */
function openPolygonInfo(id) {
$.post(API_URL, { polygon_id: id }, function (html) {
showModal(html);
}).fail(function () {
showModal("<p class='text-danger'>Нет связи с сервером</p>");
});
}
/* -----------------------------------------------------------
МОДАЛКА
----------------------------------------------------------- */
function showModal(content) {
$("#modal-content-area").html(content);
$("#result-modal").modal("show");
}
</script>
<style>
#address-input {
height: 60px !important;
font-size: 28px;
border-radius: 40px;
}
#suggest-box a {
font-size: 22px;
border-left: 0; border-right:0;
}
.modal-content {
font-size: 20px;
}
</style>