/** * copy-email.js — Copie de l'adresse e-mail dans le presse-papiers * ============================================================================= * Détail d'ergonomie qui compte sur un site de contact : tout le monde * n'a pas de client mail configuré, et un lien mailto: qui ouvre un * logiciel inattendu est une impasse. Le bouton de copie offre la voie * alternative sans supprimer le lien mailto. * * Le retour à l'utilisateur passe par deux canaux : * - visuel : le libellé du bouton change temporairement * - vocal : une région aria-live annonce la copie aux lecteurs d'écran * * L'API Clipboard exige un contexte sécurisé (HTTPS ou localhost). En cas * d'échec, on ne laisse pas l'utilisateur sans réponse : on lui indique * de copier manuellement. */ /** Durée d'affichage du message de confirmation, en millisecondes. */ const FEEDBACK_DURATION = 2200; /** * Initialise le bouton de copie. * * @param {object} options * @param {HTMLElement} options.button - Bouton portant data-copy="". * @param {HTMLElement} options.status - Région aria-live pour l'annonce. * @returns {void} */ export function initCopyEmail({ button, status }) { if (!button) return; const value = button.dataset.copy; if (!value) return; const label = button.querySelector("[data-copy-label]"); const originalLabel = label?.textContent ?? ""; let resetTimer; /** * Affiche un retour temporaire, visuel et vocal. * @param {string} message * @returns {void} */ const announce = (message) => { if (label) label.textContent = message; if (status) status.textContent = message; clearTimeout(resetTimer); resetTimer = setTimeout(() => { if (label) label.textContent = originalLabel; if (status) status.textContent = ""; }, FEEDBACK_DURATION); }; button.addEventListener("click", async () => { try { await navigator.clipboard.writeText(value); announce("Adresse copiée"); } catch { // Contexte non sécurisé, permission refusée ou API absente. announce("Copie impossible"); } }); }