yehudis grosz
yehudis grosz

Reputation: 83

Filtering out words that don't match sequence when user types in text in javascript

I'm trying to make a list of names, and every time the user types in text, it should filter the names to only show the ones that match the text that the user typed in. When the user clicks the clear button, it should clear the input and show all the names again.

So I made an array of names to show up in a div. The problem is that the first time it goes through all the names, it filters perfectly (at every keyup event, it loops through all the names to check...). The second time it loops through (the second letter the user types in), it doesn't remove the words anymore... Can somebody help me solve the problem?

Also, when I click the clear button, it clears the screen and puts back all the words from the array, but it doesn't work anymore—it doesn't remove words...

This is my code in my javascript file:

words = ["MARY", "PATRICIA", "LINDA", "BARBARA", "ELIZABETH", "JENNIFER", "MARIA", "SUSAN"]
window.addEventListener("load", CreateWords);
function CreateWords() {
    for (var i = 0; i < words.length; i++) {
        newP = document.createElement('p');
        newP.appendChild(document.createTextNode(words[i]));
        var div = document.getElementById("wordDiv");
        div.appendChild(newP);
        newP.style.fontSize = 20;
        newP.id = words[i];
    }
}

var lettersTyped = document.getElementById("userInput");
lettersTyped.addEventListener("keyup", filterWords);
var clearButton = document.getElementById("clearButton");
clearButton.addEventListener("click", ClearScreen);

function filterWords() {
    for (var i = 0; i < words.length; i++) {
        var val = words[i].toLocaleLowerCase().search(lettersTyped.value);

        if (val == -1) {
            var child = document.getElementById(words[i]);
            child.parentNode.removeChild(child);
        }
    }
}

function ClearScreen() {
    for (var i = 0; i < words.length; i++) {
        newP = document.createElement('p');
        newP.appendChild(document.createTextNode(words[i]));
        var div = document.getElementById("wordDiv");
        div.appendChild(newP);
        newP.style.fontSize = 20;
        newP.id = words[i];
    }
    lettersTyped.value = " ";
}

Upvotes: 2

Views: 165

Answers (1)

user94559
user94559

Reputation: 60153

Here's a fairly minimal fix.

  1. I got rid of CreateWords and just used ClearScreen instead.
  2. I set wordDiv's innerHTML to "" at the top of ClearScreen to avoid seeing duplicate entries. (Your code always adds all the words again, even if some are already there.)
  3. I guarded child.parentNode with an if (child) so it doesn't break when the word is already filtered out.
  4. I set lettersTyped.value to "" instead of " ". (The space was probably breaking things for you.)
  5. I used indexOf instead of search, since you want to match the exact string, not a regular expression.

Here's my completed code:

words = ["MARY", "PATRICIA", "LINDA", "BARBARA", "ELIZABETH", "JENNIFER", "MARIA", "SUSAN"]
window.addEventListener("load", ClearScreen);

var lettersTyped = document.getElementById("userInput");
lettersTyped.addEventListener("keyup", filterWords);
var clearButton = document.getElementById("clearButton");
clearButton.addEventListener("click", ClearScreen);

function filterWords() {
    for (var i = 0; i < words.length; i++) {
        var val = words[i].toLocaleLowerCase().indexOf(lettersTyped.value);

        if (val === -1) {
            var child = document.getElementById(words[i]);
            if (child) {
                child.parentNode.removeChild(child);
            }
        }
    }
}

function ClearScreen() {
    document.getElementById("wordDiv").innerHTML = "";
    for (var i = 0; i < words.length; i++) {
        newP = document.createElement('p');
        newP.appendChild(document.createTextNode(words[i]));
        newP.style.fontSize = 20;
        newP.id = words[i];
        var div = document.getElementById("wordDiv");
        div.appendChild(newP);
    }
    lettersTyped.value = "";
    lettersTyped.focus();
}

Note that there are still some issues with this code. E.g. if you type "mary" and then delete the Y to get "mar", you probably want "MARIA" to show up again. Also, you probably want comparisons to be case-insensitive. (If you type a capital M, it shouldn't filter out "MARY".)

EDIT

A more complete fix, taking into account the other issues I called out. Note that I've gotten rid of the "clear" button altogether, since now the user can just delete their input to see the full list again.

words = ["MARY", "PATRICIA", "LINDA", "BARBARA", "ELIZABETH", "JENNIFER", "MARIA", "SUSAN"];

function filter() {
    document.getElementById("wordDiv").innerHTML = "";
    var typed = document.getElementById("userInput").value.toLocaleLowerCase();

    for (var i = 0; i < words.length; i++) {
        if (words[i].toLocaleLowerCase().indexOf(typed) !== -1) {
            var p = document.createElement("p");
            p.appendChild(document.createTextNode(words[i]));
            document.getElementById("wordDiv").appendChild(p);
        }
    }
}

window.addEventListener("load", filter);
document.getElementById("userInput").addEventListener("keyup", filter);

Upvotes: 2

Related Questions