Как создать свой Select на CSS и JavaScript?

Александр Мальцев
Александр Мальцев
10K
17
Как создать свой Select на CSS и JavaScript?
Содержание:
  1. Зачем разрабатывать свой Select, если есть тег <select>
  2. Подключение и использование компонента Select
  3. Как использовать компонент CustomSelect
  4. Как устроен компонент Select
  5. Комментарии

В этой статье разберём, как, используя CSS и JavaScript, написать свою реализацию компонента, который будет очень похож по функционалу на элемент интерфейса, создаваемого с помощью стандартного HTML тега <select>.

Зачем разрабатывать свой Select, если есть тег <select>

При создании селекта с помощью стандартного HTML-элемента <select>, мы ограничены в его изменении. Т.к. не всегда можем его настроить и стилизовать так, как нам это необходимо в том или ином случае.

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

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

Вид селекта, спроектированного на чистом CSS и JavaScript, в закрытом состоянии Вид селекта, спроектированного на чистом CSS и JavaScript, в открытом состоянии

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

Подключение и использование компонента Select

Исходные коды разработанного компонента Select расположены на Github. Написан он с использованием CSS и чистого JavaScript. Зависимостей от jQuery и каких-либо других js-плагинов нет.

Для подключения компонента к странице достаточно к ней просто подключить CSS и JavaScript файл этого компонента или поместить эти коды в соответствующие свои файлы.

<!-- подключаем CSS селекта -->
<link rel="stylesheet" href="custom-select.css">

<!-- подключаем JS селекта -->
<script src="custom-select.js"></script>

Как использовать компонент CustomSelect

Компонент CustomSelect можно использовать на странице 2 способами.

Первый способ подразумевает непосредственную вставку HTML-кода селектора на страницу:


<div class="select" id="select-1">
  
  <button type="button" class="select__toggle" name="car" value="" data-select="toggle" data-index="-1">Выберите из списка</button>
  
  <div class="select__dropdown">
    <ul class="select__options">
      <li class="select__option" data-select="option" data-value="volkswagen" data-index="0">Volkswagen</li>
      <li class="select__option" data-select="option" data-value="ford" data-index="1">Ford</li>
      <li class="select__option" data-select="option" data-value="toyota" data-index="2">Toyota</li>
      <li class="select__option" data-select="option" data-value="nissan" data-index="3">Nissan</li>
    </ul>
  </div>
</div>

Элемент <button> представляет собой кнопку, предназначенную для открытия выпадающего списка. Её действие в JavaScript коде определяется с помощью атрибута data-select="toggle".

Также кнопка содержит пару «имя=значение» (где значение – это значение выбранной опции). Имя устанавливается атрибутом name, а значение – value. Поэтому если CustomSelect поместить в форму, то значение выбранной опции вместе с другими данными будут отправлены на сервер.

data-index содержит индекс выбранной опции. Если по умолчанию не должна быть установлена какая-то опция, то атрибуту value следует задать пустую строку, а data-index – значение -1.

В select__options находятся опции: <li> с классом select__option. data-select="option" определяет действие аналогично с кнопкой, data-value – значение опции, а data-index – её индекс (порядковый номер).

Если изначально какая-то опция должна быть активна, то к ней необходимо добавить класс select__item_selected. А также поместить в кнопку: в value – её значение, в data-index – её индекс, в содержимое – её контент.


<div class="select" id="select-1">
  <button type="button" class="select__toggle" name="car" value="ford" data-select="toggle" data-index="1">Выберите из списка</button>
  <div class="select__dropdown">
    <ul class="select__options">
      <li class="select__option" data-select="option" data-value="volkswagen" data-index="0">Volkswagen</li>
      <li class="select__option select__option_selected" data-select="option" data-value="ford" data-index="1">Ford</li>
      <li class="select__option" data-select="option" data-value="toyota" data-index="2">Toyota</li>
      <li class="select__option" data-select="option" data-value="nissan" data-index="3">Nissan</li>
    </ul>
  </div>
</div>

После создания необходимой HTML-структуры необходимо активировать корневой элемент (.select) как CustomSelect с помощью JavaScript.

Выполняется это следующим образом:

// #select-1 - селектор для выбора элемента, который необходимо инициализировать как CustomSelect
const select1 = new CustomSelect('#select-1');

Второй способ предполагает использование CustomSelect без необходимости непосредственной вставки HTML-структуры компонента на страницу. Здесь достаточно лишь поместить контейнер (пустой элемент) в HTML-документ.

<div id="select-2"></div>

Варианты и дефолтный текст (начальное значение) селекту необходимо передать при создании объекта в виде аргумента.

const select2 = new CustomSelect('#select-2', {
  name: 'car', // значение атрибута name у кнопки
  targetValue: 'ford', // значение по умолчанию
  options: [['volkswagen', 'Volkswagen'], ['ford', 'Ford'], ['toyota', 'Toyota'], ['nissan', 'Nissan']], // опции
});

Значение options - это массив массивов. Первый элемент массива – это значение опции, а второй – её текстовое представление.

Если не нужно чтобы CustomSelect имел какое-то значение по умолчанию, то установите ключу targetValue пустую строку или вообще его не указывайте:

const select2 = new CustomSelect('#select-2', {
  name: 'car', // значение атрибута name у кнопки
  options: [['volkswagen', 'Volkswagen'], ['ford', 'Ford'], ['toyota', 'Toyota'], ['nissan', 'Nissan']], // опции
});

После инициализации селекта, доступны следующие свойства и методы:

  • value – позволяет как получить выбранную опцию, так и установить её;
  • selectedIndex – индекс выбранного элемента (нумерация начинается с 0);
  • show() – показывает выпадающий список с опциями;
  • hide() – скрывает dropdown меню;
  • toggle() – переключает видимость выпадающего меню;
  • dispose() - удаляет обработчики событий, связанных с этим селектом.

Использование свойства value:

// установим в качестве выбранной опции элемент со значением toyota
select2.value = 'toyota';
// получим значение выбранной опции
console.log( select2.value ); // toyota

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

// сбросим выбранную опцию
select2.value = '';

Использование свойства selectedIndex:

// установим в качестве выбранной опции элемент с индексом 2
select2.selectedIndex = 2;
// получим индекс выбранной опции
console.log( select2.selectedIndex );

Если ни один из элементов не выбран, то selectedIndex возвращает -1:

select2.value = '';
// получим индекс выбранного элемента
console.log( select2.selectedIndex ); // -1

Сбросить выбранный элемент можно не только посредством value, но также, если установить selectedIndex число -1 или индекс элемента, которого нет:

select2.selectedIndex = -1;

Если нам необходимо выполнить некоторые действия при выборе элемента отличного от текущего, то мы можем воспользоваться событием select.change, генерируемым в JavaScript коде:

document.querySelector('#select-2').addEventListener('select.change', (e) => {
  const btn = e.target.querySelector('.select__toggle');
  // выбранное значение
  console.log(`Выбранное значение: ${btn.value}`);
   // индекс выбранной опции
  console.log(`Индекс выбранной опции: ${btn.dataset.index}`);
  // выбранный текст опции
  const selected = e.target.querySelector('.select__option_selected');
  const text = selected ? selected.textContent : '';
  console.log(`Выбранный текст опции: ${text}`);
});

Кроме как использовать событие, это действие также можно выполнить с помощью метода onSelected при создании экземпляра объекта CustomSelect:

2 способ (через метод onSelect):

new CustomSelect('#select-2', {
  name: 'car',
  targetValue: 'ford',
  data: [['volkswagen', 'Volkswagen'], ['ford', 'Ford'], ['toyota', 'Toyota'], ['nissan', 'Nissan']],
  onSelected(select, option) {
    // выбранное значение
    console.log(`Выбранное значение: ${select.value}`);
    // индекс выбранной опции
    console.log(`Индекс выбранной опции: ${select.selectedIndex}`);
    // выбранный текст опции
    const text = option ? option.textContent : '';
    console.log(`Выбранный текст опции: ${text}`);
  }
});

Как устроен компонент Select

Компонент Select построен с использованием HTML, CSS и JavaScript.

HTML код компонента Select:

