Build a Small Client-Side Search: Worked Workshop

This self-study workshop searches three fictional reading-card titles entirely inside a local page. You will define the matching rule, predict the result for empty and mixed-case queries, and display a title containing angle brackets without treating it as markup. The output is a small transparent filter, not a search service or a connection to a real catalogue.

The MDN filter reference explains that filter() returns a new array of elements that pass a supplied test. An unmatched query can therefore produce an empty result without changing the source list.

Specify the matching contract

Our source titles are Map basics, Model building and the literal text Map <b>card</b>. Ignore surrounding query whitespace and compare the English text without case differences. Match a substring anywhere in the title. An empty trimmed query returns all three titles in their original order.

Complete expected results under this simple contract
Query Matching titles Count
map Map basics; literal Map card markup text 2
MODEL Model building 1
ocean None 0
Spaces only All three titles 3

Before coding, distinguish substring matching from word matching. Under our rule, a query such as mod finds Model building. A production catalogue might need language-specific matching, ranking or spelling support, but those features are outside this deliberately small contract.

Worked filtering and display

const titles = ["Map basics", "Model building", "Map <b>card</b>"];
function findTitles(query) {
  const needle = query.trim().toLowerCase();
  return titles.filter(title => title.toLowerCase().includes(needle));
}

The MDN text-content reference distinguishes plain text from HTML parsing. Assigning textContent replaces a node’s children with text; it does not interpret the supplied title as element markup.

<label>Find a fictional card <input id="query"></label>
<p id="result"></p>
<script>
const query = document.querySelector("#query");
const result = document.querySelector("#result");
function render() {
  const matches = findTitles(query.value);
  result.textContent = matches.length ? matches.join(" | ") : "No matching cards.";
}
query.addEventListener("input", render);
render();
</script>

In the complete local fixture, place the filtering function before this handler. On initial rendering the empty query returns all three titles. The final title’s angle brackets remain visible characters, and the result paragraph contains no bold child element. This is an important part of the answer, rather than an incidental visual preference.

For map, the exact displayed string is Map basics | Map <b>card</b>. For ocean, it becomes No matching cards.. The query field remains unchanged in both cases. The source title array also remains available for the next query.

Diagnose plausible wrong implementations

If the query is lowercased but titles are compared without the corresponding transformation, the mixed-case rule is incomplete. Test the stipulated capitalised query instead of judging the function only on the easiest lowercase example.

If a failed search empties the source array, a later empty query cannot recover all three titles. Keep the collection being searched separate from the current result. A local test should perform an unmatched query followed by a cleared query to expose this kind of state loss.

If the code writes the joined result as HTML, the literal angle-bracket title may no longer be represented as the supplied text. The worked display step deliberately uses a text assignment. This avoids making the interpretation of a title depend on whether its characters happen to resemble tags.

For a next exercise, add tags to each fictional card and decide whether a query searches titles, tags or both. Write an example that distinguishes those policies. A title-only match and an all-fields match answer different questions; switching between them without changing the contract would make the expected-results table misleading.

Questions and final evidence

Retain the four-case table, exact decoded example text, source-array snapshot and the unmatched-to-cleared trace. The local exercise proves neither search quality across languages nor the behaviour of a real website search backend.

Does filtering need to discard the original list?

No. It returns a new array containing the matching elements.

Should the angle-bracket title become a bold element?

No. The worked display assigns plain text.

What does an empty trimmed query return here?

All three fictional titles, in source order.

This is an original INTIAU editorial self-study activity; no qualification is awarded. See Courses and Contact for institutional information.

Related guides

View the study diagram
Three cards separate a matching rule, preserved source collection and literal title display in an original local search exercise.
Original explanatory diagram; consult the linked official guidance for current requirements.

Privacy choices

Optional analytics, advertising measurement and personalisation, and hosting telemetry stay off until you accept. Essential sign-in, security and application tools remain available. You can change this choice at any time.

Read our privacy policy