Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
JavaScript

Les API Clipboard et Notifications

Découvrez deux API du navigateur très utilisées : l'API Clipboard pour copier du texte ou une image dans le presse-papiers et le lire, et l'API Notifications pour afficher des messages système. La leç...

0 chapitres 0 QCM Accès gratuit
Dans cet article

À propos de ce cours

Découvrez deux API du navigateur très utilisées : l'API Clipboard pour copier du texte ou une image dans le presse-papiers et le lire, et l'API Notifications pour afficher des messages système. La leçon présente les permissions, les conditions de sécurité, un exemple complet (bouton Copier, coller, rappel de pause), les options des notifications, leurs limites sur mobile et le rôle des Service Workers. Avec des activités corrigées.
  1. Objectifs

    • Copier du texte dans le presse-papiers et le lire avec l'API Clipboard.
    • Demander la permission et afficher une notification système avec l'API Notifications.
    • Respecter les règles de sécurité de ces API : contexte sécurisé, action de l'utilisateur, permissions.
  2. L'API Clipboard (presse-papiers)

    • Elle est accessible par navigator.clipboard. Toutes ses méthodes renvoient une promesse: on les utilise avec await.
    • Elle remplace l'ancienne commande document.execCommand("copy"), aujourd'hui obsolète: ne l'utilisez plus dans un nouveau code.
    MéthodeRôleConditions
    writeText(texte)Copie du texteContexte sécurisé, déclenchée par une action de l'utilisateur (clic, touche)
    readText()Lit le texte copiéLe navigateur demande l'autorisation (ou affiche un bouton « Coller »)
    write([items])Copie un contenu riche : image PNG, HTMLComme writeText
    read()Lit un contenu richeComme readText
    • Cas d'usage : bouton « Copier » à côté d'un code, d'un lien de partage, d'un numéro de commande, d'un mot de passe généré, d'un code promo.

    API Clipboard et API Notifications : méthodes et états de la permission

  3. Exemple complet : copier, coller, rappeler

  4. La page suivante réunit les deux API de la leçon : un bouton qui copie une commande Git, un bouton qui colle le contenu du presse-papiers, et un rappel de pause sous forme de notification.

    index.html:

    <!doctype html>
    <html lang="fr">
      <head>
        <meta charset="utf-8" />
        <title>Presse-papiers et notifications</title>
        <script src="presse.js" defer></script>
      </head>
      <body>
        <h2>1. Copier un code</h2>
        <pre id="code">git commit -m "Ajout du formulaire"</pre>
        <button id="btn-copier" type="button">📋 Copier</button>
    
        <h2>2. Coller</h2>
        <button id="btn-coller" type="button">📥 Coller ici</button>
        <p id="colle"></p>
    
        <h2>3. Rappel de pause</h2>
        <label>Dans <input id="minutes" type="number" min="1" max="120" value="25" /> minute(s)</label>
        <button id="btn-rappel" type="button">🔔 Programmer</button>
        <p id="etat-rappel"></p>
      </body>
    </html>

    presse.js:

    // ---------- 1. Copier du texte
    const btnCopier = document.getElementById("btn-copier");
    
    btnCopier.addEventListener("click", async () => {
      const texte = document.getElementById("code").textContent;
      try {
        await navigator.clipboard.writeText(texte);
        btnCopier.textContent = "✅ Copié !";
      } catch (erreur) {
        btnCopier.textContent = "❌ Échec";
        console.error("Copie impossible :", erreur.message);
      }
      setTimeout(() => (btnCopier.textContent = "📋 Copier"), 2000);
    });
    
    // ---------- 2. Lire le presse-papiers (le navigateur demande l'autorisation)
    document.getElementById("btn-coller").addEventListener("click", async () => {
      const zone = document.getElementById("colle");
      try {
        const texte = await navigator.clipboard.readText();
        zone.textContent = texte ? `Contenu : ${texte}` : "Le presse-papiers est vide.";
      } catch {
        zone.textContent = "Lecture refusée par le navigateur.";
      }
    });
    
    // ---------- 3. Notification de rappel
    const etatRappel = document.getElementById("etat-rappel");
    
    async function autoriserNotifications() {
      if (!("Notification" in window)) {
        return false;
      }
      if (Notification.permission === "granted") {
        return true;
      }
      if (Notification.permission === "denied") {
        return false;
      }
      return (await Notification.requestPermission()) === "granted";
    }
    
    document.getElementById("btn-rappel").addEventListener("click", async () => {
      if (!(await autoriserNotifications())) {
        etatRappel.textContent = "Notifications refusées ou non disponibles.";
        return;
      }
      const minutes = Number(document.getElementById("minutes").value);
      etatRappel.textContent = `Rappel programmé dans ${minutes} minute(s). Laissez l'onglet ouvert.`;
      setTimeout(() => {
        const notif = new Notification("C'est l'heure de la pause ☕", {
          body: `Vous travaillez depuis ${minutes} minute(s). Levez-vous et étirez-vous !`,
          icon: "icone.png",
          tag: "rappel-pause", // remplace un éventuel rappel précédent
        });
        notif.addEventListener("click", () => {
          window.focus();
          notif.close();
        });
        etatRappel.textContent = "";
      }, minutes * 60 * 1000);
    });
  5. Copier du texte : les points clés

    • On copie le textContent de l'élément : le texte exact, sans balises.
    • Le retour visuel (« ✅ Copié ! » pendant 2 secondes) est indispensable : la copie est invisible pour l'utilisateur.
    • On entoure l'appel de try / catch: la copie peut échouer (page non sécurisée, onglet en arrière-plan, autorisation bloquée).
    • Pour copier une image, on passe un ClipboardItem à write():
    // Copier une image (PNG) : on passe par ClipboardItem
    async function copierImage(url) {
      const reponse = await fetch(url);
      const blob = await reponse.blob(); // type "image/png"
      await navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]);
    }
  6. Lire le presse-papiers

    • La lecture est plus sensible que l'écriture : le presse-papiers peut contenir un mot de passe ou un message privé. Le navigateur demande donc l'accord de l'utilisateur (Chrome affiche une demande d'autorisation, Firefox et Safari un petit bouton « Coller » à valider).
    • Pour un simple champ de saisie, inutile d'utiliser l'API : le Ctrl + V de l'utilisateur fonctionne déjà. On peut aussi écouter l'événement paste d'un élément et lire event.clipboardData.getData("text").
  1. L'API Notifications

    • Elle affiche un message en dehors de la page, dans le centre de notifications du système (Windows, macOS, Android…), même si l'utilisateur regarde un autre onglet.
    • Trois étapes :
    1. Vérifier que l'API existe : "Notification" in window.
    2. Demander la permission, à la suite d'un clic : await Notification.requestPermission() renvoie "granted", "denied" ou "default" (l'utilisateur a fermé la demande sans répondre).
    3. Créer la notification: new Notification(titre, options).
    OptionRôle
    bodyTexte sous le titre
    iconImage affichée à côté du message
    tagIdentifiant : une nouvelle notification de même tag remplace l'ancienne au lieu de s'empiler
    requireInteractiontrue: reste affichée jusqu'à une action de l'utilisateur (selon le système)
    silenttrue: sans son ni vibration
    • L'objet créé émet des événements : click (on ramène souvent l'utilisateur sur la page avec window.focus()), close, error. La méthode close() la ferme.
    • La propriété Notification.permission donne l'état actuel sans rien demander.
  2. Limites et bonnes pratiques des notifications

    • Les notifications créées avec new Notification() ne s'affichent que tant que la page est ouverte (dans un onglet, même en arrière-plan). Pour notifier un utilisateur qui a fermé le site (nouveau message, commande expédiée), il faut un Service Worker et les notifications push (Push API) envoyées par un serveur : c'est le fonctionnement des applications web installables (PWA).
    • Sur téléphone, new Notification() n'est pas toujours disponible : sur Android, Chrome exige de passer par un Service Worker ; sur iPhone et iPad, seules les applications web ajoutées à l'écran d'accueil peuvent recevoir des notifications.
    • Ne demandez jamais la permission dès l'ouverture de la page : les navigateurs masquent ou bloquent automatiquement les sites qui le font. Expliquez d'abord à quoi serviront les notifications (« M'alerter s'il pleut »), puis demandez au clic.
    • Un refus est définitif pour la page : respectez-le et n'insistez pas.
    • Notifiez avec modération : trop de notifications poussent l'utilisateur à toutes les bloquer.
  3. Tester ces API

    • Utilisez Live Server (http://127.0.0.1:5500) : en ouvrant le fichier directement (file://), certaines fonctions sont bloquées.
    • Vérifiez que les notifications de votre navigateur sont autorisées dans les réglages du système (Windows : Paramètres → Système → Notifications) et que le mode « Ne pas déranger » est désactivé.
    • Pour revenir à l'état « pas encore demandé » : icône à gauche de l'adresse → Réinitialiser les autorisations.
  4. Activités

  5. Activité 1 : boutons « Copier » automatiques

  • Dans le dossier clipboard de votre dépôt js-api-navigateur, créez une page contenant au moins trois blocs <pre> avec des commandes Git.
  • Écrivez un script qui ajoute automatiquement un bouton « Copier » à chaque <pre> de la page (querySelectorAll, createElement), avec le retour visuel « ✅ Copié ! ».
  • Utilisez un seul écouteur grâce à la délégation d'événements.

Activité 2 : générateur de mot de passe

  • Créez un générateur de mot de passe de 16 caractères (lettres, chiffres, symboles) avec crypto.getRandomValues(), et un bouton qui copie le résultat.
  • Pour plus de sécurité, videz le presse-papiers 30 secondes après la copie (writeText("")). Que se passe-t-il si l'onglet n'est plus actif à ce moment-là ?

Activité 3 : minuteur Pomodoro

  • Créez un minuteur de travail de 25 minutes suivi d'une pause de 5 minutes. Une notification annonce chaque changement de phase (utilisez tag pour ne pas les empiler).
  • Le titre de l'onglet affiche le temps restant (document.title).
  • Gérez les trois cas : permission accordée, refusée, API absente (dans ce cas, affichez un message dans la page).

Activité 4 : questions

  • Pourquoi la lecture du presse-papiers est-elle plus contrôlée que l'écriture ?
  • Quelle valeur renvoie Notification.requestPermission() si l'utilisateur ferme la demande sans répondre ?
  • Un site d'actualités veut prévenir ses lecteurs d'une information urgente, même quand ils n'ont pas le site ouvert. new Notification() suffit-il ?
Corrigés. Activité 2 : la copie programmée peut échouer, car le navigateur exige que la page ait le focus ; il faut donc un try / catch. Activité 4 : le presse-papiers peut contenir des données privées copiées dans d'autres applications ; "default"; non, il faut un Service Worker et des notifications push envoyées par un serveur, car new Notification() ne fonctionne que si la page est ouverte.
  • À retenir

    • await navigator.clipboard.writeText(texte) après un clic, avec un retour visuel et un try / catch.
    • La lecture (readText()) est soumise à l'accord de l'utilisateur.
    • Notifications : vérifier l'API, requestPermission() au clic, puis new Notification(titre, { body, tag }).
    • Sans Service Worker, une notification n'est possible que si la page est ouverte.

    Sources : MDN Web Docs, web.dev, W3C, WHATWG, open-meteo.com.