Костомация оформления заказа в 1c- bitrix — IT — Блог Страницы Свободного Человека

С выходом нового шаблона компонента sale.order.ajax на форумах битрикса разгораются возмущения и недомения. Мол, теперь код всего шаблона на JavaScript и как его кастомизировать непонятно. На самом деле да, код js-скрипта составляет почти семь тысяч строк. Сходу в таком количестве кода, даже хорошо написанного (к сожалению, битрикс этим не балует), соблюдая паттерны программирования, будет непросто.

В этой заметке я покажу способ, как можно кастомизировать основной скрипт логики шаблона оформления заказа (order_ajax.js), не прибегая к его правке. Что нам это даёт? Когда прилетят очередные обновления шаблона, мы просто заменим его и всё. Все наши кастомизации будут работать (в теории).

Итак, поехали!

Кастомизируем

Создаём файл order_ajax_ext.js в папке с шаблоном компонента sale.order.ajax (там же, где лежит файл order_ajax.js) с содержимым:

(function () { use strict; var initParent = BX.Sale.OrderAjaxComponent.init, getBlockFooterParent = BX.Sale.OrderAjaxComponent.getBlockFooter, editOrderParent = BX.Sale.OrderAjaxComponent.editOrder ; BX.namespace(BX.Sale.OrderAjaxComponentExt); BX.Sale.OrderAjaxComponentExt = BX.Sale.OrderAjaxComponent; BX.Sale.OrderAjaxComponentExt.init = function (parameters) { initParent.apply(this, arguments); var editSteps = this.orderBlockNode.querySelectorAll(.bx-soa-editstep), i; for (i in editSteps) { if (editSteps.hasOwnProperty(i)) { BX.remove(editSteps[i]); } } }; BX.Sale.OrderAjaxComponentExt.getBlockFooter = function (node) { var parentNodeSection = BX.findParent(node, {className: bx-soa-section}); getBlockFooterParent.apply(this, arguments); if (/bxsoaauth|bxsoaproperties|bxsoabasket/.test(parentNodeSection.id)) { BX.remove(parentNodeSection.querySelector(.pull-left)); BX.remove(parentNodeSection.querySelector(.pull-right)); } }; BX.Sale.OrderAjaxComponentExt.editOrder = function (section) { editOrderParent.apply(this, arguments); var sections = this.orderBlockNode.querySelectorAll(.bx-soa-section.bx-active), i; for (i in sections) { if (sections.hasOwnProperty(i)) { if (!(/bxsoaauth|bxsoaproperties|bxsoabasket/.test(sections[i].id))) { sections[i].classList.add(bx-soa-section-hide); } } } this.show(BX(bx-soa-properties)); this.editActiveBasketBlock(true); this.alignBasketColumns(); if (!this.result.IS_AUTHORIZED) { this.switchOrderSaveButtons(true); } }; BX.Sale.OrderAjaxComponentExt.initFirstSection = function (parameters) { }; })();

Подробнее, что происходит

В отдельных переменных определяем функции-методы родительского BX.Sale.OrderAjaxComponent, чтобы их можно было вызвать в дочерних функциях и не получить ошибку Maximum call stack size exceeded.

Копируем ссылку с BX.Sale.OrderAjaxComponent в BX.Sale.OrderAjaxComponentExt.

В методе BX.Sale.OrderAjaxComponentExt.init вызываем родительский init, следом прибиваем ссылки «изменить» у всех блоков. Они нам не нужны.

В методе BX.Sale.OrderAjaxComponentExt.getBlockFooter прибиваем кнопки «Назад» и «Вперед» у блоков. Они нам тоже не понадобятся — все блоки у нас развёрнуты.

В методе BX.Sale.OrderAjaxComponentExt.editOrder ненужным блокам-секциям добавляем css-класс bx-soa-section-hide. По нему мы и будем скрывать ненужные блоки. А так же в этом методе раскрываем только нужные нам блоки: «Покупатель» и «Товары в заказе».

Метод BX.Sale.OrderAjaxComponentExt.initFirstSection оставляем просто пустым. Если этого не сделать, то у анонимов при попытке оформления будет вываливаться эксепшен, по поводу отсутствия необходимых обязательных полей.

Идем дальше.

Правки шаблона: подключаем наш скрипт и меняем вызов BX.Sale.OrderAjaxComponent на свой

В файле template.php нашего шаблона нового оформления добавляем подключение нашего скрипта order_ajax_ext.js:

После строчки:

$this->addExternalJs($templateFolder./order_ajax.js);

добавляем:

$this->addExternalJs($templateFolder./order_ajax_ext.js);

А так же в файле template.php меняем все вызовы BX.Sale.OrderAjaxComponent на BX.Sale.OrderAjaxComponentExt

Правки CSS

Ну и не забываем добавить в файл стилей, чтобы ненужные блоки скрылись:

.bx-soa-section-hide { display: none;}

На этом всё. Всегда старайтесь подходить к задачам творчески 🙂

Похожие записи

1С-Битрикс. Защита от спама в регистрации без капчи

Не редкость, когда боты начинают регистрироваться на сайтах и захламлять списки пользователей своим присутствием. В «1С-Битрикс» можно включить капчу для защиты от спама. Но порой и капча не спасает, да и заставлять пользователей вводить код с капчи, я считаю, не гуманно. Воспользуемся другим трюком.

1С-Битрикс. Пишем человеческий шаблон многоуровнего меню каталога

