VELO49

Pour VELO49, nous avons développé un configurateur de vélos sur mesure, offrant une expérience client interactive et personnalisée.

Client:

Velo49 Sàrl

				
					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);
});
				
			

des attentes personnalisées

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.