document.addEventListener('DOMContentLoaded', function () {
var wrap = document.querySelector('.wapf-wrapper');
if (wrap && !wrap.classList.contains('flycase-init-loading')) {
wrap.classList.add('flycase-init-loading');
}
});
jQuery(document).ready(function($) {
// ====================================================================
// ⚙️ MOTEUR PRINCIPAL DU CONFIGURATEUR
// ====================================================================
function initFlycaseConfigurator() {
// 1. MISE À JOUR DU TITRE DE LA MATIÈRE
function updateMaterialTitle() {
var $selected = $('input[name="wapf[field_69943ac28ddfa]"]:checked');
if ($selected.length > 0) {
var materialName = $selected.attr('data-wapf-label');
if(materialName) {
materialName = materialName.replace(/\.\.\./g, '').replace(/\*/g, '').trim();
$('.wapf-field-label.wapf--above label').first().html(
'Choix de la matière : ' + materialName + ''
);
}
}
}
updateMaterialTitle();
$(document).off('change', 'input[name="wapf[field_69943ac28ddfa]"]').on('change', 'input[name="wapf[field_69943ac28ddfa]"]', updateMaterialTitle);
$(document).off('click', '.wapf-swatch.wapf-swatch--color').on('click', '.wapf-swatch.wapf-swatch--color', function() {
setTimeout(updateMaterialTitle, 50); // Laisse le plugin cocher l'input caché
});
// 2. NETTOYER LES LABELS
$('.wapf-field-label label').each(function() {
var text = $(this).text();
text = text.replace(/\.\.\./g, '').replace(/\.\./g, '').replace(/\*/g, '').trim();
$(this).text(text);
});
// 3. CRÉATION ET GESTION DES ACCORDÉONS
var $allSeparators = $('.section-separator');
if ($('.flycase-accordion-header').length === 0) { // Évite de les recréer en double
$allSeparators.each(function(index) {
var $separator = $(this);
var title = $separator.find('h3').text().trim() || $separator.text().trim();
if (!title) return;
var stepNumber = index + 1;
var $header = $('
' + title + '
');
var $fields;
if (index === $allSeparators.length - 1) {
$fields = $separator.nextAll('.wapf-field-container');
} else {
$fields = $separator.nextUntil('.section-separator');
}
if ($fields.length === 0) return;
$fields.wrapAll('');
$separator.replaceWith($header);
var $content = $header.next('.flycase-accordion-content');
$content.hide();
// On ne met QUE active-step au premier, on ne l'ouvre pas
if (index === 0) {
$header.addClass('active-step');
}
// Clic manuel sur l'accordéon
$header.on('click', function() {
var $this = $(this);
if (!$this.hasClass('active-step') && !$this.hasClass('completed-step')) {
return;
}
var $thisContent = $this.next('.flycase-accordion-content');
var isOpen = $this.hasClass('active');
if (isOpen) {
$this.removeClass('active');
$thisContent.slideUp(300);
} else {
$('.flycase-accordion-header').removeClass('active');
$('.flycase-accordion-content').slideUp(300);
$this.addClass('active');
$thisContent.slideDown(300);
setTimeout(function() {
// Si l'écran est petit (mobile), on ne laisse que 15px de marge au-dessus, sinon 100px sur PC
var scrollOffset = $(window).width() 0 ||
$field.find('[required]').length > 0 ||
$field.find('[data-is-required="1"]').length > 0;
if (isRequired) {
var isChecked = $field.find('input:checked').length > 0;
var hasValue = $field.find('select').val() || $field.find('input[type="text"]').val();
var hasSwatchChecked = $field.find('.wapf-checked').length > 0;
if (!isChecked && !hasValue && !hasSwatchChecked) {
allFilled = false;
return false;
}
}
});
return allFilled;
} // 👈 VOICI L'ACCOLADE QUI MANQUAIT !
function moveToNextAccordion($currentHeader) {
var $nextHeader = $currentHeader.nextAll('.flycase-accordion-header').first();
if ($nextHeader.length > 0) {
// 1. On lance les animations de fermeture/ouverture (qui durent 300ms)
$currentHeader.removeClass('active-step active').addClass('completed-step');
$currentHeader.next('.flycase-accordion-content').slideUp(300);
$nextHeader.addClass('active-step active');
$nextHeader.next('.flycase-accordion-content').slideDown(300);
// 2. 👇 LA CORRECTION : On attend 320ms que les boîtes aient fini de bouger
// pour calculer la vraie position finale de l'accordéon cible.
setTimeout(function() {
var scrollOffset = $(window).width() 0 ||
$field.find('[required]').length > 0 ||
$field.find('[data-is-required="1"]').length > 0;
if (isRequired) {
var isChecked = $field.find('input:checked').length > 0;
var hasValue = $field.find('select').val() || $field.find('input[type="text"]').val();
var hasSwatchChecked = $field.find('.wapf-checked').length > 0;
$field.find('.wapf-error-message').remove();
$field.removeClass('wapf--invalid');
// Si c'est obligatoire MAIS vide
if (!isChecked && !hasValue && !hasSwatchChecked) {
hasError = true;
var fieldLabel = $field.find('.wapf-field-label label').text().trim() || "ce champ";
var errorMsg = '
Veuillez sélectionner une option pour : ' + fieldLabel + '
';
$field.addClass('wapf--invalid');
if($field.find('.wapf-swatch-wrapper').length > 0) {
$field.find('.wapf-swatch-wrapper').after(errorMsg);
} else {
$field.find('.wapf-field-input').after(errorMsg);
}
// On force l'ouverture de l'accordéon qui contient l'erreur pour que le client le voie
var $accordionContent = $field.closest('.flycase-accordion-content');
var $accordionHeader = $accordionContent.prev('.flycase-accordion-header');
if ($accordionContent.length > 0 && !$accordionContent.is(':visible')) {
$('.flycase-accordion-header').removeClass('active');
$('.flycase-accordion-content').hide();
$accordionHeader.addClass('active');
$accordionContent.show();
}
}
}
});
// S'IL Y A LA MOINDRE ERREUR, ON COUPE TOUT :
if (hasError) {
e.preventDefault(); // Bloque l'action par défaut
e.stopImmediatePropagation(); // 👈 L'ARME FATALE : Bloque WooCommerce et WAPF
setTimeout(function() {
$('html, body').animate({
scrollTop: $('.wapf--invalid').first().offset().top - 150
}, 500);
}, 100);
return false; // Double sécurité
}
});
// 5. BIS : On bloque aussi la soumission globale du formulaire au cas où le client tape sur "Entrée"
$('form.cart').on('submit', function(e) {
if ($('.wapf--invalid').length > 0) {
e.preventDefault();
e.stopImmediatePropagation();
return false;
}
});
// 6. BOUTON RECOMMENCER (Version propre - Hard Reset)
// On compte combien d'options avancées WAPF sont présentes sur ce produit
var nbOptionsWapf = $('.wapf-field-container').length;
// On affiche le bouton UNIQUEMENT si c'est un configurateur avec PLUS DE 2 options (donc 3 ou plus)
if (nbOptionsWapf > 2) {
if ($('.wapf-reset-button').length === 0) {
var $totalSection = $('*:contains("Total du produit")').filter(function() {
return $(this).children().length === 0 && $(this).text().trim() === 'Total du produit';
}).first().parent();
if ($totalSection.length > 0) {
$totalSection.before(
''
);
}
}
$(document).off('click', '.wapf-reset-button').on('click', '.wapf-reset-button', function() {
if (confirm('Êtes-vous sûr de vouloir recommencer ? Toutes vos sélections seront effacées.')) {
window.location.reload();
}
});
}
// 7. APPARITION FINALE INSTANTANÉE
$('.wapf-wrapper').addClass('flycase-ready').removeClass('flycase-init-loading');
}
// ====================================================================
// 📡 LE RADAR : SE DÉCLENCHE DÈS QUE LE PLUGIN EST PRÊT (Toutes les 50ms)
// ====================================================================
var checkWapfReady = setInterval(function() {
if ($('.section-separator').length > 0 || $('.wapf-wrapper').length > 0) {
clearInterval(checkWapfReady); // On coupe le radar
initFlycaseConfigurator(); // On lance le moteur instantanément
}
}, 50);
// Sécurité : au bout de 4 secondes, on force l'affichage pour éviter un écran blanc
setTimeout(function() {
clearInterval(checkWapfReady);
$('.wapf-wrapper').addClass('flycase-ready');
}, 4000);
});
Pour offrir les meilleures expériences, nous utilisons des technologies telles que les cookies pour stocker et/ou accéder aux informations des appareils. Le fait de consentir à ces technologies nous permettra de traiter des données telles que le comportement de navigation ou les ID uniques sur ce site. Le fait de ne pas consentir ou de retirer son consentement peut avoir un effet négatif sur certaines caractéristiques et fonctions.
Fonctionnel
Toujours activé
Le stockage ou l’accès technique est strictement nécessaire dans la finalité d’intérêt légitime de permettre l’utilisation d’un service spécifique explicitement demandé par l’abonné ou l’utilisateur, ou dans le seul but d’effectuer la transmission d’une communication sur un réseau de communications électroniques.
Préférences
Le stockage ou l’accès technique est nécessaire dans la finalité d’intérêt légitime de stocker des préférences qui ne sont pas demandées par l’abonné ou l’utilisateur.
Statistiques
Le stockage ou l’accès technique qui est utilisé exclusivement à des fins statistiques.Le stockage ou l’accès technique qui est utilisé exclusivement dans des finalités statistiques anonymes. En l’absence d’une assignation à comparaître, d’une conformité volontaire de la part de votre fournisseur d’accès à internet ou d’enregistrements supplémentaires provenant d’une tierce partie, les informations stockées ou extraites à cette seule fin ne peuvent généralement pas être utilisées pour vous identifier.
Marketing
Le stockage ou l’accès technique est nécessaire pour créer des profils d’utilisateurs afin d’envoyer des publicités, ou pour suivre l’utilisateur sur un site web ou sur plusieurs sites web ayant des finalités marketing similaires.