Виджет Accordion

191

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

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

Создание виджета Accordion

Как вы, наверное, уже догадались, для создания виджета Accordion jQuery UI используется метод accordion(). Пример создания такого виджета представлен ниже:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>jQuery UI</title>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="//ajax.aspnetcdn.com/ajax/jquery.ui/1.10.3/jquery-ui.min.js"></script>
    <link rel="stylesheet" href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.10.3/themes/sunny/jquery-ui.css">
<script type="text/javascript">
$(function() {
	
	$('#accordion').accordion();
	$('button').button();
	
});
</script>
</head>
<body>
<h1>Цветочный магазин</h1>
    <form>      
            <div id="accordion">
                <h2><a href="#">Ряд 1</a></h2>
                <div id="row1" class="drow">
                    <div class="dcell">
                        <img src="http://professorweb.ru/downloads/jquery/astor.png"/>
                        <label for="astor">Астра:</label>
                        <input name="astor" value="0" required>
                    </div>
                    <div class="dcell">
                        <img src="http://professorweb.ru/downloads/jquery/daffodil.png"/>
                        <label for="daffodil">Нарцисс:</label>
                        <input name="daffodil" value="0" required >
                    </div>
                    <div class="dcell">
                        <img src="http://professorweb.ru/downloads/jquery/rose.png"/>
                        <label for="rose">Роза:</label>
                        <input name="rose" value="0" required>
                    </div>                
                </div>
                <h2><a href="#">Ряд 2</a></h2>
                <div id="row2" class="drow">
                    <div class="dcell">
                        <img src="http://professorweb.ru/downloads/jquery/peony.png"/>
                        <label for="peony">Пион:</label>
                        <input name="peony" value="0" required>
                    </div>
                    <div class="dcell">
                        <img src="http://professorweb.ru/downloads/jquery/primula.png"/>
                        <label for="primula">Примула:</label>
                        <input name="primula" value="0" required>
                    </div>            
                    <div class="dcell">
                        <img src="http://professorweb.ru/downloads/jquery/snowdrop.png"/>
                        <label for="snowdrop">Подснежник:</label>
                        <input name="snowdrop" value="0" required>
                    </div>            
                </div>
                <h2><a href="#">Ряд 3</a></h2>
                <div id="row2" class="drow">
                    <div class="dcell">
                        <img src="http://professorweb.ru/downloads/jquery/carnation.png"/>
                        <label for="carnation">Гвоздика:</label>
                        <input name="carnation" value="0" required>
                    </div>
                    <div class="dcell">
                        <img src="http://professorweb.ru/downloads/jquery/lily.png"/>
                        <label for="lily">Лилия:</label>
                        <input name="lily" value="0" required>
                    </div>            
                    <div class="dcell">
                        <img src="http://professorweb.ru/downloads/jquery/orchid.png"/>
                        <label for="orchid">Орхидея:</label>
                        <input name="orchid" value="0" required>
                    </div>            
                </div>          
            </div>
        <div id="buttonDiv"><button type="submit">Заказать</button></div>                    
    </form>
</body>
<style>
        h1 {
            min-width: 70px; border: thick double black; margin-left: auto;
            margin-right: auto; text-align: center; font-size: x-large; padding: .5em;
            color: darkgreen; background-image: url("http://professorweb.ru/downloads/jquery/border.png");
            background-size: contain; margin-top: 0;
        }     
        .dcell {display: table-cell; padding: 10px;}
        .dcell > * {vertical-align: middle}
        input {width: 2em; text-align: right; border: thin solid black; padding: 2px;}
        label {width: 6em;  padding-left: .5em; display: inline-block;}
        #buttonDiv {text-align: center;}
        button {padding: 12px;}
        #oblock {display: block; margin-left: auto; margin-right: auto; min-width: 700px; }
		#accordion {margin:5px; }
		.dcell img {height:60px}
</style>
</html>

Запустить пример

Наиболее важной частью этого примера является содержимое контейнера div с идентификатором accordion:

<div id="accordion">
   ...
</div>

Здесь форматирование HTML-разметки было незначительно изменено, чтобы сделать структуру элементов более очевидной. Элемент div верхнего уровня — это базовый элемент, для которого вызывается метод accordion(). После вызова этого метода jQuery UI просматривает содержимое базового элемента в поиске заголовков (элементы от h1 до h6) и разбивает содержимое на отдельные разделы таким образом, чтобы с каждым заголовком был связан следующий за ним элемент. В данном случае в качестве заголовков используются элементы h2, за каждым из которых следует элемент div.

Обратите внимание на элементы <a>, добавленные в каждый элемент h2. С помощью этих элементов мы определяем заголовки для панелей содержимого. Как именно jQuery UI выполняет преобразование элемента div верхнего уровня и его содержимого, показано на рисунке:

