Une nouvelle façon de créer des expériences d'édition Web personnalisées à l'aide de l'API EditContext

Il n'a pas toujours été une tâche simple pour les développeurs d'intégrer des fonctionnalités de retouche avancées à leurs applications Web. La plate-forme Web permet de modifier les documents en texte brut et HTML à l'aide d'éléments tels que <input> et <textarea>, ou en appliquant l'attribut contenteditable aux éléments. Toutefois, les fonctionnalités de base de ces types d'éléments ne suffisent souvent pas à atteindre l'objectif des développeurs dans leurs applications.

Souvent, les développeurs ont implémenté leur propre vue d'éditeur personnalisée qui implémente les fonctionnalités dont leurs utilisateurs avaient besoin. La vue de l'éditeur peut être créée avec un DOM complexe, ou même avec un élément <canvas>. Toutefois, comme le seul moyen pour le développeur de recevoir du texte nécessite un élément modifiable ciblé, il devra toujours placer un élément contenteditable masqué sur sa page.

Par conséquent, alors que l'utilisateur semble modifier directement le contenu dans la vue de l'éditeur personnalisé de l'application, le développeur reçoit en fait l'entrée avec des gestionnaires d'événements dans l'élément masqué, puis la duplique dans la vue de l'éditeur visible. Cela peut entraîner des problèmes, car le développeur finit par se heurter au comportement de modification par défaut du navigateur dans l'élément contenteditable masqué.

Pour résoudre ce type de problèmes, l'équipe Microsoft Edge a favorisé la standardisation de EditContext, une nouvelle API de plate-forme Web qui permet aux développeurs de recevoir directement du texte sans être liés aux comportements de modification par défaut du navigateur.

Un exemple concret

Par exemple, lorsque les utilisateurs collaborent dans Word Online. Chaque utilisateur peut apporter des modifications, et voir les modifications et la position du curseur de ses autres utilisateurs. Toutefois, si un collaborateur utilise une fenêtre Éditeur de mode de saisie (IME) pour rédiger du texte en japonais, par exemple, son éditeur ne sera pas mis à jour pour afficher les modifications des autres utilisateurs tant que l'utilisateur IME n'aura pas terminé sa composition. En effet, les modifications apportées à la zone du DOM en cours de modification alors qu'il existe une composition IME active peuvent entraîner l'annulation prématurée de la composition. L'application doit attendre que la fenêtre IME soit fermée pour mettre à jour la vue, ce qui peut retarder l'utilisateur et entraver la collaboration.

Problèmes de collaboration dans Word Online lors de la rédaction de texte

Pour offrir une meilleure expérience aux développeurs et aux utilisateurs, les développeurs ont besoin d'un moyen de dissocier l'entrée de texte de la vue DOM HTML. L'API EditContext est la solution à ce problème.

Principes de base d'EditContext

Avec EditContext, vous pouvez recevoir des entrées de texte et de composition directement via la surface de l'API EditContext, plutôt qu'en observant les modifications apportées au DOM. Cela permet de contrôler plus étroitement la façon dont les entrées sont traitées et d'ajouter des possibilités de modification à l'élément <canvas>.

Vous pouvez modifier un élément en associant une instance EditContext à un élément:

// This will be our editable element.
const element = document.querySelector('#editor-element');

// Creating the EditContext object.
const editContext = new EditContext();

// Associating the EditContext object with our DOM element.
// The element is now focusable and can receive text input.
element.editContext = editContext;

// In order to render the text typed by the user onto the
// page, as well as the user's selection, you'll need to
// receive the input in a textupdate event callback.
editContext.addEventListener('textupdate', event => {
  element.textContent = editContext.text;

  // For brevity, the code to render the selection
  // isn't shown here.
    renderSelection(event.selectionStart, event.selectionEnd);
 });

Responsabilités de l'auteur

L'API EditContext facilite la compatibilité avec les modes de saisie avancés, tels que les fenêtres de composition IME, les sélecteurs d'emoji et d'autres surfaces de saisie du système d'exploitation. Pour rendre tout cela possible dans votre élément modifiable, l'API EditContext nécessite certaines informations. Outre l'affichage du texte et de la sélection, vous devez effectuer d'autres opérations lorsque vous utilisez l'API EditContext.

Gérer le côté d'une région modifiable ou si la sélection de l'utilisateur change

