Lacier
  • Alternance Lacier
    • Gestion des Canvas dans le Panier
    • Chatbot
      • Étapes pour intégrer la suggestion de produit
    • Monitoring
    • Compression Image Excel
    • Inventaire
    • Gravure Laser
    • Cleaner Module
    • Scripts JavaScript Indépendants
      • Croix pour fermer le widget d'avis
      • Section Instagram
      • Section Panier Commander
      • Chatbot
    • Notification de Retard de Commande
    • Gestion des Templates de Mails
    • Relance Devis
    • Image FIlter
    • Affichage des produits
    • Attribute Replacer
Powered by GitBook
On this page
  • Fonctionnalités principales
  • Structure et fonctionnement du code
  • Contraintes
  • Code complet
  • Emplacement du fichier
  1. Alternance Lacier

Gestion des Canvas dans le Panier

PreviousAlternance LacierNextChatbot

Last updated 5 months ago

Ce module est conçu pour capturer les aperçus visuels des personnalisations réalisées par les utilisateurs dans un configurateur de produit, enregistre ces aperçus dans le localStorage, et les affiche dans le panier. Cette approche se concentre uniquement sur le frontend, ce qui simplifie son intégration.


Fonctionnalités principales

  1. Capture du Canvas

    • Combinaison des calques upper-canvas et lower-canvas en une image unique.

    • Génération d'une image en Base64 pour l'afficher facilement.

  2. Enregistrement dans le localStorage

    • Utilisation d'une clé unique basée sur l'ID produit et un timestamp.

    • Ajout de métadonnées (texte, police, taille du texte, etc.) si disponibles.

  3. Affichage dans le Panier

    • Récupération des aperçus à partir du localStorage.

    • Affichage de l'image et des détails (texte, police, etc.) sous chaque article.

  4. Suppression des données

    • Suppression des images et métadonnées du localStorage lorsque l'utilisateur retire un article du panier.


Structure et fonctionnement du code

1. Capture et enregistrement

Code source

document.addEventListener('DOMContentLoaded', function() {
    var saveButton = document.getElementById('cv-saveCompositionButton');

    if (saveButton) {
        saveButton.addEventListener('click', function() {
            var upperCanvas = document.querySelector('canvas.upper-canvas');
            var lowerCanvas = document.querySelector('canvas.lower-canvas');
            var textContentElement = document.getElementById('text-content-line-0');
            var textContent = textContentElement ? textContentElement.value : null;

            // Capture des autres informations : police, hauteur de texte
            var fontFamilyElement = document.querySelector('#font-family-line-0-button .ui-selectmenu-text');
            var fontFamily = fontFamilyElement ? fontFamilyElement.textContent : null;
            var textHeightElement = document.getElementById('textHeightInput-line-0');
            var textHeight = textHeightElement ? textHeightElement.value : null;

            // Vérification des canvases et création d'une image combinée
            if (upperCanvas && lowerCanvas) {
                var combinedCanvas = document.createElement('canvas');
                combinedCanvas.width = upperCanvas.width;
                combinedCanvas.height = upperCanvas.height;
                var ctx = combinedCanvas.getContext('2d');
                ctx.drawImage(lowerCanvas, 0, 0);
                ctx.drawImage(upperCanvas, 0, 0);

                setTimeout(function() {
                    try {
                        var canvasData = combinedCanvas.toDataURL('image/png');
                        var uniqueKey = 'canvasImage_' + Date.now();
                        var dataToStore = { canvas: canvasData, textContent, fontFamily, textHeight };
                        localStorage.setItem(uniqueKey, JSON.stringify(dataToStore));
                    } catch (e) {
                        console.error('Erreur lors de la capture du canvas :', e);
                    }
                }, 500);
            }
        });
    }
});

Explications

  • Capture des données clés : contenu texte, police d'écriture, taille.

  • Fusion des calques pour générer une image unique.

  • Stockage des données dans localStorage avec une clé unique.


2. Affichage dans le panier

Code source