Виджет Accordion jQuery UI

Присвоение атрибуту href значения # — это общепринятый способ идентификации элементов в тех случаях, когда с ними предполагают работать только средствами JavaScript. Этот подход использован здесь исключительно ради упрощения примера, но в целом я рекомендую использовать динамическую вставку элементов <a> с помощью jQuery, чтобы не создавать помех для тех пользователей, в браузерах которых выполнение JavaScript-сценариев запрещено.

Во вновь созданном виджете отображается лишь содержимое первой панели, в то время как остальные панели закрыты. Содержимое элементов <a> используется в качестве заголовков панелей, и щелчок на каком-либо заголовке приводит к закрытию текущей панели и открытию панели, заголовок которой был выбран (этот переход выполняется с применением эффекта анимации).

Настройка виджета Accordion

Виджет Accordion поддерживает ряд настраиваемых свойств, позволяющих управлять различными аспектами его поведения. Эти свойства приведены в таблице ниже. Возможности настройки виджета Autocomplete с помощью этих опций описаны в следующих разделах.

Свойства виджета Accordion
Свойство Описание
active Позволяет определить, какая панель отображается или должна отображаться. По умолчанию первоначально отображается первая панель
animated Определяет тип анимации, используемой при смене панелей содержимого. Значение по умолчанию — slide
autoHeight Если эта опция равна true, то для всех панелей устанавливается одинаковая высота, соответствующая панели с наибольшим по размеру содержимым. Значение по умолчанию — true. Отсутствует в библиотеке jQuery UI версии 1.9 и выше, нужно использовать свойство heightStyle
clearStyle Если эта опция равна true, то по завершении анимационного перехода значения высоты всех панелей сбрасываются и заново пересчитываются для учета возможного изменения высоты панели с максимальным размером содержимого. Значение по умолчанию — false. Отсутствует в библиотеке jQuery UI версии 1.9 и выше, нужно использовать свойство heightStyle
collapsible Если эта опция равна true, то щелчок на открытой панели приводит к ее закрытию, в результате чего все панели оказываются закрытыми. Значение по умолчанию — false
disabled Если эта опция равна true, то виджет отключен. Значение по умолчанию — false
event Определяет для элемента заголовка событие, при наступлении которого происходит переключение панелей. Значение по умолчанию — click
fillSpace Если эта опция равна true, то виджет будет занимать все пространство своего родительского элемента по высоте. Значение по умолчанию — false, при котором высота виджета определяется высотой панелей содержимого. Отсутствует в библиотеке jQuery UI версии 1.9 и выше, нужно использовать свойство heightStyle
header Определяет элементы, используемые в качестве заголовков
icons Определяет значки, используемые в виджете Accordion

Настройка высоты виджета Accordion

Высоту виджета Accordion можно регулировать различными способами, в которых исходят либо из высоты содержимого панелей, либо из высоты родительского элемента. Чаще всего можно ничего не менять и оставить значение по умолчанию, определяемое опцией autoHeight. Эта опция, значением которой по умолчанию является true, устанавливает для всех панелей одинаковую высоту (совпадающую с высотой максимальной по размеру содержимого панели) и на основании этого определяет высоту всего виджета.

Именно такой подход был использован в предыдущем примере, однако им необходимо пользоваться с осторожностью в тех случаях, когда содержимое включает изображения, особенно если элементы img добавляются в документ средствами jQuery. Проблема в том, что метод accordion() может быть вызван еще до того, как будут загружены все изображения, в результате чего информация о высоте панелей содержимого, полученная jQuery UI от браузера, окажется ложной.

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

.dcell img {height:60px}

Продолжим наш пример. Используя значение по умолчанию опции autoHeight, равное true, можно установить одинаковую высоту для всех панелей содержимого, что будет выглядеть не очень привлекательно при больших отличиях в размерах содержимого различных панелей. В примере ниже приведен сценарий, в котором способ вставки элементов, содержащих информацию о продуктах, несколько изменен:

$(function() {
	
	$('<h2><a href=#>Все</a></h2><div id=row0></div>')
		 .prependTo('#accordion').filter('div')
		 .append($('#row1, #row2, #row3').clone())
		 
    $('#accordion').accordion();
	$('button').button();
	
});

Запустить пример

В этом примере для создания панели содержимого, высота которой значительно превышает высоту остальных панелей, имеющиеся элементы содержимого div клонируются с помощью jQuery и помещаются в новую панель, в результате чего создается панель, в которой отображаются все продукты. Высота этой панели в раскрытом состоянии в три раза превышает высоту любой другой панели, что приводит к образованию пустого пространства при отображении панелей с содержимым небольшого размера. Все это можно увидеть на рисунке:

