Pour VELO49, nous avons développé un configurateur de vélos sur mesure, offrant une expérience client interactive et personnalisée.
document.addEventListener('DOMContentLoaded', function() {
// Attendre que tous les éléments soient chargés
setTimeout(function() {
// Fonction pour récupérer la valeur sélectionnée d'un bouton radio
function getRadioValue(containerId) {
const container = document.getElementById(containerId);
if (!container) {
return '';
}
// Rechercher les boutons radio dans le conteneur
const checkedRadio = container.querySelector('input[type="radio"]:checked');
if (!checkedRadio) {
return '';
}
// Récupérer le label associé au bouton radio
const radioId = checkedRadio.id;
const label = document.querySelector('label[for="' + radioId + '"]');
if (label) {
return label.textContent.trim();
}
// Si on ne trouve pas le label avec for, essayons de le trouver autrement
const parentItem = checkedRadio.closest('.ue-radio-buttons-item');
if (parentItem) {
const labelInParent = parentItem.querySelector('.ue-radio-buttons-item-label');
if (labelInParent) {
return labelInParent.textContent.trim();
}
}
// Si tout échoue, retourner la valeur du bouton radio
return checkedRadio.value || '';
}
// Ajout de l'écouteur d'événement pour le modeleContainer
const modeleContainer = document.querySelector('#modeleContainer');
if (modeleContainer) {
modeleContainer.addEventListener('click', function () {
// Réinitialiser le dropdown
const dropdown = document.querySelector('.ue-dropdown-field-select');
if (dropdown) {
dropdown.selectedIndex = 0;
}
// Cacher le message d'avertissement
const warningMessage = document.querySelector('.warning-message');
if (warningMessage) {
warningMessage.style.display = 'none';
}
// Mettre à jour les champs cachés après la réinitialisation
setTimeout(updateHiddenFields, 100);
});
}
// Fonction améliorée pour récupérer la valeur sélectionnée d'un dropdown
function getDropdownValue(containerId) {
const container = document.getElementById(containerId);
if (!container || container.offsetParent === null) {
return ''; // Le dropdown n'est pas visible
}
const select = container.querySelector('select');
if (select && select.options && select.selectedIndex >= 0) {
return select.options[select.selectedIndex].text;
}
return '';
}
// Fonction pour récupérer la valeur d'un slider
function getSliderValue(containerId) {
// L'ID du slider est différent de l'ID du conteneur
const sliderId = 'ue-range-slider-field_' + containerId;
const slider = document.getElementById(sliderId);
if (slider) {
return slider.value;
}
// Si on ne trouve pas le slider avec l'ID construit, essayons de trouver le conteneur
const container = document.getElementById(containerId);
if (container) {
// Chercher l'input de type range dans le conteneur
const sliderInContainer = container.querySelector('input[type="range"]');
if (sliderInContainer) {
return sliderInContainer.value;
}
// Chercher l'affichage de la valeur
const valueDisplay = container.querySelector('.ue-range-slider-current-value');
if (valueDisplay) {
return valueDisplay.textContent.trim();
}
}
return '';
}
// Fonction pour récupérer les accessoires sélectionnés
function getAccessoires(containerId) {
const container = document.getElementById(containerId);
if (!container) {
return [];
}
const accessoires = [];
const checkedItems = container.querySelectorAll('input[type="checkbox"]:checked, input[type="radio"]:checked');
checkedItems.forEach(function(item) {
const radioId = item.id;
const label = document.querySelector('label[for="' + radioId + '"]');
if (label) {
accessoires.push(label.textContent.trim());
} else {
// Essayer de trouver le label autrement
const parentItem = item.closest('.ue-radio-buttons-item');
if (parentItem) {
const labelInParent = parentItem.querySelector('.ue-radio-buttons-item-label');
if (labelInParent) {
accessoires.push(labelInParent.textContent.trim());
}
}
}
});
return accessoires;
}
// Fonction pour calculer le prix total en fonction des valeurs des champs
function calculerPrixTotal(modeleContainerId, montageContainerId, accessoiresContainerId) {
let prixTotal = 0;
// Récupérer le prix du modèle sélectionné
const modeleContainer = document.getElementById(modeleContainerId);
if (modeleContainer) {
const modeleRadio = modeleContainer.querySelector('input[type="radio"]:checked');
if (modeleRadio) {
const prixModele = parseInt(modeleRadio.value, 10) || 0;
prixTotal += prixModele;
}
}
// Récupérer le prix du montage sélectionné
const montageContainer = document.getElementById(montageContainerId);
if (montageContainer) {
const montageRadio = montageContainer.querySelector('input[type="radio"]:checked');
if (montageRadio) {
const prixMontage = parseInt(montageRadio.value, 10) || 0;
prixTotal += prixMontage;
}
}
// Récupérer le prix des accessoires sélectionnés
const accessoiresContainer = document.getElementById(accessoiresContainerId);
if (accessoiresContainer) {
const accessoiresChecked = accessoiresContainer.querySelectorAll('input[type="checkbox"]:checked, input[type="radio"]:checked');
accessoiresChecked.forEach(function(accessoire) {
const prixAccessoire = parseInt(accessoire.value, 10) || 0;
prixTotal += prixAccessoire;
});
}
return prixTotal;
}
// Fonction pour calculer les mensualités
function calculerMensualites(modeleContainerId, montageContainerId, accessoiresContainerId, dureeContainerId, acompteContainerId) {
let prixTotal = 0;
// Récupérer le prix du modèle sélectionné
const modeleContainer = document.getElementById(modeleContainerId);
if (modeleContainer) {
const modeleRadio = modeleContainer.querySelector('input[type="radio"]:checked');
if (modeleRadio) {
const prixModele = parseInt(modeleRadio.value, 10) || 0;
prixTotal += prixModele;
}
}
// Récupérer le prix du montage sélectionné
const montageContainer = document.getElementById(montageContainerId);
if (montageContainer) {
const montageRadio = montageContainer.querySelector('input[type="radio"]:checked');
if (montageRadio) {
const prixMontage = parseInt(montageRadio.value, 10) || 0;
prixTotal += prixMontage;
}
}
// Récupérer le prix des accessoires sélectionnés
const accessoiresContainer = document.getElementById(accessoiresContainerId);
if (accessoiresContainer) {
const accessoiresChecked = accessoiresContainer.querySelectorAll('input[type="checkbox"]:checked, input[type="radio"]:checked');
accessoiresChecked.forEach(function(accessoire) {
const prixAccessoire = parseInt(accessoire.value, 10) || 0;
prixTotal += prixAccessoire;
});
}
// Récupérer l'acompte
const acompteValue = getSliderValue(acompteContainerId);
// Soustraire l'acompte du prix total
prixTotal -= parseInt(acompteValue, 10) || 0;
// Récupérer le nombre de mensualités
const nombreMensualites = parseInt(getDropdownValue(dureeContainerId), 10) || 1;
// Calcul des mensualités
return (prixTotal / nombreMensualites).toFixed(2);
}
// Fonction pour mettre à jour les champs cachés
function updateHiddenFields() {
// Urbain 2
if (document.getElementById('section-urbain-2') && !document.getElementById('section-urbain-2').classList.contains('masque')) {
document.getElementById('form-field-couleur_urbain_2').value = getRadioValue('uc_radio_button_elementor_3140943d') || 'URBAIN 2';
// Récupération des textes sélectionnés des deux champs dropdown pour la taille
var taille1 = getDropdownValue('uc_dropdown_field_custom_elementor_63a6c34');
var taille2 = getDropdownValue('uc_dropdown_field_custom_elementor_4a3250f');
document.getElementById('form-field-taille_urbain_2').value = taille1 + ' ' + taille2;
document.getElementById('form-field-montage_urbain_2').value = getRadioValue('uc_radio_button_elementor_2a71e2c1');
document.getElementById('form-field-accessoires_urbain_2').value = getAccessoires('uc_radio_button_copy_elementor_545db38c').join(', ');
document.getElementById('form-field-duree_urbain_2').value = getDropdownValue('uc_dropdown_field_elementor_9cfa385');
document.getElementById('form-field-acompte_urbain_2').value = getSliderValue('uc_range_slider_elementor_6dd48af6');
document.getElementById('form-field-prix_urbain_2').value = calculerPrixTotal(
'uc_radio_button_elementor_3140943d',
'uc_radio_button_elementor_2a71e2c1',
'uc_radio_button_copy_elementor_545db38c'
);
const mensualitesUrbain2 = calculerMensualites(
'uc_radio_button_elementor_3140943d',
'uc_radio_button_elementor_2a71e2c1',
'uc_radio_button_copy_elementor_545db38c',
'uc_dropdown_field_elementor_9cfa385',
'uc_range_slider_elementor_6dd48af6'
);
document.getElementById('form-field-mensualites_urbain_2').value = mensualitesUrbain2;
}
// Sport 2
if (document.getElementById('section-sport-2') && !document.getElementById('section-sport-2').classList.contains('masque')) {
document.getElementById('form-field-couleur_sport_2').value = getRadioValue('uc_radio_button_elementor_28b4303d') || 'SPORT 2';
// Récupération des textes sélectionnés des deux champs dropdown pour la taille
var taille1 = getDropdownValue('uc_dropdown_field_custom_elementor_ad26ab9');
var taille2 = getDropdownValue('uc_dropdown_field_custom_elementor_2b0edb1');
document.getElementById('form-field-taille_sport_2').value = taille1 + ' ' + taille2;
document.getElementById('form-field-montage_sport_2').value = getRadioValue('uc_radio_button_elementor_29bf0430');
document.getElementById('form-field-accessoires_sport_2').value = getAccessoires('uc_radio_button_copy_elementor_2e6a56af').join(', ');
document.getElementById('form-field-duree_sport_2').value = getDropdownValue('uc_dropdown_field_elementor_6a89e12');
document.getElementById('form-field-acompte_sport_2').value = getSliderValue('uc_range_slider_elementor_77619a36');
document.getElementById('form-field-prix_sport_2').value = calculerPrixTotal(
'uc_radio_button_elementor_28b4303d',
'uc_radio_button_elementor_29bf0430',
'uc_radio_button_copy_elementor_2e6a56af'
);
const mensualitesSport2 = calculerMensualites(
'uc_radio_button_elementor_28b4303d',
'uc_radio_button_elementor_29bf0430',
'uc_radio_button_copy_elementor_2e6a56af',
'uc_dropdown_field_elementor_6a89e12',
'uc_range_slider_elementor_77619a36'
);
document.getElementById('form-field-mensualites_sport_2').value = mensualitesSport2;
}
// Sport +
if (document.getElementById('section-sport-plus') && !document.getElementById('section-sport-plus').classList.contains('masque')) {
document.getElementById('form-field-couleur_sport_plus').value = getRadioValue('uc_radio_button_elementor_4e9d99a3') || 'SPORT +';
// Récupération des textes sélectionnés des deux champs dropdown pour la taille
var taille1 = getDropdownValue('uc_dropdown_field_custom_elementor_3451541');
var taille2 = getDropdownValue('uc_dropdown_field_custom_elementor_639a576');
document.getElementById('form-field-taille_sport_plus').value = taille1 + ' ' + taille2;
document.getElementById('form-field-montage_sport_plus').value = getRadioValue('uc_radio_button_elementor_70d214e7');
document.getElementById('form-field-accessoires_sport_plus').value = getAccessoires('uc_radio_button_copy_elementor_50cab6aa').join(', ');
document.getElementById('form-field-duree_sport_plus').value = getDropdownValue('uc_dropdown_field_elementor_44f37672');
document.getElementById('form-field-acompte_sport_plus').value = getSliderValue('uc_range_slider_elementor_4a583e09');
document.getElementById('form-field-prix_sport_plus').value = calculerPrixTotal(
'uc_radio_button_elementor_4e9d99a3',
'uc_radio_button_elementor_70d214e7',
'uc_radio_button_copy_elementor_50cab6aa'
);
const mensualitesSportPlus = calculerMensualites(
'uc_radio_button_elementor_4e9d99a3',
'uc_radio_button_elementor_70d214e7',
'uc_radio_button_copy_elementor_50cab6aa',
'uc_dropdown_field_elementor_44f37672',
'uc_range_slider_elementor_4a583e09'
);
document.getElementById('form-field-mensualites_sport_plus').value = mensualitesSportPlus;
}
}
// Ajouter des écouteurs d'événements pour tous les éléments interactifs
function addEventListeners() {
// Liste des conteneurs à surveiller
const containers = [
// Urbain 2
'uc_radio_button_elementor_3140943d',
'uc_dropdown_field_custom_elementor_63a6c34',
'uc_dropdown_field_custom_elementor_4a3250f',
'uc_radio_button_elementor_2a71e2c1',
'uc_radio_button_copy_elementor_545db38c',
'uc_dropdown_field_elementor_9cfa385',
'uc_range_slider_elementor_6dd48af6',
// Sport 2
'uc_radio_button_elementor_28b4303d',
'uc_dropdown_field_custom_elementor_ad26ab9',
'uc_dropdown_field_custom_elementor_2b0edb1',
'uc_radio_button_elementor_29bf0430',
'uc_radio_button_copy_elementor_2e6a56af',
'uc_dropdown_field_elementor_6a89e12',
'uc_range_slider_elementor_77619a36',
// Sport +
'uc_radio_button_elementor_4e9d99a3',
'uc_dropdown_field_custom_elementor_3451541',
'uc_dropdown_field_custom_elementor_639a576',
'uc_radio_button_elementor_70d214e7',
'uc_radio_button_copy_elementor_50cab6aa',
'uc_dropdown_field_elementor_44f37672',
'uc_range_slider_elementor_4a583e09'
];
// Ajouter des écouteurs à tous les conteneurs
containers.forEach(function(id) {
const container = document.getElementById(id);
if (container) {
const inputs = container.querySelectorAll('input, select');
inputs.forEach(function(input) {
input.addEventListener('change', function() {
setTimeout(updateHiddenFields, 100);
});
});
container.addEventListener('click', function() {
setTimeout(updateHiddenFields, 100);
});
}
});
// Ajouter des écouteurs spécifiques pour les sliders
const sliders = [
'ue-range-slider-field_uc_range_slider_elementor_6dd48af6',
'ue-range-slider-field_uc_range_slider_elementor_77619a36',
'ue-range-slider-field_uc_range_slider_elementor_4a583e09'
];
sliders.forEach(function(id) {
const slider = document.getElementById(id);
if (slider) {
slider.addEventListener('input', function() {
setTimeout(updateHiddenFields, 100);
});
}
});
// Écouter les boutons de modèle
const modelButtons = [
'bouton-urbain-2',
'bouton-sport-2',
'bouton-sport-plus'
];
modelButtons.forEach(function(id) {
const button = document.getElementById(id);
if (button) {
button.addEventListener('click', function() {
// Augmentation du délai pour laisser le temps aux conditions de visibilité de s'appliquer
setTimeout(updateHiddenFields, 1000);
});
}
});
}
// Observer les changements de visibilité des dropdowns
const dropdownObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
setTimeout(updateHiddenFields, 500);
}
});
});
const dropdowns = document.querySelectorAll('.uc-dropdown-field-wrapper');
dropdowns.forEach((dropdown) => {
dropdownObserver.observe(dropdown, { attributes: true });
});
// Initialiser les écouteurs d'événements
addEventListeners();
// Exécuter une première mise à jour
setTimeout(updateHiddenFields, 1000);
// Observer les changements dans le DOM pour détecter quand les sections sont affichées/masquées
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
const target = mutation.target;
if (target.id && target.id.startsWith('section-')) {
setTimeout(updateHiddenFields, 500);
}
}
});
});
// Observer les sections de modèles
const sections = document.querySelectorAll('#section-urbain-2, #section-sport-2, #section-sport-plus');
sections.forEach(function(section) {
if (section) {
observer.observe(section, { attributes: true });
}
});
}, 1500);
});
Les fonctionnalités clés incluent le calcul dynamique des prix en fonction des options sélectionnées, la gestion automatisée des mensualités, et une interface utilisateur réactive.
Notre code permet une gestion multi-modèles et une adaptation facile aux évolutions futures.
Ce configurateur améliore significativement l’expérience client sur le site web de VELO49.