Tagjavascript

[Magento 2] Afficher un lien vers la fiche produit depuis la quickview en exploitant le localStorage

edit: je me suis rendu compte que la solution #1 n’était pas fonctionnelle. En effet, à l’utilisation, le local storage (clé: product_data_storage) était vide/n’avait aucune valeur!

Solution #2 (fonctionnelle)

app/design/frontend/Vendor/theme/Magento_Catalog/templates/product/list.phtml: au clic sur un item produit (parce qu’au clic sur le trigger de la quickview, il ne se passait rien), on cherche dans le markup enfant le lien vers la fiche produit cible et on le stocke dans le local storage via window.localStorage.setItem('clé', valeur);.

app/design/frontend/Vendor/theme/Magento_Catalog/templates/product/view/product-url.phtml: au clic sur le lien « voir la fiche produit », on récupère l’URL dans le local storage (clé quickviewRelatedProductURL):

Le layout XML et les styles de la solution #1 restent valables. Merci de vous y référer.


Solution #1 (pas focntionnelle)

Quickview rattachée au module CartQuickPro fourni avec le thème Venuse.

La quickview s’affiche en cliquant sur un item produit dans le listing produit (page catégorie) du site Magento 2. Elle affiche, dans une iFrame, une partie des éléments de la fiche produit (c’est le même code qui est utilisé pour la quickview et la fiche produit).

Le fichier template PHTML:

  • Objectif: placer un lien vers la fiche produit dans la page.
  • On récupère l’URL de la fiche produit en consultation dans le localStorage (clé: product_data_storage) sous forme de chaîne JSON. Il faut convertir cette chaîne JSON en objet JavaScript pour pouvoir l’exploiter.
  • On récupère l’ID du produit dans le DOM.
  • Au clic sur l’élément a#currentlyViewedProductURL (le lien « Voir la fiche produit »)…
    • …on fait une redirection JS dans la fenêtre parente de l’iFrame (la quickview) qui contient une partie de la fiche produit
    • …et seulement ensuite, on simule le click sur la croix de fermeture de la quickview.

app/design/frontend/Vendor/theme/Magento_Catalog/templates/product/view/product-url.phtml

Bonus:

(inutile pour ce qu’on essaye de faire, mais bon à savoir) Récupérer la première clé d’un objet JSON sans connaître le libellé de cette clé:

Le fichier layout XML:

On s’en sert pour positionner le template PHTML dans la page.

app/design/frontend/Vendor/theme/Magento_Catalog/layout/catalog_product_view.xml

Les styles:

[Magento 2] Mise à jour du prix final dans une fiche produit lorsqu’on vide dynamiquement via javascript une option sous forme de champ texte

Je me suis retrouvé dans un cas extrêmement particulier dans lequel l’utilisateur pouvait, depuis une fiche produit, rajouter des options en cascade: il pouvait en premier lieu choisir une couleur de papier cadeau (+2,00 €).

Une fois le papier cadeau sélectionné (et seulement à cette condition), il pouvait choisir d’ajouter une étiquette avec un prénom (+0,50 €).

Ce champ étiquette était limité à 14 caractères. La fonctionnalité était gérée via un widget remaining-characters.js fourni dans Magento 2.

Problème: lorsque l’utilisateur avait renseigné choisi un papier cadeau et renseigné un prénom, le prix total s’incrémentait de la somme des deux options (+2,00 € +0,50 €). Mais lorsque l’utilisateur décidait finalement de ne pas prendre de papier cadeau en décochant l’option de couleur, seul le prix du papier se décrémentait (-2,00 €) et le prix total comprenait encore celui de l’option étiquette (+0,50 €).

Solution: le plug-in qui compte le nombre de caractères présents dans le champ écoute les événements change keyup paste:

Lorsqu’un utilisateur décoche l’option papier cadeau, on vide l'input text de l’option étiquette avec la méthode .val(''), mais de cette manière le plug-in qui écoute les événements change keyup paste n’a pas « capté » que le champ a été vidé et, de ce fait, ne remet pas le pric total à jour correctement.

