1
0
mirror of https://github.com/nextapps-de/flexsearch.git synced 2025-09-25 12:58:59 +02:00
Files
flexsearch/demo/autocomplete.html
2025-04-13 15:44:20 +02:00

269 lines
8.1 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1, maximum-scale=1.0, user-scalable=no, viewport-fit=cover, shrink-to-fit=no, minimal-ui">
<title>Demo: Auto-Complete</title>
<style>
body{
padding: 0;
margin: 0 10px;
font-family: Helvetica, Arial, sans-serif;
font-size: 14px;
}
#header{
position: fixed;
top: 10px;
left: 10px;
width: 100%;
display: flex;
justify-content: flex-start;
flex-direction: row;
max-width: 500px;
table-layout: fixed;
background-color: #fff;
z-index: 1;
}
input[type="text"]{
width: 100%;
border: 1px solid #ddd;
border-radius: 4px;
outline: none;
background-color: transparent;
position: absolute;
-webkit-appearance: none;
}
#autocomplete{
color: #999;
background-color: #f5f5f5;
pointer-events: none;
}
#trigger-prev,
#trigger-next{
pointer-events: none
}
input{
padding:7px 5px;
box-sizing: border-box;
}
#suggestions{
position: relative;
top: 50px;
}
#suggestions div{
padding: 10px 8px;
border-bottom: 1px solid #ddd;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: calc(100% - 16px);
}
#suggestions b{
color: blue;
}
#suggestions:empty:before{
content: "No resuls found";
font-size: 12px;
color: #999;
margin-left: 7px;
}
#info{
position: absolute;
bottom: 7px;
left: 12px;
color: #888;
}
label{
width: 100px;
height: 32px;
display: flex;
align-items: center;
margin: 0 10px;
}
@media only screen and (max-width: 600px) {
body{
font-size: 12px;
}
input[type="text"]{
/*width: 98%;*/
}
}
</style>
</head>
<body>
<div id="header">
<div style="position: relative; width: 100%;">
<input type="text" id="trigger-prev">
<input type="text" id="autocomplete" disabled>
<input type="text" id="userinput" placeholder="Search by movie title ..." autocorrect="off" spellcheck="false" autocomplete="off" autofocus>
<input type="text" id="trigger-next">
</div>
<label>
<input type="checkbox" id="suggest" checked> Suggest
</label>
</div>
<div id="suggestions"></div>
<!--<div id="info">iterate results by arrow keys</div>-->
<script type="module">
//import { Document, Charset } from "https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@master/dist/flexsearch.bundle.module.min.js";
import { Document, Charset } from "../src/bundle.js";
//import EnglishPreset from "../src/lang/en.js";
import data from "https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@master/demo/data/movies.js";
// for "Result Highlighting" it requires the usage of a Document Index
// also when just adding id-content-pairs to a single index
const index = new Document({
// the cache is a perfect addition
// for an instant search on keypress
cache: true,
document: {
// it requires storing the documents
store: true,
index: [{
field: "title",
// a forward tokenizer is minimum
// required by an instant search
tokenize: "forward"
}]
}
});
for(let i = 0; i < data.length; i++){
// pass a flat pseudo document when using
// result highlighting on plain string inputs
index.add(i, {
"title": data[i]
});
}
const suggestions = document.getElementById("suggestions");
const autocomplete = document.getElementById("autocomplete");
const userinput = document.getElementById("userinput");
const suggest = document.getElementById("suggest");
const trigger_prev = document.getElementById("trigger-prev");
const trigger_next = document.getElementById("trigger-next");
let results;
let iterate = 0;
userinput.addEventListener("input", show_results, true);
userinput.addEventListener("keyup", accept_autocomplete, true);
userinput.addEventListener("keydown", iterate_autocomplete, true);
suggest.addEventListener("change", toggle_suggest, true);
suggestions.addEventListener("click", accept_suggestion, true);
trigger_prev.addEventListener("focus", function(){
if(iterate > 0) {
iterate_autocomplete({ key: "ArrowUp"});
}
userinput.focus();
}, true);
trigger_next.addEventListener("focus", function(){
if(iterate < results.length){
iterate_autocomplete({ key: "ArrowDown"});
}
userinput.focus();
}, true);
function toggle_suggest(){
// changing any of the search options requires
// deletion of cached results (when using cache)
index.cache.clear();
show_results();
}
function show_results(){
let value = userinput.value;
results = index.searchCache({
query: value,
limit: 25,
suggest: suggest.checked,
enrich: true,
highlight: "<b>$1</b>"
});
results = results[0] || results;
results = results.result || results;
iterate = 0;
let entry, childs = suggestions.childNodes;
let i = 0, len = results.length;
for(; i < len; i++){
entry = childs[i];
if(!entry){
entry = document.createElement("div");
suggestions.appendChild(entry);
}
entry.innerHTML = results[i].highlight; //data[results[i]];
}
while(childs.length > len){
suggestions.removeChild(childs[i]);
}
iterate_autocomplete()
}
function iterate_autocomplete(event){
suggestions.childNodes[iterate] &&
(suggestions.childNodes[iterate].style.backgroundColor = "");
if(event){
const key = event.key;
if(key === "ArrowUp"){
if(iterate > 0){
iterate--;
}
event.preventDefault &&
event.preventDefault();
}
else if(key === "ArrowDown"){
if(iterate < results.length){
iterate++;
}
event.preventDefault &&
event.preventDefault();
}
}
let value = userinput.value;
let first_result = results && results[iterate] && data[results[iterate].id];
let match = first_result && first_result.toLowerCase().indexOf(value.toLowerCase());
if(first_result && (match !== -1)){
autocomplete.value = value + first_result.substring(match + value.length);
autocomplete.current = first_result;
suggestions.childNodes[iterate] &&
(suggestions.childNodes[iterate].style.backgroundColor = "rgb(0 0 255 / 10%)");
}
else{
autocomplete.value = autocomplete.current = value;
}
}
function accept_autocomplete(event){
if((event || window.event).keyCode === 13) {
this.value = autocomplete.value = autocomplete.current;
suggestions.textContent = "";
}
}
function accept_suggestion(event){
let target = (event || window.event).target;
userinput.value = autocomplete.value = target.textContent;
suggestions.textContent = "";
return false;
}
</script>
</body>
</html>