document.addEventListener('DOMContentLoaded', function() {
    var cartItems = document.querySelectorAll('.cart-grid ul li');

    cartItems.forEach(function(cartItem) {
        var designerRefLabel = cartItem.querySelector('.label:contains("designer-ref:")');

        if (designerRefLabel) {
            var productId = designerRefLabel.innerText.match(/-(\d+)$/)[1];
            var canvasKeys = Object.keys(localStorage).filter(key => key.includes(productId));

            if (canvasKeys.length > 0) {
                var storedData = JSON.parse(localStorage.getItem(canvasKeys[0]));
                var img = document.createElement('img');
                img.src = storedData.canvas;
                img.style.width = '100%';
                cartItem.querySelector('.product-line-grid-right').appendChild(img);
            }
        }
    });
});

Explications

  • Recherche des données dans le localStorage associées au produit.

  • Affichage des images dans une disposition responsive.

  • Insertion des métadonnées si présentes (texte, police, taille).


3. Suppression des données

Code source

document.addEventListener('DOMContentLoaded', function () {
    var deleteButtons = document.querySelectorAll('.remove-from-cart');

    deleteButtons.forEach(function (deleteButton) {
        deleteButton.addEventListener('click', function () {
            var productItem = deleteButton.closest('.cart-item');
            var canvasImage = productItem.querySelector('img').src;

            if (canvasImage) {
                for (var i = 0; i < localStorage.length; i++) {
                    var key = localStorage.key(i);
                    var storedData = JSON.parse(localStorage.getItem(key));

                    if (storedData && storedData.canvas === canvasImage) {
                        localStorage.removeItem(key);
                        break;
                    }
                }
            }
            productItem.remove();
        });
    });
});

Explications

  • Vérifie si l'image du canvas correspond à une entrée du localStorage.

  • Supprime l'entrée correspondante.

  • Met à jour le DOM pour refléter la suppression.


Contraintes

  1. Frontend uniquement : Toutes les opérations sont effectuées côté client, ce qui limite les possibilités (ex. : pas de sauvegarde sur serveur).

  2. Performance : L'utilisation de localStorage est rapide mais peut être limitée en taille (5 Mo en général).

  3. Responsive Design : Les images sont redimensionnées dynamiquement pour s'adapter à différentes tailles d'écran.


Code complet

document.addEventListener('DOMContentLoaded', function() {
    var saveButton = document.getElementById('cv-saveCompositionButton');

    if (saveButton) {
        saveButton.addEventListener('click', function() {
            var upperCanvas = document.querySelector('canvas.upper-canvas');
            var lowerCanvas = document.querySelector('canvas.lower-canvas');

            // Capture du contenu du texte, avec une vérification de son existence
            var textContentElement = document.getElementById('text-content-line-0');
            var textContent = textContentElement ? textContentElement.value : null;

            // Capture de la police
            var fontFamilyElement = document.querySelector('#font-family-line-0-button .ui-selectmenu-text');
            var fontFamily = fontFamilyElement ? fontFamilyElement.textContent : null;

            // Capture de la hauteur du texte
            var textHeightElement = document.getElementById('textHeightInput-line-0');
            var textHeight = textHeightElement ? textHeightElement.value : null;

            var url = window.location.href;
            var productIdMatch = url.match(/\/(\d+)-/); // Extrait l'ID produit
            var productId = productIdMatch ? productIdMatch[1] : null;

            if (upperCanvas && lowerCanvas && productId) {
                var combinedCanvas = document.createElement('canvas');
                combinedCanvas.width = upperCanvas.width;
                combinedCanvas.height = upperCanvas.height;
                var ctx = combinedCanvas.getContext('2d');

                ctx.drawImage(lowerCanvas, 0, 0);
                ctx.drawImage(upperCanvas, 0, 0);

                setTimeout(function() {
                    try {
                        var canvasData = combinedCanvas.toDataURL('image/png');
                        var uniqueKey = 'canvasImage_' + productId + '_' + Date.now(); // Ajout d'un timestamp pour un identifiant unique

                        // Préparation de l'objet à stocker dans le localStorage
                        var dataToStore = { canvas: canvasData };

                        // Ajout conditionnel des autres propriétés uniquement si elles existent
                        if (textContent) {
                            dataToStore.textContent = textContent;
                        }
                        if (fontFamily) {
                            dataToStore.fontFamily = fontFamily;
                        }
                        if (textHeight) {
                            dataToStore.textHeight = textHeight;
                        }

                        // Stocker les données dans le localStorage
                        localStorage.setItem(uniqueKey, JSON.stringify(dataToStore));

                        console.log('Données sauvegardées pour l\'ID produit ' + productId);
                    } catch (e) {
                        console.error('Erreur lors de la capture du canvas :', e);
                    }
                }, 500);
            } else {
                console.error('Upper-canvas, lower-canvas ou ID produit introuvable.');
            }
        });
    } else {
        console.error('Bouton "Ajouter au panier" introuvable.');
    }
});





