---
title: Fuzzy Search
description: Dynamically filter list of items on a page
sass: ./scss/_fuzzysearch.scss
js: ./js/bonsai.fuzzy.search.js
---

## How to use

The Fuzzy Search component can be used to filter a list of data in any container, `li`, `tr`, `div` or any other HTML
element.

In order for the Fuzzy Search component to be able to correctly filter the data, `data-fuzzy-title` attribute
needs to be added to the container element with the text to be used to filter based on the users input.

The last required element in the DOM is what to be shown when there are no results that match the users input, will
default to an element with an id of `no-results`.

**JavaScript Initialization**
```javascript
import { BonsaiFuzzySearch } from "@ithaka/bonsai/js/bonsai.fuzzy.search";

// Initialize the Fuzzy Search component passing in the containers to be hidden/shown
const ExampleSearch = new BonsaiFuzzySearch($("ul#title-search li")});
let searchTimer = 0,
    userQuerySize = 0;

$("#search-filter").on("input propertychange paste", (event) => {
    clearTimeout(searchTimer);

    // Creating a 1/2 sec delay from the users input to when to run the Fuzzy Search
    searchTimer = setTimeout(() => {
        userQuerySize = event.target.value.length;
        // Calling search method with the users query only if there is
        // more than one letter or if the user clears their initial query
        if (userQuerySize === 0 || userQuerySize > 1) {
            ExampleSearch.search(event.target.value);
        }
    }, 500);
});
```

**DOM**
```html_example
<label for="title-search-filter">
    Use this search box to filter the titles below
</label>
<input type="text" id="title-search-filter" class="plm mbl small-8" maxlength="100" placeholder="Search for a title..." aria-controls="title-search">

<ul id="title-search">
    <li data-fuzzy-title="The Shawshank Redemption">
        <div><strong>Title:</strong> The Shawshank Redemption</div>
        <div><strong>Director:</strong> Frank Darabont</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Crime, Drama</div>
    </li>
    <li data-fuzzy-title="The Godfather">
        <div><strong>Title:</strong> The Godfather</div>
        <div><strong>Director:</strong> Francis Ford Coppola</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Crime, Drama</div>
    </li>
    <li data-fuzzy-title="The Dark Knight">
        <div><strong>Title:</strong> The Dark Knight</div>
        <div><strong>Director:</strong> Christopher Nolan</div>
        <div><strong>Rated:</strong> PG-13</div>
        <div><strong>Genre:</strong> Action, Crime, Drama</div>
    </li>
    <li data-fuzzy-title="The Godfather: Part II">
        <div><strong>Title:</strong> The Godfather: Part II</div>
        <div><strong>Director:</strong> Francis Ford Coppola</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Crime, Drama</div>
    </li>
    <li data-fuzzy-title="Pulp Fiction">
        <div><strong>Title:</strong> Pulp Fiction</div>
        <div><strong>Director:</strong> Quentin Tarantino</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Crime, Drama</div>
    </li>
    <li data-fuzzy-title="Schindler's List">
        <div><strong>Title:</strong> Schindler's List</div>
        <div><strong>Director:</strong> Steven Spielberg</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Biography, Drama, History</div>
    </li>
    <li data-fuzzy-title="The Lord of the Rings: The Return of the King">
        <div><strong>Title:</strong> The Lord of the Rings: The Return of the King</div>
        <div><strong>Director:</strong> Peter Jackson</div>
        <div><strong>Rated:</strong> PG-13</div>
        <div><strong>Genre:</strong> Adventure, Drama, Fantasy</div>
    </li>
    <li data-fuzzy-title="The Good, the Bad and the Ugly">
        <div><strong>Title:</strong> The Good, the Bad and the Ugly</div>
        <div><strong>Director:</strong> Sergio Leone</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Western</div>
    </li>
</ul>

<div id="no-results" class="hide">
    No results matching your query
</div>
```

### Additional Filter Data

In some cases, there is a need for more than a single field to filter against. The Fuzzy Search component supports this
by adding additional data attributes with the prefix `data-fuzzy-*`, the `*` just needs to be replaced with the desired
key. The additional keys also need to be passed in the initialization of the component.

**JavaScript Initialization**
```javascript
// The only difference from the default example is on the initialization
// of the Fuzzy Search component to pass in the keys to be used in filtering
// as well as the no results messaging

const ExampleSearch = new BonsaiFuzzySearch(
    $("ul#add-field-search li"),
    {keys: ["title", "director", "genre"]},
    $("#add-field-no-results")
);
```

