WordPress DemoSite

Тестовый сайт для экспериментов и демонстраций возможностей

Реализация избранного без авторизации (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();
});

Особенности реализации

  1. Приоритет хранилищ: сначала пробуем localStorage, затем cookies
  2. Резервное сохранение: если localStorage недоступен (например, в приватном режиме), автоматически используется cookies
  3. Производительность: минимальное количество операций с DOM
  4. Масштабируемость: легко добавить синхронизацию с сервером для авторизованных пользователей
  5. Доступность: корректная работа даже при отключенном JavaScript (если добавить PHP-проверку)

Это решение обеспечит стабильную работу функционала «Избранное» для всех пользователей, независимо от их статуса авторизации.

Полный стэк: .NET | Agile | AJAX | AMQP | Android | api | Bash | Bootstrap | C++ | cms | Composer | css | Data | Elasticsearch | email | ERP | ESP32 | Fenom | Git | GraphQL | Gulp | JavaScript | JetStream | Joomla | js | Kotlin | Laravel | Lean | LEMP | Linux | LMS | Markdown | MODX | Moodle | MySQL | NATS | Nginx | Node.js | OpenCart | Parsedown | PHP | Python | RabbitMQ | Scrum | SCSS | SEO | Simpla | SLA | SOAP | Sphinx | SQL | startup | Swift | Symfony | Tailwind | Translation | Twig | Ubuntu | Unit | W3C | Waterfall | web3 | Webasyst | Webpack | WebSocket | Wishlist | WooCommerce | WordPress | XML | Автоматизация | Безопасность | Бизнес | блокчейн | Вёрстка | движок | ИИ | интернет-магазин | ЛК | Руководство | ТЗ | фреймворк | шаблонизатор | Яндекс.Трекер