Wprowadzanie zaawansowanych funkcji edycji w aplikacji internetowej nie zawsze było proste. Platforma internetowa umożliwia edytowanie zarówno dokumentów tekstowych, jak i dokumentów HTML za pomocą elementów takich jak <input>
i <textarea>
lub przez zastosowanie atrybutu contenteditable
do elementów. Jednak podstawowe możliwości tych typów elementów często nie wystarczają do tego, co deweloperzy chcą osiągnąć w swoich aplikacjach.
Deweloperzy często implementowali własne widoki niestandardowego edytora, które zapewniały funkcje potrzebne użytkownikom. Widok edytora może być utworzony za pomocą złożonego DOM-u lub nawet elementu <canvas>
, ale ponieważ jedynym sposobem, w jaki deweloper może otrzymywać tekst, jest skupiony element edytowalny, musi on gdzieś na stronie umieścić ukryty element contenteditable
.
W efekcie, gdy użytkownik wydaje się bezpośrednio edytować zawartość w widoku niestandardowego edytora aplikacji, deweloper faktycznie otrzymuje dane wejściowe za pomocą elementów obsługujących zdarzenia w ukrytym elemencie, a potem odzwierciedla je w widocznym widoku edytora. Może to powodować problemy, ponieważ deweloper musi walczyć z domyślnym zachowaniem przeglądarki w ukrytym elemencie contenteditable
.
Aby rozwiązać tę klasę, zespół Microsoft Edge wprowadził ustandaryzowanie EditContext, nowego interfejsu API platformy internetowej, który umożliwia programistom bezpośrednie otrzymywanie tekstu bez konieczności łączenia się z domyślnymi ustawieniami edycji w przeglądarce.
Przykład praktycznego zastosowania
Na przykład, gdy użytkownicy współpracują w Word Online. Użytkownicy mogą wspólnie edytować pliki i widzieć zmiany oraz pozycje kursorów innych użytkowników. Jeśli jednak jeden z współpracowników używa okna edytora metody wprowadzania (IME), aby tworzyć tekst w języku japońskim, jego edytor nie będzie aktualizowany, aby uwzględniać zmiany wprowadzane przez innych użytkowników, dopóki użytkownik IME nie zakończy tworzenia tekstu. Dzieje się tak, ponieważ wprowadzanie zmian w obszarze DOM podczas aktywnej kompozycji IME może spowodować przedwczesne anulowanie kompozycji. Aplikacja musi poczekać, aż okno IME zostanie zamknięte, aby zaktualizować widok. Może to powodować opóźnienia i utrudniać współpracę.
Aby zapewnić lepsze wrażenia zarówno deweloperom, jak i użytkownikom, deweloperzy muszą mieć możliwość rozdzielenia danych wejściowych tekstu od widoku DOM HTML. Rozwiązaniem tego problemu jest interfejs EditContext API.
Podstawy funkcji EditContext
Dzięki EditContext możesz otrzymywać dane wejściowe dotyczące tekstu i kompozycji bezpośrednio przez interfejs EditContext API, a nie przez obserwowanie zmian w interfejsie DOM. Zapewnia to ściślejszą kontrolę nad sposobem obsługi danych wejściowych, a nawet umożliwia dodanie możliwości edycji elementu <canvas>
.
Powiązanie instancji EditContext z elementem umożliwia jej edycję:
// 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
Użycie interfejsu EditContext API ułatwia obsługę zaawansowanych metod wprowadzania, takich jak okna kompozycji IME, selektory emotikonów i inne platformy do wprowadzania danych w systemie operacyjnym. Aby umożliwić edycję elementu, interfejs EditContext API wymaga podania pewnych informacji. Oprócz renderowania tekstu i wyboru musisz wykonać jeszcze kilka innych czynności podczas korzystania z interfejsu EditContext API.
Zarządzanie bokiem obszaru do edycji lub po zmianie wyboru użytkownika
Wywołuj metody updateControlBounds()
i updateSelectionBounds()
, aby poinformować instancję EditContext, gdy rozmiar edytowalnego regionu lub zaznaczenie użytkownika ulegnie zmianie. Ułatwia to platformie podjęcie decyzji, gdzie mają wyświetlić się okna IME i inny interfejs użytkownika do edycji dostosowany do platformy.
// 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 pozycją interfejsu edytora.
Nasłuchuj zdarzenia characterboundsupdate
i w odpowiedzi na nie wywołuj metody updateCharacterBounds()
, aby pomóc platformie zdecydować, gdzie wyświetlać okna IME i inne interfejsy edycji specyficzne dla platformy.
Stosowanie formatowania
Nasłuchuj zdarzenie textformatupdate
i zastosuj formatowanie określone przez to zdarzenie w widoku edytora. Dekoracje tekstu są używane przez edytory IME podczas tworzenia wiadomości w określonych językach. Na przykład japoński edytor IME użyje podkreślenia, by pokazać, która część tekstu jest aktywnie tworzona.
Obsługa zachowań edycji tekstu sformatowanego
Słuchaj zdarzenia beforeinput
, aby obsługiwać dowolne zachowania edycji tekstu sformatowanego, które chcesz obsługiwać, takie jak skróty klawiszowe do pogrubienia lub pochylenia tekstu czy stosowanie korekty pisowni.
Zarządzanie zmianami w wyborach użytkownika
Gdy wybór użytkownika zmieni się z powodu danych wejściowych z klawiatury lub myszy, musisz poinformować o tej zmianie instancję EditContext. Jest to konieczne, ponieważ interfejs EditContext API jest przydatny w wielu przypadkach użycia, w tym w przypadku edytorów renderowanych za pomocą elementu <canvas>
, w których przeglądarka nie może automatycznie wykryć zmian w wybranym obszarze.
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, którego używasz w EditContext, jest elementem <canvas>
, musisz też zaimplementować zachowania nawigacyjne zaznaczania i nawigacji przy użyciu kursora, np. nawigowanie po tekście za pomocą klawiszy strzałek. Ponadto wbudowana funkcja sprawdzania pisowni w przeglądarce działa tylko w elementach innych niż <canvas>
.
EditContext a contenteditable
EditContext to świetny wybór, jeśli wdrażasz w pełni funkcjonalny edytor i chcesz mieć pełną kontrolę nad sposobem obsługi wprowadzania tekstu lub jeśli dodajesz zaawansowane funkcje, takie jak współedytowanie przez wielu użytkowników. Jeśli jednak wystarczy Ci proste edytowanie tekstu, nadal użyjesz elementów <input>
, <textarea>
lub atrybutu contenteditable
.
Pozdrawiam
Zespół Microsoft Edge wdrożył rozszerzenie EditContext w Chromium przy pomocy inżynierów Chrome. Udostępniane są wersje 121 (styczeń 2024 r.) Chrome i Edge. W tej chwili jest on dostępny tylko w przeglądarkach opartych na Chromium, ale informacje o pozycji Mozilli i WebKit znajdziesz w interfejsie EditContext API.
Chcemy ułatwić programistom stron internetowych tworzenie zaawansowanych, niestandardowych funkcji edycji w internecie. Wierzymy, że interfejs EditContext API pozwala to osiągnąć, rozwiązując istniejące problemy i oferując bardziej bezpośredni sposób wprowadzania tekstu.
Więcej informacji o interfejsie API znajdziesz w dokumentacji MDN. Aby przesłać opinię na temat interfejsu API, otwórz zgłoszenie w repozytorium GitHub interfejsu EditContext API. Aby zgłosić błędy implementacji interfejsu API, prześlij raport o błędach na stronie crbug.com.