Birçok sohbet arayüzü, kullanıcı <textarea> içinde Enter tuşuna bastığında mesajı gönderir.
Bu yöntem, doğrudan Latin klavye girişiyle (ör. İngilizce) yazan kullanıcılar için işe yarar ancak Japonca, Çince veya Korece gibi dillerde metin oluşturmak için Giriş Yöntemi Düzenleyici (IME) kullanan kullanıcılar için çalışmaz.
Bu bağlamlarda, geçerli karakter dönüştürme adayını onaylamak için Enter/Return tuşu kullanılır. Özel JavaScript, Enter üzerinde keydown dinler ve hemen gönderirse kullanıcının mesajı, karakterleri dönüştürürken gönderilir. Bu da eksik, parçalı veya yanlış mesajlara neden olur.
Yazma etkin kontrolü, yalnızca çok satırlı <textarea> alanları için değil, Enter üzerinde işlem yapan tüm özel keydown işleyiciler için geçerlidir. Arama ve bulma çubukları, satır içi yeniden adlandırma alanları, kalıcı iletişim kutusu alanları ve komut paletleri gibi kendi Enter işleme özelliklerine sahip tek satırlı <input> alanları, <textarea> ile aynı IME onaylayan Enter tuşuna basma işlemini alır ve isComposing, true olarak ayarlanır. Özel Enter işleyicisi olmayan bir <input> öğesinden <form> öğesinin yerel dolaylı gönderimi için açık bir işleme gerek yoktur. Çünkü tarayıcılar, Enter tuş vuruşu bir IME tarafından kullanıldığında dolaylı gönderimi engeller.
Uygulama stratejisi
Özel gönderme için Enter tuşuna basılan bir <textarea> veya <input> için içeriği göndermeden önce KeyboardEvent öğesinin yerel isComposing özelliğini kontrol edin. Ayrıca event.preventDefault() çağrısı yapın: Enter için varsayılan işlem, <textarea> içine yeni bir satır ekler ve <form> içindeki bir <input> içinde tarayıcının örtük gönderimini tetikler. Bu da ikinci kez gönderim yapar.
<form id="chat-form">
<label for="chat-input" class="visually-hidden">Message</label>
<textarea id="chat-input" placeholder="Type a message..."></textarea>
<button type="submit" id="send-button">Send</button>
</form>
const textarea = document.getElementById('chat-input');
const form = document.getElementById('chat-form');
textarea.addEventListener('keydown', (event) => {
if (event.key === 'Enter' && !event.shiftKey) {
// Prevent the default action (newline in a textarea, implicit form submission in an input)
event.preventDefault();
// If the user is composing text, return early.
if (event.isComposing) {
return;
}
form.requestSubmit();
}
});
Tek satırlık <input> için !event.shiftKey koşulu olmadan aynı işleyiciyi kullanın. Bu koşul yalnızca Shift+Enter, <textarea> içine yeni bir satır eklediği için mevcuttur.
Erişilebilirlik ve test
- Açık gönder düğmesi: Her zaman bir
<button type="submit">öğesi ekleyin. Klavye kısayolları yardımcıdır; yerel form gönderme yollarının yerini almamalıdır. - Erişilebilir girişler: Tüm
<input>ve<textarea>öğelerinin, eşleşenidveforözellikleri kullanılarak programatik olarak bir<label>ile ilişkilendirildiğinden emin olun.
Yedek stratejiler
Safari'nin son sürümlerinde, bir etkinlik sıralama sorunu (WebKit hatası 165004), temel etkinlikler ters sırada gönderilmesine rağmen, onaylayan Enter keydown'den önce komut dosyası işleyicilerine compositionend gönderdi. keydown işleyicisi çalıştırıldığında event.isComposing zaten false olarak sıfırlanmıştı. Bu, standart kontrolün tek başına erken gönderimi önleyemeyeceği anlamına gelir.
Safari'nin eski sürümlerinde ve diğer platformlarda tarayıcılar arası uyumluluğu desteklemeniz gerekiyorsa aşağıdaki yedek stratejilerden birini uygulayın:
1. strateji: keyCode === 229 kontrolü ekleme (önerilir)
event.isComposing ile event.keyCode === 229 kontrolünü eşleyerek Safari'nin sırasız onaylama Enter tuşuna basma işlemini güvenilir bir şekilde yakalayabilirsiniz. Bu, event.key === 'Enter' kapısının altında iç içe yerleştirildiğinden normal karakter düzeni girişi için 229 kullanabilen mobil sanal klavyelerden korunur.
textarea.addEventListener('keydown', (event) => {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
// Block submission if composing natively or if keyCode is 229
if (event.isComposing || event.keyCode === 229) {
return;
}
form.requestSubmit();
}
});
2. strateji: event.timeStamp penceresi geçici çözümü (alternatif)
keyCode gibi desteği sonlandırılmış API'lerin kullanımını kesinlikle yasaklayan kod tabanları için veya belirli hedef ortamlarda 229 kontrolüyle ilgili bilinen sorunlar varsa bunun yerine tarayıcı tarafından bildirilen etkinlik gönderim zaman damgasını izleyebilirsiniz.
Safari, onaylayan Enter keydown etkinliğini compositionend etkinliğine son derece yakın bir zamanda (genellikle 5 ms içinde ve bazen işleyici teslim sırasının tersine çevrilmesi nedeniyle keydown zaman damgası biraz daha erken olacak şekilde) gönderdiğinden, zaman farkını kontrol etmek son derece güvenilirdir ve standart koşullar altında mobil sanal klavyelerde yanlış pozitifleri tetikleme olasılığı düşüktür.
let lastCompositionEndAt = null;
textarea.addEventListener('compositionend', (event) => {
// IMPORTANT: Always use event.timeStamp, not Date.now() or performance.now().
// Handler-time measurements are vulnerable to drift when the main thread is blocked.
lastCompositionEndAt = event.timeStamp;
});
textarea.addEventListener('keydown', (event) => {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
if (event.isComposing) {
return;
}
// Block submission if the event occurs within a 50ms window of composition ending.
// Math.abs handles Safari's inverted event delivery timing bug.
if (
lastCompositionEndAt !== null &&
Math.abs(event.timeStamp - lastCompositionEndAt) < 50
) {
return;
}
form.requestSubmit();
}
});