UNPKG

fz-search

Version:

Fast aproximate string matching library for use in autocomplete, perform both search and highlight.

318 lines (226 loc) 10 kB
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>Demo page for FuzzySearch Suggestion engine</title> <link href="demo.css" rel="stylesheet" type="text/css" /> <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script> <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.11.1/typeahead.jquery.min.js"></script> <!--script src="../dist/FuzzySearch.min.js"></script--> <script src="../dist/FuzzySearch.js"></script> </head> <body> <h1>FuzzySearch Demo</h1> <p>Demo page for <a href="https://github.com/jeancroy/FuzzySearch">FuzzySearch Suggestion engine</a>. </p> <p>Want a minimal setup demo? it's <a href="simple.html">here</a>. </p> <h2>Using Twitter Typeahead</h2> <div class="typeahead"> <input id="demo-query" class="twitter-typeahead" name="demo-query" autocomplete="off" type="text"> </div> <h2>Using Jquery UI Autocomplete</h2> <div class="typeahead"> <input id="demo-query-ui-auto" class="twitter-typeahead" name="demo-query-ui-auto" autocomplete="off" type="text"> </div> <form> <div style="text-align: left;display:inline-block; width:90%; max-width:450px; margin:auto; clear:both; margin-top:40px"> <strong>Tip!</strong> Your query can match multiple field, for example "war&nbsp;scalzi" will score in both title and author fields. You can also use <strong>title:</strong> or <strong>author:</strong> to match a specific field </div> <h2>Dataset</h2> <div style="text-align: left; display:block; width:90%; max-width:500px; margin:auto"> <label><input type="radio" name="source" value="small" checked/> Small book dataset, <a href="books.json">about 2kb</a>* </label><br> <label><input type="radio" name="source" value="medium"/> Medium movie dataset, list of title <a href="movies.json">about 20kb</a> </label><br> <label><input type="radio" name="source" value="large"/> Large book dataset, <a href="books_large.json">about 220kb</a> </label><br> <label><input type="radio" name="source" value="dir"/> Directory dataset (token separated by "/" instead of spaces), <a href="dir.json">about 75kb</a> </label><br> <label><input type="radio" name="source" value="names30k"/> Name dataset (30K names, using faker.js), <a href="names30k.json">about 500kb</a> </label><br> <label><input type="radio" name="source" value="names100k"/> Name dataset (100K names, using faker.js), <a href="names100k.json">about 1.6Mb</a> </label><br> <br> <div> * small book dataset is provided for comparison against a good edit distance implementation <a href="http://fusejs.io/">fuse.js</a> </div> </div> <h2>Options</h2> <div style="text-align: left; display:block; width:90%; max-width:500px; margin:auto"> <label><input type="checkbox" name="fused" id="fused"/> Enable score across word "oldmanwar" -> "<b>old man war</b>" </label><br> <label><input type="checkbox" name="acro" id="acro"/> Enable acronym score "jrrt" can match <b>J</b>ohn <b>R</b>onald <b>R</b>euel <b>T</b>olkien </label><br> <label><input type="checkbox" name="store" id="store"/> Enable Index Store (Can take a few seconds on large data set) </label><br> </div> </form> <!-- allow to scroll so autocomplete is at top of page --> <div style="height: 500px;"></div> <script> // // Create main object // We will fill the data once we have the JSON loaded // var fuzzyhound = new FuzzySearch({output_limit: 6, output_map:"alias"}); // output_limit: number of item to return // // output_map:"alias" : Build a custom output object. // This can be used to reuse same template with different source format // Input - Output mapping is set using keys options see "Dataset switch UI" below // - - - - - - - - - - - - - - - - - - - - - - - // Item template, shared for both auto-completes // - - - - - - - - - - - - - - - - - - - - - - - function itemTemplate(suggestion) { //This template is the same despite the fact source input change format. //This is because we use alias option to transform output. // to make the specific search (title:, author:) work with highlight // the highlight function take an optional second argument: tag name (alias) return [ "<div>", "<span class='title'>\"", fuzzyhound.highlight(suggestion.title,"title"), "\"</span>", "<span class='author'>", (suggestion.author)? " by " + fuzzyhound.highlight(suggestion.author,"author"): "" , "</span>", "<span class='score' title='", suggestion._match ,"'>(&nbsp;", suggestion._score.toFixed(2), "&nbsp;)</span>", "</div>" ].join(""); } // // Use footer to show some performance stats // function footerTemplate() { var render_end = Date.now(); return "<div class='typeahead-footer'> " + "Search took <strong>" + fuzzyhound.search_time.toFixed(3) + " ms</strong><br>" + "Total (search+highlight+render): <strong>" + (render_end - fuzzyhound.start_time).toFixed(3) + " ms</strong><br>" + "Query: <strong>" + fuzzyhound.query.normalized.length + "</strong> chars <br>" + "Source contain " + fuzzyhound.source.length + " Items<br>" + "</div>"; } //- - - - - - - - - - - // Typeahead Setup // - - - - - - - - - - - $('#demo-query').typeahead({ minLength: 2, highlight: false //we'll use FuzzySearch highlight instead }, { name: 'books', limit: 100, // let fuzzyhound.output_limit apply limit source: fuzzyhound, display: "item.title", templates: { suggestion: itemTemplate, footer: footerTemplate, pending: "" } }).bind('typeahead:select', function (ev, suggestion) { alert('Selection: ' + suggestion.item.title); }); //- - - - - - - - - - - // Jquery UI Setup // - - - - - - - - - - - var $el = $("#demo-query-ui-auto"); $el.autocomplete({ minLength: 2, delay: 0, //use FuzzySearch debounce source: function (request, response) { response(fuzzyhound.search(request.term)); } }); //Get instance to extend var $inst = $el.autocomplete("instance"); //Custom item $inst._renderItem = function (ul, item) { return $("<li>").append(itemTemplate(item)).appendTo(ul); }; //Custom footer $inst._renderMenu = function (ul, items) { var nbitems = items.length, i = -1; while (++i < nbitems) { var display = items[i].title; this._renderItem(ul, items[i]).data("ui-autocomplete-item",{display: display, value: display}); } $("<li>").append(footerTemplate()).data("ui-autocomplete-item", {display: "", value: ""}).appendTo(ul); }; // - - - - - - - - - - - - // Setup dataset switch //- - - - - - - - - - - - - $.ajaxSetup({cache: true}); function setsource(url, keys) { $.getJSON(url).then(function (response) { fuzzyhound.setOptions({ source: response, keys: keys }) }); } //Load small dataset by default setsource("books.json", ["title", "author"]); // - - - - - - - - - - - - // Dataset switch UI //- - - - - - - - - - - - - $('input[name=source]:radio').change(function () { switch (this.value) { case "large": setsource("books_large.json", {title:"title", author:"authors.author"} ); break; case "medium": setsource("movies.json", {title:"."} ); //Movie is a list of title. Set output.title to the item break; case "dir": setsource("dir.json", {title: "."}); break; case "names30k": setsource("names30k.json", {title: "."}); break; case "names100k": setsource("names100k.json", {title: "."}); break; case "small": default: setsource("books.json", ["title", "author"]); break; } if (this.value == "dir") { //directory list use slashes as token separator fuzzyhound.setOptions({token_sep: "\\/"}) } else { //undefined is used as a special value to reset option to default fuzzyhound.setOptions({token_sep: undefined}) } }); $('#free').change(function () { fuzzyhound.setOptions({ score_per_token: $(this).is(":checked") }) }); $('#fused').change(function () { fuzzyhound.setOptions({ score_test_fused: $(this).is(":checked") }); }); $('#acro').change(function () { fuzzyhound.setOptions({ score_acronym:$(this).is(":checked"), dirty: true //Acronym building is done at source processing stage so we need to reprocess the source. }); }); $('#store').change(function () { fuzzyhound.setOptions({ use_index_store: $(this).is(":checked"), dirty: true //store is done at source processing stage so we need to reprocess the source. }); }); </script> </body> </html>