document.addEventListener('DOMContentLoaded', function() {
    var cartItems = document.querySelectorAll('#main > div.cart-grid.row > div.cart-grid-body.col-xs-12.col-lg-8 > div > div > ul > li');

    var productCanvasMap = {};

    cartItems.forEach(function(cartItem, index) {
        // Rechercher toutes les étiquettes dans la classe "product-line-info"
        var infoLabels = cartItem.querySelectorAll('.product-line-grid-right .product-line-info .label');

        var designerRefLabel = null;

        // Parcourir les labels pour trouver celui qui contient "designer-ref:"
        infoLabels.forEach(function(label) {
            if (label.innerText.trim() === 'designer-ref:') {
                designerRefLabel = label;
            }
        });

        // Si "designer-ref:" a été trouvé
        if (designerRefLabel) {
            console.log('Designer-ref trouvé:', designerRefLabel.innerText.trim());

            var designerRefValue = designerRefLabel.nextElementSibling ? designerRefLabel.nextElementSibling.innerText : null;

            // Extraire l'ID produit après le dernier "-"
            var productIdMatch = designerRefValue ? designerRefValue.match(/-(\d+)$/) : null;
            var productId = productIdMatch ? productIdMatch[1] : null;

            if (productId) {
                if (!productCanvasMap[productId]) {
                    productCanvasMap[productId] = [];

                    // Parcourir tous les éléments du localStorage et ajouter les clés qui commencent par 'canvasImage_' ou 'canvasOtherImage_'
                    for (var i = 0; i < localStorage.length; i++) {
                        var key = localStorage.key(i);
                        if (key.startsWith('canvasImage_' + productId) || key.startsWith('canvasOtherImage_' + productId)) {
                            productCanvasMap[productId].push(key);
                        }
                    }

                    // Trier les clés par timestamp
                    productCanvasMap[productId].sort(function(a, b) {
                        var timestampA = parseInt(a.split('_').pop());
                        var timestampB = parseInt(b.split('_').pop());
                        return timestampA - timestampB; // Tri du plus ancien au plus récent
                    });
                }

                // Associer les canvas dans l'ordre au bon produit
                if (productCanvasMap[productId].length > 0) {
                    var canvasKey = productCanvasMap[productId].shift(); // Prend le plus ancien canvas
                    var storedData = JSON.parse(localStorage.getItem(canvasKey));

                    if (storedData) {
                        var canvasData = storedData.canvas;

                        var img = document.createElement('img');
                        img.src = canvasData;
                        img.alt = 'Aperçu de la personnalisation';

                        // Utilisation de styles responsives
                        img.style.width = '100%';  // S'adapte à 100% de la largeur du parent
                        img.style.maxWidth = '600px';  // Ne dépassera pas 600px sur les écrans plus grands
                        img.style.height = 'auto';  // Maintient le ratio de l'image
                        img.style.marginTop = '20px';

                        var previewDiv = document.createElement('div');
                        previewDiv.id = 'canvas-image-preview-' + canvasKey;
                        previewDiv.appendChild(img);

                        var targetElement = cartItem.querySelector('div.product-line-grid-right.product-line-actions.ms-auto.mt-20.col-md-10.col-xs-12');

                        // Vérifier si l'élément de destination existe
                        if (targetElement) {
                            targetElement.appendChild(previewDiv);

                            // Créer un élément texteInfo pour afficher les informations supplémentaires (si disponibles)
                            var textInfo = document.createElement('p');
                            if (storedData.textContent) {
                                textInfo.innerHTML += `<strong>Texte :</strong> ${storedData.textContent}<br>`;
                            }
                            if (storedData.fontFamily) {
                                textInfo.innerHTML += `<strong>Police :</strong> ${storedData.fontFamily}<br>`;
                            }
                            if (storedData.textHeight) {
                                textInfo.innerHTML += `<strong>Hauteur :</strong> ${storedData.textHeight} cm<br>`;
                            }

                            // Ajouter les informations texte si elles existent
                            if (textInfo.innerHTML !== '') {
                                targetElement.appendChild(textInfo);
                            }
                        } else {
                            console.error('L\'élément cible pour insérer le canvas n\'a pas été trouvé.');
                        }
                    }
                } else {
                    console.error('Aucun canvas disponible pour le produit avec ID ' + productId);
                }
            } else {
                console.error('ID produit introuvable dans le panier.');
            }
        } else {
            console.error('Élément designer-ref introuvable pour cet article.');
        }
    });
});