**DOM**
```html_example
<label for="add-field-search-filter">
    Use this search box to filter the titles below
</label>
<input type="text" id="add-field-search-filter" class="plm mbl small-8" maxlength="100" placeholder="Search for a title, director or genre..." aria-controls="add-field-search">

<ul id="add-field-search">
    <li data-fuzzy-title="The Shawshank Redemption" data-fuzzy-genre="Crime Drama" data-fuzzy-director="Frank Darabont">
        <div><strong>Title:</strong> The Shawshank Redemption</div>
        <div><strong>Director:</strong> Frank Darabont</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Crime, Drama</div>
    </li>
    <li data-fuzzy-title="The Godfather" data-fuzzy-genre="Crime Drama" data-fuzzy-director="Francis Ford Coppola">
        <div><strong>Title:</strong> The Godfather</div>
        <div><strong>Director:</strong> Francis Ford Coppola</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Crime, Drama</div>
    </li>
    <li data-fuzzy-title="The Dark Knight" data-fuzzy-genre="Action Crime Drama" data-fuzzy-director="Christopher Nolan">
        <div><strong>Title:</strong> The Dark Knight</div>
        <div><strong>Director:</strong> Christopher Nolan</div>
        <div><strong>Rated:</strong> PG-13</div>
        <div><strong>Genre:</strong> Action, Crime, Drama</div>
    </li>
    <li data-fuzzy-title="The Godfather: Part II" data-fuzzy-genre="Crime Drama" data-fuzzy-director="Francis Ford Coppola">
        <div><strong>Title:</strong> The Godfather: Part II</div>
        <div><strong>Director:</strong> Francis Ford Coppola</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Crime, Drama</div>
    </li>
    <li data-fuzzy-title="Pulp Fiction" data-fuzzy-genre="Crime Drama" data-fuzzy-director="Quentin Tarantino">
        <div><strong>Title:</strong> Pulp Fiction</div>
        <div><strong>Director:</strong> Quentin Tarantino</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Crime, Drama</div>
    </li>
    <li data-fuzzy-title="Schindler's List" data-fuzzy-genre="Biography Drama History" data-fuzzy-director="Steven Spielberg">
        <div><strong>Title:</strong> Schindler's List</div>
        <div><strong>Director:</strong> Steven Spielberg</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Biography, Drama, History</div>
    </li>
    <li data-fuzzy-title="The Lord of the Rings: The Return of the King" data-fuzzy-genre="Adventure Drama Fantasy" data-fuzzy-director="Peter Jackson">
        <div><strong>Title:</strong> The Lord of the Rings: The Return of the King</div>
        <div><strong>Director:</strong> Peter Jackson</div>
        <div><strong>Rated:</strong> PG-13</div>
        <div><strong>Genre:</strong> Adventure, Drama, Fantasy</div>
    </li>
    <li data-fuzzy-title="The Good, the Bad and the Ugly" data-fuzzy-genre="Western" data-fuzzy-director="Sergio Leone">
        <div><strong>Title:</strong> The Good, the Bad and the Ugly</div>
        <div><strong>Director:</strong> Sergio Leone</div>
        <div><strong>Rated:</strong> R</div>
        <div><strong>Genre:</strong> Western</div>
    </li>
</ul>

<div id="add-field-no-results" class="hide">
    No results matching your query
</div>
```

## Fuzzy Search Configurations

The backend of the Fuzzy Search component uses the node package [Fuse.js](http://fusejs.io/). Besides `keys` attribute,
there are additional configurations related to the logic behind the Fuzzy Search that can be changed.

```javascript
const defaultOptions = {
    // Whether to sort the result list, by score.
    shouldSort: false,

    // List of properties that will be searched.
    keys: ["title"],

    // The maximum length of the pattern. The longer the pattern (i.e. the search query),
    // the more intensive the search operation will be.
    maxPatternLength: 100,

    // Determines how close the match must be to the fuzzy location (specified by location).
    distance: 1000,

    // Determines approximately where in the text is the pattern expected to be found.
    location: 0,

    // At what point does the match algorithm give up. A threshold of 0.0 requires a
    // perfect match (of both letters and location), a threshold of 1.0 would match
    // anything.
    threshold: 0.1,

    // When true, the algorithm will search individual words and the full string,
    // computing the final score as a function of both.
    tokenize: true,

    // When true, the result set will only include records that match all tokens. Will
    // only work if tokenize is also true.
    matchAllTokens: true,

    // The name of the identifier property. If specified, the returned result will be
    // a list of the items' identifiers, otherwise it will be a list of the items.
    id: "itemId"
};
```