SiteIS

jQuery - безграничные возможности в дизайне Вашего сайта!

- Один из самых популярных на сегодня среди веб разработчиков фреймворк

- Позволяет быстро и легко создать потрясающие веб-приложения

- Удивительно красивые анимационные эффекты

- Улучшение пользовательского интерфейса

Расширяем функциональность аккордеона

Перед нами стоит задача доработать аккордеон, оснастив его некоторыми приятными возможностями. Топаем на свое рабочее место и попытаемся порассуждать, что требуется сделать. Итак, нам необходимо:

1. Добавить маркеры к пунктам меню, которые имеют вложенные списки.

2. Сделать видимым субменю только одного пункта меню верхнего уровня. При клике на следующий пункт, подменю текущего пункта должно прятаться.

3. Маркеры должны менять отображение в зависимости от того, скрыто в данный момент подменю, или видимо.

Начнем с первого пункта. За основу возьмем html разметку первого варианта (реализованную списками). Маркеры у нас будут в виде треугольника черного цвета, вершина которого будет направлена вправо, если подменю скрыто и вниз, если подменю открыто. Сами треугольники можно было бы выполнить с помощью фоновой картинки (спрайта), но мы усложним задачу, а заодно попрактикуемся в рисовании треугольников с помощью css.

Нам понадобится отобрать элементы li, в которых прячутся списки подменю и вставить внутрь этих элементов конструкцию вида <span> </span>. А в css для этой конструкции задать необходимые правила, что бы спан принял форму треугольника, отобразился в нужном месте и менял свое положение в зависимости от состояния меню.

Что делать, вроде бы ясно - осталось все это внедрить... В html коде менять ничего не нужно, там все нас устраивает. Открываем в блокноте js файл и приступим к реализации первого пункта нашего плана. В самом верху уже существующего кода вписываем такую строку.

$('ul li:has("ul")').append('<span></span>');

В итоге, если вы использовали js файл примера, описанного в статье "Простейший аккордеон ", то весь код теперь должен выглядеть так:

$(function () {
	$('ul li:has("ul")').append('<span></span>');
	$('ul li a').click(function() {
		var checkElement = $(this).next();
		checkElement.stop().animate({'height':'toggle'}, 500);	
		if((checkElement.is('ul')) && (checkElement.is(':visible'))) {
			return false;
		}
	});
});	

Теперь займемся стилями. Элементам li присваиваем свойство position:relative; и оформляем, добавленные с помощью js спаны, позиционируя их абсолютно относительно элемента li, в котором он находится.

ul li {
position:relative;
}
ul li span {
width:0;
height:0;
position:absolute;
top:9px;
right:9px;
border-top:5px solid transparent;
border-bottom:5px solid transparent;
border-left:10px solid #000;
}

Можно полюбоваться промежуточным результатом - стрелки отобразились на нужных пунктах меню, как мы того и хотели. Положения своего, в зависимости от состояния подменю, они пока не меняют, но это на данном этапе и не требуется.

Приступаем ко второму пункту. Нам понадобиться проверить есть ли у пункта меню, по которому кликнули, подменю и ели есть то показать его, а все остальные подменю, открытые в данный момент, если таковые имеются, спрятать. Вносим в код соответствующие изменения:

$(function () {
	$('ul li:has("ul")').append('<span></span>');
	$('ul li a').click(function() {
		var checkElement = $(this).next();
		
		if((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
			$('ul ul:visible').stop().animate({'height':'toggle'}, 500);
			checkElement.stop().animate({'height':'toggle'}, 500);
			return false;
        }	
		if((checkElement.is('ul')) && (checkElement.is(':visible'))) {
			return false;
		}
	});
});	

Код можно еще немного улучшить, если конструкцию $('ul ul:visible') хранить в переменной. Так и поступим.

$(function () {
	$('ul li:has("ul")').append('<span></span>');
	$('ul li a').click(function() {
		var checkElement = $(this).next(),
			visibleElement = $('ul ul:visible');
		
		if((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
			visibleElement.stop().animate({'height':'toggle'}, 500);
			checkElement.stop().animate({'height':'toggle'}, 500);
			return false;
        }	
		if((checkElement.is('ul')) && (checkElement.is(':visible'))) {
			return false;
		}
	});
});	

Осталось выполнить третий пункт. Поступим так - элементу li верхнего уровня, у которого есть вложенные пункты, если подменю открыто, будем добавлять класс (например, active). Соответственно, если подменю скрыто, класс будем убирать.

$(function () {
	$('ul li:has("ul")').append('<span></span>');
	$('ul li a').click(function() {
		var checkElement = $(this).next(),
			visibleElement = $('ul ul:visible');
		
		if((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
			visibleElement.stop().animate({'height':'toggle'}, 500).parent().removeClass('active');
			checkElement.stop().animate({'height':'toggle'}, 500).parent().addClass('active');
			return false;
        }	
		if((checkElement.is('ul')) && (checkElement.is(':visible'))) {
			return false;
		}
	});
});	

Теперь добавим стили для span активного пункта меню и можно любоваться конечным результатом.

ul li.active span {
border-top:10px solid #000;
border-left:5px solid transparent;
border-right:5px solid transparent;
}	

Не знаю как вы, а лично я нашел небольшой недочет. Открыв вложенный список хотя бы один раз мы уже не сможем свернуть все подменю. Исправить это не составляет труда - код, отвечающий за сворачивание вложенных списков нужно вынести за условие:

$(function () {
	$('ul li:has("ul")').append('<span></span>');
	$('ul li a').click(function() {
		var checkElement = $(this).next(),
			visibleElement = $('ul ul:visible');
			
		visibleElement.stop().animate({'height':'toggle'}, 500).parent().removeClass('active');		
		if((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
			checkElement.stop().animate({'height':'toggle'}, 500).parent().addClass('active');
			return false;
        }	
		if((checkElement.is('ul')) && (checkElement.is(':visible'))) {
			return false;
		}
	});
});	

Вот теперь можно радоваться полученному результату и демонстрировать работу начальству. Но у нас же есть еще и другой вариант, реализованный без списков - как раз о том, как добиться такого же результата, имея другую разметку и пойдет речь в следующей статье.

Конечный результат примера, если требуется, качаем по ссылке ниже.

Скачать готовый код

Автор: Super User