Итак. Множество людей, которые имеют магазин на Битриксе, хотят сделать добавление в корзину без перезагрузки страницы, не включая режим AJAX у компонентов catalog (Это страшно!). Да и мне лично не нравится библиотека от Битрикса. И использую я всегда jQuery. У нас на форумах сообщений по данной теме достаточно много, но там надо лезть в исходный код и писать скрипт под свою верстку, создавать отдельный файл с компонентом корзины и т.д. Я же предлагаю универсальный метод. Все действия будут описаны ниже, они включают в себя: 1. подключение библиотеки jQuery в header.php 2. обертка компонента корзины в тэг и все!
Сразу поясню, данный метод чисто мои задумки на универсальность, сам я его не использую, а пишу обновление корзины под каждый конкретный случай верстки и т.д.
Итак приступим:
1. подключаем jQuery, для этого открываем файл /bitrix/templates/ваш_шаблон/header.php и между <head> и </head> вставляем код:
2. теперь обновим маленькую корзину. Для этого нужно обернуть вызов компонента нашей корзины. Находим где она подлючается и оборачиваем в <!--start--><div id="bid"> </div><!--end-->. Примерно это будет выглядеть так:
тут мы разом заменяем все сслыки на добавление товара в корзину. Но ссылка нам еще понадобится, копируем ее в атрибут rel. Плюс в том, что если у кого то отключен JS, все будет работать по старому!
Теперь при клике по ссылке посылаем запрос к этой же странице на добавление товара в корзину. Тут минус - страница срабатывает полностью, но без видимой перезагрузки. Тоесть для пользователя все прозрачно.
И самый извращенный момент вырезать из html кода, который нам пришел от Ajax запроса, обновленное тело корзины:
тут мы режем html и, обратите внимание, берем элемент массива с индексом 2, потому что в этой функции мы тоже использовали <!--start--><div id="bid"> и первый раз split разрежет по ней. Можно использовать рег. выражения, но я сделал так.
Вариант для добавления товара в корзину с указанием количества(для стандартного шаблона).
Косоротов Алексей, по моему это костыль чуть более, чем полностью, так же как и совать название товара в url По самой статье: <div id="bid"> на всякий случай id можно было сделать более уникальным, пусть, например, он содержит в себе название компонента и название шаблона. Вообще всю эту тему с обновлением информера корзины можно сделать так: пинаем ajax запрос к той же странице, на которой находимся, например /catalogue/krovati/14138/?action=BUY&id=14138 , ловим результат, вырезаем содержимое id="bid" из пришедшего контента и заменяем содержимое id="bid" на странице.
вариант 2: более производительный. пинаем запрос ?action=BUY&id=14138 в специально заготовленному скрипту , например ajax_add_to_basket.php , в этом скрипте ручками добавляем товар в корзину, и сразу же узнаём количество товара в корзине, и может ещё какую инфу по корзине, которая может понадобиться (смотря что там выводится в информере помимо количества товара).
Есть небольшая задача. Имеется у нас некий сайт, на котором авторизация и регистрация происходит при помощи логина и пароля, а нам вдруг захотелось отказаться от логина и регистрировать/авторизовывать человека по емайлу. Предложеные решения на форумах и блогах, с кастомизацией компонентов и скрытием поля при помощи js меня не привлекло и я написал небольшой код, который решает данную проблему.
При переходе на авторизацию по email возникает вопрос, а как быть с теми кто уже зарегистрирован? можно конечно сделать рассылку всем пользователям, что теперь надо авторизовываться по email. Но не все читают почту. Делаем так, добавляем в init.php:
и все! осталось только в шаблонах регистрации и редактирования профиля сделать поле логина hidden. Старые пользователи смогут заходить как по логинам так и по емайл до следующего редактирования профиля. Строчку:
$arFields["LOGIN"] = $arFields["EMAIL"];
можно заменить на любое формирование Логина, например часть емайла до @.
Напрашивается вопрос почему не сделать наоборот, в шаблоне напротив поля логин написать e-mail и пусть вбивают туда свой email, а мы его будем копировать пользователю, но не факт, что пользователь вобьет туда именно емайл, а зачем еще раз писать проверку когда она уже есть в стандартном функционале для поля EMAIL.
P.S. Закоментированная строчка:
/*else $arFields["LOGIN"] = "";*/
запретит авторизацию по старым логинам. Минусы - авторизация по емайл будет работать везде, даже при входе в админку. Но это можно обойти если поставить проверку на группу администраторов, например, в обработчиках.
Спасибо. Только в фильтре надо писать =EMAIL, иначе будет нестрогое соответствие и будут находиться любые другие email'ы, подходящие под "сложную логику", описанную в документации.
А сделав поле логина инпутом с type="hidden" , просто так не отделаться, по крайней мере для main.register Нужен еще один костыль - дефолтное value задать, например "123456" чтобы поле прошло валидацию контроллером компонента (это происходит до события OnBeforeUserRegister)
UPD: При регистрации через компонент одношагового оформления заказа sale.order.ajax событие OnBeforeUserRegister не обрабатывается.
Недавно пришел к нам клиент и сказал: «Хочу при редактировании товара указывать скидку на этот товар, только чтобы применялась она исключительно для данного товара, причем была возможность вводить скидку как в процентах, так и фиксированную величину в рублях». Порывшись в скидках увидел, что к скидке можно привязывать товар, на который она будет дейсвовать. Однако, как обычно, процесс выбора товара не совсем удобен.
Немного подумав, родился следующий алгоритм:
Создаем два свойства у инфоблока FIXED_DISCOUNT и PERCENT_DISCOUNT. При срабатывании событий OnAfterIBlockElementAdd и OnAfterIBlockElementUpdate проверяем заполненность этих свойств. Если свойство скидки заполнено - создаем скидку( н.п. percent10 — если в PERCENT_DISCOUNT стоит значение 10) и в список товаров на которые действует эта скидка добавляем ID редактируемого элемента. Если же скидка percent10 уже существует, то просто дописываем товар к ней. Если поля со скидками оказываются пустыми надо проверить, к какой скидке принадлежит редактируемый товар и убрать его из списка. Важный момент! Необходимо проверять есть ли в списке товаров у скидки хотя бы 1 элемент, если нет — то скидку надо удалить, иначе она будет действовать на все товары.
Такой же подход и к фиксированной скидке. Ниже приведен исходный код для реализации ввода процентной скидки в форме редактирования товара. Помещаем его в init.php и не забываем создать свойство типа «строка» или «целое число» с кодом PERCENT_DISCOUNT.
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", Array("CYDiscount", "SetDiscount"));
/* до сохранения элемента сбрасываем скидку, на случай если она изменилась */
AddEventHandler("iblock", "OnBeforeIBlockElementUpdate", Array("CYDiscount", "DropDiscount"));
class CYDiscount
{
function SetDiscount($arFields)
{
if(!CModule::IncludeModule('catalog'))
return;
/* Выбираем элемент который изменяется */
$obs = CIBlockElement::GetByID($arFields["ID"]);
if($res = $obs->GetNextElement())
{
/* Достаем свойства */
$props = $res->GetProperties();
$pdisc = $props["PERCENT_DISCOUNT"]["VALUE"];
/* Проверяем валидность введенной скидки */
if(!$pdisc || !intval($pdisc))
{
/* Удаляем скидку если скидка не целое число или пустое */
CYDiscount::DropDiscount($arFields);
return;
}
$discount = $pdisc;
/* Проверяем размер скидки, чтобы скидка была от 1 до 99 % включительно*/
if($discount == 0 || $discount == 100)
CYDiscount::DropDiscount($arFields);
}
else
return;
/* Выбираем скидку по имени, percent - это префикс для скидки, который использую я, допустим скидки 1% и 10 % будут именть имена percent1 и percent10 соответственно */
$dbProductDiscounts = CCatalogDiscount::GetList( array(), array( "ACTIVE" => "Y", "NAME"=>"percent".$discount) , false, false, array("ID"));
if($arProductDiscounts = $dbProductDiscounts->GetNext())
{
/* Выбираем все товары которые принадлежат данной скидке */
$res = CCatalogDiscount::GetDiscountProductsList( array() , array("DISCOUNT_ID"=>$arProductDiscounts["ID"]));
$ids = array();
/* Собираем новый массив ID товаров, которые уже были в скидке*/
while($el = $res->Fetch())
$ids[] = $el["PRODUCT_ID"];
/* и дописываем к нему ID редактируемого товара */
$ids[] = $arFields["ID"];
/* Обновляем скидку */
CCatalogDiscount::Update($arProductDiscounts["ID"], array("ACTIVE"=>"Y", "PRODUCT_IDS" => $ids));
}
else
{
/* если такой скидки не существует, создаем ее и привязываем к ней 1 товар */
CCatalogDiscount::Add(array("SITE_ID"=>"s1", "ACTIVE"=>"Y", "NAME"=>"percent".$discount, "VALUE_TYPE"=>"P", "VALUE"=>$discount, "CURRENCY"=>"RUB", "PRODUCT_IDS"=>array($arFields["ID"])));
}
}
function DropDiscount($arFields)
{
if(!CModule::IncludeModule('catalog'))
return;
/* Выбираем все скидки */
$dbProductDiscounts = CCatalogDiscount::GetList( array(), array( "ACTIVE" => "Y") , false, false, array("ID", "NAME"));
while($arProductDiscounts = $dbProductDiscounts->GetNext())
{
/* По префиксу проверяем наша ли это скидка */
if(substr_count($arProductDiscounts["NAME"], "percent") == 1)
{
$res = CCatalogDiscount::GetDiscountProductsList( array() , array("DISCOUNT_ID"=>$arProductDiscounts["ID"]));
$ids = array();
/* Заново группируем массив элементов этой скидки */
while($el = $res->Fetch())
$ids[] = $el["PRODUCT_ID"];
$idsn = array();
/* Удираем из массива элемент который редактируется */
for($i=0; $i < count($ids); $i++)
if($ids[$i]!=$arFields["ID"])
$idsn[] = $ids[$i];
/* проверяем, если в скидке нет элементов то удаляем ее, иначе - обновляем */
if(count($idsn)>0)
CCatalogDiscount::Update($arProductDiscounts["ID"], array("ACTIVE"=>"Y", "PRODUCT_IDS" => $idsn));
else CCatalogDiscount::Delete($arProductDiscounts["ID"]);
}
}
}
}
P.S.
В обеих функциях желательно сделать обертку для каких инфоблоков выполнять это действие. Например так:
завести новый тип цены "Цена со скидкой" и при редактировании элемента пересчитывать "Базовую цену" с введенной скидкой и записывать ее в новый тип цены. Но такой вариант отпал по техническим причинам.
Шилов Андрей, скажите, пожалуйста, можно ли реализовать такой метод при выгрузке товаров из 1С. Т.е. при выгрузке товаров проверять, есть ли в поле "скидка" значение и далее создавать эту скидку методом CCatalogDiscount::Add(). Или при импорте нужно как-то по-другому реализовывать скидки?
Андрей, у нас при работе вашей функции цены для 3 позиций обновляются чуть больше минуты либо сваливается в 504 gateway timeout .. не подскажете как оптимизировать ? явно где-то длинная рекурсия идет, но где ?
Представляю вам небольшой отладчик для Битрикса. Надоело мне все время писать print_r, или использовать навешанную на горячую клавишу самописную функцию или участок кода аля if($USER->GetID()==15){...}, в которую все равно приходилось вписывать имя переменной или массива. И объединил я все это в BXDebugger v.1.0.0
Функционал дебаггера:
установка множества точек остановки в скрипте;
прерывание скрипта только для определенного пользователя, прозрачная работа скриптов для других пользователей;
добавление/удаление переменных в список отслеживаемых;
Шаг 2. Включение/Выключение отладчика. После того как вы подключили файлы отладчика в init.php, в публичной части сайта на "Панели инструментов" рядом с кнопкой "Выйти" появится зеленая кнопка "START DEBUG" (см. рисунок ниже).
После включения отладчика появится кнопка выключения и две кнопки перехода по шагам, об этом чуть позже.
Шаг 3. Добавление точки остановки в исходный код. Для примера откроем страницу index.php и добавим туда такой код:
функция dbg - вызывает остановку сценария в месте где она вызвана. На вход она получает ID или Login пользователя, под которым вы работаете (обязательно с правами администратора) и массив переменных среди которых будет произведен поиск. Теперь сценарий будет прерван только для пользователя, который указан в функции dbg.
Шаг 4. Вывод отладочной информации на экран. Для того чтобы отследить значение какой нибудь переменной, необходимо добавить ее в список. Для этого вводим ее имя в поле add variable(array) и жмем ОК. список переменных сохраняется в файле array.php, поэтому нет необходимости добавлять одну и ту же переменную на каждом шаге.
После добавления переменной, она появляется в списке. Слева имя переменной, справа - значение или тип. Переменную можно удалить из списка, нажав на красный крестик справа. Слева от имени меременой, в ромбике стоит буква, обозначающая тип переменной. (String, boolean, double, integer)
Чтобы просмотреть значение переменной в всплывающем окне, кликните на него.
На скриншоте вы можете видеть в правом верхнем углу таинственную надпись mark name: dbg, о ней читайте в Шаге 6.
Шаг 5. Пошаговая отладка. для примера разберем следующий код:
запустите отладчик и понажимайте стрелки "NEXT STEP" и "PREV STEP", вы увидите, что при переходе на следующий шаг, первый вызов функции игнорируется, затем второй и так далее.
Можно dbg(1, get_defined_vars()) вставлять в цикл и следить за переменными цикла, например за изменением arItem в шаблоне компонента news.list
Шаг 6. Вывод имен меток. Что это такое? Рассказываю. Иногда надо поставить разные метки в разных участках скрипта и посмотреть какое условие выполняется. Что мы обычно для этого делаем? Вот что:
if(...)
{
echo "1";
}
else
{
echo "2";
}
можно сделать тоже самое при помощи глобальной переменной $BXD, но при этом получить доступ ко всем объявленным переменным и просмотреть их в окне дебаггера.
Можно писать любое имя метода и вы будете знать где у вас сработала точка остановки.
P.S. Естественно функции dbg() и варианты $BXD->mark1(), $BXD->mark2() и т.д. нужно повесить на горячие клавиши вашего текстового редактора для удобства.
Верстку смотрел в FF3.6 и Opera 9.64, в остальных не знаю как себя ведет. И еще не видел как выводятся кнопки дебаггера с новой админ панелью Битрикса
И если картинки кнопок не отображаются, пошаманьте над .htaccess в /php_interface/
Прошу кого-нибудь откликнуться! Автор, к сожалению, молчит. Существует или нет обновленная версия отладчика - хотя бы под битрикс v14. Или проект больше не развивается?
Вот пытаюсь настроить xDebag, для отладки выгрузки. Ни как не могу заставить чтобы сработал xDebag, хотя сам отладчик работает при тесте допустим какого либо функционала. Может кто знает как заставить его чтобы он сработал.
ссылка на этот пост есть в пункте "Сервисы->Ресазер 2.0->Справка"
ВНИМАНИЕ!! в конце поста есть решение некоторых проблем при установке!
Ресайзер 2.0 — это новый модуль по работе с изображениями элемента инфоблока. Обратной совместимости с первым ресайзером к сожалению(а может и к счастью) нет. Это обусловлено полной сменой алгоритмов хранения изображений, теперь достаточно одного множественного свойства типа Файл для организации хранилища различных размеров фотографий.
Ну, а теперь к установке: Устанавливается модуль как обычно, после оплаты, мы добавим вас в список клиентов и у вас в сторонних обновлениях появится новый модуль.
Рабочий стол -> Настройки -> Marketplace -> Сторонние обновления
После его установки вас автоматически перекинет в раздел справки. Обязательно прочитайте ее.
Сервисы->Ресайзер 2.0->Наcтройка Основные настройки ресайзера — это настройки по позиционированию водяного знака. Отдельное внимание хочу обратить на подключение библиотек с которыми работает модуль (jquery, ligthbox, fancybox и т. д.) Их можно подключать самостоятельно или выделить галочку и библиотека будет подключена автоматически на всех страницах сайта. Для добавление своего шрифта - скопируйте файл с расширением .ttf в папку /yenisite.resizer2/fonts/. После чего он появится в списке в настройках.
Сервисы->Ресайзер 2.0->Наборы Набор - это сущность которая включает себя характеристики изображения (ширину, высоту, качество и т.д.). Каждую такую сущность вы сможете использовать для генерации изображения.
Сервисы->Ресайзер 2.0->Кэширование Тут можно сбросить закешированные фотографии
Использование: Приятная особенность данного модуля — это добавление статического всплывающего изображения через визуальный редактор. Тут проще показать на видео-примере.
В комплекте с ресайзером 2.0 идет компонент resizer2.box (+ шаблоны), который позволяет выводить фотографии элемента используя созданные наборы при помощи популярных jquery библиотек. В настройках компонента необходимо указать ID элемента и настроить наборы. Видео по вставке компонента в шаблоны
Ресайз при помощи API: Общий принцип хранения изображениий: Любое изображение прошедшее обработку с помощью API ресайзера 2.0 сохраняется на диске с определенным именем, которое содержит в себе ID набора и url.
Метод ResizeGD2 получает на вход 2 параметра: 1 - путь к картинке; 2 - ID набора(Наборы создаются в Сервисы->Ресайзер 2.0->Наборы) Метод возвращает путь к новому изображению. Причем изображение создается только в том случае если его нет физически на диске, если же оно существует, то повторного ресайза произведено не будет. Если необходимо перегенерация изображений, можно перейти в Сервисы->Ресайзер 2.0->Кэширование и сбросить кеш.
API модуля позволяет сбросить кэш для определенного набора:
<?Cresizer2Resize::ClearCacheByID($set_id);?>
где $set_id - ID набора
Для генерации изображения так же можно использовать системный скрипт /yenisite.resizer2/resizer2GD.php:
CResizer2Set::GetList(); // возвращает объект CDBResult всех наборов
Решение некоторых проблем:
1. Веб-антивирус обнаружил вирус в системных файлах модуля Для устранения проблемы добавьте два исключения в веб-антивирус. Перейдите в Настройки-Проактивная защита-Веб Антивирус, Затем откройте вкладку исключения и добавьте исключения как на скриншоте.
2. Не работают js скрипты Такая ошибка возникает из за конфликта библиотек, чаще всего конфликтуют библиотеки jquery, попробуйте отключить все библиотеки в настройках модуля "Ресайзер". Если не помогло, то обратитесь в нашу тех.поддержу (перейти)
Хочу обратить внимание разработчиков на то, что скрипту передается URL картинки относительно корня сайта и номер набора (предварительно созданного пользователем в админке сайта). А это значит, что злоумышленнику нельзя будет заDDoSисть сайт путем подсовывания скрипту ссылок на внешние картинки или например бесконечно перегенирацией картинок с шагом 1 пиксел (встречали и такие реализации на некоторых проектах) — все в рамках созданных наборов и имеющихся на сервере изображений.
Удобно, что этот код для ресайза, можно использовать прямо в HTML — без знаний PHP. Минусы — не уверен что картинка с таким адресом будет скушена поисковым роботом, надо проверить.
Разработчики могут пережимать картинки с помощью мощного API модуля. Функции ресайза содержат алгоритмы со сложными математическими вычислениями наложения водяного знака и могут быть использованы в работе любых других модулях и компонентах Битрикс.
Отдельное внимание хочу обратить на подключение библиотек с которыми работает модуль (jquery, ligthbox, fancybox и т. д.) Их можно подключать самостоятельно или выделить галочку и библиотека будет подключена автоматически на всех страницах сайта.
Разработчикам будет удобно всегда иметь под рукой актуальную версию библиотеки jQuery и плагинов к ней.
Кстати, мы столкнулись с рядом проблем при попытке красивого подключения библиотек через события модуля — модуль проактивной защиты Битрикс распознает эти действия как попытку взлома..
Доброго времени суток. Зарегистрировался у вас на сайте, попытка входа (авторизации) /не успешно/ повторная попытка авторизации - пишет: "Внимание! Превышено количество лицензированных пользователей! Вам необходимо приобрести дополнительные лицензии. В случае возникновения вопросов обратитесь в службу технической поддержки. " У меня есть вопросы по наладке вашего продукта. ...
В настройках выбрал PREVIEW_PICTURE как код свойства картинки, галочка "не использовать стандартные свойства" не включена. при выводе пишет "нет картинки" превью элементов ИБ заполнены. В чём может быть проблема?
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».
По самой статье: <div id="bid"> на всякий случай id можно было сделать более уникальным, пусть, например, он содержит в себе название компонента и название шаблона.
Вообще всю эту тему с обновлением информера корзины можно сделать так: пинаем ajax запрос к той же странице, на которой находимся, например /catalogue/krovati/14138/?action=BUY&id=14138 , ловим результат, вырезаем содержимое id="bid" из пришедшего контента и заменяем содержимое id="bid" на странице.
вариант 2: более производительный. пинаем запрос ?action=BUY&id=14138 в специально заготовленному скрипту , например ajax_add_to_basket.php , в этом скрипте ручками добавляем товар в корзину, и сразу же узнаём количество товара в корзине, и может ещё какую инфу по корзине, которая может понадобиться (смотря что там выводится в информере помимо количества товара).