Как добавить кнопку "В корзине" в miniShop2: модернизация default.js

Введение

По умолчанию интернет-магазины на MODX Revolution + miniShop2 имеют простую кнопку «Купить».\ После добавления товара в корзину она не меняет состояние --- пользователь не видит, что товар уже добавлен.

Исправим это и научим miniShop2 динамически менять кнопку на зелёную "В корзине" со ссылкой на корзину,\ а при удалении из корзины --- возвращать исходную синюю «Купить».


Цель

Сделать так, чтобы:


 Шаг 1. Добавляем хелпер miniShop2.UI

Открой /assets/components/minishop2/js/web/default.js\ и вставь после блока miniShop2.Utils = { ... }; (или перед $(document).ready(...))\ новый объект miniShop2.UI.

miniShop2.UI = {
  cartUrl: 'korzina.html', // путь к корзине — замени под свой сайт

  //  Меняем кнопку на ссылку "В корзине"
  markInCart: function(pid){
    if (!pid) return;
    pid = String(pid);
    document.querySelectorAll('[data-product-id="'+pid+'"]').forEach(function(el){
      // Если уже ссылка "В корзине" — выходим
      if (el.tagName === 'A' && el.classList.contains('in-cart')) return;

      // Создаём ссылку
      var a = document.createElement('a');
      a.href = miniShop2.UI.cartUrl;
      a.className = 'btn btn-success in-cart';
      a.setAttribute('data-product-id', pid);
      a.setAttribute('aria-pressed','true');
      a.textContent = 'В корзине';

      // Заменяем исходный элемент
      el.replaceWith(a);
    });
  },

  //  Возвращаем исходную кнопку "Купить"
  unmarkInCart: function(pid){
    if (!pid) return;
    pid = String(pid);
    document.querySelectorAll('[data-product-id="'+pid+'"]').forEach(function(el){
      if (el.tagName === 'A') {
        var btn = document.createElement('button');
        btn.type = 'submit';
        btn.className = 'btn btn-primary add-to-cart';
        btn.name = 'ms2_action';
        btn.value = 'cart/add';
        btn.setAttribute('data-product-id', pid);
        btn.textContent = 'Купить';
        el.replaceWith(btn);
      } else if (el.tagName === 'BUTTON') {
        el.classList.remove('btn-success','in-cart');
        el.classList.add('btn','btn-primary','add-to-cart');
        el.disabled = false;
        el.textContent = 'Купить';
        el.removeAttribute('aria-pressed');
      }
    });
  }
};

Шаг 2. Модернизируем обработчики корзины

Теперь подключим наши методы к событиям miniShop2.\ В том же файле default.js найди блок miniShop2.Cart = { ... }\ и подправь функции add, remove, change.

Добавление товара

callbacks.add.response.success = function (response) {
  this.Cart.status(response.data);

  // Получаем ID товара (универсально)
  var pid =
    (response && response.data && (response.data.id || response.data.product_id)) ||
    miniShop2.Utils.getValueFromSerializedArray('id');

  if (pid) miniShop2.UI.markInCart(String(pid));

  try { $(document).trigger('ms2_cart_add', response); } catch(e){}
};

Удаление из корзины

callbacks.remove.response.success = function (response) {
  this.Cart.remove_position(miniShop2.Utils.getValueFromSerializedArray('key'));
  this.Cart.status(response.data);

  var pid =
    (response && response.data && (response.data.id || response.data.product_id)) ||
    miniShop2.Utils.getValueFromSerializedArray('id');

  if (pid) miniShop2.UI.unmarkInCart(String(pid));

  try { $(document).trigger('ms2_cart_remove', response); } catch(e){}
};

Изменение количества

callbacks.change.response.success = function (response) {
  if (typeof (response.data.key) == 'undefined') {
    this.Cart.remove_position(miniShop2.Utils.getValueFromSerializedArray('key'));
  }
  this.Cart.status(response.data);

  var d = (response && response.data) || {};
  var pid = d.id || d.product_id || miniShop2.Utils.getValueFromSerializedArray('id');
  if (pid && String(d.count) === '0') {
    miniShop2.UI.unmarkInCart(String(pid));
  }

  try { $(document).trigger('ms2_cart_change', response); } catch(e){}
};

Шаг 3. Разметка товара

В шаблоне карточки товара кнопка должна иметь:

<form class="form-horizontal ms2_form" method="post">
  <input type="hidden" name="id" value="" />
  <button type="submit"
          class="btn btn-primary add-to-cart"
          name="ms2_action"
          value="cart/add"
          data-product-id="">
    Купить
  </button>
</form>

Атрибут data-product-id обязателен --- по нему минишоп будет знать, какую кнопку менять.


Шаг 4. Очистка кэша

MiniShop2 кэширует JS-файлы, поэтому обязательно:

  1. Очисти кэш MODX (Очистить кэш сайта);

  2. Сделай hard reload страницы (Ctrl + F5);

  3. При необходимости обнови query-параметр подключения:

    <script src="/assets/components/minishop2/js/web/default.js?v=2"></script>
    

Результат

Теперь после нажатия на «Купить»: - кнопка меняется на зелёную ссылку «В корзине», ведущую на /korzina.html; - при удалении товара из корзины или очистке корзины --- возвращается исходная кнопка «Купить».


Почему этот способ лучший


Автор: Антон Тарасов\ Решение протестировано на MODX Revolution 2.8.x и miniShop2 v4.0+