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

Bagi developer, menggabungkan kemampuan pengeditan lanjutan di aplikasi web mereka bukanlah hal yang mudah. Platform web menyediakan kemampuan pengeditan untuk dokumen teks biasa dan HTML menggunakan elemen seperti <input> dan <textarea>, atau dengan menerapkan atribut contenteditable ke elemen. Namun, kemampuan dasar jenis elemen ini sering kali tidak cukup untuk mencapai hal yang ingin dicapai developer di aplikasi mereka.

Developer sering kali akhirnya menerapkan tampilan editor kustom mereka sendiri yang menerapkan fungsi yang dibutuhkan pengguna. 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 yang dapat diedit dan difokuskan, mereka masih perlu menempatkan elemen contenteditable tersembunyi di halaman mereka.

Hasilnya adalah saat pengguna tampak langsung mengedit konten dalam tampilan editor kustom aplikasi, developer sebenarnya menerima input dengan pengendali peristiwa di elemen tersembunyi, lalu mencerminkannya ke tampilan editor yang terlihat. Hal ini dapat menyebabkan masalah karena developer akhirnya harus berurusan dengan perilaku pengeditan default browser di 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 mengedit bersama serta melihat perubahan dan posisi kursor satu sama lain. Namun, jika satu kolaborator menggunakan jendela Editor Metode Input (IME) untuk menulis teks bahasa Jepang, misalnya, editornya tidak akan diperbarui untuk menampilkan perubahan dari pengguna lain hingga pengguna IME menyelesaikan komposisinya. Hal ini karena membuat perubahan pada area DOM yang sedang diedit saat ada komposisi IME aktif dapat menyebabkan komposisi dibatalkan sebelum waktunya. Aplikasi harus menunggu hingga jendela IME ditutup untuk memperbarui tampilan, yang dapat menyebabkan penundaan dan menghambat kolaborasi.

Masalah saat berkolaborasi di Word Online saat menulis teks

Untuk memberikan pengalaman developer dan pengguna 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 melalui pengamatan 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 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 di 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 wilayah 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 menampilkan jendela IME dan UI pengeditan khusus platform lainnya.

Menerapkan pemformatan

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

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

Menangani perilaku pengeditan rich text

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

Mengelola perubahan pada 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 untuk sejumlah besar kasus penggunaan, termasuk editor yang dirender dengan elemen <canvas> tempat browser tidak dapat mendeteksi perubahan pilihan 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 menerapkan perilaku navigasi kursor dan tanda kurung, seperti menavigasi teks dengan tombol panah. Selain itu, fitur periksa ejaan bawaan browser hanya berfungsi di 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 masih 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 dirilis bersama rilis 121 (Januari 2024) Chrome dan Edge. Untuk saat ini, fitur ini hanya tersedia di browser berbasis Chromium, tetapi Anda dapat membaca posisi Mozilla dan WebKit di EditContext API.

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

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