Створення вертикального меню акордеон на jQuery

15

Від автора: у цьому уроці ми познайомимося з одним з віджетів бібліотеки jQuery UI під назвою Accordion (Акордеон). Найчастіше даний віджет використовується для розміщення в ньому якоїсь блокової пов’язаної інформації, що те саме з табами. Набагато рідше можна знайти використання в якості віджету меню.

Ми з Вами спробуємо створити функціональне, вертикальне меню акордеон з допомогою однойменного віджета jQuery, який буде відмінно виглядати на сайті.

Отже, приступимо…

Створення вертикального меню акордеон на jQueryСтворення вертикального меню акордеон на jQuery

Використання віджету акордеон в якості меню особливо підходить для інтернет-магазинів, де в меню категорій практично завжди є дочірні категорії товарів. Саме тому для наших цілей ми візьмемо готове меню одного з проектів — інтернет-магазин з продажу мобільних телефонів.

Насамперед визначимося з версткою і стилями. Такий буде розмітка меню:

— Мобільні телефони

  • Alcatel
  • Ericsson
  • LG
    • — Слайдери
    • — Сенсори
    • — Розкладачки
    • — Моноблок
  • Mitsubish
  • Motorola
  • HTC
    • — Слайдери
    • — Сенсори
    • — Розкладачки
    • — Моноблок

  • Samsung
    • — Слайдери
    • — Сенсори
    • — Розкладачки
    • — Моноблок
  • NEC
  • Nokia
  • Panasonic
  • Ericsson

Такими будуть стилі меню:

*{ margin: 0; padding: 0; }
ul{list-style:none;}
body{background:#f2f2f2;}
.nav-catalog{
padding:10px 10px 20px 55px;
border-bottom:1px solid #e1e1e1;
}
.nav-catalog ul{
padding:5px 0 0 20px;
}
.nav-catalog ul li{
margin: 0;
}
.nav-catalog li{
margin: 0 0 5px 0;
}
.nav-catalog h3 li{
margin: 0 0 5px 0;
list-style-position: outside;
}
.nav-catalog li a{
font:bold 14px Verdana;
color:#000;
text-decoration:none;
}
.nav-catalog li a:hover{
font:bold 14px Verdana;
color:#1b7cb1;
text-decoration:none;
}

В результаті ми отримаємо приблизно наступну картину:

Створення вертикального меню акордеон на jQuery

Дочірні категорії не приховані і меню виглядає надто громіздко. Ось в цьому і полягає ідея використання віджету — підпункти повинні бути спочатку приховані і повинні відкриватися тільки при кліці на батьківській категорії. Це перша із завдань уроку.

Для її вирішення підключимо віджет. З бібліотекою jQuery UI ми вже працювали з Вами в ряді попередніх уроків, а тому далі лише кілька слів без детальних пояснень. На сайті віджета йдемо в меню Download, вибираємо для скачування лише необхідний нам віджет Accordion, при необхідності вибираємо зі списку тему оформлення віджета або конструюємо власну тему (оскільки оформлення меню у нас є, то я виберу пункт No Theme). Після цього тиснемо кнопку Download і отримуємо в архіві запитана.

В отриманому архіві з папки js скопіюємо 2 файлу зі скриптами в каталог нашого проекту (у нас це також каталог js). Підключимо ці скрипти до документа:

Отже, ми підключили бібліотеку jQuery і скрипт віджета. Тепер змусимо працювати все це. У документації до віджета Ви можете знайти опис необхідної розмітки, вона повинна бути наступною: батьківські пункти повинні бути за замовчуванням заголовками H3, дочірні пункти повинні бути розміщені в блоці і все це разом також має бути укладена в блок.

У нашому випадку поточна розмітка меню також підійде, у нас: батьківські пункти є заголовками H3, дочірні пункти поміщені в список ul, який є блоковим елементом, і все меню укладена також в списку ul з ідентифікатором accordion.

Для підключення акордеона досить звернутися до необхідного елементу (у нас це id=»accordion») і викликати для нього метод accordion(). Зробимо це:

$(document).ready(function(){
$(«#accordion»).accordion({
});
});

В результаті ми отримаємо наступне:

Створення вертикального меню акордеон на jQuery

Тепер всі підпункти приховані і меню стало компактним. Вже краще. По кліку на батьківську категорію дочірній блок красиво виїжджає. По кліку на будь-який інший пункт меню, крім дочірнього, розкритий дочірній блок також красиво ховається.

Але тут є кілька нюансів, які необхідно врахувати, щоб отримати дійсно якісний меню:

При кліці на розкриту батьківську категорію дочірній блок не згортається… а хотілося б.

