Динамический список рубрик: полное руководство по внедрению кнопки показать скрыть

Показывать справа: 0

В современном веб-дизайне важна не только привлекательность, но и удобство использования. Динамические элементы, такие как интерактивные списки рубрик или тегов, помогают пользователям быстрее находить нужную информацию, улучшая навигацию и, как следствие, SEO вашего сайта. В этом уроке мы разберем, как реализовать функционал "Показать/Скрыть" для списка рубрик, используя JavaScript (jQuery), HTML и CSS.

Введение: Зачем нужен динамический список рубрик?

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

Шаг 1: HTML-структура

Основой для нашего динамического списка служит следующая HTML-разметка. Каждый список рубрик помещен в контейнер .seotags_cloud, а сам список имеет класс .seotags_list и уникальный атрибут data-id. Элементы списка — это ссылки <a>.


<div class="seotags_cloud">
    <div class="seotags_list" data-id="1">
        <!-- Здесь будут ссылки на рубрики -->
        <a href="/vafelnye-plyajnye-polotenca1/" class="filter_button_gg myshow" style="display: inline-block;">Вафельные пляжные полотенца (37)</a>
        <a href="/vafelnye-polotenca-s-risunkom1/" class="filter_button_gg myshow" style="display: inline-block;">Вафельные полотенца с рисунком (36)</a>
        <!-- ... другие ссылки ... -->
    </div>
    <!-- ... другие .seotags_list блоки, если есть ... -->
</div>
        

Шаг 2: CSS-стили

CSS отвечает за внешний вид нашего списка. Важные стили включают классы для скрытия элементов (.myhide) и позиционирование кнопок "Показать/Скрыть" (.show__button_serv).


.seotags_cloud {
    position: relative;
    margin: 20px 0;
}
.seotags_cloud .seotags_list {
    display: block;
    position: relative;
    font-size: 14px;
    padding: 0;
    width: auto;
}
.seotags_cloud .seotags_list a {
    color: #065679;
    background: #FFFFFF;
    border: 1px solid #065679;
    border-radius: 4px;
}
.seotags_cloud .seotags_list a
{
    display: inline-block;
    color: #23a1d1;
    border: 1px solid #23a1d1;
    padding: 4px 20px;
    margin: 0 5px 10px 5px;
    border-radius: 5px;
    transition: 0.3s;
}
.seotags_list a.myhide {
    display: none; /* Класс для скрытия элементов */
}
.show__button_serv {
    visibility: hidden; /* Изначально скрыта, пока не будет определено положение */
    position: absolute !important; /* Позволяет точно позиционировать кнопку */
    bottom: 0px;
}
  @media (max-width: 700px) {
       .show__button_serv  {
     
    position: initial!important; /* На маленьких экранах кнопка становится обычной */
     
   }
  }
        

Шаг 3: JavaScript (jQuery) для динамической функциональности

Основная магия происходит в JavaScript. Этот код анализирует структуру, определяет, сколько элементов помещается в заданное количество строк, скрывает лишние и добавляет интерактивные кнопки "Показать/Скрыть".


/*@ ***********************
  Рубрики
  ****************************/

