define([
'jquery',
'jquery-ui-modules/widget',
'Magento_ConfigurableProduct/js/configurable',
'slick'
], function($, configurable) {
'use strict';
let ATTRIBUTE_SELECTOR_ELEMENT_ID, // Peut être un ID de <select> ou de <ul> (carousel)
SELECTED_OPTION_INDEX; // Index de l'option sélectionnée par l'utilisateur dans un <select> ou un <ul> (carousel)
$.widget('mage.attributeCarousel', {
options: {
attributeSelectorId: '[id^="attribute"]',
slick: {
infinite: false,
slidesToShow: 3,
slidesToScroll: 3,
prevArrow: '<button type="button" class="clear slick-prev"><svg viewBox="0 0 100 100" class="icon icon-arrow-back-chevron"><use xlink:href="#icon-arrow-back-chevron"></use></svg></button>',
nextArrow: '<button type="button" class="clear slick-next"><svg viewBox="0 0 100 100" class="icon icon-arrow-forward-chevron"><use xlink:href="#icon-arrow-forward-chevron"></use></svg></button>'
}
},
_create: function () {
const $_THIS = $(this.options.attributeSelectorId),
that = this;
// 1. On clone le <select>
// 2. On le transforme en <ul>/<li>
// 3. On initialise le carousel sur le markup du <select> cloné et transformé en <ul>/<li>
// 4. On injecte le carousel dans le DOM
that.appendCarouselToDOM($_THIS, that.ulToCarousel(that.clonedSelectToUl(that.cloneSelect($_THIS))));
// Lorsqu'on change la valeur d'un attribut produit depuis le carousel
$('.slick-slide').on('click', function () {
const $_THIS = $(this);
// Mise à jour de:
ATTRIBUTE_SELECTOR_ELEMENT_ID = $_THIS.closest('ul').attr('id');
SELECTED_OPTION_INDEX = $_THIS.attr('data-slick-index');
that.synchronizeCarouselWithSelect(ATTRIBUTE_SELECTOR_ELEMENT_ID, SELECTED_OPTION_INDEX);
that.handleCarouselSelectedOptionClass(ATTRIBUTE_SELECTOR_ELEMENT_ID, SELECTED_OPTION_INDEX);
});
// Lorsqu'on change la valeur d'un attribut produit depuis le select
$_THIS.on('change', function () {
// Mise à jour de:
ATTRIBUTE_SELECTOR_ELEMENT_ID = $_THIS.attr('id');
SELECTED_OPTION_INDEX = $_THIS.prop('selectedIndex');
that.synchronizeSelectWithCarousel(ATTRIBUTE_SELECTOR_ELEMENT_ID, SELECTED_OPTION_INDEX);
that.handleCarouselSelectedOptionClass(ATTRIBUTE_SELECTOR_ELEMENT_ID, SELECTED_OPTION_INDEX);
});
},
// 1. On clone le <select>, sous conditions...
cloneSelect: function(thisObj) {
const $_THIS = thisObj,
$_THIS_ID = $_THIS.attr('id');
// Vérifier si le select est [disabled] ou si il a déjà été cloné
// [TODO_DEV] Rajouter une condition qui vérifie si les options du select affichent des images. Si false, on ne créera pas de carousel pour ce champ.
if ($_THIS.attr('disabled') || $('ul#' + $_THIS_ID).length) {
// Si l'un des deux cas est true, on ne fait rien
return false;
} else {
// Sinon
return $_THIS.clone().prop('id', $_THIS_ID);
}
},
// 2. On transforme le <select> cloné en <ul>/<li>
clonedSelectToUl: function(clonedSelect) {
const $_CLONED_SELECT = $(clonedSelect);
return $_CLONED_SELECT.find("option").map(function() {
const $_THIS = $(this);
return $("<li>").attr("value", $_THIS.attr("value")).text($_THIS.text()).get();
}).appendTo($("<ul>").attr({
id: $_CLONED_SELECT.attr("id"),
name: $_CLONED_SELECT.attr("name")
})).parent().replaceAll($_CLONED_SELECT);
},
// 3. On initialise le carousel (slick) sur le markup du <select> cloné et transformé en <ul>/<li>
ulToCarousel: function(clonedSelectToUl) {
return clonedSelectToUl.slick({
infinite: this.options.slick.infinite,
slidesToShow: this.options.slick.slidesToShow,
slidesToScroll: this.options.slick.slidesToScroll,
prevArrow: this.options.slick.prevArrow,
nextArrow: this.options.slick.nextArrow
});
},
// 4. On injecte le carousel dans le DOM
appendCarouselToDOM: function(thisObj, carouselElement) {
return carouselElement.insertBefore(thisObj);
},
// On gère la classe CSS sur l'option sélectionnée par l'utilisateur dans le carousel
handleCarouselSelectedOptionClass: function(relatedElementID, selectedOptionIndex) {
$('ul#' + relatedElementID).find('.is-selected-option').removeClass('is-selected-option');
$('[data-slick-index="' + selectedOptionIndex + '"]', 'ul#' + relatedElementID).addClass('is-selected-option');
},
// Synchronization slick>select (select2 se gère tout seul)
synchronizeCarouselWithSelect: function(relatedElementID, selectedOptionIndex) {
const SELECTED_OPTION_VALUE = $('option', 'select#' + relatedElementID).eq(selectedOptionIndex).attr('value');
$('select#' + relatedElementID).val(SELECTED_OPTION_VALUE).trigger('change');
},
// synchronization select>slick (select2 se gère toujours encore tout seul :))
synchronizeSelectWithCarousel: function(relatedElementID, selectedOptionIndex) {
$('ul#' + relatedElementID).slick('slickGoTo', parseInt(selectedOptionIndex));
// https://github.com/kenwheeler/slick/issues/235#issuecomment-43406956
$(window).trigger('resize');
}
});
return $.mage.attributeCarousel;
});
// https://www.siphor.com/different-ways-using-javascript-magento-2/
// https://jason.codes/2019/06/magento-2-create-jquery-ui-widget/