web-components/i-gene/components/smartinput.js

83 lines
2.7 KiB
JavaScript

class SmartInput extends HTMLElement {
#data = null;
#rootdoc = null;
#delay = 300;
#value = null;
#timeoutid = null;
#input = null;
#list = null;
#label = null;
constructor(){
super()
this.#rootdoc = this.attachShadow({ "mode" : "open"})
this.render()
}
connectedCallback(){}
set data(data){ this.#data = data; this.render() }
render(){
this.#rootdoc.innerHTML = `
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div>
<div class="d-flex align-items-center" style="gap:5px">
<input class="form-control"/>
<small id="restriction-enzyme-feedback" class="form-text text-muted"></small>
</div>
<div>
<ul class="d-none list-group" style="position:absolute;z-index:1000"></ul>
</div>
<div>
`
this.#list = this.#rootdoc.querySelector("ul")
this.#input = this.#rootdoc.querySelector("input")
this.#label = this.#rootdoc.querySelector("small#restriction-enzyme-feedback")
this.#rootdoc.addEventListener("keydown", ev=>{
if(ev.code === "Escape"){
this.#list.classList.add("d-none")
}
})
this.#input.addEventListener("input", ev=>{
this.#value = ev.target.value
this.#label.textContent = ""
if(this.#timeoutid != null) window.clearTimeout(this.#timeoutid)
this.#timeoutid = window.setTimeout(()=>{
this.renderOptions()
}, this.#delay)
})
this.#input.addEventListener("keypress", ev=>{
if(ev.code === "Enter"){
this.#list.classList.add("d-none")
document.querySelector("igene-data-display").updateEnzyme(this.#input.value)
}
})
this.#list.addEventListener("click", ev=>{
if(ev.target.classList.contains("list-group-item")){
this.#input.value = ev.target.getAttribute("data-sequence")
this.#label.textContent = ev.target.getAttribute("data-enzyme")
this.#list.classList.add("d-none")
document.querySelector("igene-data-display").updateEnzyme(this.#input.value)
}
})
}
renderOptions(){
if(this.#value == null || this.#value === ""){
this.#list.classList.add("d-none")
return
}
const options = this.#data.filter(d=>{
return d.name.startsWith(this.#value) || d.sequence.startsWith(this.#value)
}).map(o=>{
return `
<li class="list-group-item d-flex" style="gap:5px; cursor: pointer;" data-sequence="${o.sequence}" data-enzyme="${o.name}"><span style="pointer-events: none;">${o.name}</span><span style="pointer-events: none;" class="badge bg-primary">${o.sequence}</span></li>
`
}).join("")
this.#list.innerHTML = options
this.#list.classList.remove("d-none")
}
}
window.customElements.define('nw-smart-input', SmartInput);