b2bon.ru

Модуль каталогов (cybervela.catalogs.js)

Обзор

Модуль каталогов предоставляет функциональность для отображения и управления каталогами товаров/услуг с поддержкой категорий, позиций, изображений и рейтингов участников.

Структура модуля

Основные классы

  1. catalog - Класс для управления отдельным каталогом
  2. catalogs - Главный класс для управления всеми каталогами на странице

Класс `catalog`

Конструктор

constructor(core, (props = {}));

Параметры:

  • core - Основной объект приложения
  • props - Объект с настройками каталога
    • e - DOM элемент каталога
    • caption - Заголовок каталога
    • categories - Категории товаров
    • startpage - Начальная страница
    • limit - Лимит элементов на странице

Пример использования:

const catalogInstance = new catalog(core, {
  e: document.querySelector('.catalog'),
  caption: 'Наш каталог товаров',
  categories: ['Электроника', 'Одежда'],
  startpage: 1,
  limit: 20,
});

Методы

loadData()

Загружает данные каталога с сервера.

loadData() {
  var data = new FormData();
  data.append('catalog', 'load');        
  this.core.requestBack({ data: data }, (data) => {
    if (data instanceof Object) {
      this.categories = data.payload.catalog.categories;
      this.positions = data.payload.catalog.positions;
      
      this.drawCatalog();
    }    
  });        
}

Пример ответа сервера:

{
  payload: {
    catalog: {
      categories: [
        { id: 1, name: 'Электроника' },
        { id: 2, name: 'Одежда' }
      ],
      positions: [
        {
          id: 1,
          name: 'Смартфон iPhone',
          images: [
            { src: '/img/iphone1.jpg', alt: 'iPhone вид 1' },
            { src: '/img/iphone2.jpg', alt: 'iPhone вид 2' }
          ],
          sharers: [
            { title: 'Магазин А', raiting: 4.5 },
            { title: 'Магазин Б', raiting: 4.2 }
          ]
        }
      ]
    }
  }
}

drawCatalog()

Отрисовывает весь каталог на основе загруженных данных.

drawCatalog() {
  jQuery.each(this.positions, (index, val) => {
    this.drawPosition(index, val);
  });
  
  this.core.onUpdateDOM();
  this.core.moduleIsLoaded(this);
}

drawPosition(index, position)

Отрисовывает отдельную позицию товара.

drawPosition(index, position) {
  let template = jQuery(this.templates[0]);
  let card = jQuery(template[0].content).clone(true);
  
  // Добавление изображений
  jQuery.each(position.images, function (index, value) {
    let item = jQuery('<div />', {
      class: 'item' + ((index <= 0) ? ' active' : '')
    });
    let image = jQuery('<img />', {
      src: value.src,
      alt: (value.alt) ? value.alt : position.name
    });
    image.appendTo(item);
    item.appendTo(card.find('.images'));
  });
  
  // Заполнение данных позиции
  card.find('.inform .title').html(position.name);
  card.find('.inform .sharers .count').html(position.sharers.length);
  
  // Создание подсказки со списком участников
  let tooltip = jQuery('<div />', {});
  tooltip.append(jQuery('<b>Список участников:</b>'));
  
  jQuery.each(position.sharers, (index, value) => {
    tooltip.append('<div>'+value.title+' - '+value.raiting+'</div>');
  });
  
  card.find('.inform .sharers .hint.info').data('tooltip', tooltip.html());
  
  // Расчет максимального рейтинга
  let maxraiting = 0;
  jQuery.each(position.sharers, function (index, value) {
    maxraiting = (parseFloat(value.raiting) > maxraiting) ? parseFloat(value.raiting) : maxraiting;
  });
  
  card.find('.inform .maxraiting').html(maxraiting);
  
  // Добавление данных для кнопки ставки
  card.find('.btn.bid').data('props', $.param({"id" : position.id}));
  
  jQuery(this.container).append(card);
}

Класс `catalogs`

Конструктор

constructor(core);

Параметры:

  • core - Основной объект приложения

Свойства

  • instances - Массив экземпляров каталогов

Методы

update()

Метод для обновления каталогов (пока не реализован).

update() {
  // Логика обновления каталогов
}

HTML структура

Шаблон каталога


      <div
         class="catalog"
         data-categories="Электроника,Одежда"
         data-caption="Наш каталог"
         data-page="1"
         data-limit="20"
       >
         <div class="caption"></div>
         
         <div class="container">
           <!-- Шаблон карточки товара -->
           <template>
             <div class="card">
               <div class="images">
                 <!-- Изображения товара -->
               </div>
               
               <div class="inform">
                 <div class="title"></div>
                 
                 <div class="sharers">
                   <span class="count"></span>
                   <div class="hint info" data-tooltip=""></div>
                 </div>
                 
                 <div class="maxraiting"></div>
               </div>
               
               <button class="btn bid" data-props=""></button>
             </div>
           </template>
         </div>
       </div>
          

Особенности реализации

1. Использование шаблонов

Модуль использует HTML5 <template> элементы для создания карточек товаров, что обеспечивает:

  • Переиспользование структуры
  • Изоляцию стилей
  • Простоту клонирования

2. Асинхронная загрузка

Каталоги загружаются асинхронно с уведомлением основного приложения о состоянии загрузки:

  • moduleToLoad() - начало загрузки
  • moduleIsLoaded() - завершение загрузки