<div class="select">
  <button type="button" class="select__toggle" name="car" value="" data-select="toggle" data-index="-1">Выберите из списка</button>
  <div class="select__dropdown">
    <ul class="elect__options">
      <li class="elect__option" data-select="option" data-value="volkswagen" data-index="0">Volkswagen</li>
      <li class="elect__option elect__option_selected" data-select="option" data-value="ford" data-index="1">Ford</li>
      <li class="elect__option" data-select="option" data-value="toyota" data-index="2">Toyota</li>
    </ul>
  </div>
</div>

Элемент с классом select определяет этот компонент. В нём находится вся HTML-структура селекта. Тег <button> с классом select__toggle и атрибутами data-select="toggle", data-index предназначен для отображения выбранного значения и открытия при нажатии на него выдающего списка с опциями. Само выпадающее меню реализовано посредством элемента select__dropdown. Оно с помощью CSS настраивается так, чтобы оно было расположено под <button>. Список вариантов (.select__options) организован посредством маркированного списка. Выбранный элемент в нём отмечается посредством добавления к нему класса select__option_selected.

Кроме непосредственной вставки HTML кода на страницу, предоставим также возможность создавать его автоматически с помощью JavaScript. Таким образом, на страницу будет достаточно поместить пустой элемент и инициализировать его как CustomSelect. Как устроен JavaScript код приведём ниже.

Классы элементов будем использовать в CSS для добавления к ним стилей, а data атрибуты - в JavaScript.

CSS стили компонента Select можно посмотреть на GitHub.

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

.select {
  position: relative;
  ...
}

Элемент с классом select__toggle стилизуем в виде кнопки (текущий вариант в ней будем выводить как её содержимое).

.select__toggle {
  display: flex;
  background-color: #fff;
  border: 1px solid #ccc;
  border-radius: 0.3125rem;
  cursor: pointer;
  align-items: center;
  width: 100%;
  font-size: 1rem;
  padding: 0.375rem 0.75rem;
  line-height: 1.4;
  user-select: none;
  font-size: 1rem;
  justify-content: space-between;
  font-style: italic;
}

Иконку к кнопке добавим через псевдоэлемент ::after:

.select__toggle::after {
  content: '';
  width: 0.75rem;
  height: 0.75rem;
  background-size: cover;
  background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" height="100" width="100"%3E%3Cpath d="M97.625 25.3l-4.813-4.89c-1.668-1.606-3.616-2.41-5.84-2.41-2.27 0-4.194.804-5.777 2.41L50 52.087 18.806 20.412C17.223 18.805 15.298 18 13.03 18c-2.225 0-4.172.804-5.84 2.41l-4.75 4.89C.813 26.95 0 28.927 0 31.23c0 2.346.814 4.301 2.439 5.865l41.784 42.428C45.764 81.174 47.689 82 50 82c2.268 0 4.215-.826 5.84-2.476l41.784-42.428c1.584-1.608 2.376-3.563 2.376-5.865 0-2.26-.792-4.236-2.375-5.932z"/%3E%3C/svg%3E');
}

По умолчанию dropdown меню не будет показываться. Включение его отображения будем осуществлять посредством добавления к нему класса select_show:

.select_show .select__dropdown {
  display: block;
}

При этом при показе dropdown меню иконку будем поворачивать на 180 градусов посредством CSS трансформации:

.select_show .select__toggle::after {
  transform: rotate(180deg);
}

CSS код для стилизации dropdown меню:

.select__dropdown {
  display: none;
  position: absolute;
  top: 2.5rem;
  left: 0;
  right: 0;
  border: 1px solid #ccc;
  max-height: 10rem;
  overflow-y: auto;
  border-radius: 0.3125rem;
}
.select__options {
  margin: 0;
  padding: 0;
  list-style: none;
}
.select__option {
  padding: 0.375rem 0.75rem;
}

Стилизация при наведении на пункт меню:

.select__option:hover {
  background-color: #f5f5f5;
  cursor: pointer;
  transition: 0.2s background-color ease-in-out;
}

JavaScript код компонента доступен на GitHub. Его можно открыть, используя эту ссылку.

Код написан с использованием класса:


class CustomSelect {
  ...
}

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

