css, html, php, javascript, jQuery, ajax … – решения, примеры, рецепты
18 Авг
Что такое Accordion наверное все знают, но если кто не знает, тому лучше сначала прочитать статью jQuery UI – виджет Accordion, в ней довольно подробно все рассказано. А сегодняшняя статья написана благодаря довольно многочисленным вопросам и моему обещанию рассказать, как, используя accordion, сделать на его основе меню для сайта. Естественно, что при переходе по ссылке открытая секция аккордеона должна оставаться открытой и активный пункт меню должен быть как-то выделен….
Сразу приведу пример и выложу архив демо, а то меня, не без оснований конечно, обвиняли в отсутствии демо в статьях про jQuery UI. Поскольку ничего особенно сложного в этом решении нет, то я буду краток – только код, пример и минимум необходимых пояснений.
Итак, сначала мы делаем все в точности так же, как написано в статье jQuery UI – виджет Accordion. Т.е. подключаем необходимые файлы к HTML-странице. Здесь же внесем первое дополнение. Для того, чтобы иметь возможность запоминать состояние секций аккордеона, нам потребуется подключить еще один небольшой, но весьма полезный плагин – jQuery Cookie.
<script src="js/jquery.cookie.js" type="text/javascript"></script>
Поиметь свежую версию этого плагина можно на http://plugins.jquery.com/project/Cookie.
Теперь приведу пример HTML-разметки меню-аккордеона.
<div id="accordion">
<h3><a href="#">Секция 1</a></h3>
<ul>
<li><a href="?1-1">Пункт меню 1-1</a></li>
<li><a href="?1-2">Пункт меню 1-2</a></li>
<li><a href="?1-3">Пункт меню 1-3</a></li>
</ul>
<h3><a href="#">Секция 2</a></h3>
<ul>
<li><a href="?2-1">Пункт меню 2-1</a></li>
<li><a href="?2-2">Пункт меню 2-2</a></li>
<li><a href="?2-3">Пункт меню 2-3</a></li>
</ul>
<h3><a href="#">Секция 3</a></h3>
<ul>
<li><a href="?3-1">Пункт меню 3-1</a></li>
<li><a href="?3-2">Пункт меню 3-2</a></li>
<li><a href="?3-3">Пункт меню 3-3</a></li>
</ul>
<h3><a href="#">Секция 4</a></h3>
<ul>
<li><a href="?4-1">Пункт меню 4-1</a></li>
<li><a href="?4-2">Пункт меню 4-2</a></li>
<li><a href="?4-3">Пункт меню 4-3</a></li>
</ul>
</div>
Ничего загадочного тут и вовсе нет. Что еще? Добавим немного стилей, чтобы выделять активный пункт меню. Например так:
a.open { color: #f00;}
т.е. в примере просто выделяем текст ссылки в меню красным цветом.
А теперь самое интересное – javascript-код:
<script type="text/javascript">
$(function(){
$("#accordion").accordion({
navigation: true
});
$("#accordion li a").click(function(){
$.cookie("openItem", $(this).attr("href"));
});
$("#accordion li a[href$=`" + $.cookie("openItem") +
"`]").addClass("open");
});
</script>
И здесь ничего сложного! Отыскали нужный элемент по идентификатору #accordion, применили к нему возможности плагина. Из опций передали только одну, но в нашем случае необходимую опцию navigation, которой присвоили значение true. Это обеспечит нам открытие нужной секции аккордеона при переходе по ссылке.
На следующем шаге необходимо обрабатывать щелчок мышкой по пункту меню, чтобы поставить соответствующую куку. Что мы и делаем – находим все элементы a внутри li, внутри нашего аккордеона, связываем с ними событие click, по которому будет вызвана функция-обработчик.
Тут нам пригодятся возможности плагина jQuery Cookie. Мы устанавливаем куку с именем openItem, и значением, которое получаем из атрибута href той ссылки, по которой был совершен клик.
И последний шаг – при загрузке страницы мы должны прочитать куку (если она конечно есть) и в соответствии с ее значением «подсветить» нужный пункт меню. Делаем это – ищем нужный пункт меню выбирая элемент a внутри li аккордеона. Но не просто, а значение атрибута href которого соответствует значению, сохраненному в куке.
Знак $ используем потому, что некоторые браузеры возвращают значения атрибута href по разному. Некоторые отдают абсолютный путь, некоторые – относительный. Чтобы исключить эту неоднозначность мы ищем такое значение атрибута href, которое заканчивается одинаково со значением, сохраненным в куке.
Если такая ссылка будет найдена, то с помощью метода addClass мы добавим ей класс open, что заставит ее «покраснеть».
Собственно это все, больше тут рассказывать не о чем…
Отзывов (63) на «Как использовать виджет Accordion в качестве меню?»
Это всё хорошо, статья тоже положительная (-:
Но есть одно «но»: у Вас навигация и ссылки происходят внутри одного файла ac_menu.html.
А ведь такое редко бывает – практически не бывает… поэтому по новой ссылке Accordition будет создаваться вновь и откроется на первой вкладке. Поэтому мне пришлось использовать при инициализации оного ещё парочку строк:
collapsible: true,
active: 3,
т.е. выбираеть, какая из вкладок должна быть активная при создании страницы.
Хотя… может я и ошибаюсь (-:
Ээээ, уважаемый… Насчет практически не бывает – Вы не правы. Сплошь и рядом… Так Вам выложить пример, где несколько разных файлов и все также работает???
Пожалуйста, пример.
Вы бы прежде, чем писать текст слов, попробовали бы, испытали…
Так что Вы действительно ошибаетесь.
Крута (-:
пойду у себя так попробую (-:
х-м… не запоминает, странно…
правда, без кукизов… ладно, буду делать, как делал (-: хотя мне и не надо подсвечивать пункт меню, мне надо просто, чтоб был открыт нужный раздел…
о с примерчиками, жыр!
Спасибо огромное за статью! Просто выручили)
Gennady, скажи использование библиотеки jQuery для коммерческих проектах свободное?
Библиотека распространяется под лицензиями MIT и GPL. В общем, если коротко, то свободное, но есть нюансы, про которые стоит прочитать. Можно например в Википедии…
Добрый день, уважаемый Геннадий и комменторы.
С удовольствием читаю ваш блог, много полезного доступным языком – спасибо.
У меня есть вопрос к профессионалам, я незнал куда его задать, поэтому пишу в этот последний пост.
Итак есть ajax запрос, реализованный через
$.ajax({
url: ‘ajax.php’,
type: ‘POST’,
dataType:»html»,
data: «id=1″,
success: function(answer)
{
$(‘#tablelist’).text(answer);
}
});
Серверный код возвращает информацию в виде уже сформироанной верстки:
if($_SERVER['HTTP_X_REQUESTED_WITH']==’XMLHttpRequest’)
{
if($_POST)
{
$id=$_POST['id'];
//Тут выбирается например из базы по id инфа
$result_html = «{$mysql_result}»;
print $result_html; //Возвращается инфа.
}
}
но при попытке вставить ее в нужное место , выводится сама верстка, как простой текст, а не таблица с данными.
Есть ли способ получить данные и вставить в верстку как нормальный html – и если есть, то как?
Очень буду благодарен вам за ответ.
Теги подрезались
В общем в $result_html = «[table][tr][td]{$mysql_result}[/td][/tr][/table]«;
квадратные скобки на угловые..
$(’#tablelist’).text(answer); – Вы вставляете ответ сервера как текст, он и вставляется…
Вам надо:
$(’#tablelist’).html(answer);
Спасибо за статью.
А в вашем примере вы используете jquery-ui-1.7.2.custom.css – там столько ненужного (datepicker, dialog …..) где можно взять минимальный СSS для вашего примера?
Спасибо за ответ.
Разобрался, CSS можно тут себе настраивать http://jqueryui.com/themeroller/
хотя зачем столько вариантов, если нужен аккордион ?
Да, универсальный файл получается довольно тяжелый. Каждый сам решает нужно ему оно или нет. Я вообще это оформление не использую, пишу свое…
А можно посмотреть минимальный пример CSS? Пытаюсь собрать ЦСС согласно http://docs.jquery.com/UI/Accordion#theming – что-то не то получается
заранее спасибо
kibi, но минимальный пример CSS – это когда стили вообще не определены. Наверное от этого интереснее танцевать. Так сказать «голый» виджет, а дальше понемногу оформлять…
Конечно, в процессе работы элементам добавляются определенные классы, с помощью которых можно менять визуальное представление в зависимости от состояния виджета. Но имхо, в большинстве практических случаев это лишнее.
Добрый день, Геннадий.
Не подскажите, вроде бы элементарная вещь, а не понимаю..
$(«#74″).click(function () {
$(«#rightcolumn»).load(«1.html»);
alert(«Привет»);
});
Приветствие выскакивает, а страничка не подгружается.
Если просто поставить строчку
$(«#rightcolumn»).load(«1.html»);
вне клика, то все нормально подгружается.
Я в недоумении.
Вопрос: пробовали сделать вложенные аккордионы? такое будет работать?
например:
меню1
меню2
меню3
—меню3.1
………меню 3.1.1
……… меню 3.1.2
……….меню 3.1.3
—меню 3.2
меню 4
вот как-то не представляется, как это можно сделать ?
Доброго времени суток!
Такой вопрос – а можно сделать так чтобы открытая секция 1 не закрывалась когда открывается секция 2 и/или чтобы она выезжала вниз, а не вверх?
Люди добрые, может кто-то видел какой=то пример многовложенных аккордиронов ? а не 2-х уровневый аккордион. Подскажите пожалуйста
Двухуровневый видел http://jsbin.com/axulo, а больше нет. В принципе такая реализация возможна, но там возникают проблемы с высотой области содержимого….
Алексей, accordion – это по определению всегда только одна открытая вкладка. Собственно виджет немаленький потому, что достичь такого поведения не так-то просто. А если Вам нужно держать открытыми несколько вкладок одновременно – Вам не нужен большой виджет. Достаточно этого:
$(function(){ $('.accordion .head').click(function() { $(this).next().toggle('slow'); return false; }).next().hide(); });Если вам не составит труда скиньте пример пожалуйста.
Просто, я хочу реализовать чтобы вкладка открывалась и закрывалась заголовком и вместе с тем можно было держать 2 и больше открытыми вместе.
В скриптонаписании 1 день)))
Так я Вам пример и написал – это все…. Сама html-разметка как в обычном аккордеоне. Ну, разве что в примере селектор другой. Но тут смысл в том, чтобы выбрать в нем заголовки аккордеона и по клику на них открывать/закрывать секции.
Спасибо вам огромное,все получилось!
Генадий, а в примерах с двух-уровневыми аккордионами установка кукиз чтобы аккордион был открыт на месте, где нажималась ссылка как-то не работает
вот пример: http://blog.evaria.com/wp-content/themes/blogvaria/jquery/index-multi.php
тут уже пробовал так:
$(«#theMenu ul li a»).click(function(){
$.cookie(«openItem», $(this).attr(«href»));
});
$(«#theMenu ul li a[href$='" + $.cookie("openItem") + "']«).addClass(«open»);
Кукиз ставится, но аккордион не открывается.
Пожалуйста, подскажите, что я делаю не так ?
Спасибо.
Не очень понял какая ссылка не работает…. Но это ладно.
Если пользуетесь версией библиотеки 1.3+, то знак $ в селекторе атрибута использовать не надо (это где Вы ищете а по значению атрибута href). Если версия библиотеки ниже 1.3 – тогда все правильно.
Это – общие слова, так сказать. Что касается двухуровневого аккордеона – то вероятно и cookie надо ставить для двух уровней. А при перезагрузке открывать сначала первый уровень, затем второй.
Упссс… Про знак $ в селекторе загнул. Конечно имелось ввиду @…
Спасибо за ответ.
все отлично – не так поняли меня Генадий.
Ссылка работает.
Прочитал Ваш ответ – вроде бы понятно. Но как поочередно открывать уровни через имеющиеся кукиз? я так понимаю – делать сохранение кукиз так: уровен 1 (кукиз 1), уровень2 (кукиз), а потом делать октрытие для уровня 1 – кукиз 1 , а для вложенного уровня 2 – кукиз 2
А как определить нажат уже конечный подуровень или родительский уровень ? там же идет вложенность ul – li ?
Открываете первый уровень – ставите куку с именем, например oneLevel, открываете – второй, соответственно другая кука, с именем twoLevel. При перезагрузке страницы их читаете и открываете нужные секции первого и второго уровня.
Это теоретически, а на практике Вам и предстоит попробовать, я такого не делал.
» Поиметь свежую версию этого плагина можно на http://plugins.jquery.com/project/Cookie. »
Улыбнуло
У меня вопрос, как добится того, чтобы при каждой загрузке главной страницы все секции были закрыты, но открыта та, из которой переходишь по ссылке на др.страницу.
Лев, тут cookie могут помочь (если такой вариант конечно подходит), либо сохранение состояния на сервере.
Пример пока не готов дать, но, если хотите, сбросьте мне свой email вот отсюда можно, я Вам кину ссылку, где можно посмотреть (здесь ссылку не даю – тот проект не закончен еще).
и еще вопрос к Генадию. В вашем примере урл стостоит из 1 переменной: a href=»?2-3″
а если будет a href=»?var1=2-3&var2=22&var3=33″ кукиз сможет отрыть по полному УРЛ соответственно ?
Сможет. Ибо нет принципиальной разницы между урл, который в примере и тем, который нужен Вам.
Как оказалось, можно сделать всё проще
При использовании navigation: true активная ссылка имеет свой класс:
.ui-accordion-content-active
Добавив вот такую строчку в css файл можно выделять активную нажатую ссылку без использование кукисов
li a.ui-accordion-content-active {
color: red;
}
Подскажите пожалуйста. Возможно ли реализовать на некоторых пунктах переход по ссылке вместо разворачивания аккордеона?
Можно. Надо просто написать отдельный обработчик клика по этой ссылке. Пусть например такая ссылка имеет класс out, тогда:
$("a.out").click(function(){ location.href='http://www.yandex.ru'; });аккордеон не будет разворачиваться, а вместо этого мы попадем на главную страницу Яндекса.
Геннадий, спасибо за ответ. А что нужно прописать там где выводятся дивы?
[h3] [А href=# class=out] text [/А] [/h3]
Может глупый вопрос), но не силен с ява скриптом.
Идею поняли верно. Класс out (например) для той ссылки, клик по которой должен не открывать секцию, а вызвать переход на другую страницу. Ну и + обработчик…
А там где div’ы…. Ну пустой div например…
Спасибо получилось.. когда обработчик после вывода аккордеона поставил)
Ну, да – это естественно. Именно после…
Gennady, а подскажите какие изменения нужно сделать в коде, чтобы аккардион не имел полосы прокрутки при разном количестве пунктов во вкладках?
Вот например как здесь http://demos.mootools.net/Accordion. Я так понял аккардион jQuery опирается на высоту первой вкладки и если последующие больше, то появляется прокрутка. Как понимаете для меню это не годится!!!!
Что можете посоветовать???
Да, что-то я поспешил с вопросом, надо было внимательнее почитать описание плагина. Прошу прощения за лишний вопрос.
Garro, Вы не очень правильно поняли. Высота секций может быть как одинакова (по высоте самой большой), так и разная для каждой секции (по высоте ее контента). Просто Вы несколько не ту статью читаете. Вам надо почитать jQuery UI – виджет Accordion и сначала попробовать использовать какую-либо из предустановленных тем оформления. Полосы прокрутки, которые у Вас появляются – это чистый CSS…
To Garro,
а я уже успел ответить…
Сплагиатили ваш материал:
www . 4itcrowd . ru/2009/08/jquery-ui-accordion-menu/Что сказать? Нехорошо это, но думаю никакой реальной выгоды вору не принесет… Если человек способен только на то, чтобы воровать чужие статьи, то имхо он – неудачник.
а не подскажите как сделать так, чтобы при клике на любую ссылку на странице, вид меню не менялся.
To Pavel:
Ваш вопрос не понятен, поясните, что Вы имеете ввиду?
меню висит сбоку, при клике по раскрывающимся пунктам(ссылкам), происходит переход на другую страницу и меню сохраняет свой вид(остается открытым в той части где была ссылка), а при клике на ссылку например внутри основной части страницы, меню не сохраняет свой вид. т.е оно обновляется. надо как то прописать, чтобы записывалась кука о состоянии меню при клике на любую ссылку на странице.
ОГРОМНОЕ СПАСИБО!!! за статью,очень интересно. я только начал изучать jQuery поэтому по голове ногами не бить…
тащу из базы секции, отображаются нормально,
но вот беда, как реализовать подгрузку ссылок для выбранной(нажатой секции)…помогите разобраться.
Заранее спасибо
Вопроса не понял…. Вы из БД получаете данные и на их основании генерируется разметка. Так в чем проблема? «Рисуете» ту разметку которая нужна, со всеми секциями и ссылками в них и проч. и проч.
Пример требуемой разметки в статье приведен. Без JS вся разметка будет видна как есть. А как только страница будет инициализирована с подключенной библиотекой + соответствующим виджетом и несколькими строками кода – все и заработает как надо.
Спасибо за статью!
Подскажите.. как получать адрес ссылки из href в виджете?
Просто мне надо сделать так, чтобы некоторые ссылки не разворачивали подменю, а чтоб по ним можно было перейти на др. страницу.
Вариант, кот. вы предложили выше не оч. удобен, так как адрес надо указывать в скрипте..
$(«a.out»).click(function(){
location.href=’http://www.yandex.ru’;
});
А хотелось бы писать адрес в href ссылки…
Ну Вы уж право… Я не предлагал способ, а всего лишь показывал как сделать так, чтобы по щелчку по заголовку осуществлялся переход….
$(”a.out”).click(function(){ location.href=$(this).attr('href'); });Переходим на url, указанный в href ссылки, по которой кликнули. Но я тогда не понимаю, в чем будет смысл использования виджета – ведь вместо того, чтобы открыть секцию, Вы направляете пользователя куда-то….
Gennady, спасибо большое.
Дело в том, что меню может состоять из нескольких пунктов, где не будет подпунктов… что не есть хорошо.
ps: никого обидеть не хотел
А, ну если в таком смысле… Тогда да
$(document).ready(function() { $("#firstpane p.menu_head").click(function() { $(this).css({backgroundImage:"url(/Dscs/a2.png)"}) .next("div.menu_body").slideToggle(300) .siblings("div.menu_body") .slideUp("slow"); $(this).siblings() .css({backgroundImage:"url(/Dscs/a1.png)"}); }); });сделайте пожалуйста сохранение в куки для этого меню
Gennady, здравствуйте, есть небольшой вопрос, у меня тоже возникла необходимость делать некоторые заголовки меню неактивными, тоесть что-бы они были толко как ссылками, сделал как Вы тут советовали:
$(”a.out”).click(function(){
location.href=$(this).attr(‘href’);
});
Но в таком случае, заголовок при нажатии всеравно попытается раскрыться, но конечно тут же схлопнется, когда произойдет переход по ссылке.
Как вот сделать так, что-бы он был совсем статичным?
Еще один вопросик… я вот замечаю что в IE при обновлении страницы, меню секунду выглядит в развернутом виде… это немного некрасиво выглядит… можно ли это как-то исправить? в описании я ничего не нашел…
To Digkill:
Я готов что-то советовать и подсказывать, но делать – не готов. Это принципиально.
Есть довольно подробная статья про то, как поставить cookie, считать или удалить.
Добавьте в Ваш обработчик клика постановку cookie, а при инициализации страницы считывайте его(их) и на основании полученных значений управляйте своим меню.
To Kotoff:
Навскидку ничего не посоветую – надо экспериментировать, пробовать. Может кто-то и нашел хорошее решение…
По первому своему вопросу я решение нашел, оно может выходит за рамки данной статьи, но может кому-то оно будет полезным.
Суть заключается в том, что-бы отказать от использования плагина Accordion, поскольку средствами чистого jQuery сделать такое меню, как мне показалось, не намного сложнее:
function jMenu() {
$(‘#menu ul’).hide();
$(‘#menu li a’).click( function() {
var checkElement = $(this).next();
if((checkElement.is(‘ul’)) && (checkElement.is(‘:visible’))) {
$(‘#menu ul:visible’).slideUp(‘normal’);
return false;
}
if((checkElement.is(‘ul’)) && (!checkElement.is(‘:visible’))) {
$(‘#menu ul:visible’).slideUp(‘normal’);
checkElement.slideDown(‘normal’);
return false;
}
});
}
$(document).ready(function() {jMenu();});
Мне показалось что данный способ даже более гибок в настройке, не так удобен, но тут зато все как на ладони, отслеживается весь процесс, так сказать. Вот html разметка:
[ul id="menu"]
[li][a href="#"] 1 [/a][/li]
[li][a href="#"] 2 [/a][/li]
[li]
[a href="#" ] 3 [/a]
[ul]
[li][a href="#"] 3 – 1 [/a][/li]
[li][a href="#"] 3 – 2 [/a][/li]
[li][a href="#"] 3 – 3 [/a][/li]
[/ul]
[/li]
[/ul]
…скобки, чтоб движок не сожрал текст
В таком случае открываться будет только третий элемент меню.
Обсуждение статьи можно продолжить на форуме jQuery.