Не буду писать про боль при интегации дефотного шаблона. Давайте просто напишем свой, с блекджеком и вот этим всем.

В заметке будет (интересного):

  • построение древовидного массива без рекурсии (неограниченной вложенности)
  • анонимная рекурсивная функция
  • формирование урлов для секций супер-быстрым способом
  • поработаем с сущностями инфоблока через ORM D7

Дальше много кода.

Добавить комментарий

Определение местоположения пользователя в автоматическом режиме

Стоит задача: Определять местоположение пользователя, например, по геотаргетингу, или как-то еще – не важно. Факто в том, что в куках у пользователя уже установлен город. Как передать этот город в новый компонент? На форуме разработчиков было предложено решение:

use BitrixMainEventManager; $eventManager = EventManager::getInstance();$eventManager->addEventHandler(“sale”, “OnSaleComponentOrderProperties”, Array(“Example”, “OnSaleComponentOrderProperties”));class Example{ /** * У меня по условию задачи известны ID и NAME местоположения */ static $curCityId = XX; // числовое значение идентификатора местоположения static $curCityName = ‘Название города’; /** * ID свойств заказа */ const PROP_LOCATION = 6; const PROP_ZIP = 4; const PROP_LOCATION_NAME = 5; static function OnSaleComponentOrderProperties(&$arFields) { $rsLocaction = CSaleLocation::GetLocationZIP(self::$curCityId); $arLocation = $rsLocaction->Fetch(); $arFields[‘ORDER_PROP’][self::PROP_ZIP] = $arLocation[‘ZIP’]; $arFields[‘ORDER_PROP’][self::PROP_LOCATION_NAME] = self::$curCityName; $arFields[‘ORDER_PROP’][self::PROP_LOCATION] = CSaleLocation::getLocationCODEbyID(self::$curCityId); }}

А вот такая модификация позволяет определить местоположение только по названию города:

class Example { static function OnSaleComponentOrderProperties(&$arFields) { static $curCityName = ‘Название города’; const PROP_LOCATION = 6; // – Идентификатор свойства с местоположением static function OnSaleComponentOrderProperties(&$arFields) { $res = BitrixSaleLocationLocationTable::getList(array( ‘filter’ => array(‘=NAME.NAME’ => self::$curCityName, ‘=NAME.LANGUAGE_ID’ => LANGUAGE_ID), ‘select’ => array(‘CODE’ => ‘CODE’, ‘NAME_RU’ => ‘NAME.NAME’, ‘TYPE_CODE’ => ‘TYPE.CODE’) //’*’, )); while($item = $res->fetch()) { $code = $item[“CODE”]; } $arFields[‘ORDER_PROP’][self::PROP_LOCATION] = $code; } }}

Скрыть какое-то свойство

Если необходимо скрыть какое-то свойство, например, свойство индекс – задать значение по умолчанию и не показывать пользователям это поле, то можно внести корректировку в JS. В функции getPropertyRowNode после switch (propertyType) добавляем скрытие данного свойства:

if(property.getId()==6){// идентификатор скрываемого свойства var addressInput=propsItemNode.querySelector(‘textarea’); propsItemNode.style=’display:none;’; addressInput.value=’нужное значение’;}

Исключить из показа нулевой цены за доставку

Очень распространена ситуация, когда при покупке в интернет-магазине пользователь оплачивает именно товар, а доставку оплачивает уже непосредственно транспортной компании. Но если поставить стоимость доставки равной нулю, то визуально будет выглядеть так, что доставка пользователю ничего не будет стоить, что не корректно. Для исключения такой ситуации можно просто скрыть этот ноль из выдачи. Для этого нужно внести небольшие правки в файл order_ajax.js шаблона.

В функции getDeliveryPriceNodes: function(delivery) в блоке “else” заменяем. Вместо:

priceNodesArray = [delivery.PRICE_FORMATED];

пишем:

if(delivery.PRICE>0) priceNodesArray = [delivery.PRICE_FORMATED];

Так мы спрячем нулевую цену из свернутого блока с выбранной доставкой.

Дальше нужно скрыть нули в списке служб доставки. Для этого в функции createDeliveryItem: function(item) делаем строгую проверку на ноль. Вместо:

if (item.PRICE >= 0 || typeof item.DELIVERY_DISCOUNT_PRICE !== ‘undefined’)

пишем:

if (item.PRICE > 0 || typeof item.DELIVERY_DISCOUNT_PRICE !== ‘undefined’)

А также вместо:

else if (deliveryCached && (deliveryCached.PRICE >= 0 || typeof deliveryCached.DELIVERY_DISCOUNT_PRICE !== ‘undefined’))

пишем:

else if (deliveryCached && (deliveryCached.PRICE > 0 || typeof deliveryCached.DELIVERY_DISCOUNT_PRICE !== ‘undefined’))

И последним нужно скрыть нулевую доставку из итоговых сумм. Для этого в функции editTotalBlock: function() также ставим строгую проверку на ноль. Вместо

if (parseFloat(total.DELIVERY_PRICE) >= 0 && this.result.DELIVERY.length)

пишем:

if (parseFloat(total.DELIVERY_PRICE) > 0 && this.result.DELIVERY.length)

В результате нулевая доставка не будет показана пользователю.

Вариант кастомизации компонента оформления от Александры Плотниковой

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

Рейтинг
( 1 оценка, среднее 5 из 5 )
Загрузка ...