// Ожидаем полной загрузки DOM перед выполнением скрипта
jQuery(document).ready(function(){

  // filter_servicekol: Количество строк, которые должны быть видны сразу.
  // Элементы будут скрываться, если они не помещаются в это количество строк.
  var filter_servicekol = 2;

  // filter_servicekol_was: Количество элементов, которое будет показываться за один клик по кнопке "Показать".
  // Эта переменная определяет "шаг" пагинации или "порцию" элементов для отображения.
  // Меньшее значение = более мелкая пагинация.
  var filter_servicekol_was = 20; // Пример: показывать по 20 элементов за клик. Можно уменьшить.

  // filter_servicekol__new: Массив, который будет хранить для каждого .seotags_list,
  // сколько элементов должно быть видимо изначально (рассчитано по строкам).
  var filter_servicekol__new = [];


  /*@ ***********************
     Добавляем две кнопки к списку скрыть и показать
   ****************************/
  // Проверяем, существует ли хотя бы один блок с классом ".seotags_list"
   if  (jQuery(".seotags_list").length>0)
 {

    // Каждому блоку ".seotags_list" присваиваем data-id="n".
    // Важно: если блоков несколько, data-id должен быть уникальным для каждого.
    // В данном примере предполагается, что этот атрибут будет корректно назначен в HTML или здесь.
 

 

 jQuery( ".seotags_list" ).each(function( index3 ) {
      var obj2 = jQuery(this);
      obj2.attr('data-id',index3 );
      obj2.append(`<a data-id="`+index3+`" class="show__button_serv filter_button_tags more_button_tags" id="show" style="visibility: visible; display:none">
         <i class="fa-solid fa-chevron-down"></i>
        </a>
        <a data-id="`+index3+`" style="display:none" class="hide__button_serv filter_button_tags more_button_tags" id="hide">
          <i class="fa-solid fa-chevron-up"></i>
        </a>`);



       });
      
 }
 
      
 
 
 

  /****************** end@ */

  // per: Вспомогательная переменная, используемая в обработчике клика по кнопке "Показать".
  // Она получает значение filter_servicekol_was.
  per = filter_servicekol_was;
  // items_gr: Массив, который будет хранить jQuery-объекты всех ссылок (.filter_button_gg)
  // для каждого блока .seotags_list.
  var items_gr = [];
  // i_mm_gr: Массив, хранящий количество видимых элементов (.filter_button_gg.myshow)
  // для каждого блока .seotags_list.
  var i_mm_gr = [];
  // total_mm_gr: Массив, хранящий общее количество элементов, которое должно быть показано
  // после нажатия на кнопку "Показать" (начиная с первого).
  var total_mm_gr = [];
  // start__sp_gr: Массив, вероятно, для хранения начальной позиции или количества элементов.
  // В текущей логике не используется активно.
  var start__sp_gr = [];

  // new_global_start__postiton_tags: Функция для инициализации и перерасчета
  // начального положения элементов. Определяет, сколько элементов помещается в заданное количество строк.
  function new_global_start__postiton_tags() {

    // Сброс переменных для корректного пересчета при каждом вызове
    per = filter_servicekol_was;
    items_gr = [];
    i_mm_gr = [];
    total_mm_gr = [];
    start__sp_gr = [];
    filter_servicekol__new = [];

    // Перебираем каждый блок с классом ".seotags_list"
    jQuery(".seotags_list").each(function(index) {
      var obj2 = jQuery(this); // Текущий блок .seotags_list

      // Перед расчетом, удаляем классы, которые могли быть добавлены ранее,
      // и делаем все элементы видимыми, чтобы корректно измерить их положение.
      obj2.find(".myhide").removeClass('myhide');
      obj2.find(".myshow").removeClass('myshow');
      obj2.find('a').css('display', 'inline-block');

      var counter = {}; // Счетчик для определения элементов, находящихся в одной строке (по Y-координате)

      // Проходим по всем ссылкам внутри текущего блока .seotags_list
      obj2.find("a").each(function(index) {
        var obj = jQuery(this); // Текущая ссылка

        // Игнорируем кнопки "Показать"/"Скрыть", обрабатываем только элементы списка
        if (obj.hasClass('filter_button_tags') == false) {
          obj.addClass('filter_button_gg'); // Добавляем общий класс для всех элементов рубрик

          var offset2 = obj.offset(); // Получаем координаты элемента
          var offset = 1 * offset2.top; // Получаем Y-координату (верхнюю границу элемента)

          // Если Y-координата больше 0 (элемент видим), увеличиваем счетчик для этой строки.
          // Это позволяет определить, сколько элементов помещается в одну строку.
          if (offset > 0)
            counter[offset] = counter[offset] ? counter[offset] + 1 : 1;
        }
      });

      // console.log(counter); // Отладочный вывод: показывает, сколько элементов в каждой строке

      var kol_m = 0; // Общее количество элементов, которые должны быть видны по умолчанию
      var k = 1; // Вспомогательная переменная для цикла (счетчик строк)

      // Перебираем счетчик строк (объект 'counter')
      // Цель: определить, сколько элементов помещается в первые 'filter_servicekol' строк.
      for (property in counter) {
        // Добавляем количество элементов из текущей строки к общему счетчику видимых элементов
        kol_m += counter[property] * 1;
        k = k + 1; // Увеличиваем счетчик строк

        // Прерываем цикл, если мы прошли количество строк, заданное в filter_servicekol
        if (k > filter_servicekol) {
          break;
        }
      }

      // console.log(' kol_m =' + kol_m); // Отладочный вывод
      // console.log(' filter_button_gg total =' + obj2.find(".filter_button_gg").length); // Отладочный вывод

      // Показываем кнопку "Показать", если она была скрыта
      obj2.find(".show__button_serv").show();

      // Если общее количество элементов (.filter_button_gg) равно рассчитанному количеству видимых элементов (kol_m),
      // значит, все элементы помещаются и скрывать ничего не нужно. В этом случае скрываем обе кнопки.
      if (obj2.find(".filter_button_gg").length == (kol_m)) {
        obj2.find(".more_button_tags").hide(); // Скрываем обе кнопки "Показать"/"Скрыть"
      }

      // Сохраняем рассчитанное количество видимых элементов для текущего блока .seotags_list.
      // Это значение будет использоваться в функции start__postiton_tags.
      filter_servicekol__new.push(kol_m);

      // Изначально скрываем кнопку "Скрыть"
      obj2.find(".hide__button_serv").hide();

    }); // Конец цикла по .seotags_list

  } // Конец функции new_global_start__postiton_tags

  // start__postiton_tags: Функция для установки начального состояния видимости элементов.
  // Она применяет классы 'myhide' (для скрытия) и 'myshow' (для показа) на основе расчетов из new_global_start__postiton_tags.
  function start__postiton_tags() {

    // Перебираем каждый блок с классом ".seotags_list"
    jQuery(".seotags_list").each(function(index3) {
      var obj2 = jQuery(this); // Текущий блок .seotags_list
      var kol = 0; // Счетчик элементов в текущем блоке

      // Сначала скрываем все элементы, которые не должны быть видны по умолчанию,
      // и удаляем класс 'myshow', чтобы начать заново.
      obj2.find(".filter_button_gg").hide();
      obj2.find(".myshow").removeClass('myshow');

      var obh_k = 0; // Вспомогательная переменная для получения позиции предыдущего видимого элемента

      // Проходим по всем ссылкам внутри текущего блока .seotags_list
      obj2.find("a").each(function(index) {
        var obj = jQuery(this); // Текущая ссылка

        // Обрабатываем только ссылки, которые не являются кнопками
        if (obj.hasClass('filter_button_tags') == false) {
          kol++; // Увеличиваем счетчик элементов

          // Если текущий элемент (kol) больше, чем рассчитанное количество видимых элементов (filter_servicekol__new[index3]),
          // то этот элемент должен быть скрыт.
          if (kol > filter_servicekol__new[index3] && obj.hasClass('filter_button_tags_active') == false) {
            // Не видимые элементы - присваиваем класс 'myhide'
            obj.addClass('myhide');

            // Пытаемся установить позицию кнопки "Показать" справа от последнего видимого элемента.
            // Эта часть требует, чтобы 'obh_k' был корректно установлен как предыдущий видимый элемент.
            var left = obh_k.position().left * 1; // Получаем левое смещение предыдущего видимого элемента
            var w = obh_k.width() * 1; // Получаем ширину предыдущего видимого элемента

            var dop_ww = 50; // Дополнительное смещение для кнопки "Показать"
            // Уменьшаем смещение на очень маленьких экранах
            if (jQuery(window).width() < 350) {
              var dop_ww = 15;
            }

            // Применяем CSS к кнопке "Показать" для установки ее позиции
            obj2.find(".show__button_serv").css('left', (left + w + dop_ww));
          } else {
            // Видимые элементы - присваиваем класс 'myshow' и убеждаемся, что они отображаются
            obh_k = obj; // Обновляем 'obh_k' текущим видимым элементом
            obj.addClass('myshow'); // Добавляем класс 'myshow'
            obj.css('display', 'inline-block'); // Убеждаемся, что элемент виден
          }
        }
      }); // Конец цикла по ссылкам

    }); // Конец цикла по .seotags_list

  } // Конец функции start__postiton_tags

  // filter__analiz: Основная функция, которая запускает все процессы инициализации и расчета.
  // Она вызывается при загрузке страницы и при изменении размера окна.
  function filter__analiz() {

    // Сначала пересчитываем начальное положение и видимость элементов
    new_global_start__postiton_tags();
    // Затем применяем эти настройки, скрывая/показывая элементы
    start__postiton_tags();

    // Инициализация массивов для хранения данных по каждому блоку .seotags_list
    jQuery(".seotags_list").each(function(index) {
      var obj = jQuery(this); // Текущий блок .seotags_list

      // Сохраняем jQuery-объект всех ссылок (.filter_button_gg) для этого блока
      // Используем data-id для индексации массива
      items_gr[obj.data('id') * 1] = obj.find('.filter_button_gg');
      // Сохраняем количество видимых элементов (.filter_button_gg.myshow) для этого блока
      i_mm_gr[obj.data('id') * 1] = obj.find('.filter_button_gg.myshow').length;
      // Инициализируем счетчик показанных элементов, который будет увеличиваться при клике на "Показать"
      total_mm_gr[obj.data('id') * 1] = 0;
      // Инициализируем начальное положение (не используется в текущей логике)
      start__sp_gr[obj.data('id') * 1] = 0;
    });

    // Делаем кнопки "Показать" видимыми после всех расчетов
    jQuery(".show__button_serv").css('visibility', 'visible');

  }

  // Обработчик клика по кнопке "Показать"
  jQuery(".show__button_serv").on("click", function() {
    var obj = jQuery(this); // Текущая кнопка "Показать"
    var index_gr = obj.data('id') * 1; // Получаем data-id текущего блока .seotags_list

    obj.addClass('position_initial'); // Добавляем класс (возможно, для стилизации или анимации)

    // Увеличиваем общее количество элементов, которое должно быть показано.
    // Добавляем 'per' (количество элементов за клик, равное filter_servicekol_was)
    i_mm_gr[index_gr] = i_mm_gr[index_gr] + per;
    // Обновляем общее количество показанных элементов
    total_mm_gr[index_gr] = i_mm_gr[index_gr];

    // Показываем элементы, начиная с первого, до рассчитанного общего количества
    // slice(0, N) берет первые N элементов
    items_gr[index_gr].slice(0, total_mm_gr[index_gr]).css('display', 'inline-block');

    // Проверяем, достигли ли мы конца списка (показаны все доступные элементы)
    if (total_mm_gr[index_gr] >= items_gr[index_gr].length) {
      $(this).hide(); // Скрываем кнопку "Показать"
      // Показываем кнопку "Скрыть" для этого блока
      $('.hide__button_serv[data-id="' + index_gr + '"]').show();
    } else {
      // Если список еще не полностью показан, кнопка "Показать" остается видимой
      $(this).show();
    }
  });

  // Обработчик клика по кнопке "Скрыть"
  $("body").on("click", ".hide__button_serv", function() {
    var obj = jQuery(this); // Текущая кнопка "Скрыть"
    var index_gr = obj.data('id') * 1; // Получаем data-id текущего блока .seotags_list

    obj.hide(); // Скрываем кнопку "Скрыть"

    // Здесь происходит "сброс" до начального состояния.
    // Скрываются все, кроме тех, что должны быть видны по умолчанию.
    // Обращение к '.myhide' здесь может быть не совсем явным, но эффект достигается
    // тем, что после этого пересчитывается количество видимых элементов (myshow).
    jQuery('.seotags_list[data-id="' + index_gr + '"]').find('.myhide').hide(),
      // Показываем кнопку "Показать" и убираем класс 'position_initial'
      jQuery('.show__button_serv[data-id="' + index_gr + '"]').show();
    jQuery('.show__button_serv[data-id="' + index_gr + '"]').removeClass('position_initial');

    // Сбрасываем счетчики для корректного отображения при следующем нажатии "Показать".
    // Пересчитываем количество видимых элементов (myshow) в текущем блоке.
    i_mm_gr[index_gr] = jQuery('.seotags_list[data-id="' + index_gr + '"]').find('.filter_button_gg.myshow').length;
    // Сбрасываем общее количество показанных элементов для следующего цикла "Показать".
    total_mm_gr[index_gr] = 0;

  });

  // Запускаем функцию инициализации filter__analiz с небольшой задержкой (100ms).
  // Это нужно, чтобы скрипт выполнился после полной отрисовки DOM и корректного расчета размеров элементов.
  // setTimeout(filter__analiz, 100);
  // Альтернативный, более надежный способ - использовать window.addEventListener("load", ...),
  // но setTimeout также часто применяется в подобных случаях.
  // Для данного случая, где фильтрация нужна сразу, setTimeout работает.

  // Перезапуск анализа при изменении размера окна браузера.
  // Это обеспечивает адаптивность: при изменении ширины экрана пересчитывается,
  // сколько элементов помещается в заданное количество строк.
  jQuery(window).resize(function() {
    setTimeout(filter__analiz, 100);
  });
  /****************** end@ */

}); // Конец jQuery(document).ready
        

Заключение

Реализация динамического списка рубрик с функциями "Показать/Скрыть" — это отличный способ улучшить UX и положительно повлиять на SEO вашего сайта. Пользователи получают более чистый интерфейс, а поисковые системы — структурированную информацию. Вы можете легко адаптировать значения filter_servicekol (количество видимых строк) и filter_servicekol_was (шаг показа элементов) под нужды вашего проекта.

Покупка готового скрипта joomla 3

или просто напишите в телеграмм https://t.me/webalan