Статьи

Создайте простой, интеллектуальный эффект аккордеона, используя Prototype и Scriptaculous

Мы все видели эффект типа «аккордеон», используемый на многих сайтах Web 2.0; однако, многие скрипты для аккордеона тяжелые, плохо используют библиотеки, на которых они основаны, и не занимаются такими вещами, как обеспечение того, что аккордеон поддерживает постоянную высоту. В этом руководстве мы будем использовать библиотеки Prototype и Scriptaculous для создания легкого интеллектуального аккордеона.




Наша цель — создать легкий аккордеонный скрипт на основе библиотек Prototype и Scriptaculous javascript.
Аккордеон должен:

  • Разрешить неограниченное количество аккордеонных панелей
  • Полностью стилизован под CSS
  • Будьте ненавязчивы — пользователи без включенного JavaScript должны видеть весь ваш аккордеонный контент
  • Быть легковесным — с относительно небольшим количеством строк кода; использовать делегирование событий для ограничения потребления памяти.
  • Поддержите любой контент в аккордеоне
  • Убедитесь, что при изменении содержимого каждой панели аккордеона высота аккордеона остается постоянной, чтобы избежать
    раздражающий эффект «подпрыгивания страницы»

Это относительно продвинутый учебник, предполагающий, что читатель имеет достаточные знания Javascript, CSS, HTML, Object-Oriented
программирование и базовое понимание библиотек Prototype и Scriptaculous. Тем не менее, полный исходный код
доступны для изучения, а код очень прост для чтения и изучения, если вы не знакомы с конкретными
используемые библиотеки

Прежде чем мы начнем, вы можете увидеть рабочую демонстрацию аккордеона в действии.


Для начала мы создадим простую HTML-разметку для нашего аккордеона:

01
02
03
04
05
06
07
08
09
10
<div id=»test-accordion» class=»accordion»>
     <div class=»accordion-toggle»>Toggle 1</div>
     <div class=»accordion-content»>Content 1</div>
     <div class=»accordion-toggle»>Toggle 2</div>
     <div class=»accordion-content»>Content 2</div>
     <div class=»accordion-toggle»>Toggle 3</div>
     <div class=»accordion-content»>Content 3</div>
     <div class=»accordion-toggle»>Toggle 4</div>
     <div class=»accordion-content»>Content 4</div>
</div>

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
div#test-accordion{
    margin: 10px;
    border: 1px solid #aaa;}
 
div.accordion {
    position: relative;
}
 
div.accordion-toggle{
    position: relative;
    z-index: 10;
    background: #eee;
    cursor: pointer;
}
 
div.accordion-toggle-active{
    background: #fff;
}
 
div.accordion-content{
    overflow: hidden;
    background: #aaa;
}

Посмотрите основной аккордеон с простой таблицей стилей.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
var Accordion = Class.create({
    initialize: function(){
        this.accordion = null;
        this.contents = null;
        this.options = null;
        this.maxHeight = 0;
        this.current = null;
        this.toExpand = null;
        this.isAnimating = false;
 
    },
 
    checkMaxHeight: function(){}, /* Determines the height of the tallest content pane */
    initialHide: function(){}, /* Hides the panes which are not displayed by default */
    attachInitialMaxHeight: function(){}, /* Ensures that the height of the first content pane matches the tallest */
    expand: function(el){}, /* Tells the animation function which elements to animate */
    animate: function(){}, /* Performs the actual animation of the accordion effect */
    handleClick: function(e){} /* Determine where a user has clicked and act based on that click */
 
});

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


Классы прототипов имеют специальный метод, называемый initalize (), который является конструктором; это означает, что действует, когда пользователь
создает новый экземпляр объекта этого класса. Для любого аккордеона нам нужно знать 2 вещи, прежде чем мы начнем:

  1. Идентификатор элемента аккордеона.
  2. Начальная позиция аккордеона по умолчанию (если она отличается от первой позиции)

Итак, нам нужно позволить нашему конструктору принять эти два параметра. Кроме того, наш конструктор должен:

  1. Получить и сохранить аккордеон и его содержимое как указатели на эти элементы
  2. Установите пользовательские параметры
  3. Установить текущий расширенный элемент
  4. Определите максимальную высоту, которую мы будем использовать в качестве высоты для всех наших панелей контента, и примените ее
  5. Скрыть панели содержимого, которые не отображаются по умолчанию
  6. Добавьте слушателя событий в аккордеон, чтобы наблюдать клики пользователей.

