1import { Controller } from "@hotwired/stimulus"; 2 3// Affiche un spinner pendant : 4// - Les navigations Turbo Drive (page reload) - `turbo:before-visit` 5// - Les soumissions de formulaire Turbo (button_to / form_with) - `turbo:submit-start` 6// Le spinner DOIT exister comme enfant `.is-loading-spinner` du contrôleur. 7export default class extends Controller { 8 static targets = ["message", "detail"]; 9 10 connect() { 11 this.defaultMessage = "Traitement en coursâ¦"; 12 this.beforeVisit = this.showLoading.bind(this); 13 this.load = this.hideLoading.bind(this); 14 this.submitStart = this.showLoading.bind(this); 15 this.submitEnd = this.hideLoading.bind(this); 16 17 document.addEventListener("turbo:before-visit", this.beforeVisit); 18 document.addEventListener("turbo:load", this.load); 19 // Submit (form_with, button_to, etc.) - montre le spinner pendant la requête 20 document.addEventListener("turbo:submit-start", this.submitStart); 21 document.addEventListener("turbo:submit-end", this.submitEnd); 22 } 23 24 disconnect() { 25 document.removeEventListener("turbo:before-visit", this.beforeVisit); 26 document.removeEventListener("turbo:load", this.load); 27 document.removeEventListener("turbo:submit-start", this.submitStart); 28 document.removeEventListener("turbo:submit-end", this.submitEnd); 29 } 30 31 showLoading(event) { 32 // turbo:before-visit ne se déclenche QUE pour les navigations Turbo Drive 33 // (pleine page) - on filtre pour ignorer turbo frame visits. 34 // Pour turbo:submit-start, on accepte tout submit (form ou button_to). 35 if (event.type === "turbo:before-visit" && event.target !== document) return; 36 37 // Message + détail contextuels lus sur le form soumis (data-loading-message 38 // / data-loading-detail). Fallback au message générique sinon (navigations, 39 // autres forms de la page). 40 const form = event?.detail?.formSubmission?.formElement; 41 const message = form?.dataset?.loadingMessage || this.defaultMessage; 42 const detail = form?.dataset?.loadingDetail || ""; 43 44 if (this.hasMessageTarget) this.messageTarget.textContent = message; 45 if (this.hasDetailTarget) { 46 this.detailTarget.textContent = detail; 47 this.detailTarget.classList.toggle("hidden", detail === ""); 48 } 49 50 this.element.classList.add("is-loading"); 51 const spinner = this.element.querySelector(".is-loading-spinner"); 52 if (spinner) spinner.classList.remove("hidden"); 53 } 54 55 hideLoading() { 56 this.element.classList.remove("is-loading"); 57 const spinner = this.element.querySelector(".is-loading-spinner"); 58 if (spinner) spinner.classList.add("hidden"); 59 } 60}
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.