Вкладки и кнопка Back
Дата публикации: 21.11.2011
Задача
Сделать так чтобы пользователь имел возможность открыть страницу сразу с открытой нужной вкладкой. Так же чтобы при навигации по вкладкам

Решение
В этом нам помогут Javascript событие hashchange и CSS3 псевдокласс :target (для красоты решения). Использование :target мы уже как-то рассматривали и в данном материале повторяться не будем.
Событие hashchange происходит при изменении URL, когда новый отличается от предыдущего только фрагментом идентификатора (часть URL, которая идет после знака # и называется хеш (hash)).
Как применять на практике продемонстрирует простой пример: сделаем блок, состоящий из трех вкладок:
<dl id="tabs"> <dt><a href="#menu">Меню</a></dt> <dd id="menu"><div>Содержимое вкладки меню</div></dd> <dt><a href="#info">Инфо</a></dt> <dd id="info"><div>Содержимое вкладки инфо</div></dd> <dt><a href="#photo">Фото</a></dt> <dd id="photo"><div>Содержимое вкладки фото</div></dd> </dl>
Замечу ,что <div> используется в декоративных целях.
В CSS тоже в целом ничего особенного и нового:
#tabs dt {
float: left;
line-height: 25px;
margin: 0 2px 0 0;
background: #ff8600;
border: 1px solid #e47200;
border-bottom: none;
color: #f4ece1;
-moz-border-radius: 8px 8px 0 0;
-webkit-border-radius: 8px 8px 0 0;
border-radius: 8px 8px 0 0;
cursor: pointer;
position: relative;
}
#tabs dt:first-child {
margin-left: 10px;
}
#tabs dt a {
display: block;
height: 24px;
color: #fff;
text-decoration: none;
padding: 0 22px;
}
#tabs dt.active {
background: #77b001;
border: 1px solid #679200;
cursor: default;
}
#tabs dt a:hover {
text-decoration: underline;
}
#tabs dt.active a { /* вид активной вкладки */
cursor: default;
text-decoration: none !important;
}
#tabs dd {
width: 100%;
display: none; /* все вкладки по умолчанию не видимы */
float: right;
margin: 0 0 0 -100%;
padding-top: 25px;
}
#tabs dd.target,
#tabs dd:target {
display: block; /* вкладка получившая target становится видимой */
}
К этому добавляем небольшой JS:
jQuery(document).ready(function(){
var tabs = ["#menu", "#info", "#photo"], // создаем массив id вкладок для удобства проверок
tabList = jQuery("#tabs"),
ltie9 = jQuery.browser.msie && (jQuery.browser.version <= 9);
/*
ltie9 будет true если используется IE8 или ниже
IE9 сюда попал из-за того что при нажатии на Back предыдущая вкладка не скрывалась
*/
// смена таба
function changeTab(tabId){
if (!tabId) window.location.hash = tabs[0]; // если не указана вкладка показываем первую
tabList.find(".active").removeClass("active");
jQuery(tabId).prev().addClass("active"); // активной вкладке добавляем класс чтобы придать нужный вид
/*
определив id вкладки можно выполнить какие-то дополнительные действия,
например, выполнить ajax запрос
*/
switch (tabId)
{
case tabs[1]: jQuery("#info div").append("<p>динамически добавленный код</p>quot;);
break;
default: break;
};
}
// проверка хеша
function checkHash(){
var tabId = window.location.hash,
result = false;
// для ИЕ6-8 эмуляция :target
function setTarget(obj){
jQuery("#tabs dd").removeClass("target");
jQuery(tabId).addClass("target");
};
// при загрузке страницы проверяем какую вкладку следует открыть
jQuery.each(tabs, function(){
if (tabId == this)
{
changeTab(tabId);
result = true;
ltie9 ? setTarget(tabId) : false;
return false;
};
});
if (result == false) changeTab();
};
// проверка хеша при загрузке
checkHash();
// отслеживаем изменение хеша
jQuery(window).bind("hashchange", function() {
checkHash();
});
});
Демо пример. Проверено:
- IE 8-9
- Opera 11.11
- Firefox 8
- Safari 5
- Chrome
Следует отметить что событие hashchange многими браузерами поддерживается достаточно давно: IE8, FF 3.6, Opera 10.6 уже поддерживали данное событие. Если же требуется поддержка более старых браузеров, можно воспользоваться jQuery плагином от Ben Alman.