Вот код для нашего метода initialize ():

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
initialize: function(id, defaultExpandedCount) {
    if(!$(id)) throw(«Attempted to initalize accordion with id: «+ id + » which was not found.»);
    this.accordion = $(id);
    this.options = {
        toggleClass: «accordion-toggle»,
        toggleActive: «accordion-toggle-active»,
        contentClass: «accordion-content»
    }
    this.contents = this.accordion.select(‘div.’+this.options.contentClass);
    this.isAnimating = false;
    this.maxHeight = 0;
    this.current = defaultExpandedCount ?
    this.toExpand = null;
 
    this.checkMaxHeight();
    this.initialHide();
    this.attachInitialMaxHeight();
 
    var clickHandler = this.clickHandler.bindAsEventListener(this);
    this.accordion.observe(‘click’, clickHandler);
}

Как видите, мы установили для всех наших свойств приемлемые значения по умолчанию и вызвали 3 метода, чтобы помочь установить вещи
вверх. Наконец, мы прикрепили обработчик событий к аккордеону. Давайте создадим эти три метода и обработчик событий.


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

1
2
3
4
5
6
7
checkMaxHeight: function() {
    for(var i=0; i<this.contents.length; i++) {
        if(this.contents[i].getHeight() > this.maxHeight) {
            this.maxHeight = this.contents[i].getHeight();
        }
    }
}

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

1
2
3
4
5
6
7
8
initialHide: function(){
    for(var i=0; i<this.contents.length; i++){
        if(this.contents[i] != this.current) {
            this.contents[i].hide();
            this.contents[i].setStyle({height: 0});
        }
    }
}

Теперь, когда мы скрыли все, кроме панели контента по умолчанию, нам нужно убедиться, что панель контента по умолчанию отображается правильно;
к заголовку должен быть применен «активный» стиль, а его высота должна соответствовать свойству maxHeight:

1
2
3
4
attachInitialMaxHeight: function() {
    this.current.previous(‘div.’+this.options.toggleClass).addClassName(this.options.toggleActive);
    if(this.current.getHeight() != this.maxHeight) this.current.setStyle({height: this.maxHeight+»px»});
}

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

1
2
3
4
5
6
clickHandler: function(e) {
    var el = e.element();
    if(el.hasClassName(this.options.toggleClass) && !this.isAnimating) {
        this.expand(el);
    }
}

Эта функция состоит из двух частей. Сначала мы определяем, на что нажали. Затем мы проверяем, чтобы это было
заголовок, по которому щелкнули и анимация не запущена. Если это так, мы вызываем метод expand ()
чтобы начать процесс аккордеона. Переменная, которую мы передаем методу expand (), является заголовком, по которому щелкнул пользователь.


Теперь мы можем начать процесс создания эффекта аккордеона. Мы знаем, что метод expand () должен принимать параметр для
элемент, который был нажат Используя этот параметр, метод раскрытия определяет, какую область содержимого развернуть, и если
еще не раскрыт, вызывает метод animate (), чтобы «сделать свое волшебство!»

1
2
3
4
5
6
7
expand: function(el) {
    this.toExpand = el.next(‘div.’+this.options.contentClass);
    if(this.current != this.toExpand){
        this.toExpand.show();
        this.animate();
    }
},

