Przedstawiamy nowy sposób tworzenia niestandardowych funkcji do edytowania stron internetowych za pomocą interfejsu EditContext API

Stosowanie zaawansowanych funkcji edycyjnych w aplikacjach internetowych nie zawsze było łatwe dla programistów. Platforma internetowa umożliwia edytowanie zarówno w postaci zwykłego tekstu, jak i dokumentów HTML. Służą do tego elementy takie jak <input> i <textarea>. Można też stosować do nich atrybut contenteditable. Podstawowe możliwości tych elementów często nie wystarczają jednak do osiągnięcia tego, co deweloperzy chcą osiągnąć w swoich aplikacjach.

Deweloperzy często wdrażają własny niestandardowy widok edytora, który zapewnia funkcje potrzebne użytkownikom. Widok edytora może być utworzony za pomocą złożonego modelu DOM lub nawet z elementem <canvas>. Ponieważ jednak jedyny sposób, w jaki deweloper może otrzymywać dane wejściowe, wymaga skupionego elementu możliwego do edytowania, więc nadal musi umieścić ukryty element contenteditable na stronie.

W efekcie użytkownik wydaje się, że edytuje bezpośrednio zawartość w edytorze niestandardowym, a deweloper otrzymuje dane wejściowe za pomocą modułów obsługi zdarzeń w ukrytym elemencie, a następnie powiela je w widocznym widoku edytora. Może to spowodować problemy, ponieważ deweloper będzie walczyć z domyślnym działaniem edycji w ukrytym elemencie contenteditable.

Aby rozwiązać ten problem, zespół Microsoft Edge wprowadził standaryzację EditContext – nowego interfejsu API platformy internetowej, który umożliwia programistom bezpośrednie otrzymywanie tekstu wejściowego bez konieczności uzależniania się od domyślnych ustawień edycji w przeglądarce.

Autentyczny przykład

na przykład gdy użytkownicy współpracują w Word Online. Użytkownicy mogą wspólnie edytować i widzieć zmiany wprowadzane przez innych oraz pozycje kursorów. Jeśli jednak jeden współpracownik używa okna edytora metody wprowadzania (IME) do tworzenia tekstu w języku japońskim, jego edytor nie zostanie zaktualizowany i będzie pokazywać zmiany wprowadzone przez innych użytkowników, dopóki użytkownik IME nie skończy tworzyć kompozycji. Dzieje się tak, ponieważ wprowadzanie zmian w obszarze edytowanego elementu DOM przy aktywnej kompozycji IME może spowodować jej przedwczesne anulowanie. Aby zaktualizować widok, aplikacja musi poczekać do zamknięcia okna IME. Może to spowodować opóźnienia i utrudnić współpracę.

Problemy ze współpracą w Word Online podczas tworzenia tekstu

Aby zapewnić lepsze wrażenia programistom i użytkownikom, programiści potrzebują sposobu na oddzielenie wpisanego tekstu od widoku HTML DOM. Rozwiązaniem tego problemu jest interfejs EditContext API.

Podstawy EditContext

Dzięki funkcji EditContext można otrzymywać dane wejściowe dotyczące tekstu i kompozycji bezpośrednio przez platformę EditContext API, a nie przez obserwację zmian DOM. Zapewni to ściślejszą kontrolę nad sposobem obsługi danych wejściowych, a nawet umożliwi edytowanie elementu <canvas>.

Powiązanie instancji EditContext z elementem umożliwia jej edytowanie:

// 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);
 });

Obowiązki autora

Interfejs EditContext API ułatwia obsługę zaawansowanych metod wprowadzania, takich jak okna tworzenia IME, selektory emotikonów i inne platformy wejściowe systemu operacyjnego. Aby było to możliwe w edytowalnym elemencie, interfejs EditContext API wymaga pewnych informacji. Korzystając z interfejsu EditContext API, musisz nie tylko renderować tekst i zaznaczać tekst, ale też wykonywać inne czynności.

