What you will build and need

A glossary is a useful first filtering project: it has a small set of entries, a search field, and an immediate result you can see. In this version, every entry lives in a local JavaScript array. There is no server, package manager, or database. Typing part of a term or its definition narrows the visible entries without changing the original array.

You need a modern browser with developer tools and a page you can edit. Save the script below as app.js and load it from your page after the document body is available, such as with a deferred script. You can also run it in the developer console on a page you control. The example uses standard browser DOM methods and JavaScript features including const, arrow functions, and array filtering.

Store the glossary as data

Each glossary entry will be an object with a term and a definition. Keeping entries in one array makes them easier to review and extend than scattering text throughout the interface code. The sample includes three web-development terms, but the filter does not depend on those particular words.

The script checks both fields when it searches. That means someone who remembers a concept but not its name can still find it by typing a word from its definition. The search is case-insensitive and ignores spaces at the beginning or end of the query. It does not attempt to correct spelling or find synonyms; those would be separate features.

Create the interface and filter the entries

Add this complete script to app.js. It creates a heading, a labeled search field, a status message, and a list. Because the script creates its own elements, the page does not need pre-existing glossary elements. Make sure it runs only once per page load, or it will add a second interface.

const entries = [ { term: "Array", definition: "An ordered collection of values." }, { term: "DOM", definition: "A browser representation of a web page." }, { term: "Event", definition: "An action a page can respond to, such as typing." } ]; const heading = document.createElement("h1"); heading.textContent = "Web development glossary"; const label = document.createElement("label"); label.textContent = "Search terms and definitions: "; const search = document.createElement("input"); search.type = "search"; label.append(search); const status = document.createElement("p"); status.setAttribute("role", "status"); const list = document.createElement("ul"); document.body.append(heading, label, status, list); function render(query) { const normalizedQuery = query.trim().toLowerCase(); const matches = entries.filter((entry) => { const searchableText = `${entry.term} ${entry.definition}`.toLowerCase(); return searchableText.includes(normalizedQuery); }); list.replaceChildren(); status.textContent = matches.length === 0 ? "No matching entries." : `${matches.length} ${matches.length === 1 ? "entry" : "entries"} found.`; matches.forEach((entry) => { const item = document.createElement("li"); const term = document.createElement("strong"); term.textContent = entry.term; item.append(term, document.createTextNode(`: ${entry.definition}`)); list.append(item); }); } search.addEventListener("input", () => render(search.value)); render("");

The first call to render shows every entry: every string includes an empty search string. After that, the input event runs the same function whenever the field changes, including when someone deletes text. Each render clears the previous results before adding the new ones, so entries do not accumulate. The status message makes a zero-result search understandable instead of leaving an unexplained blank list.

Try it, then make it your own

Load the page and check the starting list. Type “array” to find the first entry, then try “browser” to match the DOM definition. Search for a word that is not present to check the empty state, and clear the field to bring all entries back. Try mixed-case text and extra spaces to confirm that normalization works. If nothing appears, check the browser console for an error and confirm that app.js runs after the page body exists.

To expand the project, add another object to entries with the same term and definition keys. The renderer uses textContent and createTextNode rather than treating glossary text as page markup, so an entry containing characters such as angle brackets displays as text. For a longer glossary, you might later sort results or add category filters. Keep this first version small enough that you can explain its full path: data goes into filter, matches go into render, and render updates the page.

Back to category ↗