EditContext API'yi kullanarak özel web düzenleme deneyimleri oluşturmanın yeni bir yolu

Geliştiriciler için, web uygulamalarına gelişmiş düzenleme özelliklerini eklemek her zaman kolay bir görev olmamıştır. Web platformu, <input> ve <textarea> gibi öğeleri kullanarak veya öğelere contenteditable özelliğini uygulayarak hem düz metin hem de HTML dokümanları için düzenlenebilirlik sağlar. Ancak bu öğe türlerinin temel özellikleri, geliştiricilerin uygulamalarında ulaşmak istedikleri hedefler için genellikle yeterli değildir.

Geliştiriciler genellikle kullanıcılarının ihtiyaç duyduğu işlevleri uygulayan kendi özel düzenleyici görünümlerini uygulamaya koymuştur. Düzenleyici görünümü karmaşık bir DOM ile veya hatta bir <canvas> öğesiyle oluşturulabilir ancak geliştiricinin metin girişi almasının tek yolu odaklanmış bir düzenlenebilir öğe gerektirdiğinden, sayfalarına bir yere gizli bir contenteditable öğesi yerleştirmeleri gerekir.

Sonuç olarak kullanıcı, içeriği doğrudan uygulamanın özel düzenleyici görünümünde düzenliyor gibi görünürken geliştirici aslında gizli öğedeki etkinlik işleyicilerle girişi alıyor ve daha sonra bunu görünür düzenleyici görünümüne yansıtıyor. Bu durum, geliştiricinin gizli contenteditable öğesinde tarayıcının varsayılan düzenleme davranışıyla mücadele etmesi nedeniyle sorunlara yol açabilir.

Microsoft Edge ekibi, bu tür sorunları gidermek için geliştiricilerin tarayıcı varsayılan düzenleme davranışlarına bağlı kalmadan doğrudan metin girişi almasına olanak tanıyan yeni bir web platformu API'si olan EditContext'in standartlaştırılmasını sağladı.

Gerçek hayattan bir örnek

Örneğin, kullanıcılar Word Online'da ortak çalışma yaparken. Kullanıcılar birlikte düzenleme yapabilir, birbirlerinin değişikliklerini ve imleç konumlarını görebilir. Ancak, ortak çalışanlardan biri Japonca metin oluşturmak için Giriş Yöntemi Düzenleyicisi (IME) penceresi kullanıyorsa IME kullanıcısı metin oluşturmayı tamamlayana kadar düzenleyicisi, diğer kullanıcıların yaptığı değişiklikleri gösterecek şekilde güncellenmez. Bunun nedeni, etkin bir IME bileşimi varken düzenlenen DOM alanında değişiklik yapılmasının bileşimin erken iptal edilmesine neden olabilmesidir. Uygulamanın, görünümü güncellemek için IME penceresi kapatılana kadar beklemesi gerekir. Bu durum, gecikmelere ve ortak çalışmayı engelleyebilir.

Metin oluştururken Word Online'da ortak çalışmayla ilgili sorun oluştu

Geliştiricilerin hem geliştiricilere hem de kullanıcılara daha iyi bir deneyim sunmak için metin girişini HTML DOM görünümünden ayırmaları gerekir. EditContext API, bu sorunun çözümüdür.

EditContext ile ilgili temel bilgiler

EditContext ile, DOM'daki değişiklikleri gözlemlemek yerine metin ve kompozisyon girişini doğrudan EditContext API yüzeyi üzerinden alabilirsiniz. Bu, girişin işlenme şekli üzerinde daha fazla kontrole ve <canvas> öğesine düzenlenebilirlik eklenmesine olanak tanır.

EditContext örneğini bir öğeyle ilişkilendirmek, örneği düzenlenebilir hale getirir:

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

Yazarın sorumlulukları

EditContext API'yi kullanmak, IME kompozisyon pencereleri, emoji seçicileri ve diğer işletim sistemi giriş yüzeyleri gibi gelişmiş giriş yöntemlerini desteklemeyi kolaylaştırır. Düzenlenebilir öğenizde tüm bunları mümkün kılmak için EditContext API bazı bilgilere ihtiyaç duyar. EditContext API'yi kullanırken metni ve seçimi oluşturmanın yanı sıra yapmanız gereken başka şeyler de vardır.