Zarządzanie stroną edytowalnego obszaru lub zmianą wyboru użytkownika

Wywołuj metody updateControlBounds() i updateSelectionBounds(), aby informować instancję EditContext o każdej zmianie rozmiaru obszaru do edycji lub zmiany wyboru użytkownika. Pomaga to platformie określić, gdzie mają być wyświetlane okna IME i inne elementy interfejsu edycji przeznaczone na daną platformę.

// 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);

Zarządzanie położeniem interfejsu edytora

Wykrywaj zdarzenie characterboundsupdate i w odpowiedzi wywołaj updateCharacterBounds(), aby pomóc platformie zdecydować, gdzie mają wyświetlać się okna IME i inny interfejs do edycji specyficzny dla danej platformy.

Stosuję formatowanie

Wykryj zdarzenie textformatupdate i zastosuj w widoku edytora formatowanie określone przez zdarzenie. Te dekoracje tekstu są używane przez edytory IME podczas tworzenia określonych języków. Na przykład w japońskim edytorze tekstu zastosowano podkreślenie, aby pokazać, która część tekstu jest obecnie tworzona.

Zrzut ekranu z oknem edytora metody wprowadzania służącym do wprowadzania znaków japońskich.

Obsługa zachowań związanych z edytowaniem tekstu sformatowanego

Słuchaj zdarzenia beforeinput, aby obsługiwać działania związane z edytowaniem tekstu sformatowanego, które chcesz obsługiwać, takie jak klawisze skrótów do pogrubienia lub kursywy albo stosowanie korekty pisowni.

Zarządzanie zmianami w wyborach użytkowników

Gdy wybór użytkownika zmieni się w wyniku działania klawiatury lub myszy, musisz poinformować o zmianie wystąpienie EditContext. Jest to konieczne, ponieważ interfejs EditContext API ma zastosowanie w wielu różnych przypadkach, w tym w przypadku edytorów renderowanych za pomocą elementu <canvas>, gdy przeglądarka nie może automatycznie wykryć zmian wyboru.

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);
});

Jeśli element używany z elementem EditContext jest też elementem <canvas>, musisz też zaimplementować zachowania wyboru i nawigowania po kursorze, takie jak nawigowanie po tekście za pomocą klawiszy strzałek. Poza tym wbudowane sprawdzanie pisowni w przeglądarce działa tylko w elementach spoza <canvas>.

EditContext a contenteditable

EditContext to doskonały wybór, jeśli wdrażasz w pełni funkcjonalny edytor i chcesz mieć pełną kontrolę nad sposobem wprowadzania tekstu lub dodajesz zaawansowane funkcje, takie jak wspólne edytowanie z wieloma użytkownikami. Biorąc jednak pod uwagę wszystkie poprzednie wymagania dotyczące korzystania z elementu EditContext i potrzebujesz jedynie prostej edycji tekstu, prawdopodobnie nadal będziesz używać elementów <input>, <textarea> lub atrybutu contenteditable.

Plany na przyszłość

Zespół Microsoft Edge wdrożył EditContext w Chromium we współpracy z inżynierami Chrome i jest wysyłany wraz z wersją 121 (stycznia 2024 r.) zarówno przeglądarki Chrome, jak i Edge. Obecnie jest on dostępny tylko w przeglądarkach opartych na Chromium, ale pozycje Mozilli i WebKit można odczytać w interfejsie EditContext API.

Chcemy ułatwić programistom internetowym tworzenie zaawansowanych funkcji niestandardowych edycji w internecie. Jesteśmy przekonani, że interfejs EditContext API pozwala to rozwiązać, eliminując istniejące problemy i oferując bardziej bezpośredni sposób obsługi wprowadzania tekstu.

Więcej informacji o interfejsie API znajdziesz w dokumentacji MDN. Aby przesłać opinię na temat projektu interfejsu API, zgłoś problem w repozytorium na GitHubie interfejsu EditContext API. Aby zgłosić błędy związane z implementacją interfejsu API, zgłoś błąd na stronie crbug.com.