Pour lui signifier que le champ a été vidé de manière dynamique, il faut chaîner notre déclaration avec la méthode .trigger() qui contient en argument l’événement change:

Le code complet pour gérer les deux options en cascade

La deuxième contrainte était de faire fonctionner des checkboxes un peu comme des boutons radio (un seul des x checkboxes devait pouvoir être sélectionné à la fois), mais de pouvoir n’en sélectionner aucune.

[Magento 2] Comment inclure et utiliser un fichier JS custom placé dans un thème depuis un template PHTML avec data-mage-init

C’est par ici: [Magento 2] Vérifier qu’un utilisateur client est connecté à son compte et afficher son prénom dans un template PHTML.

Voir aussi: [Magento 2] Comment inclure et utiliser un fichier JS custom avec requireJS.

[Magento 2] Vérifier qu’un utilisateur client est connecté à son compte et afficher son prénom dans un template PHTML

Quelques ressources pour comprendre:

  • Customer Data Management in Magento 2 – récupérer des infos sur le customer en cache (local storage) via l’objet customer déclaré dans le composant JS Magento_Customer/js/view/customer.
  • Sections in Magento 2 – Magento sets customer related data in local storage of browser in key value pair. Each key is known as section. In this post we will see How we can create custom section in our module and use the data in the section in our template file.

Choisissez votre méthode:

Avec javascript (pour afficher le prénom de l’utilisateur)