На этом этапе все части на месте; мы знаем, какая панель контента отображается в данный момент, мы знаем, какой заголовок
пользователь нажал, и мы знаем, какую панель контента пользователь запросил для показа. Теперь мы должны создать аккордеон
анимация. Для этого мы создадим метод animate (), который будет использовать класс Scriptaculous Effect.Parallel для визуализации.
две анимации вместе; и класс Effect.Scale для изменения размера каждой панели содержимого. Одушевленный метод
выполните эти шаги:

  1. Создайте массив, который будет использоваться для хранения наших объектов Effect.Scale
  2. Соберите параметры для передачи конструктору Effect.Scale для области содержимого, которая будет показана, и создайте
    объект
  3. Добавьте этот объект в наш массив
  4. Соберите параметры для передачи конструктору Effect.Scale для области содержимого, которая будет скрыта, и создайте
    объект
  5. Добавьте этот объект в наш массив
  6. Создать объект Effect.Parallel, который будет запускать наши объекты Effect.Scale, — это синхронизация.
  7. Скажите нашему объекту Аккордеон, что мы анимируем
  8. Запустите анимацию
  9. Уберите любые стили, оставленные позади
  10. Скажите нашему объекту Accordion, что мы закончили анимацию
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
animate: function() {
    var effects = new Array();
    var options = {
        sync: true,
        scaleFrom: 0,
        scaleContent: false,
        transition: Effect.Transitions.sinoidal,
        scaleMode: {
            originalHeight: this.maxHeight,
            originalWidth: this.accordion.getWidth()
        },
        scaleX: false,
        scaleY: true
    };
 
    effects.push(new Effect.Scale(this.toExpand, 100, options));
 
    options = {
        sync: true,
        scaleContent: false,
        transition: Effect.Transitions.sinoidal,
        scaleX: false,
        scaleY: true
    };
 
    effects.push(new Effect.Scale(this.current, 0, options));
 
    new Effect.Parallel(effects, {
        duration: 0.5,
        fps: 35,
        queue: {
            position: ‘end’,
            scope: ‘accordion’
        },
        beforeStart: function() {
            this.isAnimating = true;
            this.current.previous(‘div.’+this.options.toggleClass).removeClassName(this.options.toggleActive);
            this.toExpand.previous(‘div.’+this.options.toggleClass).addClassName(this.options.toggleActive);
        }.bind(this),
        afterFinish: function() {
            this.current.hide();
            this.toExpand.setStyle({ height: this.maxHeight+»px» });
            this.current = this.toExpand;
            this.isAnimating = false;
        }.bind(this)
    });
}

Для полного объяснения параметров опций мы передаем объекты Effect.Scale и Effect.Parallel,
пожалуйста, смотрите документацию Scriptaculous .
Важными аспектами метода являются методы beforeStart и afterFinish в нашем Effect.Parallel. До начала
Метод сообщает аккордеону, что он в данный момент анимируется. Это предотвратит попытку запуска обработчиком события
любые дальнейшие изменения, пока идет анимация. Это также гарантирует, что заголовок, на который нажали
дали «активное» имя класса. Метод afterFinish полностью скрывает панель контента, которая ранее отображалась
(после того, как он исчез из-за анимации). Это также гарантирует, что конечная высота вновь отображаемого контента
панель правильная. Теперь, когда обмен завершен, он сообщает нашему аккордеону, что в настоящее время расширенная панель содержимого
тот, который мы недавно расширили и что анимация завершена.


На данный момент у нас есть прилично выглядящий аккордеон, который вы можете увидеть в действии здесь . Но с небольшим количеством CSS мы можем сделать все это более эффектным. Итак, сначала мы создадим быстрый макет Photoshop, чтобы иметь общее представление о том, как все это должно выглядеть. Имея это в виду, нам понадобятся три изображения:

  1. Изображение с логотипом —
  2. Пара красивых фоновых изображений — и

И вот пересмотренный код CSS:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
body {
    padding: 130px 50px 50px 50px;
    background: #252422 url(../img/logo.gif) no-repeat;
    background-position: 60px 40px;
    font-family: «Lucida Grande», «Lucida Sans Unicode», Arial, Sans-serif;
    font-size: 11px;
    line-height: 18px;
}
 
div#test-accordion{
    border: 1px solid #343230;
    background-color: #21201f;
    padding: 10px;
}
 
div.accordion {
    position: relative;
    width: 800px;
}
 
div.accordion-toggle{
    position: relative;
    z-index: 10;
    background: #3f3c38 url(../img/off.jpg) repeat-x;
    background-position: bottom;
    color: #fff;
    cursor: pointer;
    margin-bottom: 1px;
    padding: 9px 14px 6px 14px;
    border-top: 1px solid #5d5852;
}
 
div.accordion-toggle:hover, div.accordion-toggle-active{
    background-image: url(../img/on.jpg);
    background-color: #6d493a;
    border-top: 1px solid #a06b55;
}
 
div.accordion-content{
    overflow: hidden;
    background: #302e2c;
    color: #c4bab1;
    border-bottom: 1px solid #000;
}
 
div.accordion-content p{
margin: 9px 24px 6px 24px;
}

Как вы можете видеть здесь, мы имеем:

  1. Добавлены некоторые стили фона вокруг страницы и класс аккордеона
  2. При условии аккордеонного переключателя div обычный цвет фона
  3. Установите переключатель аккордеон: hover и активные состояния, чтобы использовать тот же красноватый фон

Вы можете увидеть рабочую демонстрацию здесь. Вы также можете добавить свой собственный CSS и изображения
адаптировать внешний вид к вашему сайту.

Загрузить: accordion.js & accordion.css