Работа с #хэшем в url + history api
Последний проект, который я делал состоит из одной страницы, и все действия выполняются через Ajax.
Конечно, понадобилось сохранять состояние страницы, и самое универсальное решение — хэш.
Если кто не в курсе, хэшем url зовется всё, что идет после символа #. Изначально это было придумано для якорей и используется до сих пор всякими способами из-за одной особенности — изменение хэша не обновляет страницу.
То есть, при клике на ссылку, которая ссылается на саму себя, но с хэшем — документ пролистывается до нужного места, но страница не перезагружается.
Более простого и универсального способа сохранения статуса Ajax приложений пока не придумано. Все браузеры работают с ним нативно, без заморочек.
Поэтому я написал простенький объект, методы которого позволили мне удобно работать с хэшем. Предлагаю его вам:
Сохраняем это в javascript файл, и можно пользоваться методами Hash.get(), Hash.set() и т.д.
Теперь пример использования. Предположим, мы хотим, чтобы при клике на ссылку с классом alert у нас происходило событие — окно с алертом:
А теперь мы хотим дать прямую ссылку на этот алерт, чтобы любой, кто по ней перейдет увидел его, без клика:
Вот так просто. Код для сохранения статуса табов:
Конечно, понадобилось сохранять состояние страницы, и самое универсальное решение — хэш.
Если кто не в курсе, хэшем url зовется всё, что идет после символа #. Изначально это было придумано для якорей и используется до сих пор всякими способами из-за одной особенности — изменение хэша не обновляет страницу.
То есть, при клике на ссылку, которая ссылается на саму себя, но с хэшем — документ пролистывается до нужного места, но страница не перезагружается.
Более простого и универсального способа сохранения статуса Ajax приложений пока не придумано. Все браузеры работают с ним нативно, без заморочек.
Поэтому я написал простенький объект, методы которого позволили мне удобно работать с хэшем. Предлагаю его вам:
Hash = {
// Получаем данные из адреса
get: function() {
var vars = {}, hash, splitter, hashes;
if (!this.oldbrowser()) {
var pos = window.location.href.indexOf('?');
hashes = (pos != -1) ? decodeURIComponent(window.location.href.substr(pos + 1)) : '';
splitter = '&';
}
else {
hashes = decodeURIComponent(window.location.hash.substr(1));
splitter = '/';
}
if (hashes.length == 0) {return vars;}
else {hashes = hashes.split(splitter);}
for (var i in hashes) {
if (hashes.hasOwnProperty(i)) {
hash = hashes[i].split('=');
if (typeof hash[1] == 'undefined') {
vars['anchor'] = hash[0];
}
else {
vars[hash[0]] = hash[1];
}
}
}
return vars;
},
// Заменяем данные в адресе на полученный массив
set: function(vars) {
var hash = '';
for (var i in vars) {
if (vars.hasOwnProperty(i)) {
hash += '&' + i + '=' + vars[i];
}
}
if (!this.oldbrowser()) {
if (hash.length != 0) {
hash = '?' + hash.substr(1);
}
window.history.pushState(hash, '', document.location.pathname + hash);
}
else {
window.location.hash = hash.substr(1);
}
},
// Добавляем одно значение в адрес
add: function(key, val) {
var hash = this.get();
hash[key] = val;
this.set(hash);
},
// Удаляем одно значение из адреса
remove: function(key) {
var hash = this.get();
delete hash[key];
this.set(hash);
},
// Очищаем все значения в адресе
clear: function() {
this.set({});
},
// Проверка на поддержку history api браузером
oldbrowser: function() {
return !(window.history && history.pushState);
},
};
Внимание! Объект был переписан и работает теперь через history api, по возможности. Если нет — то через хэш, как раньше.
Это означает, что в современных браузерах будут прямые адреса типаtest.ru/?var1=1&var2=2А в IE8 и нижеtest.ru/#var1=1&var2=2
Метод Hash.oldbrowser() определяет режим работы. Вы можете перезагружать страницу при переходе на адрес с хэшем, если нужно:
Так, например, работает mSearch2 при фильтрации.if (window.location.hash != '' && Hash.oldbrowser()) { var uri = window.location.hash.replace('#', '?'); window.location.href = document.location.pathname + uri; }
Сохраняем это в javascript файл, и можно пользоваться методами Hash.get(), Hash.set() и т.д.
Теперь пример использования. Предположим, мы хотим, чтобы при клике на ссылку с классом alert у нас происходило событие — окно с алертом:
$(document).on('click', 'a.alert', function(e) {
alert('Событие!');
});
А теперь мы хотим дать прямую ссылку на этот алерт, чтобы любой, кто по ней перейдет увидел его, без клика:
// Обрабатываем клик по сслылке
$(document).on('click', 'a.alert', function(e) {
Hash.add('event', 'alert'); // добавляем в хэш #event=alert
alert('Событие!');
});
// Проверяем, что есть в хэше при загрузке страницы
$(document).ready(function() {
var hash = Hash.get(); // получаем все значения
if (hash.anchor) {
window.location.hash = hash.anchor; // сохраняем родной функционал якорей
}
else if (hash.event == 'alert') { // если есть событие alert - как бы кликаем по нужной ссылке
$('a.alert').trigger('click');
}
})
Вот так просто. Код для сохранения статуса табов:
// Обработка табов
$(document).on('click', '.nav a[data-toggle="tab"]', function (e) {
e.preventDefault();
var href = $(this).attr('href').substr(1);
Hash.add('tab', href);
});
// Переключение таба при загрузке страницы
$(document).ready(function() {
var hash = Hash.get();
if (hash.tab) {
$('.nav a[href="#' + hash.tab + '"]').trigger('click');
}
})
Комментарии: 14
Все это фигня. Захешенные страницы нужно отдавать по другому спец урлу для индексации поисковиками, а это лишний гемор. В итоге я свой аналогичный проект переписал на history.js
Речь про состояние переключенных табов, всплывших окошек, или кнопок фильтров.
Причем тут индексация?
Причем тут индексация?
С точки зрения организации кода, все четко. Аккуратно и ничего лишнего.
Если с главной страницы нажать кнопку «Читать дальше», страница открывается с хэшем #cut и на этой странице справа менять вкладки «Комметарии» и «Публикации» в адресной строке появляется это:
http://modx.pro/development/520/#cut=undefined/tab=tickets
Принято, спасибо.
Подумаю на досуге, как разделить хэш для собственных нужд и настоящие якоря.
Подумаю на досуге, как разделить хэш для собственных нужд и настоящие якоря.
Дописал обработку якорей.
Теперь, если что, они сохраняются в #anchor=имяякоря. Если при загрузке есть такое значение в хэше — то оно перекрывает остальные и хэш меняется на якорь.
Пытался подружить это дело с scrollTo.js, чтобы перекручивало на якорь и срабатывали остальные параметры — но глюки не смог одолеть. Поэтому теперь так: реальный якорь важнее остального.
Проверяем — bezumkin.ru/sections/components/516/#anchor=cut/tab=tickets
Теперь, если что, они сохраняются в #anchor=имяякоря. Если при загрузке есть такое значение в хэше — то оно перекрывает остальные и хэш меняется на якорь.
Пытался подружить это дело с scrollTo.js, чтобы перекручивало на якорь и срабатывали остальные параметры — но глюки не смог одолеть. Поэтому теперь так: реальный якорь важнее остального.
Проверяем — bezumkin.ru/sections/components/516/#anchor=cut/tab=tickets
Василий, у вас небольшая ошибка в тексте сообщения:
после вставки первого кода
п.с.
Много полезного у вас на ресурсе, спасибо за множество интересной информации =)
после вставки первого кода
Сохраняем это в javascript файл, и можно пользоваться методами Hah.get(), Hash.set() и т.д.букву s пропустили)
п.с.
Много полезного у вас на ресурсе, спасибо за множество интересной информации =)
Поправил, спасибо!
Нужная вещь. Очень обрадовался. Взял для табов. Но как у тебя не работает. :( Мой страница с табами. Вроде все по инструкции, но не работает.
П.С. Использую скрипт Organictab. Может он виноват?
П.С. Использую скрипт Organictab. Может он виноват?
У тебя все события перехватывает скрипт табов. Смотри, как ему задать callback на переключение.
Проверять, срабатывает событие, или нет, можно простым alert().
Проверять, срабатывает событие, или нет, можно простым alert().
Понял. А у тебя что за скрипт табы обрабатывает, если не секрет?
При полном отсутствии знаний по js допилил — работает! Извиняюсь за ламерские вопросы, я не программист.
Это сообщение было удалено
К сожалению я совсем не программист, и представленный код понимаю в лучшем случае на треть, и пользователь я не modx, а joomla, хотя для этого кода вроде бы всё равно должно быть. Попробовал прикрутить на страницу — не работает, ошибок не пишет, но и не работает, к сожалению понять что именно не пашет не разобраться, может гляните? Код в принципе интересный, и хотелось бы его попользовать.
ЗЫ сайт на который пытался приделать travelsbase.ru
ЗЫ сайт на который пытался приделать travelsbase.ru
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.