При оновленні сторінки не запам’ятовується стан меню, тобто якщо ми мали відкритий блок, наприклад, LG, то при оновленні сторінки (при переході на нову сторінку) він знову буде приховано… це зовсім недобре.

Отже, давайте їх виправляти. Для цього звернемося до документації віджета і скористаємося двома властивостями методу accordion — active і collapsible. Друга властивість вирішить якраз першу проблему, змусивши згортатися дочірній блок при кліці по батькові. Ну а перше властивість відповідає за те, якою блок буде відкрито при ініціалізації акордеона:

$(document).ready(function(){
$(«#accordion»).accordion({
active: 2,
collapsible: true
});
});

Отже, вказавши значення властивості collapsible TRUE, ми вирішили першу проблему. Тепер до другої. Тут значенням властивості active ми вказали 2. Це значення є індексом елемента меню, який потрібно зробити активним (розкрити). Нумерація починається з нульового індексу, і у ній беруть участь всі недочерние елементи меню. У нашому випадку Alcatel має індекс 0, Ericsson — 1, LG — 2 і т. д. Таким чином, при ініціалізації відкривається пункт меню LG.

Вже непогано, але знову ж таки, немає запам’ятовування стану меню. Якщо тепер ми розкриємо інший пункт меню, то при оновленні знову буде відкрито пункт меню LG. Логічно, що нам необхідно реалізувати наступний алгоритм для рішення питання:

По кліку на батьківський (має дочірні) пункт меню ми повинні отримати і запам’ятати його індекс.

При ініціалізації необхідно перевірити чи є значення запомненного нами раніше індексу і, якщо є, то зробити такий пункт меню активним, тобто записати цей індекс значенням властивості active.

Як записати індекс значенням властивості active, ми вже знаємо. Як отримати індекс, ми можемо знайти в документації. Логічно, що основна проблема полягає в тому, щоб запам’ятати цей індекс і не втратити його при оновленні сторінки.

Тут нам допоможуть куки. Для розв’язання задачі скористаємося плагіном jquery.cookie, який Ви можете знайти в мережі або в додаткових матеріалах до уроку. Підключаємо плагін:

Використання плагіна в роботі вкрай просто. Фактично воно включає в себе всього 3 можливі дії:

установка куки;

читання куки;

видалення куки.

Отже, давайте створимо куку з ім’ям, наприклад, openItem, і запишемо її значенням індекс батьківського пункту меню при натисканні на нього:

$(document).ready(function(){
$(«#accordion»).accordion({
active: 2,
collapsible: true
});
$(«#accordion h3»).click(function(){
$.cookie(«openItem», $(«#accordion»).accordion(«option», «active»));
});
});

Як бачите, нічого складного. Першим параметром методу cookie є ім’я створюваної куки, другим — її значення. Отже, ми створили куку openItem при кліці на батьківський пункт меню. В браузерах Chrome або Mozilla Ви легко можете спостерігати це, клікаючи по батьківським пунктів меню та оновлюючи сторінку. Зауваження! У браузері Chrome скрипт буде працювати тільки на сервері.

Кука у нас є, але поки що вона не використовується нами… виправимо це:

$(document).ready(function(){
if($.cookie(«openItem»)){
var openItem = parseInt($.cookie(«openItem»));
}
$(«#accordion»).accordion({
active: openItem,
collapsible: true
});
$(«#accordion h3»).click(function(){
$.cookie(«openItem», $(«#accordion»).accordion(«option», «active»));
});
});

Ми перевіряємо перед ініціалізацією меню є що-то в кука openItem. Якщо умова виконується, то значення cookie ми отримуємо в однойменну змінну, при цьому обов’язково наводячи значення до числового типу (за замовчуванням тип рядковий). Справа в тому, що значення опції active обов’язково повинно бути числового типу.

Відмінно! Тепер стан меню запам’ятовується. При оновленні сторінки відкритий пункт меню залишається відкритим. Але якщо тепер клацнути по пункту без дочірніх елементів — відкритий пункт згорнеться, так і має бути… але при оновленні він знову розгортається. Це тому, що кука є і нікуди не пропадає. Виправимо цей нюанс, видаляючи куку по кліку на самостійний пункт меню:

$(document).ready(function(){
if($.cookie(«openItem»)){
var openItem = parseInt($.cookie(«openItem»));
}
$(«#accordion»).accordion({
active: openItem,
collapsible: true
});
$(«#accordion h3»).click(function(){
$.cookie(«openItem», $(«#accordion»).accordion(«option», «active»));
});
$(«#accordion li»).click(function(){
$.cookie(«openItem», null);
});
});

Ось тепер все відмінно і працює практично так, як нам і хотілося… чому практично? Зараз в меню першим пунктом йде самостійний пункт. Давайте зробимо першим пунктом батьківський пункт, наприклад LG.

