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

Tidak selalu mudah bagi developer untuk menyertakan kemampuan pengeditan lanjutan dalam aplikasi web mereka. Platform web memberikan kemampuan edit 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 cukup untuk mencapai hal yang ingin dicapai developer di aplikasi mereka.

Developer sering kali 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 terfokus yang dapat diedit, mereka masih harus 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 pada akhirnya melawan perilaku pengeditan default browser di elemen contenteditable 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 sampai pengguna IME menyelesaikan komposisinya. Hal ini karena melakukan perubahan pada area DOM yang sedang diedit selagi 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.

Kesulitan 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 dengan mengamati perubahan pada DOM. Hal ini memungkinkan kontrol yang lebih ketat atas cara penanganan input, dan bahkan memungkinkan penambahan kemampuan edit 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 memudahkan 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 bagian wilayah 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 menentukan 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 menentukan tempat 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 menulis bahasa tertentu. Misalnya, IME Jepang akan menggunakan garis bawah untuk menunjukkan bagian teks mana yang secara aktif disusun.

Screenshot jendela Input Method Editor yang digunakan untuk input karakter bahasa 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 pemberlakuan EditContext API pada banyak kasus penggunaan, termasuk editor yang dirender dengan elemen <canvas> yang browsernya 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 pemilihan dan tanda sisipan, seperti menjelajahi 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, dengan mempertimbangkan semua persyaratan sebelumnya untuk menggunakan EditContext, jika yang Anda perlukan hanyalah dukungan pengeditan teks sederhana, Anda mungkin tetap perlu menggunakan elemen <input>, <textarea>, atau atribut contenteditable.

Harapan ke depan

Tim Microsoft Edge telah mengimplementasikan EditContext di Chromium melalui kolaborasi dengan engineer Chrome, dan akan dirilis pada 121 (Januari 2024) untuk 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 memudahkan developer web dalam membuat pengalaman pengeditan kustom yang andal di web, dan kami percaya bahwa EditContext API mencapai tujuan ini dengan mengatasi tantangan yang ada dan menawarkan cara yang lebih langsung untuk menangani input teks.

Jika Anda ingin mempelajari API ini 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.