PageSourceSearch

https://www.desaignes.fr/assets/controllers/google-map-autocomplet…troller-3032003cb7e88f8808f48945f16e5dd7.js

js desaignes.fr collected 2026-10-02 23:17:27 UTC 4,692 bytes, 131 lines download raw bytes

1/**
2 * Ce contrôleur Stimulus permet de gérer l'autocomplétion des champs d'adresse
3 * et de les remplir automatiquement à l'aide de l'API Google Maps Places.
4 *
5 * Il gère également l'affichage ou la masquage des champs de saisie manuelle en cas d'absence
6 * de correspondance trouvée par Google Maps.
7 *
8 * Champs requis :
9 * - Les champs pour le "n° et nom de rue", "code postal", "ville", "pays" doivent avoir les attributs Stimulus suivants :
10 *   - `data-google-map-autocomplete-target="googleAutocomplete"` pour être ciblés par le contrôleur.
11 *
12 * - Le champ de recherche Google doit avoir les attributs suivants :
13 *   - `name="googleAutocomplete"` et `id="address_googleMaps"`, ainsi que le target Stimulus correspondant pour l'autocomplétion :
14 *     `data-google-map-autocomplete-target="autoInput"`.
15 *
16 * - Les champs à cacher se trouvent dans une div avec `data-google-map-autocomplete-target="manuelAdresse"` et la classe `d-none` par défaut.
17 *   - Ils seront affichés lorsque l'utilisateur clique sur le bouton pour saisir une adresse manuellement.
18 *
19 * - Le bouton pour afficher les champs d'adresse manuels doit se trouver dans une div avec `data-google-map-autocomplete-target="noAutoAdresse"`
20 *   et la classe `d-none`. Ce bouton doit appeler l'action Stimulus `displayAddress`.
21 *
22 * A noter :
23 * - Si le champs de recherche d'adresse est géré via le bundle ivory, passer au controller le parametre `isIvoryUsed` à true pour ne pas l'initialiser ici.
24 */
25
26
27import { Controller } from '@hotwired/stimulus';
28
29export default class extends Controller {
30    static values = {
31        isIvoryUsed: Boolean
32    }
33    static targets = [
34        "manuelAdresse",
35        "noAutoAdresse",
36        "googleAutocomplete",
37        "buttonAdresseManuel",
38        "autoInput"
39    ];
40
41    connect() {
42        if (!this.isIvoryUsedValue) {
43            this.initializeGoogleAutocomplete();
44        }
45
46        this.handleFocusOut = this.handleFocusOut.bind(this);
47        this.alreadySearch = false;
48
49        document.getElementById('address_googleMaps').addEventListener('focusout', this.handleFocusOut);
50
51        if (this.fieldsAreNotEmpty()) {
52            this.displayAddress();
53            this.alreadySearch = true
54
55        }
56    }
57
58    initializeGoogleAutocomplete() {
59        const autocomplete = new google.maps.places.Autocomplete(this.autoInputTarget, {});
60
61        autocomplete.addListener("place_changed", () => {
62            const place = autocomplete.getPlace();
63            this.fillInAddress(place);
64        });
65    }
66
67    fillInAddress(place) {
68        if (place) {
69            let street_number = this.extractFromAddress(place.address_components, "street_number");
70            let street = this.extractFromAddress(place.address_components, "route");
71            let postCode = this.extractFromAddress(place.address_components, "postal_code");
72            let town = this.extractFromAddress(place.address_components, "locality");
73            let country = this.extractFromAddress(place.address_components, "country");
74
75            this.googleAutocompleteTargets.forEach(target => {
76                const fieldName = target.name;
77
78                if (fieldName.includes('adresse')) {
79                    target.value = [street_number, street].join(" ");
80                }
81
82                if (fieldName.includes('codePostal')) {
83                    target.value = postCode;
84                }
85
86                if (fieldName.includes('ville')) {
87                    target.value = town;
88                }
89
90                if (fieldName.includes('pays')) {
91                    target.value = country;
92                }
93            });
94
95            this.displayAddress();
96        }
97    }
98
99    extractFromAddress(components, type) {
100        for (let i = 0; i < components.length; i++) {
101            if (components[i].types.includes(type)) {
102                return components[i].long_name;
103            }
104        }
105        return '';
106    }
107
108    handleFocusOut() {
109        setTimeout(() => {
110            if (this.fieldsAreNotEmpty()) {
111                this.displayAddress();
112            } else {
113                this.noAutoAdresseTarget.classList.remove('d-none');
114            }
115        }, 200);
116    }
117
118    removeFocusOutListener() {
119        document.getElementById('address_googleMaps').removeEventListener('focusout', this.handleFocusOut);
120    }
121
122    displayAddress() {
123        this.manuelAdresseTarget.classList.remove('d-none');
124        this.noAutoAdresseTarget.classList.add('d-none');
125        this.removeFocusOutListener();
126    }
127
128    fieldsAreNotEmpty() {
129        return this.googleAutocompleteTargets.some(target => target.value.trim() !== '');
130    }
131}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.