Memperkenalkan cara baru untuk membuat pengalaman pengeditan web kustom menggunakan EditContext API

Memasukkan kemampuan pengeditan lanjutan ke dalam aplikasi web tidak selalu menjadi tugas yang mudah. Platform web menyediakan kemampuan pengeditan untuk teks biasa dan dokumen HTML menggunakan elemen seperti <input> dan <textarea>, atau dengan menerapkan atribut contenteditable ke elemen. Namun, kemampuan dasar jenis elemen ini sering kali tidak memadai untuk mencapai apa yang ingin dicapai developer di aplikasi mereka.

Developer sering kali akhirnya menerapkan tampilan editor kustom mereka sendiri yang mengimplementasikan fungsi yang dibutuhkan pengguna mereka. Tampilan editor mungkin dibuat dengan DOM yang kompleks—atau bahkan dengan elemen <canvas>—tetapi karena satu-satunya cara bagi developer untuk menerima input teks memerlukan elemen terfokus yang dapat diedit, mereka masih perlu menempatkan elemen contenteditable tersembunyi di suatu tempat pada halaman.

Hasilnya adalah selagi pengguna tampak mengedit konten secara langsung di tampilan editor kustom aplikasi, developer sebenarnya menerima input dengan pengendali peristiwa dalam elemen tersembunyi, lalu mencerminkannya ke dalam tampilan editor yang terlihat. Hal ini dapat menyebabkan masalah saat developer akhirnya menghadapi perilaku pengeditan default browser dalam elemen contenteditable yang tersembunyi.

Untuk mengatasi berbagai masalah ini, tim Microsoft Edge telah mendorong standardisasi EditContext, API platform web baru yang memungkinkan developer menerima input teks secara langsung tanpa terikat dengan perilaku pengeditan default browser.

Contoh dunia nyata

Misalnya, saat pengguna berkolaborasi di Word Online. Pengguna dapat saling mengedit dan melihat perubahan serta posisi kursor satu sama lain. Namun, jika misalnya, satu kolaborator menggunakan jendela Editor Metode Input (IME) untuk menulis teks bahasa Jepang, editor mereka tidak akan diperbarui untuk menampilkan perubahan dari pengguna lain hingga pengguna IME menyelesaikan komposisinya. Hal ini karena melakukan perubahan pada area DOM yang sedang diedit saat ada komposisi IME yang aktif dapat menyebabkan komposisi dibatalkan sebelum waktunya. Aplikasi harus menunggu hingga jendela IME ditutup untuk memperbarui tampilan, yang dapat menyebabkan penundaan dan menghambat kolaborasi.

Kesulitan berkolaborasi di Word Online saat menulis teks

Untuk memberikan pengalaman pengguna dan developer yang lebih baik, developer memerlukan cara untuk memisahkan input teks dari tampilan DOM HTML. EditContext API adalah solusi untuk masalah ini.

Dasar-dasar EditContext

Dengan EditContext, Anda dapat menerima input teks dan komposisi secara langsung melalui platform EditContext API, bukan dengan mengamati perubahan pada DOM. Hal ini memungkinkan kontrol yang lebih ketat atas cara penanganan input, dan bahkan memungkinkan penambahan kemampuan pengeditan ke elemen <canvas>.

Mengaitkan instance EditContext dengan suatu elemen membuatnya dapat diedit:

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

Tanggung jawab penulis

Penggunaan EditContext API mempermudah dukungan metode input lanjutan seperti jendela komposisi IME, pemilih emoji, dan platform input sistem operasi lainnya. Untuk memungkinkan semua ini dalam elemen yang dapat diedit, EditContext API memerlukan beberapa informasi. Selain merender teks dan pilihan, ada beberapa hal lain yang harus Anda lakukan saat menggunakan EditContext API.

Mengelola sisi region yang dapat diedit, atau jika pilihan pengguna berubah

Panggil metode updateControlBounds() dan updateSelectionBounds() untuk memberi tahu instance EditContext setiap kali ukuran region yang dapat diedit atau pilihan pengguna berubah. Hal ini membantu platform memutuskan tempat untuk menampilkan jendela IME dan UI pengeditan khusus platform lainnya.

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

Mengelola posisi UI editor

Proses peristiwa characterboundsupdate dan panggil updateCharacterBounds() sebagai respons untuk membantu platform memutuskan tempat untuk menampilkan jendela IME dan UI pengeditan khusus platform lainnya.

Menerapkan pemformatan

Proses peristiwa textformatupdate lalu terapkan format yang ditentukan oleh peristiwa ke tampilan editor Anda. Dekorasi teks ini digunakan oleh IME saat menyusun bahasa tertentu. Misalnya, IME Jepang akan menggunakan garis bawah untuk menunjukkan bagian teks mana yang secara aktif ditulis.

Screenshot jendela Editor Metode Input yang digunakan untuk memasukkan karakter Jepang.

Menangani perilaku pengeditan rich text

Dengarkan peristiwa beforeinput untuk menangani perilaku pengeditan rich text yang ingin Anda dukung, seperti hotkey untuk menebalkan teks atau memiringkan teks, atau menerapkan koreksi periksa ejaan.

Mengelola perubahan dalam pilihan pengguna

Saat pilihan pengguna berubah karena input keyboard atau mouse, Anda harus memberi tahu instance EditContext tentang perubahan tersebut. Hal ini diperlukan karena penerapan EditContext API pada banyak kasus penggunaan, termasuk editor yang dirender dengan elemen <canvas> tempat browser tidak dapat mendeteksi perubahan pemilihan secara otomatis.

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

Jika elemen yang Anda gunakan dengan EditContext adalah elemen <canvas>, Anda juga harus mengimplementasikan pemilihan dan perilaku navigasi tanda sisipan, seperti menavigasi teks dengan tombol panah. Selain itu, fitur periksa ejaan bawaan browser hanya berfungsi pada elemen non-<canvas>.

EditContext versus contenteditable

EditContext adalah pilihan tepat jika Anda menerapkan editor berfitur lengkap dan ingin memiliki kontrol penuh atas cara penanganan input teks, atau jika Anda menambahkan fitur lanjutan seperti pengeditan bersama dengan beberapa pengguna. Namun, mengingat semua persyaratan sebelumnya untuk menggunakan EditContext, jika yang Anda butuhkan hanyalah dukungan pengeditan teks sederhana, Anda mungkin tetap ingin menggunakan elemen <input>, <textarea>, atau atribut contenteditable.

Harapan ke depan

Tim Microsoft Edge telah menerapkan EditContext di Chromium melalui kolaborasi dengan engineer Chrome, dan akan dirilis dengan rilis 121 (Januari 2024) untuk Chrome dan Edge. Untuk saat ini, fitur ini hanya tersedia di browser berbasis Chromium, tetapi Anda dapat membaca Mozilla dan posisi WebKit di EditContext API.

Kami ingin mempermudah developer web dalam membuat pengalaman pengeditan kustom yang canggih di web, dan kami percaya bahwa EditContext API mencapainya dengan mengatasi tantangan yang ada dan menawarkan cara yang lebih langsung untuk menangani input teks.

Jika Anda ingin mempelajari API lebih lanjut, baca dokumentasi MDN. Untuk mengirimkan masukan tentang desain API, buka masalah di repositori GitHub EditContext API. Untuk melaporkan bug terkait implementasi API, kirimkan bug di crbug.com.