2017-09-28 6 views
1

J'essaie de créer un compteur/un limiteur de mots pour les champs d'entrée/de zone de texte. Je crois que ma logique fonctionne assez bien. J'ai une fonction en cours d'exécution sur l'événement input qui sert à la fois à mettre à jour le compteur de mots restants, mais également à gérer les cas où le contenu est modifié sans appuyer sur une touche (opération de collage, par exemple).L'événement d'entrée Javascript ne se déclenche pas lorsque vous collez des espaces

Cet événement est déclenché si j'essaie de copier quelques mots et de les coller (l'événement se déclenche et la valeur est tronquée). Cependant, j'ai trouvé que si je ne fais que copier et coller des espaces, l'événement ne se déclenche pas.

Est-ce que quelqu'un sait pourquoi l'événement ne se déclencherait pas lors du collage des espaces? Y at-il un meilleur événement que je peux écouter pour ramasser ce comportement.

Ceci est principalement par intérêt personnel, pas pour un vrai projet. Donc, mon JS n'est pas très amical avec les anciens navigateurs.

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>

Répondre

0

Vous devez corriger la logique ici:

if (pressedKey !== pressedKey.trim()) { 
    // On last word, no more spaces. 
    event.preventDefault(); 
} 

pressedKey est égal à " " quand il est un des espaces, soit copier + collé ou tout simplement de la barre d'espace, mais pressedKey.trim() est égal à "", donc vous empêchez le reste des écouteurs d'événement de se déclencher.

+0

J'ai essayé de désactiver cette section de code mais cela ne semble pas être la cause. 'event.preventDefault()' ne devrait pas arrêter la propagation de l'événement. – Dracs

0

J'ai réussi à trouver la solution à mon problème. L'événement input tirait sur le collage des espaces. L'instruction if suivante était le problème. J'ai eu besoin de changer l'instruction if en >=. Cela provoque la troncature se produire lorsque le nombre maximal de mots, au lieu de seulement lorsque dépassé le maximum.