Files
2026-08-05 22:40:03 +02:00

65 lines
2.1 KiB
JavaScript

/**
* 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="<valeur>".
* @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");
}
});
}