DEV Community

Amanda Jayathilaka
Amanda Jayathilaka

Posted on

Add Fast Fuzzy Search to a Directory Site with Fuse.js published: false

Build a typo-tolerant, debounced search box for a listing site using Fuse.js and vanilla JavaScript.

When a directory has hundreds of listings, users want to type "dalas" and still find Dallas. Fuse.js gives you fuzzy matching in a few lines.

I added this to a bank branch directory where people search by city, street, or branch name.

Install

npm install fuse.js
Enter fullscreen mode Exit fullscreen mode

Set up the index

import Fuse from "fuse.js";

const branches = [
  { name: "Chase Bank, Dallas", area: "LBJ and Abrams" },
  { name: "Chase Bank, Chicago", area: "Lawrence and Kedzie" },
  { name: "Chase Bank, Las Vegas", area: "Centennial Crossroads" },
];

const fuse = new Fuse(branches, {
  keys: ["name", "area"],
  threshold: 0.35,
  ignoreLocation: true,
});
Enter fullscreen mode Exit fullscreen mode

Debounce the input

Without it you re-run the search on every keystroke.

function debounce(fn, delay = 200) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}
Enter fullscreen mode Exit fullscreen mode

Wire it up

<input id="search" type="search" placeholder="Search by city or street">
<ul id="results"></ul>
Enter fullscreen mode Exit fullscreen mode
const input = document.querySelector("#search");
const list = document.querySelector("#results");

const render = (items) => {
  list.replaceChildren(
    ...items.map(({ item }) => {
      const li = document.createElement("li");
      li.textContent = `${item.name} (${item.area})`;
      return li;
    })
  );
};

input.addEventListener(
  "input",
  debounce((e) => {
    const q = e.target.value.trim();
    render(q ? fuse.search(q).slice(0, 10) : []);
  })
);
Enter fullscreen mode Exit fullscreen mode

textContent keeps user input and data from being interpreted as HTML.

Tuning

  • Lower threshold means stricter matching, higher means more forgiving.
  • Weight important keys: { name: "name", weight: 2 }.
  • For tens of thousands of records, consider a server-side search or a worker thread.

Top comments (0)