Ранее я уже делал заметку на эту тему. Тогда, мы меняли значение input-а при добавлении товара в корзину в старых шаблонах детальной карточки.
В этой заметке рассмотрю этот же функционал для нового шаблона, при этом поправим и некоторый SEO момент данного функционала.
Логика работы будет заключаться в том что при клике на кнопку "В корзину" мы ее прячем и показываем, ранее спрятанную, ссылку "В корзине" которая будет отправлять пользователя на оформление заказа.
Рассматривать буду на примере детальной карточки, но заметка подойдет и для списка элементов раздела, с небольшой модификацией. При этом, если пользователь вышел из карточки (добавив товар в корзину) и снова в нее вернулся - у него останется ссылка "В корзине".
Заменям ссылку-кнопку "В корзину" на "В корзине", при клике
Блок с ссылкой кнопкой, в шаблоне, выглядит так:
<?if ($showAddBtn){?>
<div class="mb-3">
<a
class="btn <?=$showButtonClassName?> product-item-detail-buy-button"
id="<?=$itemIds['ADD_BASKET_LINK']?>"
href="javascript:void(0);">
В корзину
</a>
</div>
<?php}?>
Сначала, давайте сменим ссылку a на span, так как для SEO не очень хорошо наличие ссылки ведущей в никуда.
В карточке, может быть это не очень критично, но вот в списке таких ссылок получается много (да, эту инструкцию можно применить и для списка товаров). Меняем a на span и удаляем href, все будет работать - больше ничего не надо дорабатывать. Заодно избавимся от переизбытка class-ов, что бы проще версталось:
<?if ($showAddBtn){?>
<div class="mb-3">
<span
class="add_to_cart"
id="<?=$itemIds['ADD_BASKET_LINK']?>">
В корзину
</span>
</div>
<?php}?>
У это spana-а есть уникальный для товара идентификатор =$itemIds['ADD_BASKET_LINK']?>, привязавшись к нему будем прятать span, при клике и показывать кнопку перехода в корзину.
<?if ($showAddBtn){?>
<div class="mb-3">
<span
class="add_to_cart"
id="<?=$itemIds['ADD_BASKET_LINK']?>">
В корзину
</span>
<a
class="link_to_card_dn"
href="<?=$arParams['BASKET_URL']?>"
id="to_cart_<?=$itemIds['ADD_BASKET_LINK']?>">
В корзине
</a>
</div>
<script>
$('#<?= $itemIds['BASKET_ACTIONS_ID'] ?>').click(function () {
$(this).addClass('add_to_cart_dn');
$('#to_cart_<?=$itemIds['ADD_BASKET_LINK']?>').addClass('link_to_card_db');
});
</script>
<style type="text/css">
<!--
.link_to_card_dn, .add_to_cart_dn {
display: none;
}
.link_to_card_db {
display: block;
}
-->
</style>
<?php}?>
Суть заключается в следующем: изначально span c "В корзину" виден, а ссылка "В корзине" спрятана в display:none.
- При клике по span-у к нему добавляется class add_to_cart_dn который его прячет (добавляет стиль с display:none)
- К ссылке "В корзине" добавляется class link_to_card_db который переводит ее в display: block;
Само собой стили и скрипты данной логики можно разнести по файлам style.css и script.js, что бы не болтались прямо в шаблоне. Оставил так для упрощения.
Здесь все готово. Но, если пользователь обновит страницу, все стили вернутся в исходное состояние и хотя товар и будет в корзине, пользователь увидит кнопку "В корзину".
Проверка наличия товара в корзине
Что бы поправить этот момент нужно проверить наличие текущего товара в корзине пользователя и обработать вывод кнопок "В корзину" и "В корзине"
В result_modifer.php карточки товара добавляем:
$dbBasketItems = CSaleBasket::GetList(
array(
"NAME" => "ASC",
"ID" => "ASC"
),
array(
"FUSER_ID" => CSaleBasket::GetBasketUserID(),
"LID" => SITE_ID,
"PRODUCT_ID" => $arResult['ID'],
"ORDER_ID" => "NULL",
"DELAY" => "N"
),
false,
false,
array("PRODUCT_ID")
);
while ($arItemsBasket = $dbBasketItems->Fetch()) {
$arResult['ITEM_HAS_IN_CART'] = $arItemsBasket['PRODUCT_ID'];
}
Методом CSaleBasket::GetList мы получили корзину текущего пользователя и отфильтровали текущий товар. Если этот товар есть в корзине-то $arResult['ITEM_HAS_IN_CART'] будет не пустой.
Далее дорабатываем наш кусочек кода:
<if ($showAddBtn){
if ($arResult['ITEM_HAS_IN_CART']) {
$itemInCart = true;
}
?>
<div class="mb-3">
<span
class="add_to_cart<?echo $itemInCart ? ' add_to_cart_dn' : ''?>"
id="<?=$itemIds['ADD_BASKET_LINK']?>">
В корзину
</span>
<a
class="link_to_card_dn<?echo $itemInCart ? ' link_to_card_db' : ''?>"
href="<?=$arParams['BASKET_URL']?>"
id="to_cart_<?=$itemIds['ADD_BASKET_LINK']?>" >
В корзине
</a>
</div>
<script>
$('#<?= $itemIds['BASKET_ACTIONS_ID'] ?>').click(function () {
$(this).addClass('add_to_cart_dn');
$('#to_cart_<?=$itemIds['ADD_BASKET_LINK']?>').addClass('link_to_card_db');
});
</script>
<style type="text/css">
<!--
.link_to_card_dn, .add_to_cart_dn {
display: none;
}
.link_to_card_db {
display: block;
}
-->
</style>
<?php}?>
Тут все просто: если $arResult['ITEM_HAS_IN_CART'] существует мы сразу прячем span и показываем ссылку "В корзине", теми же самыми стилями которые используем в js скрипте.
При желании, можно вообще попрятать все за условие, что бы в исходном коде и не было упоминания о spаn-е и скрипте. Тут уже, на ваше усмотрение:
Аналог CSaleBasket::GetList на D7
Для получения корзины пользователя на 1С-Битрикс с использованием D7, вы можете воспользоваться следующим кодом:
use Bitrix\Sale;
$basket = Sale\Basket::loadItemsForFUser(Sale\Fuser::getId(), Bitrix\Main\Context::getCurrent()->getSite());
$basketItems = $basket->getBasketItems();
$arResult['ITEM_HAS_IN_CART'] = false;
foreach ($basketItems as $basketItem) {
if ($basketItem->getField('PRODUCT_ID') == $arResult['ID'] && $basketItem->getField('ORDER_ID') === null && $basketItem->getField('DELAY') == 'N') {
$arResult['ITEM_HAS_IN_CART'] = true;
break;
}
}
В этом примере мы используем пространство имен Bitrix\Sale, чтобы работать с корзиной. Сначала мы загружаем корзину текущего пользователя, используя Sale\Basket::loadItemsForFUser(). Затем мы получаем список товаров в корзине с помощью $basket->getBasketItems().
Затем мы проходимся по каждому элементу корзины и проверяем, соответствует ли он вашему критерию (ID продукта, отсутствие заказа и отсутствие отложенного статуса). Если условие выполняется, мы устанавливаем $arResult['ITEM_HAS_IN_CART'] в true.