Реализация избранного без авторизации (Wishlist на localStorage или cookies)
Вот комплексное решение для реализации функционала «Избранное» без необходимости авторизации пользователя, используя как localStorage, так и cookies в качестве резервного хранилища.
1. HTML структура
<div class="product" data-product-id="123">
<h3>Название товара</h3>
<button class="wishlist-toggle">
<span class="icon-heart-empty"></span>
<span class="icon-heart-filled" style="display:none;"></span>
Добавить в избранное
</button>
</div>
2. JavaScript реализация (jQuery)
jQuery(document).ready(function($) {
// Инициализация избранного при загрузке страницы
initWishlist();
// Обработчик клика по кнопке избранного
$(document).on('click', '.wishlist-toggle', function() {
const productId = $(this).closest('.product').data('product-id');
toggleWishlistItem(productId);
updateWishlistButton($(this), productId);
});
// Инициализация избранного
function initWishlist() {
$('.product').each(function() {
const productId = $(this).data('product-id');
const button = $(this).find('.wishlist-toggle');
updateWishlistButton(button, productId);
});
}
// Переключение состояния избранного
function toggleWishlistItem(productId) {
const wishlist = getWishlist();
const index = wishlist.indexOf(productId);
if (index === -1) {
wishlist.push(productId);
} else {
wishlist.splice(index, 1);
}
saveWishlist(wishlist);
}
// Обновление вида кнопки
function updateWishlistButton(button, productId) {
const wishlist = getWishlist();
const isInWishlist = wishlist.includes(productId);
if (isInWishlist) {
button.find('.icon-heart-empty').hide();
button.find('.icon-heart-filled').show();
button.addClass('active');
} else {
button.find('.icon-heart-empty').show();
button.find('.icon-heart-filled').hide();
button.removeClass('active');
}
}
// Получение текущего списка избранного
function getWishlist() {
// Пробуем получить из localStorage
let wishlist = localStorage.getItem('wishlist');
// Если нет в localStorage, пробуем cookies
if (!wishlist) {
wishlist = getCookie('wishlist');
}
return wishlist ? JSON.parse(wishlist) : [];
}
// Сохранение списка избранного
function saveWishlist(wishlist) {
const wishlistStr = JSON.stringify(wishlist);
// Сохраняем в localStorage (предпочтительный метод)
try {
localStorage.setItem('wishlist', wishlistStr);
} catch (e) {
// Если localStorage недоступен (например, приватный режим)
setCookie('wishlist', wishlistStr, 30); // Храним 30 дней
}
}
// Функции для работы с cookies
function setCookie(name, value, days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
const expires = "expires=" + date.toUTCString();
document.cookie = name + "=" + encodeURIComponent(value) + ";" + expires + ";path=/";
}
function getCookie(name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1);
if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length));
}
return null;
}
});
3. PHP часть (для отображения состояния)
Если вам нужно отображать состояние избранного при первой загрузке страницы (до выполнения JS), можно добавить такой PHP код:
function display_product($product_id) {
$is_in_wishlist = false;
// Проверяем cookies на сервере (только для первоначального отображения)
if (isset($_COOKIE['wishlist'])) {
$wishlist = json_decode(stripslashes($_COOKIE['wishlist']), true);
$is_in_wishlist = in_array($product_id, (array)$wishlist);
}
$active_class = $is_in_wishlist ? 'active' : '';
echo '<div class="product" data-product-id="' . esc_attr($product_id) . '">
<button class="wishlist-toggle ' . $active_class . '">
<span class="icon-heart-empty" ' . ($is_in_wishlist ? 'style="display:none;"' : '') . '></span>
<span class="icon-heart-filled" ' . (!$is_in_wishlist ? 'style="display:none;"' : '') . '></span>
' . ($is_in_wishlist ? 'В избранном' : 'Добавить в избранное') . '
</button>
</div>';
}
4. CSS стилизация
.wishlist-toggle {
background: none;
border: 1px solid #ddd;
padding: 8px 15px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
}
.wishlist-toggle.active {
border-color: #ff0000;
color: #ff0000;
}
.icon-heart-empty, .icon-heart-filled {
width: 16px;
height: 16px;
display: inline-block;
}
.icon-heart-empty {
background: url('heart-empty.svg') no-repeat center;
}
.icon-heart-filled {
background: url('heart-filled.svg') no-repeat center;
}
5. Интеграция с авторизованными пользователями (опционально)
Если вы хотите в будущем добавить интеграцию с авторизованными пользователями, можно добавить такой модифицированный код:
function syncWishlistWithServer() {
// Только для авторизованных пользователей
if (typeof is_user_logged_in !== 'undefined' && is_user_logged_in) {
const wishlist = getWishlist();
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'sync_wishlist',
products: wishlist,
_ajax_nonce: wishlist_vars.nonce
},
success: function(response) {
if (response.success && response.data.updated) {
saveWishlist(response.data.wishlist);
initWishlist();
}
}
});
}
}
// Вызывать при загрузке страницы и после изменений
jQuery(document).ready(function($) {
syncWishlistWithServer();
});
Особенности реализации
- Приоритет хранилищ: сначала пробуем localStorage, затем cookies
- Резервное сохранение: если localStorage недоступен (например, в приватном режиме), автоматически используется cookies
- Производительность: минимальное количество операций с DOM
- Масштабируемость: легко добавить синхронизацию с сервером для авторизованных пользователей
- Доступность: корректная работа даже при отключенном JavaScript (если добавить PHP-проверку)
Это решение обеспечит стабильную работу функционала «Избранное» для всех пользователей, независимо от их статуса авторизации.