class CustomSelect {
  constructor(target, params) {
    this._elRoot = typeof target === 'string' ? document.querySelector(target) : target;
    ...
  }
  ...
  _onClick(e) { ... }
  ...
}

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

Структура JavaScript кода:

class CustomSelect {
  constructor(target, params) { }
  // обработчик события click
  _onClick(e) { }
  // сбрасывает состояние, генерирует событие 'select.change'
  _reset() { }
  // обновляет значения атрибутов в зависимости от выбранной опции, генерирует событие 'select.change'
  _update(option) { }
  // при изменении выбранной опции
  _changeValue(option) { }

  // включает отображение выпадающего списка
  show() { }
  // скрывает список с опциями
  hide() { }
  // переключает список с опциями
  toggle() { }
  // удаления слушателей события click селекта
  dispose() { }
  // возвращает значение выбранной опции
  get value() { }
  // позволяет установить опцию по значению
  set value(value) { }
  // возвращает индекс выбранной опции
  get selectedIndex() { }
  // позволяет выбрать опцию по её индексу
  set selectedIndex(index) { }
}
// функция для генерации HTML-кода селекта в зависимости от переданных аргументов
CustomSelect.template = params => { };
// для закрытия открытого селекта при клике вне его
document.addEventListener('click', (e) => {
  if (!e.target.closest('.select')) {
    document.querySelectorAll(SELECTOR_ACTIVE).forEach(select => {
      select.classList.remove(CLASS_NAME_ACTIVE);
    });
  }
});

