Плюс и минус в каунте корзины MS2
        Досточно простой вопрос, который мучает начинающих разработчиков. Решил поделиться решением, как сделать кнопки плюс и минус в корзине MS2. Что бы все было «по-фуншую»
Начнем c разметки. Я показываю на страндартной теме MS2. Вносим правки в чанк tpl.msCart
Далее подключим JS файл и подключим его последним.
И далее напишем ms2.js

Решение от @mngatoff
    
    
                                                        Начнем c разметки. Я показываю на страндартной теме MS2. Вносим правки в чанк tpl.msCart
...
<td class="count">
<form method="post" class="ms2_form" role="form">
  <input type="hidden" name="key" value="{$product.key}"/>
  <div class="form-group">
    <div class="input-group input-group-sm qty">
      <span class="input-group-prepend">
      <span class="input-group-text minus input_count_action">-</span>
      </span>
      <input type="number" name="count" value="{$product.count}" class="form-control"/>
      <span class="input-group-append">
      <span class="input-group-text plus input_count_action">+</span>
      <span class="input-group-text">{'ms2_frontend_count_unit' | lexicon}</span>
      </span>
    </div>
      <button class="btn btn-sm" type="submit" name="ms2_action" value="cart/change">
      ↻</button>
  </div>
</form>
</td>
...Далее подключим JS файл и подключим его последним.
{$_modx->regClientScript("assets/js/ms2.js")}И далее напишем ms2.js
$(document).ready(function() {
  $('.qty').on('click', '.input_count_action', function(e) {
    var $input = $(this).closest("div").find('input');
    var count = parseInt($input.val());
    if ($(this).hasClass("plus")) {
      count = count + 1;
    } else if ($(this).hasClass("minus")) {
      count = count - 1;
    }
    
    $input.val(count);
    $input.change();
    return false;
  });
  $('div.count').click(function(e) {
    var v = $(this).parent().find('input#product_price').val(),
      k = $(this).parent().find('input[name="key"]').val();
    if (($(this).hasClass('minus') || $(this).hasClass('plus')) && v > 0) {
      $.post("", {
        ms2_action: 'cart/change',
        key: k,
        count: v
      }, function(response) {
        if (typeof response.success !== "undefined") {
          if (response.success) {
            miniShop2.Order.getcost();
            miniShop2.Cart.status(response.data);
          }
        }
      }, "json");
    }
  });
	miniShop2.Callbacks.Cart.change.before = function() {
		var $field = $(miniShop2.sendData.$form[0]).find(miniShop2.Cart.countInput);
		var count = +$field.val();
		if (count < 1) {
			$field.val('1');
			miniShop2.Message.error('Ошибка! Нельзя ставить кол-во меньше 1!');
			return false;
		}
		return true;
	}
});И получаем результат.
Решение от @mngatoff
<script>
$(document)
    .on('click touchend', countButton, function (e) { // где countButton - кнопки плюс и минус
        e.preventDefault();
        var $container = $(this).closest('.ms2_form'),
        $count = $container.find('[name="count"]'),
        num = $count.val();
        if (isNaN(num) === false) { // страховочка от, например, пустого поля
            num = parseInt(num, 10);
            switch ($(this).data('ms2-count')) { // соответственно, у кнопок должен быть атрибут data-ms2-count="plus или minus"
                case 'plus':
                    num = num + 1;
                    $count.val(num);
                    break;
                case 'minus':
                    if (num <= 1) return;
                    num = num - 1;
                    $count.val(num);
                    break;
            }
        } else {
            return false;
        }
        $count.trigger('change'); // инициализируем отправку на сервер.
    })
    .on('change keypress keyup', '.ms2_form [name="count"]', function() {
        if ($(this).val().match(/\D/)) {
            this.value = $(this).val().replace(/\D/g,''); // следим на лету, чтобы в поле были только цифры
        }
        if (parseInt($(this).val(), 10) < 1) {
            this.value = 1; // следим на лету, чтобы в поле было не меньше единицы
        }
    });
</script>Ну и обязательно ставим плюсы первому комментарию)    
            
                Поблагодарить автора            
            
                 Отправить деньги            
        
        
            Комментарии: 13
                достаточно триггернуть событие change на input:count, и запрос отправится стандартными средствами минишопа.
я вот так делаю (немного вырвано из контекста, но принцип ясен):
                    я вот так делаю (немного вырвано из контекста, но принцип ясен):
<script>
$(document)
    .on('click touchend', countButton, function (e) { // где countButton - кнопки плюс и минус
        e.preventDefault();
        var $container = $(this).closest('.ms2_form'),
        $count = $container.find('[name="count"]'),
        num = $count.val();
        if (isNaN(num) === false) { // страховочка от, например, пустого поля
            num = parseInt(num, 10);
            switch ($(this).data('ms2-count')) { // соответственно, у кнопок должен быть атрибут data-ms2-count="plus или minus"
                case 'plus':
                    num = num + 1;
                    $count.val(num);
                    break;
                case 'minus':
                    if (num <= 1) return;
                    num = num - 1;
                    $count.val(num);
                    break;
            }
        } else {
            return false;
        }
        $count.trigger('change'); // инициализируем отправку на сервер.
    })
    .on('change keypress keyup', '.ms2_form [name="count"]', function() {
        if ($(this).val().match(/\D/)) {
            this.value = $(this).val().replace(/\D/g,''); // следим на лету, чтобы в поле были только цифры
        }
        if (parseInt($(this).val(), 10) < 1) {
            this.value = 1; // следим на лету, чтобы в поле было не меньше единицы
        }
    });