3. Система рейтингов

Модуль поддерживает систему рейтингов участников с:

  • Отображением количества участников
  • Расчетом максимального рейтинга
  • Подсказками с детальной информацией

4. Гибкая настройка

Каждый каталог может быть настроен через data-атрибуты:

  • data-categories - категории товаров
  • data-caption - заголовок каталога
  • data-page - начальная страница
  • data-limit - лимит элементов

Зависимости

  • jQuery - для работы с DOM и AJAX
  • cybervela.utils.js - для индикатора загрузки
  • Основной объект core - для коммуникации с сервером и управления модулями

Фильтры

Базовые классы и фильтры

class FilterBase

Базовый абстрактный класс для всех фильтров.

  • setOnChange(fn) — установить обработчик изменения значения
  • getValue() — получить текущее значение фильтра (массив)
  • setValue(values) — установить значение фильтра (массив)
  • reset() — сбросить фильтр к начальному состоянию
  • disable() — отключить фильтр (делает неактивным в UI)
  • enable() — включить фильтр
  • isDisabled() — проверить, отключён ли фильтр
  • setItems(items) — задать новые элементы для фильтра (если применимо)

class ListCheckbox extends FilterBase

Фильтр с множественным выбором (чекбоксы).

  • getValue() — возвращает массив выбранных значений (например, ["A", "B"] или ["all"])
  • setValue(values) — установить выбранные значения (массив)
  • setItems(items) — задать новые элементы чекбокса

Пример:

const filter = new ListCheckbox($('#my-list'), {
    items: [
      { value: 'A', label: 'Вариант A' },
      { value: 'B', label: 'Вариант B' },
    ],
    allLabel: 'Все',
    name: 'my-list',
  });
  filter.setValue(['A']);
  console.log(filter.getValue()); // ["A"]
  filter.reset();

class ListColorsCheckbox extends FilterBase

Фильтр с выбором цвета (чекбоксы-цвета).

  • getValue() — возвращает массив выбранных значений (например, ["red"] или ["all"])
  • setValue(values) — установить выбранные значения (массив)
  • setItems(items) — задать новые цвета

Пример:

const filter = new ListColorsCheckbox($('#my-colors'), {
    items: [
      { value: 'red', color: '#f44336', label: 'Красный' },
      { value: 'blue', color: '#2196f3', label: 'Синий' },
    ],
    name: 'my-colors',
  });
  filter.setValue(['red']);
  console.log(filter.getValue()); // ["red"]
  filter.reset();

class Toggle extends FilterBase

Фильтр-переключатель (on/off).

  • getValue() — возвращает массив с одним булевым значением ([true] или [false])
  • setValue(values) — установить значение (массив, первый элемент — булево)

Пример:

const filter = new Toggle($('#my-toggle'), {
    labelOn: 'Вкл',
    labelOff: 'Выкл',
    value: false,
    name: 'my-toggle',
  });
  filter.setValue([true]);
  console.log(filter.getValue()); // [true]
  filter.reset();

class RangeSlider extends FilterBase

Фильтр-диапазон (слайдер).

  • getValue() — возвращает массив: [min, max] если range=true, либо [value] если range=false
  • setValue(values) — установить значения диапазона (массив)
  • setMin(min) — установить минимальное значение
  • setMax(max) — установить максимальное значение
  • setStep(step) — установить шаг

Пример (диапазон):

const filter = new RangeSlider($('#my-range'), {
    min: 0,
    max: 100,
    value: [20, 80],
    step: 1,
    range: true,
  });
  filter.setValue([30, 70]);
  console.log(filter.getValue()); // [30, 70]
  filter.reset();

class Rating extends FilterBase

Фильтр-выбор рейтинга (звёзды).

  • getValue() — возвращает массив с одним числом ([3])
  • setValue(values) — установить рейтинг (массив, первый элемент — число)
  • setMin(min) — установить минимальный рейтинг
  • setMax(max) — установить максимальный рейтинг
  • syncFromInput() — синхронизировать значение с input (если изменено вручную)

Пример:

const filter = new Rating($('#my-rating'), {
    min: 1,
    max: 5,
    value: 3,
    name: 'user-rating',
  });
  filter.setValue([5]);
  console.log(filter.getValue()); // [5]
  filter.reset();

Агрегатор фильтров (в разработке)

class Filters

Создаёт и управляет набором фильтров для каталога .

  • getValues() — получить значения всех фильтров: {id: value[]}
  • setValues(obj) — установить значения для всех фильтров по id: {id: value[]}
  • resetAll() — сбросить все фильтры к начальному состоянию
  • getFilter(id) — получить инстанс фильтра по id (name+type)
  • setData([Array]) - устанавливает все имеющиеся варианты из позиций
  • update() - обновляет фильтр согласно установленным данным
  • getFiltering() : [Array] - получает массив отфильтрованных значений
  • isPassed([Array]) : Bool - проверяет, проходят ли элементы массива фильтрацию

Пример использования:


    const filters = new Filters('services', $('.filters'));
    const allValues = filters.getValues(); 
    // { companiesListCheckbox: ["A"], priceRangeSlider: [10, 50], ... }
    filters.setValues({ priceRangeSlider: [20, 80] });
    filters.resetAll();
    const ratingFilter = filters.getFilter('ratingRating');
    ratingFilter.setValue([5]);