Комментарии:

  1. Myshynov
    Myshynov
    22.01.2022, 11:07
    Здраствуйте Александр! Спасибо вам за проделанную работу. Отличная реализация кастомных селектов!

    У меня возникла небольшая проблема.
    Дело в том что в моём списке используются стили и обвертки в «span». Если назначить одну из опций по умолчанию то всё ОК и спаны с классами и стилями выводятся в кнопку. Но как только выбираешь из списка другую опцию в кнопке отображается строка без «span».
    Вот пример кода чтобы вам было проще меня понять

    const registrationSelect = new CustomSelect('#registration-select', {
      name: 'registration', // значение атрибута name у кнопки
      targetValue: 'RegularRegistration', // значение по умолчанию
      options: [
        ['RegularRegistration', 'Regular Registration <span class="price">($35.00)</span> <span class="sub-name">Breakfast pastries and refreshments included</span>'],
        ['RegularRegistration2', '2Regular Registration <span class="price">($35.00)</span> <span class="sub-name">Breakfast pastries and refreshments included</span>'],
        ['RegularRegistration3', '3Regular Registration <span class="price">($35.00)</span> <span class="sub-name">Breakfast pastries and refreshments included</span>'],
        ['RegularRegistration4', '4Regular Registration <span class="price">($35.00)</span> <span class="sub-name">Breakfast pastries and refreshments included</span>']
      ], // опции
    });
    1. Myshynov
      Myshynov
      22.01.2022, 11:29
      Я 2 дня не находил себе места перечитывал статью и все комментарии.
      И как только я написал вопрос я нашел путь к ответу. Если вдруг кто-то столкнется с таким же вопросом то вот решение. Найди верхнюю строку и замени в ней .textContent на .innerHTML:
      this._elToggle.textContent = option.textContent;
      this._elToggle.innerHTML = option.innerHTML;
      Только заметил что в самом вопросе не отобразились «span». они у меня были в значении «options»
      1. Александр Мальцев
        Александр Мальцев
        23.01.2022, 14:20
        Привет! Спасибо за отзыв! Рад, что кастомный селект понравился.
        Необходимо добавить ещё в начало метода _update следующую строчку (на Github обновил этот момент):
        _update(option) {
          option = option.closest('.select__option'); // добавить эту строчку
          // ...
        }
    2. Юрий
      Юрий
      04.12.2021, 15:43
      Здравствуйте, спасибо за плагин!!!
      Столкнулся с несколькими проблемами.
      Проект разрабатываю на Laravel.
      Первая проблема — при отправке данных на бэк, данные селектов не приходят, несмотря на наличие атрибута name и значения, но эту проблему обошел путем добавления hidden input и дальнейшего добавления в него выбранных данных при помощи js.
      Вторая проблема — есть форма с двумя селектами, которая заполняется пользователем поэтапно. Есть кнопки prev и next, при нажатии next блок с первым селектом (data-block=«1») скрывается и ajax-запросом получаются подкатегории выбранной в первом блоке категории, и на основании ответа во втором блоке (data-block=«2») создается новый селект с подкатегориями, после чего отображается второй блок.

      html код
      
      <div class="form-group" data-block="1">
                              <div class="select" id="category-select">
                                  <button type="button" class="select__toggle" id="category_id-btn" name="category_id-btn" value=""
                                          data-select="toggle" data-index="-1">
                                      Выберите категорию
                                  </button>
                                  <div class="select__dropdown">
                                      <ul class="select__options">
                                          @php $index = 0; @endphp
                                          @foreach($categories as $category)
                                              <li class="select__option" data-select="option" data-value="{{ $category->id }}"
                                                  data-index="{{ $index++ }}">{{ $category->name }}</li>
                                          @endforeach
                                      </ul>
                                  </div>
                              </div>
                              <input type="hidden" name="category_id" id="category_id">
                          </div>
                          <div class="form-group" data-block="2">
                              <div class="select" id="service-select"></div>
                              <input type="hidden" name="service_id" id="service_id">
                          </div>
      


      js код
      
      let serviceSelect = new CustomSelect('#service-select', {
                                          name: 'service_id-btn',
                                          options
                                      });
      
      Суть проблемы — при первом отображении второго селекта все работает, но когда нажимаю кнопку prev, скрываю второй селект, перехожу на первый, выбираю новую категорию и перехожу обратно на второй селект, html код с новыми подкатегориями формируется, НО при клике на селект не открывается дропдаун с подкатегориями, если еще раз вернусь назад, выбираю другую категорию, и перехожу снова на второй селект, дропдаун уже открывается, но при выборе нужной подкатегории он уже не закрывается.
      1. Александр Мальцев
        Александр Мальцев
        07.12.2021, 15:17
        Привет!
        Вот пример состоящий из 2 селектов. Может он поможет. В нём при выборе элемента из 1 селекта, второй наполняется данными посредством AJAX в зависимости от значения первого селекта.
      2. Gregory
        Gregory
        01.11.2021, 15:54
        1 — поставьте пожалуйста кнопку для комментария в начале списка комментариев, а то пригодится листать в самый низ списка комментов
        2 — в начале скрипта вы определяете константы вне класса, вне конструктора. Это для каких целей делается?
        1. Gregory
          Gregory
          01.11.2021, 12:13
          Небольшая модификация CSS для мобильных — может пригодится

          @media (max-width: 500px) {
            .select__options{
              position: fixed;
              height: 100%;
              overflow-y: scroll;
              top: 0;
              left: 0;
              background: white;
              width: 100vw;
              padding: 20px;
            }
          }
          1. Gregory
            Gregory
            01.11.2021, 12:28
            да вот ещё
            
            * {
                  box-sizing: border-box;
            }
            
          2. Александр
            Александр
            14.10.2021, 12:46
            Александр, добрый день. Имеется ли возможность задавать разные значения переменной
            selectedContent
            для разных селектов. По умолчанию стоит 'Выберите из списка';
            1. Daniel
              Daniel
              29.09.2021, 10:04
              Здраствуйте Александр. Большое спасибо за разработанный плагин CustomSelect, отличная работа. сэкономлено кучу времени. У меня возник один вопрос: на базе вашего плагина пишу калькулятор и столкнулся с небольшой проблемой, а именно: создаю функцию Reset для сброса всех значений «name», «value» в дефолтное состояние но при клике на кнопке reset не получаю никакого результата.
              Вот пример кода:
              function resetBtn() {
                let btnReset = document.queryselectorAll("select-reset");
                btnReset.value = "" ;
                btnRest. name = "" ;
              };
              <button type="reset" onClick="resetBtn()">Reset</button>
              Буду очень благодарен за помощь. Спасибо.
              1. Александр Мальцев
                Александр Мальцев
                29.09.2021, 14:20
                Добрый день! Наверно так:
                function resetBtn() {
                  let btnReset = document.querySelectorAll('.select-reset');
                  btnReset.forEach((element) => {
                    element.value = '';
                    element.name = '';
                  });
                }
                Не знаю, что такое select-reset? Класс?
                После того как выбрали элементы с помощью querySelectorAll, их нужно перебрать, например, с помощью forEach. Так напрямую нельзя.
                1. Daniel
                  Daniel
                  29.09.2021, 14:46
                  Большое спасибо за столь быстрый ответ. да, select-reset это я добавил некий клас, для сброса значений и в калькуляторе я использую несколько CustomSelect и радио-кнопки checkbox. ok, попробую с forEach. Ещё раз спасибо. Хорошего дня
              2. Daria
                Daria
                20.08.2021, 18:19
                Здравствуйте, Александр, спасибо вам за проделанную работу, ваш селект прекрасен))

                у меня возникла проблема,
                Мне нужно два селекта, они расположены рядом в форме, добавляю их Первым способом
                все работает хорошо, кроме закрытия по клику на второй селект.

                1) Кликаем на первый селект, ничего, не выбрано, кликаем, на второй селект, первый остается в открытом состоянии, но не активен при ховере, если кликнуть «оживает», получается два открытых одновременно селекта.

                При этом в обратном порядке работает правильно
                2) Кликаем второй селект, кликаем на первый второй закрыватся при клике на первый.

                1. Александр Мальцев
                  Александр Мальцев
                  21.08.2021, 12:04
                  Привет! Спасибо за отзыв. Переписал код компонента, а также исправил этот баг. Также изменил название классов и атрибутов, поэтому обратите на это внимание при обновлении кода.
                2. Кирилл
                  Кирилл
                  18.08.2021, 18:13
                  Верно ли понимаю, что мы можем управлять выбором значения по индексу или названию(value), так:
                  select1.selectedItem(6); // (где 6 — это 7 элемент списка).
                  Но у меня к сожалению, так не сработало :(

                  P.S. спасибо большое за реализацию.
                  1. Александр Мальцев
                    Александр Мальцев
                    19.08.2021, 03:34
                    Нужно передавать в формате объекта:
                    // по индексу
                    select1.selectedItem({index: 0})
                    // по значению
                    select1.selectedItem({value: 'Nissan'})
                    1. Кирилл
                      Кирилл
                      19.08.2021, 09:37
                      Благодарю!
                  2. Konstantin
                    Konstantin
                    03.06.2021, 13:35
                    Может быть это у меня что то с ip, но ни одна ссылка на материалы из этого поста не открывается. Выдает 404 ошибку. в том числе на GIT!!!
                    1. Александр Мальцев
                      Александр Мальцев
                      03.06.2021, 13:50
                      Поправил ссылки.
                    2. Александр
                      Александр
                      24.11.2020, 17:07
                      Александр, здравствуйте! Спасибо, за отличный вариант и достойную альтернативу дефолтному селекту. Пытаюсь это решение использовать в сортировке mFilter2, не получается всё сделать по уму да и вообще мало что получается честно говоря, делаю так:

                      <div class="select" id="mse2_sort">
                        <div class="select__backdrop" data-select="backdrop"></div>
                        
                       <button type="button" class="select__trigger" data-select="trigger" value="asc" data-sort="resource|pagetitle" data-icon="fa-list">
                          По умолчанию
                       </button>
                      
                      <div class="select__dropdown">
                          <ul class="select__items">
                            <li class="select__item" data-select="item"  value="asc" data-sort="extendresource|date"><i class="fa fa-play"></i>Дата</li>
                            <li class="select__item" data-select="item" value="desc" data-sort="extendresource|size"><i class="fa fa-table"></i>Размер</li>
                          </ul>
                        </div>
                      </div>
                      <script>
                       const select1 = new CustomSelect('#mse2_sort'); 
                      </script>
                      как я понимаю, так работать не будет, так как в файле default.js в параметрах скрипта mFilter2, завязано всё на теге «a»
                      sort_link: '#mse2_sort a'
                      если изменить на тег «li», то сортировка начинает работать, но не сохраняет выбранное значение при перезагрузке страницы. Александр, если возможно расскажите пожалуйста как нужно и лучше сделать, чтобы сортировка работала и сохраняла выбранное значение при перезагрузки страницы?
                      1. Александр Мальцев
                        Александр Мальцев
                        26.11.2020, 16:53
                        Привет! Спасибо за отзыв.
                        Чтобы в mFilter2 изменить sort_link можно использовать параметр &filterOptions:
                        [[!mFilter2? 
                          ...
                          &filterOptions=`{"sort_link": "#mse2_sort li"}`
                        ]]
                        Установить выбранную сортировку в CustomSelect после перезагрузки страницы можно посредством добавления следующего скрипта на страницу:
                        <script>
                        const queryString = window.location.search;
                        const urlParams = new URLSearchParams(queryString);
                        const sort = urlParams.get('sort');
                        let value = '';
                        if (sort) {
                          const delim = sort.indexOf(':');
                          const res = delim === -1 ? sort : sort.substring(0, delim);
                          const $li = document.querySelector(`#mse2_sort li[data-sort="${res}"]`);
                          if ($li) {
                            value = $li.textContent;
                          }
                        }
                        const select1 = new CustomSelect('#mse2_sort');
                        if (value) {
                          select1.selectedItem({value: value})
                        } 
                        </script>
                        1. Александр
                          Александр
                          26.11.2020, 20:20
                          Александр, огромное спасибо за решение, в очередной раз выручили.
                      2. Владимир
                        Владимир
                        07.11.2020, 23:40
                        Александр, еще момент.

                        1. Александр Мальцев
                          Александр Мальцев
                          08.11.2020, 07:28
                          Спасибо! Этот момент тоже доработал и обновил код js-файла на Github.
                        2. Владимир
                          Владимир
                          07.11.2020, 15:03
                          Еще момент.
                          Если создание нового экземпляра объекта CustomSelect происходит таким образом
                          const select1 = new CustomSelect(".select");
                          то в консоли получаю следующую ошибку
                          1. Александр Мальцев
                            Александр Мальцев
                            07.11.2020, 15:47
                            Спасибо! Поправил код скрипта на Github.
                          2. Владимир
                            Владимир
                            07.11.2020, 14:58
                            Добрый день!

                            На странице категории есть сортировка, сделанная через стандартный select. При выборе какой-либо сортировки происходит перезагрузка страницы.

                            Пытаюсь применить Ваш плагин. В итоге код получился такой
                            <div class="select">
                              <div class="select__backdrop" data-select="backdrop"></div>
                              <button type="button" class="select__trigger" data-select="trigger">По умолчанию</button>
                              <div class="select__dropdown">
                                <ul class="select__items">
                                  <?php foreach ($sorts as $sorts) { ?>
                                  <?php if ($sorts['value'] == $sort . '-' . $order) { ?>
                                  <li class="select__item select__item_selected" data-select="item" data-url="<?php echo $sorts['href']; ?>"><?php echo $sorts['text']; ?></li>
                                  <?php } else { ?>
                                  <li class="select__item" data-select="item" data-url="<?php echo $sorts['href']; ?>"><?php echo $sorts['text']; ?></li>
                                  <?php } ?>
                                  <?php } ?>
                                </ul>
                              </div>
                            </div>
                            <script>
                            const select1 = new CustomSelect(".select", { });
                            
                            document.querySelector(".select").addEventListener("select.change", (e) => {
                              location = document.querySelector(".select__item_selected").getAttribute("data-url"); 
                            });
                            </script>
                            Не получается подставить выбранное значение в button.
                            Подскажите, пожалуйста, как это можно сделать?
                            1. Александр Мальцев
                              Александр Мальцев
                              07.11.2020, 15:36
                              Здравствуйте!
                              Установите выбранное значение в button с помощью JavaScript:
                              document.querySelector('.select__trigger').textContent = document.querySelector('.select__item_selected').textContent;
                              
                              1. Владимир
                                Владимир
                                07.11.2020, 16:01
                                Оказалось все так просто.
                                Спасибо, Александр!
                            Войдите, пожалуйста, в аккаунт, чтобы оставить комментарий.