Сворачивание и разворачивание списков на jQuery

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

Автор . Дата: 18.11.2014

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

Список характеристик представлял из себя обычный список определений вида:

<dl id="properties-block">
    <dt></dt>
    <dd></dd>
    ...
</dl>
<a href="#" id="expand-btn">Подробнее</a>

 

Сначала нужно проверить, а действительно ли большой список? Может элементов в нем мало, и совершенно нет никако необходимости отображать кнопку. Реализовать это можно либо на серверной стороне, либо на клиентской. Я выбрал клиентскую:

    if ($("#properties-block").children("dd").length < 5)
        $("#expand-btn").hide();

Здесь мы проверяем, сколько у нас элементов в списке. Если меньше 5, то скрываем кнопку Подробнее. Дальше мы создаем обработчик события click для кнопки Подробнее, и отключаем действия по умолчанию. Т.е. браузер не будет переходить по ссылке:

    $("#expand-btn").click(function(event) {
        event.preventDefault();
        return false;
    });

Кнопка подробнее будет иметь 2 действия: сворачивание и разворачивание. Нам нужно каким-то образом отслеживать, в каком состоянии сейчас находится наша кнопка. Мы будет определять по тексту ссылки:

        if (this.textContent == 'Скрыть')
        {
            // действия при сворачивании
            this.textContent = 'Подробнее'
        }
        else
        { 
            // действия при разворачивании
            this.textContent = 'Скрыть'
        }

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

            $("#properties-block").animate({
                height: "76px"
            }, 700);

Я изначально посчитал какой размер будет у 4х элементов списка, поскольку размер одного элемента статистически задан в шаблоне. Скорее всего у вас размер будет меняться, но поскольку я очень ленивый, а ниже описан алгоритм разворачивания с учетом размеров элементов, то я оставляю вам эту задачку в качестве домашнего задания :-) 

Метод разворачивания у нас будет более сложный. Дело в том, что я интернет магазин крутится на движке 1С-Битрикс, и многие знают, как там все ужасно. Каким-то неизвестным образом размер всего списка оказывался намного больше, чем должен быть. Мне было дико лень отлаживать стили и искать ошибку, поэтому я сделал расчет высоты списка с помощью JS. Сделать это достаточно просто: для этого нужно пройтись по всем дочерним элементам списка, посмотреть их высоту и сложить:

            var block_height = 0;

            $('#properties-block').children("dd").each(function() {
                block_height += $(this).height();
                if ($(this).height() > 19)
                    block_height += 19;
            });

Я специально указал селектор для функции children потому, что элементы dt и dd расположены в одну строку, и высота получилась бы в 2 раза больше чем нужно. Была и ещё одна проблема: некоторые элементы dd содержали достаточно большие определения, из-за чего занимаемая высота получалась больше 19 пикселов и dd переносился на новую строку. На этот случай я приплюсовывал 19 пикселов за счет новой строки.

Вот собственно и вся магия. Полный код вы можете увидеть ниже:

$(document).ready(function() {
    if ($("#properties-block").children("dd").length < 5)
        $("#expand-btn").hide();

    $("#expand-btn").click(function(event) {
        event.preventDefault();

        if (this.textContent == 'Скрыть')
        {
            $("#properties-block").animate({
                height: "76px"
            }, 700);
            this.textContent = 'Подробнее'
        }
        else
        {        
            var block_height = 0;
            $('#properties-block').children("dd").each(function() {
                block_height += $(this).height();
                if ($(this).height() > 19)
                    block_height += 19;
            });

            $("#properties-block").animate({
                height: block_height
            }, 700);
            this.textContent = 'Скрыть'
        }
        return false;
    });
});

А вот и результат работы в свернутом состоянии:

и развернутом:


comments powered by HyperComments