</script>            
                плюс этого варианта еще и в том, что его можно без изменений использовать в карточке товара в форме добавления в корзину            
                    
                Cпасибо за решение. Добавил как альтернативное в тело статьи.            
                    .on('click touchend', countButton, function (e) { // где countButton — кнопки плюс и минусПодскажите пожалуйста, что нужно вписать в функцию countButton, у меня в консоли вылазиет ошибка:
Uncaught ReferenceError: countButton is not definedа при нажатии на сами кнопки количество не меняется.            
                У вас в коде нет «countButton», вот она и не может его найти. Попробуйте кнопкам прописать класс countButton, а в функции написать: .on('click touchend', '.countButton', function (e) {…            
                    
                Спасибо. Заработало =)            
                    
                Действительно, вот эта часть вашего кода:
ну очень не нужна
Обратите внимание, что на изменение input[name=count] повешена функция которая отправляет форму.
@mngatoff как раз и предлагает воспользоваться методом trigger или на худой конец можно было бы самостоятельно сабмитить форму
                    $('div.count').click(function(e) {
    var v = $(this).parent().find('input#product_price').val(),
      k = $(this).parent().find('input[name="key"]').val();
    if (($(this).hasClass('minus') || $(this).hasClass('plus')) && v > 0) {
      $.post("", {
        ms2_action: 'cart/change',
        key: k,
        count: v
      }, function(response) {
        if (typeof response.success !== "undefined") {
          if (response.success) {
            miniShop2.Order.getcost();
            miniShop2.Cart.status(response.data);
          }
        }
      }, "json");
    }
  });ну очень не нужна
Обратите внимание, что на изменение input[name=count] повешена функция которая отправляет форму.
@mngatoff как раз и предлагает воспользоваться методом trigger или на худой конец можно было бы самостоятельно сабмитить форму
                И еще позвольте немного покритиковать, сюдя по этой вашей строчке:
у каждого товара в корзине есть input с id=«product_price»… Транслируя готовые решения или пошаговые инструкции по хорошему нужно осознавать некую ответственность.
                    var v = $(this).parent().find('input#product_price').val(),у каждого товара в корзине есть input с id=«product_price»… Транслируя готовые решения или пошаговые инструкции по хорошему нужно осознавать некую ответственность.
Идентификатор в коде документа должен быть в единственном экземпляре
                судя*            
                    
                Соглашусь с комментариями выше и прошу исправить решение в посте в соответствии с ними! Ибо потом производятся сайты, созданные на копипасте (без мозгов), которые приходится корректировать мне или другим адекватным разработчикам.
Ну и хорошо бы вставлять код в пост не как попало, а хоть как-то его корректируя. Зачем в первом блоке с HTML кодом эти табы вначале каждой строки?
                    Ну и хорошо бы вставлять код в пост не как попало, а хоть как-то его корректируя. Зачем в первом блоке с HTML кодом эти табы вначале каждой строки?
Ну и хорошо бы вставлять код в пост не как попало, а хоть как-то его корректируя. 
Зачем в первом блоке с HTML кодом эти табы вначале каждой строки?Каюсь) Поправил.            Соглашусь с комментариями выше и прошу исправить решение в посте в соответствии с ними!Обязательно вникну и поправлю основываясь на комментариях выше.            
                Вот что странно иногда возникают ситуации когда код @mngatoff не срабатывает — у меня миникорзина выпадает через меню dropdown в выпадающий список, Bootstrap 5 — возникает какая-то ошибка и событие change на поле input ну ни в какую не хочет срабатывать. Плюс на сайте может быть несколько корзин.
И тут пригождается кусок кода ms2.js в ТС (только не удаляйте) — прием как отправить ms2_action: 'cart/change' оказался для меня лично очень полезен.
Да не по стандарту, но главное что работает. Может я не адекватный программист, но я уже не знаю как заставить сработать стандартным «правильным» способом $count.trigger('change'), т.к. возникает конфликт с Bootstrap 5 — кстати в нем по умолчанию отключили jQuery — интересно когда коды js minishop перепишут без использования jQuery?..
На другом сайте с Bootstrap 3 все работает нормально.
                    И тут пригождается кусок кода ms2.js в ТС (только не удаляйте) — прием как отправить ms2_action: 'cart/change' оказался для меня лично очень полезен.
Да не по стандарту, но главное что работает. Может я не адекватный программист, но я уже не знаю как заставить сработать стандартным «правильным» способом $count.trigger('change'), т.к. возникает конфликт с Bootstrap 5 — кстати в нем по умолчанию отключили jQuery — интересно когда коды js minishop перепишут без использования jQuery?..
На другом сайте с Bootstrap 3 все работает нормально.
                            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.