Эффект использования опции autoHeight в случае больших различий в высоте элементов содержимого

Если большие размеры пустого пространства в пределах панелей вас не устраивают, можете установить для опции autoHeight значение false, как показано в примере ниже:

...
   
    $('#accordion').accordion({
		autoHeight: false
    });
...

В версии библиотеки jQuery UI 1.9 и выше этот подход не будет работать, вместо свойства autoHeight нужно определять свойство heightStyle, как показано ниже:

...
    $('#accordion').accordion({
		heightStyle: "content" 
    });
...

Запустить пример

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

Изменение типа события, активизирующего панель

По умолчанию для открытия и закрытия панелей используются щелчки мышью. Поведением панелей можно управлять с помощью опции event, как показано в примере ниже:

$(function() {
    
    $('#accordion').accordion({
        event: "mouseover"
    })
	$('button').button();
	
});

Запустить пример

В этом примере мы указали с помощью опции event, что панели должны открываться в ответ на событие mouseover. В результате этого открытие панели будет происходить при наведении на нее указателя мыши. Я не могу продемонстрировать этот эффект с помощью снимков экрана и поэтому рекомендую выполнить код примера в браузере.

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

Изменение значков виджета Accordion

Опция icons позволяет изменить значки, используемые в заголовках панелей виджета. Соответствующий пример представлен ниже:

$(function() {
    
    $('#accordion').accordion({
        collapsible: true,
        icons: {
            header: "ui-icon-zoomin",
            headerSelected: "ui-icon-zoomout"
        }
    })
	$('button').button();
	
});

Значение опции icons задается в виде объекта, имеющего свойства header и headerSelected. Первое свойство указывает, какой значок следует использовать для закрытой панели, а второе — для открытой. Обычно я использую опцию icons в сочетании с опцией collapsible, поскольку использование значков как дополнительного средства, указывающего на возможность выполнения тех или иных действий, повышает комфортность работы пользователя. Как эти значки выглядят в заголовках панелей, показано на рисунке:

Применение настраиваемых значков в заголовках панелей

Использование методов виджета Accordion

Для виджета Accordion определен ряд методов. Большинство из них — это стандартные методы, общие для всех виджетов jQuery UI, но два из них обеспечивают возможность управления данным виджетом из кода программы. Список доступных методов приведен в таблице ниже:

Методы виджета Accordion
Метод Наличие в jQuery UI версии >= 1.9 Описание
accordion("destroy") + Полностью удаляет функциональность виджета Accordion из элемента input
accordion("disable") + Приостанавливает работу виджета Accordion для данного элемента
accordion("enable") + Возобновляет работу ранее приостановленного виджета Accordion
accordion("option") + Устанавливает значения одной или нескольких опций
accordion("activate", index) Отсутствует, нужно использовать синтаксис свойств Открывает панель, соответствующую указанному индексу (отсчет индексов ведется с нуля)
accordion("resize") Отсутствует При включенной опции fillSpace разрешает изменение размера виджета в соответствии с изменениями размера родительского элемента

Метод resize лучше всего использовать совместно с элементами, обладающими функциональностью Draggable. Поэтому здесь нам остается рассмотреть лишь метод activate, поскольку все остальные методы являются общими для всех виджетов jQuery UI, и о том, как они работают, уже рассказывалось ранее. Пример использования метода activate для программного управления виджетом Accordion приведен ниже:

$(function() {
    
    $('#accordion').accordion({
        active: false,
        collapsible: true
    })
    
    $('button').hide();
    var ids = ["2", "1", "0", "Закрыть вкладку"];
    for (var i = 0; i < ids.length; i++) {
        $('<button id=' + ids[i] + '>' + ids[i] + '</button>').insertAfter('h1')
    }
	
	$('button').button().click(function(e) {
        if (this.id == "None") {
            $('#accordion').accordion("option", "active", false);
        } else {
            $('#accordion').accordion("option", "active", Number(this.id));
        }
    });
    
	/* Для jQuery UI < 1.9 v.
    $('button').button().click(function(e) {
        if (this.id == "None") {
            $('#accordion').accordion("activate", false);
        } else {
            $('#accordion').accordion("activate", Number(this.id));
        }
    });
	*/
});

Запустить пример

В этом сценарии добавлены кнопки, соответствующие индексам панелей, а также кнопка "Закрыть вкладку", щелчок на которой приводит к закрытию всех панелей. Результат можно видеть на рисунке:

Добавление кнопок для управления активизацией панелей

Щелчок на пронумерованной кнопке активизирует соответствующую панель.

Пройди тесты
Лучший чат для C# программистов