Новый взгляд на вложенные списки
В этой статье мы рассмотрим, как с помощью CSS и jQuery можно сделать списки с вложенными элементами более удобными для просмотра и использования. Такая структура хорошо подходит для руководств, документации и файловых менеджеров.Перейдём к примерам.
Второй – всё тот же список, но с использованием jQuery плагина showTree. Плагин полностью работоспоcобен в IE 7+, Firefox, Opera, Safari и Chrome.
Именно его мы сегодня и будем изучать.
jQuery
Рассмотрим подробнее код плагина:
(function($){
$.fn.showTree = function(o){
var o = $.extend({
closeFolders: false, // по умолчанию список раскрыт целиком
classTree: null // дополнительный класс для списка
}, o);
return $(this).each(function(){ // проходим по всем спискам
var tree = $(this); // присваиваем переменной tree содержание текущего списка
tree.addClass('jquery-tree').children('li:first').prepend('<div class="first"></div>'); // добавляем класс по умолчанию и скрываем верхнюю линию в первом элементе списка
tree.children('li:last').addClass('last'); // для последнего элемента в списке добавляем класс last
tree.find('ul').each(function(){ // проходим по всем вложенным спискам
$(this).children('li:last').addClass('last'); // для последнего элемента в каждом из них добавляем класс last
}).prev('a').addClass('folder'); // добавляем класс folder каждой ссылке, за которой идёт вложенный список
if (o.classTree) tree.addClass(o.classTree); // если есть пользовательский класс, добавляем его
tree.find('a.folder').before('<span class="show"></span>'); // добавляем кнопку показа/скрытия содержимого папки
tree.find('span').click(openTree); // каждой кнопке по клику на неё ставим функцию openTree
if (o.closeFolders) { // если содержимое списков должно быть скрыто
tree.find('ul').hide(); // скрываем его
} else {
tree.find('.folder').addClass('open').prev('span').addClass('minus'); // иначе показываем что папки открыты
}
});
function openTree(){ // функция, показывающая/скрывающая содержимое папки
var button = $(this); // присваиваем переменной button значение нажатой кнопки
var link = button.next(); // находим ссылку
var files = link.next('ul'); // находим вложенные файлы
if (link.hasClass('open')) { // если папка открыта
files.hide(); // скрываем файлы
} else {
files.show(); // иначе показываем
}
link.toggleClass('open'); // переключаем классы у кнопки и папки
button.toggleClass('minus'); // если класса нет, добавляем, иначе - убираем
return false;
}
};
})(jQuery)
Зачем нужны классы first и last?
Они несут чисто декоративную функцию – скрывают линии там, где они они не нужны.Сравните:
Как происходит вызов функции?
$('.tree').showTree(); // простой вызов без дополнительных параметров
$('.tree').showTree({closeFolders: true}); // все вложенные папки скрыты
$('.tree').showTree({closeFolders: true, ,classTree:'classic'}); // все вложенные папки скрыты и используется пользовательский класс
Вот пример вызова последней функции, созданный из оглавления руководства по PHP:
- Авторские права
- Руководство по PHP
- Приступая к работе
- Установка и настройка
- Справочник языка
CSS
Основная часть CSS:
.jquery-tree ul {
padding:0;
margin:0;
}
.jquery-tree li {
list-style:none;
padding-left:8px;
margin-left:8px;
border-left:1px dotted #838383;
background:url("img/line.gif") no-repeat 0px 9px; /* добавляем горизонтальную линию около каждого элемента */
}
.jquery-tree a {
text-decoration:none;
padding-left:18px;
background:url("img/file.png") no-repeat 1px 2px; /* картинка для обычного элемента */
}
.jquery-tree a.folder {
background:url("img/folder.png") no-repeat 1px 2px; /* картинка для закрытой папки */
}
.jquery-tree .last {
border:none;
padding-left:9px;
background:url("img/line_last.gif") 0px top no-repeat; /* закрывающий элемент */
}
.jquery-tree .first { /* прикрываем верхнюю часть линии первого элемента */
margin-left:-9px;
width:2px;
height:8px;
float:left;
background-color:#FFF;
}
.jquery-tree .show {
margin-left:-16px;
width:16px;
height:16px;
background:url("img/plus.png") left 2px no-repeat; /* картинка для кнопки показа */
float:left;
display:block;
border:0;
padding:0;
}
.jquery-tree .show.minus {
background-image:url("img/minus.png"); /* картинка для кнопки скрытия */
}
.jquery-tree a.open {
background-image:url("img/folder_open.png"); /* картинка для открытой папки */
}
Дополнительные стили для элементов
Также вы можете задавать свои стили для элементов:
.jquery-tree a.photo {
background-image:url("img/photo.png");
}
.jquery-tree a.text {
background-image:url("img/text.png");
}
HTML:
<ul id="tree_two"> <li><a href="/">Главный документ</a></li> <li><a href="/">Папка</a> <ul> <li><a href="/">Папка с изображениями</a> <ul> <li><a href="/" class="photo">Изображение</a></li> <li><a href="/" class="photo">Изображение</a></li> <li><a href="/" class="photo">Изображение</a></li> </ul></li> <li><a href="/" class="text">Текстовый документ</a></li> </ul></li> </ul>Как это выглядит:
CSS-хаки
При необходимости можете добавить CSS-хак для IE:
<!--[if IE]><style>
.jquery-tree .last {background-position:0px -1px;}
.jquery-tree .first {height:9px;}
</style><![endif]-->
Если кто-то подскажет, как решить проблему с border:dotted в Opera и Chrome, я буду очень благодарна.HTML
Сам HTML довольно прост – в нём используются лишь вложенные списки, созданные с помощью тегов li и ul.
<ul class="tree">
<li><a href="/">Главный документ</a></li>
<li><a href="/">Родительская папка</a>
<ul>
<li><a href="/">Вложенный документ</a></li>
<li><a href="/">Вложенная папка</a>
<ul>
<li><a href="/">Важный документ</a></li>
<li><a href="/">Ещё один документ</a></li>
<li><a href="/">Самый важный документ</a></li>
<li><a href="/">Ненужные документы</a>
<ul>
<li><a href="/">Первый не нужный документ</a></li>
<li><a href="/">Второй</a></li>
<li><a href="/">Третий</a></li>
</ul></li>
</ul></li>
<li><a href="/">Очередной документ</a></li>
</ul></li>
<li><a href="/">Вторая родительская папка</a>
<ul>
<li><a href="/">Вложенная папка</a>
<ul>
<li><a href="/">Ещё одна папка</a>
<ul>
<li><a href="/">Спрятанный документ</a></li>
</ul></li>
<li><a href="/">Ещё один документ</a></li>
</ul></li>
</ul></li>
</ul>
Разбор очередного плагина закончен.
Успехов в работе с jQuery :)
Если вам что-то не понятно – задавайте вопросы в комментариях.



tree.find('span').click(openTree); // каждой кнопке по клику на неё ставим функцию openTree
tree.find('a.folder').click(openTree);
что-то не работает :)
Чтобы это исправить, нужно заменить содержимое функции openTree:
function openTree(){ if ($(this).hasClass('folder')) { // если это заголовок var link = $(this); // текущий объект это заголовок var button = link.prev(); // кнопка - предыдущая } else { // если это кнопка var button = $(this); // кнопка - текущий объект var link = button.next(); // заголовок - следующий } var files = link.next('ul'); if (link.hasClass('open')) { files.hide(); } else { files.show(); } link.toggleClass('open'); button.toggleClass('minus'); return false; }найдите в коде строку
tree.find('a.folder').before('<span class="show"></span>');и замените её на
tree.find('a.folder').before('<span class="show"></span>').click(openTree);та же проблема с заголовками...
Поэтому, если вам необходима функция сохранения состояния дерева, советую присмотреться к следующим скриптам:
www.linkexchanger.su/2008/49.html
habrahabr.ru/blogs/webdev/59823/
site-96.ru/blog/document287/
(все описания скриптов - на русском.)
Например так уже не работает скрипт...
Тест
Тест Или так