Это кажется крайне странным, но в 1c-bitrix в компоненте sale:basket.basket до сих пор нет полноценного Ajax-a, и при изменении количества товара в корзине приходится нажимать архаическую кнопку "пересчитать". Не удивительно, что каждый заказчик просит сделать ajax-овый пересчет корзины без перезагрузки страницы.
На двух разных сайтах мы реализовали задумку немного по разному. Сначала мы сделали корзину тут.
В шаблон корзины мы вставили простой js-код, который ловит события click и change в элементах изменения количества товара, включает битриксовскую ajax-анимацию и делает ajax-запрос к некоторому PHP-скрипту, который обновит корзину и вернет HTML новой корзины. Для данной операции в PHP-скрипте достаточно просто вставить тот же самый компонент корзины.
$('.count').each(function() { var $tmp = $(this); $tmp.find('.minus').click(function() { var $count1 = parseInt($tmp.find('input').val()); if ($count1>1) { $count1--; $tmp.find('input').val($count1).change(); } return false; }); $tmp.find('a.plus').click(function() { var $count2 = parseInt($tmp.find('input').val()); if ($count2<100) { $count2++; $tmp.find('input').val($count2).change(); } return false; }); }); $(".order-item-count input").change(function () { BX.showWait('cart_page'); $('#cart_page').load('/actions/update_cart.php?action=update_qty&id=' + $(this).attr('rel') + '&qty=' + $(this).val()); });
Однако в такой реализации есть 2 минуса:
С этими проблемами мы столкнулись на сайте компании Ньюком.
Если решение второй проблемы я в общем-то описал, то первая проблема решается так же не сложно. Во-первых, мы поставили таймер - ajax-запросы отпарвляются не сразу, а через пару секунд, после изменения количества товара, чтобы сократить нагрузку на сервер и в итоге ускорить выполнение запросов. Во-вторых мы пересчитываем стоимость товаров в корзине java-скриптом ещё до отправления запроса, что позволяет пользователю быстрее ориентирвоаться в корзине, подбирая нудное кол-во товаров и не ждать ответа на каждый запрос. В-третьих, мы блокируем кнопку "оформить заказ" до тех пор, пока все запросы не будут выполнены, а заодно вместо кнопки ставим прелоадер, чтобы пользователь понимал, что запросы находятся в стадии выполнения.
function UpdateTotalPrice() { var summPrice=0; var positions=0; $('.count').each(function(){ var id = $(this).attr('id'); var kol = parseInt($(this).find('input').val()); if(!kol) { kol = 0; /*$(this).parent().find('input').val('0');*/} // защита от ввода букв в инпут summPrice += parseFloat(Prices[id])*kol; positions++; }); $('#baskettotalprice').html(FormatPrice(summPrice)); $('.cart-total-price').html(FormatPrice(summPrice)); $('#basketpositions').html(positions); } function setTimer(el)/*ставит таймер*/ { if(!$(el).is('input')) el = this; // тут мы должны пересчитать сумму только что изменившейся позиции и общую сумму var id = $(el).parent().attr('id'); var kol = parseInt($(el).parent().find('input').val()); if(!kol) { kol = 0; /*$(this).parent().find('input').val('0');*/} // защита от ввода букв в инпут var summPrice = parseFloat(Prices[id])*kol; if(summPrice != 0) $('#price'+id.substr(4)).html(FormatPrice(summPrice)); UpdateTotalPrice(); lockButton(); // обновим таймер if(timer) clearTimeout(timer); timer = setTimeout(UpdateBasket, 1000); } function UpdateBasket()/*отправляет запрос на обновление корзины*/ { var Basket={}; // массив хранит ид=>количество товаров в корзине. Передается на сервер. // собираем массив корзины и отправляем на сервер (там уж он разберется как это обновить) $('.count').each(function(indx){ var id = $(this).attr('id'); var kol = parseInt($(this).find('input').val()); if(!kol) { kol = 0; /*$(this).parent().find('input').val('0');*/} // защита от ввода букв в инпут Basket['tov['+id.substr(4)+']'] = kol; }); ajaxregs++; // Для lock/unlock $.ajax({ type: "POST", url: '/ipol/ajax/newcartajax.php?action=updbasket', data: Basket, cache: false, success: function() { unlockButton(); } }); }