І що ми бачимо? Після оновлення сторінки пункт LG став активним. Це при тому, що значенням куки ми бачимо false:

Створення вертикального меню акордеон на jQuery

Як же так? Якщо умова приходить false, то воно не повинне виконуватися. Насправді це не логічне значення FALSE, а рядок. Тому, щоб все працювало, трохи допишемо умова і заодно створимо спочатку змінну openItem з яким-небудь змістом, відмінним від натурального числа і нуля:

$(document).ready(function(){
var openItem = false;
if($.cookie(«openItem») && $.cookie(«openItem») != ‘false’){
var openItem = parseInt($.cookie(«openItem»));
}
$(«#accordion»).accordion({
active: openItem,
collapsible: true
});
$(«#accordion h3»).click(function(){
$.cookie(«openItem», $(«#accordion»).accordion(«option», «active»));
});
$(«#accordion li»).click(function(){
$.cookie(«openItem», null);
});
});

Тепер залишилося вирішити кілька останніх нюансів. Спробуйте зараз клікнути по дочірньому елементу. Після кліка по ньому кука видаляється, відповідно, стан меню не запам’ятовується. Відбувається так тому, що дочірні елементи є також елементами списку, як і самостійні пункти меню. Давайте трохи змінимо відбір елементів, для яких будемо відслідковувати подію кліка. Виберемо тільки прямих нащадків блоку з ідентифікатором accordion:

$(document).ready(function(){
var openItem = false;
if($.cookie(«openItem») && $.cookie(«openItem») != ‘false’){
var openItem = parseInt($.cookie(«openItem»));
}
$(«#accordion»).accordion({
active: openItem,
collapsible: true
});
$(«#accordion h3»).click(function(){
$.cookie(«openItem», $(«#accordion»).accordion(«option», «active»));
});
$(«#accordion > li»).click(function(){
$.cookie(«openItem», null);
});
});

Ось тепер кука видаляється тільки при кліці по самостійним пунктів меню.
Таким своєрідним багом, який необхідно виправити, є те, що при кліці по самостійному пункту меню не відбувається перехід за його посиланням. Це тому, що скрипт віджета блокує дефолтний поведінка посилання.

Вирішити цю проблему можна наступним чином – отримаємо посилання елемента, за яким був клік, і скористаємося об’єктом window.location для переходу за посиланням:

$(document).ready(function(){
var openItem = false;
if($.cookie(«openItem») && $.cookie(«openItem») != ‘false’){
var openItem = parseInt($.cookie(«openItem»));
}
$(«#accordion»).accordion({
active: openItem,
collapsible: true
});
$(«#accordion h3»).click(function(){
$.cookie(«openItem», $(«#accordion»).accordion(«option», «active»));
});
$(«#accordion > li»).click(function(){
$.cookie(«openItem», null);
var link = $(this).find(‘a’).attr(‘href’);
window.location = link;
});
});

І, нарешті, додамо ще кілька опцій в метод accordion():

$(document).ready(function(){
var openItem = false;
if($.cookie(«openItem») && $.cookie(«openItem») != ‘false’){
var openItem = parseInt($.cookie(«openItem»));
}
$(«#accordion»).accordion({
active: openItem,
collapsible: true,
header: ‘h3’,
autoHeight: false
});
$(«#accordion h3»).click(function(){
$.cookie(«openItem», $(«#accordion»).accordion(«option», «active»));
});
$(«#accordion > li»).click(function(){
$.cookie(«openItem», null);
var link = $(this).find(‘a’).attr(‘href’);
window.location = link;
});
});

Опція header дозволяє явно вказати на елемент, який буде заголовком секцій. Цю опцію ми вказали для вирішення можливих проблем з IE, в 7-ій версії якого я спостерігав проблеми з акордеоном. Після зазначення цієї опції, проблеми вирішилися.

Друга опція – autoHeigth зі значенням false – дозволяє вирішити проблему з висотою відкриваються блоків. За замовчуванням значення цієї опції виставлено в true, що задає однакову висоту для всіх прихованих блоків. Значення висоти береться з розрахунку максимальної висоти блоку, тобто якщо в одного блоку, наприклад, 5 пунктів і висота 100 пікселів, то другий блок зі всього 1 пунктом буде також мати висоту 100 пікселів. З’явиться порожнє місце біля другого блоку, що не дуже добре.

Ось тепер дійсно все. Наше вертикальне меню акордеон, працює так, як і було задумано. В результаті ми отримали меню, яке ідеально підійде для категорій інтернет-магазину або просто для сайту, де є розділи з підкатегоріями. При цьому наше меню ще й «вміє» запам’ятовувати свій стан.

На цьому урок закінчений. Удачі Вам і до нових зустрічей!