粘贴空格时不会触发Javascript输入事件

时间:2017-09-28 00:36:16

标签: javascript events

我正在尝试为输入/ 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>

2 个答案:

答案 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语句更改为>=。这会导致在最大字数时发生截断,而不是仅在超过最大值时发生截断。