Source: Magento 2: get customer().lastname in header.phtml (le titre n’étant pas tout-à-fait juste puisqu’on récupère bien le firstName du customer.

Pas besoin de créer un module et de faire de l’injection de dépendances (comme on le voit sur les 36 fils de discussion stack overflow ou sur les 52 blogs qui sont proposés dans les premiers résultats Google…).

Dans votre fichier PHTML, initialisez votre JS sur un élément (span dans mon exemple, mais utilisez l’élément qui vous arrange):

…puis créez un fichier app/design/frontend/VotreVendor/votretheme/web/js/customerGreeting.js et mettez-y ceci:

…et en fait, bin, ça fonctionne 🙂

Pour détecter si l’utilisateur est connecté, créer un Block et le déclarer dans un Layout

app/code/MyVendor/MyModule/Block/ThemeHeader.php:

app/design/frontend/MyVendor/mytheme/Magento_Theme/layout/default.xml:

app/design/frontend/MyVendor/mytheme/Magento_Theme/layout/default.xml:

En en-tête de votre fichier PHTML:

Dans le même fichier PHTML, à l’endroit où vous souhaitez afficher le prénom lorsque l’utilisateur est connecté:

MAUVAISE PRATIQUE La même chose via l'objectManager:

La création du Block et la déclaration de celui-ci dans un Layout comme vu plus haut est inutile si on invoque l'objectManager. Invoquer constamment l’objectManager va poser des problèmes de performances.

En en-tête de votre fichier PHTML:

Vous allez trouver beaucoup de solutions proposant d’utiliser l’objectManager sur le net (stack overflow, autres…). Si elles ne sont pas optimales, elles peuvent quand-même vous apporter une information intéressante à savoir le Model à utiliser si vous souhaitez faire ça bine et créer un Block (dans notre exemple: Magento\Customer\Model\Session. Regardez dans le code du block, plus haut dans ce billet, comment ce Model est déclaré puis exploité).

[javaScript] Exploiter les Mutation Observers pour surveiller la disponibilité d’éléments dans le DOM

Source: Using Mutation Observers to Watch for Element Availability. Code source sous GIT. Version PDF pour la postérité.

[Magento 2] Ajouter le framework Foundation 6 for sites dans un thème et rendre ses widgets javascript disponibles avec RequireJS

Pour ce tuto, nous allons intégrer la version 6.5.3 de Foundation for sites. Le pre-processing des assets se fait avec Webpack et Gulp (contre Grunt dans Magento 2) et les fichiers source sont fournis au format SASS pour les styles et ES5, jQuery (version 3+) pour les javascripts, ce qui les rend inexploitables de base avec Magento 2 (LESS pour les styles et version de jQuery 1.12 pour les javascripts). Nous utiliserons donc les versions déjà compilées (CSS et javascript « vanilla ») qui se trouvent dans le dossier dist du repository Git.

Les styles

Créer un dossier app/design/<Vendor_name>/<theme_name>/web/css/vendor/foundation/ dans lequel nous allons copier/coller l’intégralité des fichiers se trouvant dans le chemin dist/css du Git.

Dans app/design/<Vendor_name>/<theme_name>/web/css/source/_theme.less:

A noter: le code CSS final du framework n’étant pas éclaté en différents fichiers, il faudra probablement que vous ré-éditiez ce fichier pour retirer les styles qui entrent en conflit avec ceux de votre thème. Vous pouvez importer foundation.min.css si vous souhaitez conserver le fichier en l’état.

Les scripts

Joindre l’intégralité des widgets

Solution la plus simple: la version minifiée dans l’intégralité du code JS du framework tient en 171ko.

Créer un dossier app/design/<Vendor_name>/<theme_name>/web/js/vendor/foundation/ dans lequel nous allons copier/coller l’intégralité des fichiers se trouvant dans le chemin dist/js du Git.

Dans app/design/<Vendor_name>/<theme_name>/requirejs-config.js:

Dans un fichier *.phtml (ou *.js pour la partie entre <script />):

Problématiques:

Modifier un paramètre du composant et inclure une chaîne de traduction i18n

Avant d’instancier un nouvel objet, on modifier un ou plusieurs paramètres par défaut. La traduction se fait par la méthode PHP de Magento 2 (et pas par la méthode Javascript).

[Magento 2] Importer les points de rupture CSS LESS pour une exploitation avec javascript jQuery

Source: Importing CSS Breakpoints Into JavaScript (adapté pour Magento 2).

!important: ce tuto demande à créer/modifier un certain nombre de fichiers. Le respect de l’organisation de ces derniers dans l’arborescence de votre thème est capital pour le bon fonctionnement de la fonctionnalité présentée. Vous pourrez bien-sûr modifier les emplacements des fichiers, mais pensez dans ce cas à mettre à jour tous les chemins en conséquence.

L’arborescence utilisée dans le code source fourni est mise à plat plus bas.

Intérêt pour le développeur Magento 2 d’importer les breakpoints LESS pour une exploitation avec javascript?

Magento 2 permet, par le biais de l’outil matchMedia.js, de déclencher du code javascript/jQuery en fonction d’un point de rupture. Extrait de la documentation officielle à ce sujet:

On remarque que la valeur du point de rupture est renseignée de manière statique (768px): media: '(min-width: 768px)'. Ce procédé a ses limites. Le jour où la valeur de ce breakpoint est modifiée dans la feuille de style, il faudra mettre à jour à la main toutes les déclarations faites avec matchMedia.

Le but est donc de rendre dynamique la valeur de media:.

Partie LESS:

Si il n’existe pas encore dans votre thème, créer un dossier app/design/frontend/<Vendor_name>/<theme_name>/web/css/vendor/less-curious/ et y placer, à la racine, l’intégralité des fichiers disponibles sur ce repository Git.

A ce stade, il est surtout important que les fichiers for.less et for-each.less soient accessibles respectivement depuis les chemins suivants:

  • app/design/frontend/<Vendor_name>/<theme_name>/web/css/vendor/less-curious/src/for.less
  • app/design/frontend/<Vendor_name>/<theme_name>/web/css/vendor/less-curious/src/for-each.less
  • Note: le repo Git pouvant disparaître du jour au lendemain, un backup au format ZIP est disponible ici 😉.
  • Note #2: si vous regardez le code source du projet less-curious, vous remarquerez peut-être que ce dernier est déprécié et que l’auteur fournit un lien vers une version plus actuelle, full JS à intégrer avec un pré-processeur comme Grunt. Problème: j’ai eu beau suivre les bonnes pratiques d’intégration d’un plug-in pour grunt-contrib-less dans le système mis en place dans Magento 2, je n’ai rien réussi à compiler… UPDATE (pas testé) 05/11/2019: la solution se situe peut-être dans la mise en place d’une configuration custom de Grunt.

Si il n’existe pas encore dans votre thème, créer un dossier app/design/frontend/<Vendor_name>/<theme_name>/web/css/source/devtools/.

Créer le fichier app/design/frontend/<Vendor_name>/<theme_name>/web/css/source/devtools/_js-mediaqueries.less et placez-y le code ci-dessous:

Dans le fichier app/design/frontend/<Vendor_name>/<theme_name>/web/css/source/_theme.less, ajouter la ligne suivante JUSTE EN-DESSOUS des potentielles surcharges que vous avez faites des variables pré-déclarées dans le(s) thème(s) parent(s) dont votre thème va hériter:

Partie JS:

Créer le fichier app/design/frontend/<Vendor_name>/<theme_name>/web/js/js-mediaqueries.js:

Créer ou adapter le fichier app/design/frontend/<Vendor_name>/<theme_name>/requirejs-config.js:

Partie XML:

Créer le fichier app/design/frontend/<Vendor_name>/<theme_name>/Magento_Theme/layout/default_head_blocks.xml:

Note: si ce fichier existe déjà dans votre thème, ajouter simplement la ligne <script src="js/js-mediaqueries.js" /> entre les balises <head>.

Commandes à exécuter en bash:

  • Un cache:clean
  • $ rm -rf pub/static/*; rm -rf var/view_preprocessed/*

Un process Grunt doit tourner ou une compilation des assets front-end via une commande Magento doit être faite.

Arborescence complète, selon les fichiers de ce tuto:

  • app/design/frontend/[Vendor_name]/[theme_name]/
    • Magento_Theme/
      • layout/
        • default_head_blocks.xml
    • web/
      • css/
        • source/
          • devtools/
            • _js-mediaqueries.less
          • vendor/
            • less-curious/
              • src/
                • for.less
                • for-each.less
          • _theme.less
      • js/
        • js-mediaqueries.js
    • requirejs-config.js

[Magento 2] Exploiter matchMedia pour passer des paramètres différents à un widget javascript en fonction du breakpoint

Ressources en ligne:

Attention: en work-in-progress… Au chargement de la page, selon qu’on soit en vue Mobile ou Desktop, les paramètres correspondants sont bien pris en compte mais il reste encore pas mal de soucis.

Doc officielle de Magento 2 relative à l’utilisation de matchMedia: JavaScript in Magento responsive design.

Fichier du core de Magento 2 à étudier: lib/web/mage/menu.js qui exploite matchMedia via l’alias mediaCheck et la brique $.ui.menu de jQueryUI.

Ressources externes, documentation…

TODOs

  • lorsqu’on change de breakpoint sans recharger la page, les paramètres du widget ne sont pas mis à jour pour la nouvelle vue correspondante (voir pour une méthode destroy ou (mieux) refresh (edit: refresh semble ne pas vouloir fonctionner avec Magento 2).
  • la fonction bindAccordion ne permet pas l’ajout de méthodes ou d’événements (edit: j’ai dégagé la fonction)
  • cherry on the cake: le breakpoint courant devrait être détecté automatiquement (changement après chargement de page compris)

Mise en place:

\app\design\frontend\<Vendor_name>\<theme_name>\web\js\accordion-config.js

\app\design\frontend\<Vendor_name>\<theme_name>\requirejs-config.js

\app\design\frontend\<Vendor_name>\<theme_name>\Magento_LayeredNavigation\templates\layer\view.phtml


HTML

JS

[Magento 2] Utiliser des media queries, points de rupture, en LESS (CSS) et en javascript avec matchMedia

Exploiter les media queries dans les fichiers styles LESS (CSS)

Variables de breakpoints

Les surcharges de valeurs de breakpoints existants (déjà déclarés dans un thème parent) se font dans le fichier _theme.less de votre thème enfant.

Utilisation des mixins .media-width fournis par Magento 2 et code compilé

Les fichiers CSS styles-m.less et styles-l.less sont auto-générés par Magento 2 lors de la compilation des fichiers *.less. Il ne faut PAS les recréer à la main dans vos thèmes enfants. Si on respecte les bonnes pratiques de déclaration des media-queries dictées par la doc officielle, on peut déclarer autant de fois qu’on veut un même breakpoint dans nos sources *.less et toutes nos déclarations seront regroupées sous une seule dans les fichiers *.css finaux. Exemple:

Avoir recours aux media queries dans les fichiers JS avec matchMedia

Doc officielle – JavaScript in Magento responsive design.

Utiliser matchMedia directement dans une vue *.phtml

Le code ci-dessous affiche une bordure rose sur les écrans de Mobile (dont la résolution est inférieure à 768px) et bleue sur les écrans dont la résolution est plus large.

Utiliser matchMedia depuis un fichier *.js

Attention: de part la nature « protectrice » de requireJS, le code encapsulé dans votre fichier Js ne sera pris en compte qu’après avoir été déclaré dans une vue *.phtml ou (mauvaise pratique) dans un JS inclus à l’arrache (dans app\design\frontend\<Vendor_name>\<theme_name>\Magento_Theme\layout\default_head_blocks.xml par exemple) et non-contrôlé par requireJS.

Dans mon exemple, je crée un fichier app\design\frontend\<Vendor_name>\<theme_name>\web\js\mediaqueries.js:

Attention, à retenir: il faut bien encapsuler le code qui doit être exécuté au chargement de la page dans une fonction anonyme $(function(){ // mon code ici... });. Sinon, pas d’exécution. C’est du jQuery 😉

Dans le fichier app\design\frontend\<Vendor_name>\<theme_name>\requirejs-config.js, je déclare mon nouveau fichier mediaqueries.js et je le rends disponible pour requireJS:

Dans un fichier *.phtml, je fais exécuter le code se trouvant dans le fichier mediaqueries.js:

[Magento 2] Exploiter le widget javascript jQuery natif Accordion dans le fichier PHTML des filtres produit (page category)

Note: ce widget Accordion fait partie d’une collection étendue de widgets fournis de base par Magento 2 (à ne pas confondre avec la bibliothèque UI Magento 2, fournie de base également, et qu’il convient de connaître aussi.

Pour ce tuto, nous allons afficher les différentes familles de tri produits (catégorie, taille, activity, color, erin recommends, genre, material, nouveau, prix, etc…) sous forme d’accordéons. De base, ils s’affichent tous ouverts, y-compris en vue Mobile ce qui force l’utilisateur à scroller bas dans la page avant de voir apparaître le premier produit. Le fonctionnalités voulues pour ce accordéon:

  • tous les accordéons (différentes familles de tri) sont ouverts au chargement de la page
  • plusieurs accordéons peuvent rester ouverts simultanément

(Note pour plus tard: il peut être intéressant, dans le cadre de la découverte des media-queries côté JS, d’initialiser ce widget avec des options différentes en fonction de l’affichage mobile/desktop).

A noter: il existe plusieurs méthodes pour initialiser du code javascript dans une vue dans Magento 2. Nous allons nous concentrer sur deux d’entre-elles qui ne sont ni meilleures, ni moins bonnes que les autres.

Imperative notation

En initialisant notre widget directement dans un fichier *.phtml, entre balises <script type="text/javascript">.

Commencer par éditer le fichier *.phtml app\design\frontend\<Vendor_name>\<theme_name>\Magento_LayeredNavigation\templates\layer\view.phtml qui constitue la base de la vue des différents filtres. Notez bien l’ajout, par rapport à la vue que nous surchargeons, des attributs data-role="collapsible", data-role="trigger" et data-role="content" respectivement placés sur les éléments dt, a et dd, ainsi que de la classe filter-options-collapsible-trigger placée sur le nouvellement ajouté élément a.

Le widget s’initialise ensuite comme suit avec requireJS (code placé dans le même fichier view.phtml, immédiatement après la ligne <?php if ($block->canShowBlock()): ?>):

Declarative notation

Le widget va s’initialiser sans avoir recours à un require déclaré dans une balise <script />, par de biais d’un attribut data-mage-init placé directement sur l’élément à partir duquel nous venons précédemment d’initialiser notre widget à la manière de jQuery.

Dans les deux cas on n’oublie pas de lancer un cache:clean en console!

© 2020 FrontEndDeveloper

Theme by Anders NorénUp ↑