Страница «Маршрут» — единственная, которая имеет две шапки вверху сайта.
Вторая навигация позволяет перемещаться по разным «вкладкам» этой страницы. При этом всплывающее окно в правой части (или внизу на мобильных устройствах) не сбрасывается при переходе между вкладками. Например, вы можете выбрать остановку в алфавитном списке на вкладке «Остановки», а затем проложить маршрут до другой остановки, найдя её на схеме.
В далеком 2022 году реализация этой фичи была чисто джаваскриптовая: кнопки в навигации вызывали метод switch_tab(tab), в аргумент которой передавалась нужная вкладка. HTML-страница включала 4 div-блока, и функция просто показывала один нужный блок и прятала остальные три. URL при этом не менялся: https://kolomna-trams.ru/route/
function switch_tab(tab) {
if (tab == "") {
tab = "map";
}
document.getElementById('content-lines').style.display = 'none';
document.getElementById('content-stops').style.display = 'none';
document.getElementById('content-visit').style.display = 'none';
document.getElementById('content-map').style.display = 'none';
document.getElementById('content-' + tab).style.display = 'block';
}
switch_tab("map");О том, что это чудовищный костыль и так делать не нужно, мы догадались почти сразу. На каком-то из сайтов мы обнаружили использование хэшей (#...) для навигации. Оказалось, что JavaScript умеет отлавливать событие изменения хэша страницы и выполнять любое действие. Теперь сайт стал лучше: кнопки в навигации стали вполне себе ссылками, содержащими хэш:
- https://kolomna-trams.ru/route/#lines — маршруты
- https://kolomna-trams.ru/route/#stops — остановки
- https://kolomna-trams.ru/route/#visit — места
- https://kolomna-trams.ru/route/#map — схема
Если никакого хэша нет, то сайт считает, что нужно показать схему. А джаваскриптовый код переехал из обработчика события нажатия на кнопку в обработчик события смены хэша.
function switch_tab() {
let tab = window.location.hash;
tab = tab.substring(1);
if (tab == "") {
tab = "scheme";
}
document.getElementById('content-lines').style.display = 'none';
document.getElementById('content-stops').style.display = 'none';
document.getElementById('content-visit').style.display = 'none';
document.getElementById('content-map').style.display = 'none';
document.getElementById('content-' + tab).style.display = 'block';
}
switch_tab();
window.addEventListener('hashchange', switch_tab);Открылся дополнительный плюс этого метода — теперь у каждой вкладки появился уникальный URL, а значит и способ поделиться. К примеру, если ваш друг спрашивает, где можно посмотреть список остановок Коломенского трамвая, вы отправляете ему: https://kolomna-trams.ru/route/#stops, и нужная вкладка сама открывается у него на устройстве.
Увы, но такой способ имел большой недостаток. Технически, эти 4 вкладки были одной веб-страницей, и поисковиками индексировались как одна страница — а значит, открывалась она всегда на вкладке по умолчанию (на вкладке со схемой). И даже если условный Google смог сообразить, что на этой странице содержится информация об остановках трамваев, то если пользователь кликнет на ссылку из поисковой выдачи, он увидит:
А должен увидеть это:
Встала непростая задача. Нам нужно сделать так, чтобы четыре разные вкладки являлись разными веб-страницами (а значит, имели разные URL-адреса), при этом переход по ним не являлся переходом в прямом смысле этого слова (не перезагружал страницу).
Оказалось, что этому есть решение. Во-первых, мы переселили все вкладки на разные страницы:
- https://kolomna-trams.ru/route/lines/ — маршруты
- https://kolomna-trams.ru/route/stops/ — остановки
- https://kolomna-trams.ru/route/visit/ — места
- https://kolomna-trams.ru/route/map/ — схема
Во-вторых, сделали кнопки в навигации настоящими ссылками на эти страницы. То есть на них можно даже нажать правой кнопкой и выбрать «Открыть в новой вкладке». А на маке ещё и так можно сделать:
А главный фокус состоит в следующем. При нажатии на кнопку JavaScript перехватывает нажатие и запрещает прямой переход по ссылке. Вместо этого он загружает содержание страницы себе во внутреннюю переменную, достает оттуда контент вкладки (то есть то, что под шапкой, — саму шапку, а также подвал, обновлять не надо) и заменяет её прямо на текущей странице.
function set_up_buttons() {
var links = document.getElementsByClassName('trams-v3-subnav-link');
for (let i = 0; i < links.length; i++) {
const link_url = links[i].getAttribute('href');
links[i].addEventListener("click", (event) => {
event.preventDefault();
switch_tab(link_url);
});
}
}
function switch_tab(url) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
build_page(this.responseText, url);
window.history.replaceState(null, null, url + window.location.hash);
}
};
xhttp.open('GET', 'https://' + window.location.hostname + url);
xhttp.send();
}
set_up_buttons();А если у пользователя по какой-то причине отключен JavaScript или скрипт просто не подгрузился — ничего страшного, кнопки будут работать как обычные ссылки. Да, страница всё же будет перезагружаться и «магия» пропадёт, но зато человек сможет пользоваться сайтом, а не останется с нерабочим «кирпичом».