Appelez les méthodes updateControlBounds() et updateSelectionBounds() pour informer l'instance EditContext chaque fois que la taille de la région modifiable ou la sélection de l'utilisateur change. Cela permet à la plate-forme de décider où afficher les fenêtres IME et d'autres interfaces de modification spécifiques à la plate-forme.

// It's necessary to provide bounds information because EditContext
// is generic enough to work with any type of web editor, even
// <canvas>-based editors. The API doesn't make any assumptions as
// to how the editor is implemented or how the selection is rendered.
// Bounds are given in the client coordinate space.
const controlBound = editorElement.getBoundingClientRect();
const selection = document.getSelection();
const selectionBound = selection.getRangeAt(0).getBoundingClientRect();
editContext.updateControlBounds(controlBound);
editContext.updateSelectionBounds(selectionBound);

Gérer la position de l'interface utilisateur de l'éditeur

Écoutez l'événement characterboundsupdate et appelez updateCharacterBounds() en réponse pour aider la plate-forme à décider où afficher les fenêtres IME et d'autres interfaces de modification spécifiques à la plate-forme.

Application de la mise en forme...

Écoutez l'événement textformatupdate et appliquez la mise en forme spécifiée par celui-ci dans la vue de l'éditeur. Ces décorations de texte sont utilisées par les IME lors de la rédaction de certaines langues. Par exemple, un IME japonais utilise un soulignement pour indiquer la partie du texte en cours de rédaction.

Capture d&#39;écran d&#39;une fenêtre de l&#39;éditeur du mode de saisie utilisée pour la saisie de caractères japonais.

Gérer les comportements de l'édition de texte enrichi

Écoutez l'événement beforeinput pour gérer les paramètres de modification du texte enrichi que vous souhaitez utiliser, comme l'utilisation de raccourcis pour mettre du texte en gras ou en italique, ou l'application d'une correction orthographique.

Gérer les modifications apportées aux sélections d'utilisateurs

Lorsque la sélection de l'utilisateur change en raison d'une saisie au clavier ou à la souris, vous devez en informer l'instance EditContext. Cela est nécessaire en raison de l'applicabilité de l'API EditContext à un grand nombre de cas d'utilisation, y compris aux éditeurs affichés avec l'élément <canvas>, lorsque le navigateur ne peut pas détecter automatiquement les modifications de sélection.

document.addEventListener('selectionchange', () => {
  const selection = document.getSelection();

  // EditContext doesn't handle caret navigation, so all the caret navigation/selection that happens
  // in DOM space needs to be mapped to plain text space by the author and passed to EditContext.
  // This example code assumes the editable area only contains text under a single node.
  editContext.updateSelection(selection.anchorOffset, selection.focusOffset);
});

Si l'élément que vous utilisez avec EditContext est un élément <canvas>, vous devez également implémenter les comportements de navigation de sélection et de curseur de saisie, tels que la navigation dans le texte à l'aide des touches fléchées. De plus, le correcteur orthographique intégré au navigateur ne fonctionne que pour les éléments non-<canvas>.

Comparaison entre EditContext et contenteditable

EditContext est un excellent choix si vous implémentez un éditeur complet et que vous souhaitez contrôler totalement la façon dont la saisie de texte est traitée, ou si vous ajoutez des fonctionnalités avancées telles que l'édition collaborative avec plusieurs utilisateurs. Toutefois, compte tenu de toutes les exigences ci-dessus concernant l'utilisation d'EditContext, si vous n'avez besoin que d'une simple fonctionnalité d'édition de texte, vous devrez probablement utiliser <input>, les éléments <textarea> ou l'attribut contenteditable.

Et demain ?

L'équipe Microsoft Edge a implémenté EditContext dans Chromium en collaboration avec les ingénieurs Chrome, et lance la version 121 (janvier 2024) de Chrome et d'Edge. Pour le moment, il n'est disponible que dans les navigateurs basés sur Chromium, mais vous pouvez consulter les positions de Mozilla et de WebKit sur l'API EditContext.

Nous souhaitons que les développeurs Web puissent créer plus facilement et plus facilement des fonctionnalités d'édition personnalisées performantes sur le Web. Nous sommes convaincus que l'API EditContext y parvient en résolvant les problèmes existants et en offrant une méthode plus directe pour gérer la saisie de texte.

Pour en savoir plus sur l'API, consultez la documentation MDN. Pour nous faire part de vos commentaires sur la conception de l'API, signalez un problème dans le dépôt GitHub de l'API EditContext. Pour signaler un bug dans l'implémentation de l'API, rendez-vous sur crbug.com.