document.addEventListener('DOMContentLoaded', function () {
    var deleteButtons = document.querySelectorAll('.remove-from-cart');

    deleteButtons.forEach(function (deleteButton) {
        deleteButton.addEventListener('click', function (event) {
            event.preventDefault();

            var productItem = deleteButton.closest('.cart-item');
            
            // Rechercher l'image du canvas et les données de personnalisation
            var canvasImage = productItem.querySelector('.product-line-grid-right img').src;

            if (canvasImage) {
                for (var i = 0; i < localStorage.length; i++) {
                    var key = localStorage.key(i);
                    var storedData = JSON.parse(localStorage.getItem(key));

                    // Vérifier que les données stockées contiennent bien un canvas et que l'image correspond
                    if (storedData && storedData.canvas && storedData.canvas === canvasImage) {
                        localStorage.removeItem(key); // Supprimer l'élément du localStorage
                        console.log('Canvas et données supprimés pour la clé : ' + key);
                        break;
                    }
                }
            } else {
                console.error("Canvas non trouvé pour ce produit.");
            }

            // Supprimer l'élément du DOM
            productItem.remove();

            // Réinitialiser le overflow du body à auto
            document.body.style.overflow = "auto";

            // Effectuer la suppression via AJAX
            var deleteUrl = deleteButton.getAttribute('href');
            fetch(deleteUrl, {
                method: 'GET' // ou 'POST' si nécessaire selon votre serveur
            })
            .then(function(response) {
                if (response.ok) {
                    // Rediriger vers le panier après suppression
                    window.location.replace("https://www.lacier.fr/panier?show");
                } else {
                    console.error('Erreur lors de la suppression du produit');
                }
            })
            .catch(function(error) {
                console.error('Erreur réseau :', error);
            });
        });
    });
});

Emplacement du fichier

Le code du module est stocké dans le fichier suivant :

Chemin : /lacier.fr/themes/classic-child/assets/js/custom.js

Raison de cet emplacement :

  • Structure claire : Le fichier est placé dans le répertoire assets/js pour séparer les scripts personnalisés des autres fichiers.

  • Thème enfant : Utilisation du dossier classic-child pour préserver les modifications lors des mises à jour du thème principal.

  • Facilité d'accès : Ce chemin permet d'accéder facilement au fichier depuis le thème actif et de le référencer dans les fichiers .tpl ou le code HTML.

Chargement dans le site : Le fichier est inclus via le système de PrestaShop, souvent dans le fichier header.tpl ou via un mécanisme d'injection dans le back-office.