Düzenlenebilir bir bölgenin tarafını yönetme veya kullanıcının seçiminin değişmesi

Düzenlenebilir bölgenin boyutu veya kullanıcının seçimi değiştiğinde EditContext örneğini bilgilendirmek için updateControlBounds() ve updateSelectionBounds() yöntemlerini çağırın. Bu, platformun IME pencerelerinin ve platforma özel diğer düzenleme kullanıcı arayüzünün nerede gösterileceğine karar vermesine yardımcı olur.

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

Düzenleyici kullanıcı arayüzünün konumunu yönetme

Platformun IME pencerelerini ve platforma özgü diğer düzenleme kullanıcı arayüzlerini nerede göstereceğine karar vermesine yardımcı olmak için characterboundsupdate etkinliğini dinleyin ve updateCharacterBounds() çağrısı yapın.

Biçimlendirmeyi uygulama

textformatupdate etkinliğini dinleyin ve etkinlik tarafından belirtilen biçimlendirmeyi düzenleyici görünümünüze uygulayın. Bu metin süslemeleri, IME'ler tarafından belirli diller yazılırken kullanılır. Örneğin, Japonca IME, metnin hangi kısmının etkin olarak yazıldığını göstermek için alt çizgi kullanır.

Japonca karakter girişi için kullanılan Giriş Yöntemi Düzenleyici penceresinin ekran görüntüsü.

Zengin metin düzenleme davranışlarını işleme

Metni kalın veya italik yazmak ya da yazım denetimi düzeltmesi uygulamak için kullanılan kısayol tuşları gibi desteklemek istediğiniz zengin metin düzenleme davranışlarını işlemek üzere beforeinput etkinliğini dinleyin.

Kullanıcı seçimlerindeki değişiklikleri yönetme

Kullanıcının seçimi klavye veya fare girişi nedeniyle değiştiğinde, EditContext örneğini değişikliği hakkında bilgilendirmeniz gerekir. EditContext API'nin, tarayıcının seçim değişikliklerini otomatik olarak algılayamadığı <canvas> öğesiyle oluşturulan düzenleyiciler de dahil olmak üzere çok sayıda kullanım alanına uygulanabilir olması nedeniyle bu gereklidir.

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

EditContext ile kullandığınız öğe bir <canvas> öğesiyse ok tuşlarıyla metinde gezinme gibi seçim ve imleç gezinme davranışlarını da uygulamanız gerekir. Ayrıca, tarayıcının yerleşik yazım denetimi yalnızca <canvas> olmayan öğelerde çalışır.

EditContext ile contenteditable karşılaştırması

Tam özellikli bir düzenleyici uyguluyorsanız ve metin girişinin nasıl işlendiği üzerinde tam kontrol sahibi olmak istiyorsanız ya da birden fazla kullanıcıyla birlikte düzenleme gibi gelişmiş özellikler ekliyorsanız EditContext mükemmel bir seçimdir. Ancak EditContext'i kullanmayla ilgili önceki tüm koşullar göz önüne alındığında, tek ihtiyacınız basit metin düzenleme desteğiyse yine de <input>, <textarea> öğelerini veya contenteditable özelliğini kullanmak isteyebilirsiniz.

Gelecek için

Microsoft Edge ekibi, Chrome mühendisleriyle işbirliği yaparak Chromium'da EditContext'i uyguladı ve hem Chrome hem de Edge'in 121 sürümü (Ocak 2024) ile birlikte çalışıyor. Şu anda yalnızca Chromium tabanlı tarayıcılarda kullanılabilir ancak EditContext API ile ilgili Mozilla'nın ve WebKit'in görüşlerini okuyabilirsiniz.

Web geliştiricilerin web'de güçlü özel düzenleme deneyimleri oluşturmasını kolaylaştırmak istiyoruz. EditContext API'nin ise mevcut zorlukları ele alarak ve metin girişi yönetimi için daha doğrudan bir yöntem sunarak bunu başardığını düşünüyoruz.

API hakkında daha fazla bilgi edinmek istiyorsanız MDN belgelerine göz atın. API'nin tasarımı hakkında geri bildirim göndermek için EditContext API'nin GitHub deposunda bir sorunu açın. API'nin uygulanmasıyla ilgili hataları bildirmek için crbug.com adresinden hata gönderin.