我正在尝试为输入/ textarea字段创建一个单词计数器/限制器。我相信我的逻辑运作得很好。我有一个在input
事件上运行的函数,它既可以更新剩余的单词计数器,也可以处理没有按键的情况下更改内容的情况(例如粘贴操作)。
如果我尝试复制几个单词并粘贴它们(事件触发并且值被截断),则会触发此事件。但是,我发现如果我只复制并粘贴空格,则事件不会触发。
有谁知道为什么事件不会在粘贴空格时触发?是否有一个更好的事件,我可以听取这种行为。
这主要是出于个人兴趣,而不是真正的项目。所以我的JS对旧浏览器不太友好。
function limitFieldKeyDown(event) {
const maxWords = parseInt(this.getAttribute('data-word-limit'), 10);
// See what character was entered.
let pressedKey = event.key;
// Check against special keys
if (pressedKey.length > 1) {
pressedKey = '';
}
// Get text (including pressed key).
const text = `${this.value}${pressedKey}`.trim();
// Get the count of words
let words;
if (text === '') {
// Handle special case of empty string
words = [];
}
else {
words = text.split(/\s+/);
}
const currentWordCount = words.length;
if (currentWordCount >= maxWords) {
// Detect if the word was whitespace.
if (pressedKey !== pressedKey.trim()) {
// On last word, no more spaces.
event.preventDefault();
}
}
}
function truncateToWords(text, words, limit) {
let currentIndex = 0;
// Find the character position which matches the current word limit.
for (let i = 0; i < limit; i++) {
currentIndex = text.indexOf(words[i], currentIndex) + words[i].length;
}
// Truncate the text to position.
return text.substring(0, currentIndex);
}
function limitFieldInput() {
const maxWords = parseInt(this.getAttribute('data-word-limit'), 10);
let text = this.value.trim();
let words;
if (text === '') {
// Handle special case of empty string
words = [];
}
else {
words = text.split(/\s+/);
}
let currentWordCount = words.length;
// Check if text is longer than maximum
if (currentWordCount > maxWords) {
// Longer than maximum, truncate.
text = truncateToWords(text, words, maxWords);
// Update variables with truncated text.
this.value = text;
words = text.split(/\s+/);
currentWordCount = words.length;
}
// Update the word counter.
const counterFields = this.parentNode.querySelectorAll('span.word-limit');
if (counterFields.length > 0) {
const remainingWords = maxWords - currentWordCount;
for (let i = 0; i < counterFields.length; ++i) {
counterFields[i].innerText = `${remainingWords} remaining`;
}
}
}
function limitField(field) {
field.addEventListener('keydown', limitFieldKeyDown);
field.addEventListener('input', limitFieldInput);
const event = new KeyboardEvent('keydown');
field.dispatchEvent(event);
const event2 = new Event('input');
field.dispatchEvent(event2);
}
const limtiedFields = document.querySelectorAll('textarea.word-limit');
for (let i = 0; i < limtiedFields.length; ++i) {
// Run on every keydown event.
limitField(limtiedFields[i]);
}
<div>
<textarea class="word-limit" data-word-limit="5"></textarea>
<span class="word-limit"></span>
</div>
答案 0 :(得分:0)
您需要在此修复逻辑:
if (pressedKey !== pressedKey.trim()) {
// On last word, no more spaces.
event.preventDefault();
}
pressedKey
等于" "
,当它是空白时,复制+粘贴或仅来自空格键,但pressedKey.trim()
等于""
,所以您正在阻止其他事件侦听器触发。
答案 1 :(得分:0)
我设法找到了解决问题的方法。 input
事件在粘贴空格时触发。以下if语句是问题所在。
// Check if text is longer than maximum
if (currentWordCount > maxWords) {
// Longer than maximum, truncate.
text = truncateToWords(text, words, maxWords);
// Update variables with truncated text.
this.value = text;
words = text.split(/\s+/);
currentWordCount = words.length;
}
我需要将if语句更改为>=
。这会导致在最大字数时发生截断,而不是仅在超过最大值时发生截断。