1C-Битрикс. Кастомизация нового шаблона компонента sale.order.ajax
С выходом нового шаблона компонента sale.order.ajax на форумах битрикса разгораются возмущения и недомения. Мол, теперь код всего шаблона на JavaScript и как его кастомизировать непонятно. На самом деле да, код js-скрипта составляет почти семь тысяч строк. Сходу в таком количестве кода, даже хорошо написанного (к сожалению, битрикс этим не балует), соблюдая паттерны программирования, будет непросто.
В этой заметке я покажу способ, как можно кастомизировать основной скрипт логики шаблона оформления заказа (order_ajax.js), не прибегая к его правке. Что нам это даёт? Когда прилетят очередные обновления шаблона, мы просто заменим его и всё. Все наши кастомизации будут работать (в теории).
Итак, поехали!
Кастомизировать будем так, чтобы в оформлении осталось только 2 блока (блока с вводом данных покупателя, а так же выводом самой корзины), вместо 6. Если у нас интернет-магазин маленький, то задача вполне себе реальная.
Чтобы получилось примерно так:
Все махинации сводятся к расширению BX.Sale.OrderAjaxComponent. Ну как, к расширению.. Полноценным расширением это сложно назвать. Так как битрикс в разработке шаблонов (и не только), практически не ориентируется на расширение этих шаблонов своими партнёрами, то нам приходится выкручивать себе яйца и изобретать костыли. По другому это не назвать. Вот зачем нужно было писать объект BX.Sale.OrderAjaxComponent без прототипа?
Ладно, ближе к делу :)
Кастомизируем
Создаём файл 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 (/bx-soa-auth|bx-soa-properties|bx-soa-basket/.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 (!(/bx-soa-auth|bx-soa-properties|bx-soa-basket/.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; }
На этом всё. Всегда старайтесь подходить к задачам творчески :-)
63 комментария
Добрый вечер, а где в новом компоненте sale.order.ajax можно добавить дополнительные поля в почтовом уведомлении о новом заказе, не могу найти(в старом это можно было сделать в компоненте
Александр, по-моему, всё так же обработчиком на событие OnOrderNewSendEmail.
Отличное решение! Спасибо.Не подскажете как мне раскрыть поля bx-soa-paysystem и bx-soa-delivery Ни как понять не могу.
я готова тебя расцеловать. Ты просто спас меня. Извини, что на ты - это я от избытка чувств )))
Ирина, рад, что сделал вашу жизнь чуточку лучше :-)
Подскажите как раскрыть поля bx-soa-paysystem и bx-soa-delivery сразу при загрузке стран цы и не закрывать их.
Рома, нужно немного попрограммировать.
Более конкретных рекомендаций не дам, так как самому такого пока не нужно было реализовывать.
Спасибо огромное. У меня антологичный вопрос Влад:
Как раскрыть поля bx-soa-paysystem и bx-soa-delivery?
Никто не решал, как все-так теперь редактировать товар на странице оформления заказа - плюс минус удалить??? Функционал удалили, взамен - ждите?
Вроде и не было никогда управление корзиной в компоненте sale.order.ajax.
На конференции говорили, что вот-вот сделают из коробки :)
Т.е. старые компоненты выпилены (в визуалке), остается только этот. Клиент набрал корзину, передумал насчет половины товаров, КАК ЕМУ БЫТЬ ДАЛЬШЕ?)))) Дальше нИ ОДНОГО товара из корзины нельзя удалить никак! Перезаходить в браузер что-ли? 80-е возвращаются?
решение с новым шаблоном достойно редкостного говнокода, к сожалению. битрикс стал кругом городить еще большие костыли и велосипеды.... тогда бы уж подключили сразу ангулар и делали с ним, всеравно каждый чих получаем новый json объект от сервера
Решение понравилось, но не работает в safari почему-то. Ставил в тч на типовой магазин.
Отличное временное решение для небольших магазинов. Спасибо за работу и публикацию.
Я это говно однажды переписал на Vue js. Вся js-лапша с кучей строк говнокода превратилась в 200 строчек на Vue.
А все потому, что нехер городить лапшу на своем "супер-говно-битрикс-js-фреймворке", а нужно js-шаблонизатор использовать для таких вещей, все за всех уже придумали.
Было бы здорово, если бы поделились своим решением.
Олег, спасибо я развернул все карточки. А то ошибка все вылезала.
В итоге вышло так:
и в файле order_ajax.js на 2283 строке за комментировал штатную обработку. А то поля регион, я убрал. При первой загрузке все поля развернуты. Как только нажимаешь способ оплаты, или доставки, то поля покупателя пропадают. После следующего выбора доставки или способа оплаты все ок. По этому закоментил.
Еще остается пустой блок, тоже убираем: .bx-soa-more {display: none;}
Не делайте это решение! Сам купился на красиво написанный пост, попробовав его с первого взгляда все нормально ,стоит пощелкать по доставкам и начинается магия, все сыпется .Есть решение лучше - либо старый шаблон -https://camouf.ru/club/user/1/blog/77/ ,либо https://dev.1c-bitrix.ru/support/forum/forum6/topic83447/?PAGEN_1=8 - ищем к сожалению функционала старого sale.order.ajax не хватило ((( пришлось "ковырять" новый ((( расскажу как я развернул все блоки, т.к. вопрос актуальный и я на него так и не нашел нормального ответа...." , делаем все пункты и все работает как надо,изменить правда остальное уже на до изучать order.ajax.js и D7
да ладно! ничо не сыпется! у меня 14 доставок и в трех группах... плюс кроссы с платежниками...
Мне вам лично записать? У меня самая последняя версия 1С битрикс ,малый бизнес,все делал по шагам. Работает до 1 раза выбора доставки или оплаты, начинаешь менять , вкладки начинают слетать ( скрываются ) , приходится перезагружать страницу. Если пользователь не авторизован, так вообще не работает так как должно. Или на слово мне не верите? Могу видео записать .
Maks, в начале заметки же написано:
Откуда вы тут взяли блок доставок? То есть мой вариант скрывает блок с доставкой вовсе. Откуда она у вас взялась?
Способ, описанный в заметке, применён на рабочем сайте. Вот скриншот с него https://yadi.sk/i/gLPSoin33Jh7UV Как видите, выбора доставки и оплаты там нет.
да, видимо я вас не так понял изначально. Спасибо за разъяснение что ваш способ работает только С ТЕМ, что вы написали. Это не тот случай когда можно вырезать функционал ( это не комплексный компонент новости, и даже не каталог) . Здесь по дефолту должно работать все, потому что этот компонент делает продажи сайта,и весь интернет -магазин строится на нем ( доставки, оплаты, расчет скидок), а полу работающий функционал на вашей совести. Если у вас не работают стандартные вещи,которые обязаны работать в таком компоненте, откуда у меня будет уверенность что вы еще что-то не вырезали или забыли? Скажем так, вы просто не разобрались в ядре D7 и не знаете как сделать ,поэтому скрыли. Если бы знали, вы оставили бы эту опцию , а люди ,читающие ваш блог сами бы выбрали скрывать им эти функции или нет. Я лично нашел это, хотя знаком с D7 2 дня, если вы считаете себя профессионалом, почему вы не сделали это ? Не вводите своим кодом людей в заблуждение, если недостаточно владеете документацией. Я считаю , выкладывать такой код не профессионально. Это сугубо мое мнение.
Maks, вы как-то между строк прочитали заметку. Я же написал, что покажу способ кастомизации нового шаблона sale.order.ajax. Постарайтесь хотя бы эту фразу вдумчиво прочитать. Но я поясню на всякий случай — описанное в заметке — это как один из вариантов кастомизации нового шаблона.
Программирование — ведь крутая штука. Одну задачу можно решить кучей способов. Мой способ и описан в заметке. У кого-то другого он может быть свой.
Почему не тот случай? Я же говорю, что это работает на боевом сайте. Если у сайта одна оплата и доставка, то к чему давать пользователю выбирать их? Поэтому они и скрыты.
Вырезано только то, что требовалось в задаче, которая описана в заметке.
Интересно, а причём здесь новый шаблон компонента, его скрипт order_ajax.js (который в заметке я и расширяю) и, указанное вами, ядро D7? Вы что-то путаете тёплое с мягким.
Кого я ввожу в заблуждение? Наверное, только вас, человека, который посчитал, что здесь прям в точности найдёт решение своей задачи. Ан-нет. Придётся попрограммировать.
А я считаю, что это мой личный блог, и я могу писать в нём что захочу. Благо, публикуя такие заметки, большинству они помогают в решении их задач (почитайте хотя бы комментарии выше). Ну а вам просто не повезло.
Пишите что хотите, я еще раз повторюсь , я сказал если выкладываете код, делайте его гибким и расширяемым, НЕ ДЛЯ ПОЛЬЗОВАТЕЛЯ , а для тех людей , кто будет его потом использовать (разработчики-интеграторы, заказчик - захочет поставить доставку) . Это Хорошо если он ничего не будет менять, но наши реалии не такие, у нас каждый день меняется что -то. Да я не изобретаю велосипеды как "некоторые", я сперва ищу готовые решения, разбираю как они работают ,если подходят - использую. А вы,видимо, любитель колес,ну удачи вам с этим. Я что -то писал про то , что в файле order_ajax.js используется D7 ? Я сказал вы не разбираетесь в нем, только и всего. Вы уже додумали. Делайте как хотите.Мое мнение останется при мне - это логично оставить возможность доставки и оплаты. Иначе у вас в админке есть, в настройках компонента есть,а в шаблоне нет. Да вы гений!Посносили то,что не смогли поправить , или просто бабла срубили, конечно , это же дольше займет по времени доработать параметры компонента и сделать отключение блоков. Можно же просто вырезать к х***м все! Вот ваша позиция. Я вас понял. Всего вам доброго
Maks, веселите меня сегодня весь день своими громкими заявлениями :)
Так он и так гибкий. Гибче некуда. Если вдруг не поняли, то: берёте любой метод из BX.Sale.OrderAjaxComponent и переопределяете его в BX.Sale.OrderAjaxComponentExt. Всё. Просто, не правда ли?
Любитель халявы, я понял. Напишите свой вариант решения задачи и покажите всем. Сделайте этот мир лучше.
Ок. Как вы тогда сделали такой вывод, если в заметке нет ни слова о D7? Парадокс.
Халявы? Я не халявщик, я не велосипедист повторяю. Вам нравится - изобретайте колеса.
Что у вас просто? Вы дурак , или прикидываетесь? Я вам говорю делайте гибко,и расширяемо, вы мне говорите метод заменить. Вы издеваетесь? Ну я посмотрю как человек сперва ваш метод использует, а потом у него вдруг появятся заявки и доставка и он заменит метод на дефолт и все будет работать.
Он сперва кастомизирует ВАШ МЕТОД, а потом уже захочет обратно доставку и оплату, и все придется переносить!
Ну так докажите. Покажите хоть один решённый вами кейс. Пока что я вижу только хныканье и полное отсутствие желания или способностей к решению своей задачи.
Я ж уже показал как делать. Непонятно? Обратитесь к программисту уже.
Ага, представляете? Когда что-то нужно сделать самому, то придётся всё-таки включить голову, а не идти плакаться по блогам, что решение какой-то задачи не соответствует вашей.
Он возьмёт и сделает. Что значит «кастомизирует мой метод»? Что там переделывать-то? Вы бы хоть на количество моего когда в расширяемом файле посмотрели. Его там аж целых 70 строк. А при виде оригинального order_ajax.js (в 8000 строк) вы и вовсе падаете в обморок, наверное.
Комментарий был удалён.
Комментарий был удалён.
Комментарий был удалён.
Комментарий был удалён.
Комментарий был удалён.
ПосонЫ!Жгите дальше! Зря что ли я чипсов с попкорном накупил???
Макс, вы походу верстальщик банальный, судя по вашей же ссылке на резюме, хотя я таких резюме могу наклепать с десяток, и шо? ниочем.
Прочитал между строк. Maks, Олег написал написал вполне хороший вариант для раскрытия блоков, т.к. они открываются по шагам и ajax то это жопа полная.
Я же используя код Олега улучшил его слегка и все доп. блоки работают и открываются. Пример можно посмотреть здесь: 100letov.ru
Задача у клиента была развернуть и переставить местами, блоки. Т.к. блоки подгружаются ajax, то при переносе какого либо блока в шаблоне tamplate блок перестает работать. Благо css позволяет менять местами, не пришлось разбираться, почему перенесенный код блока перестает работать. Видимо там какая-то жесткая привязка. Советую так же удалить в компоненте *.min.js файлы. Версия битрикса 17 и все гуд!
http://prntscr.com/fee2be скриншот для факта того что все работает, ибо клиент не принял бы не рабочий вариант. Оплата есть,, т.к. доставка только курьером, то этот блок был скрыт.
Комментарий был удалён.
Комментарий был удалён.
???
олег, случаем календарь не кастомизировал? нужно гасить прошедшие дни, чтобы нельзя было выбрать...
Сам не делал. Что-то похожее видел тут https://dev.1c-bitrix.ru/community/forums/forum6/topic83447/?PAGEN_1=12
У меня не работает! Сделал вроде все согласно инструкции. Помогите разобраться.
А как в блок местоположение передать значения, которые получаем из сессионных переменных?
Александра, разжуйте!
А как все-таки решить, если нужно оставить не 2, а три блока, т.е. оставить еще и выбор доставки?
Вроде все сделала как описано. Но почему-то для неавторизованного пользователя все равно появляется красный восклицательный знак. То есть, требует поля данных о пользователе, почему-то поля, введенные через расширения система не видит. Для неавторизованного пользователя работает эта штука?
Да, для неавторизованного пользователя в заметке и показан пример.
Это что значит? Не понял.
Применила комментарий Максима #527 Максим 21 мая 2017 в 18:02 Все получилось. Спасибо!
У меня после этих изменений кнопка "Оформить заказ" - не активна. т.е. по нажатию не оформляется заказ. что не так делаю?
Есть такая ошибка - Uncaught TypeError: this.alignBasketColumns is not a function at Object.BX.Sale.OrderAjaxComponentExt.editOrder
кнопка не активна - значит какое-то поле не заполнено и оно скрыто описанным в статье хаком. епти! в админке сделай необязательным его
Статья действительно очень полезная, но я не могу решить один вопрос. Возможно сможете подсказать. Нужно чтобы осталось два блока. Первый выбор типа плательщика Физ или Юр лицо и второй, блок с полями ФИО, адрес и т.д. Нужно чтобы они были оба открыты, чтобы можно было менять плательщика без нажатия кнопки "Изменить"
Присоединяюсь к вопросу Антона.
Присоединяюсь к комментарию(#639) Выше. Как сделать, чтобы остался еще и блок с выбором типа пользователя(Физ и Юр лицо)
Вот собственно и раскрытие карточки с Регионом где физ и юр лицо Файл автора order_ajax_ext.js , часть в которой надо менять:
Дополню к своему ранее добавленному комментарию #527
Готовый JS order_ajax_ext:
CSS
Сортировка карточек если надо кому
Иными словами, уважаемый, Вы вызовете метод
show
два раза, повстречавbx-soa-region
вsections[i].id
, верно?mr.Bro, Да но проблему все таки не удалось решить, зависимостей ajax много. Он открывает блок спустя некоторое время, При изменении типа ЮР на физ лицо начинаются чудеса) Если этот блок (Юр и физ лица + регион) не использовать, т.е. скрывать его, то работает нормально. Поигравшись снова 2-ое суток, я решил поставить старый компонент sale.order.ajax, его кастомизировать проще. Ссылка на старый компонент тут: https://camouf.ru/club/user/1/blog/77/ если, автор блога не против, то опубликует.
На маркетплейсе начали появляться готовые решения/
Скоро кастомизировать не придется.
Ищу ищу и нигде не могу найти ПОЛНОГО руководства по кастомизации. В том смысле что нужно не просто скрыть/раскрыть блок, скрыть/показать кнопку и т.п., нужно полностью переделать верстку - а это как я понял полный трындец...