I created a search bar with element suggestion after typing words. I would like here after the display of the list of suggestions that I can click on a result and that it is positioned on the input.
script.js
const articles = [
{name:'matoss'},
{name:'solution'},
{name:'moloss'},
{name:'KARKAN'}
];
const rechercheInput=document.getElementById('rechercheInput');
rechercheInput.addEventListener('keyup',function(){
const input = rechercheInput.value;
const result =
articles.filter(item=>item.name.toLocaleLowerCase().includes(input.toLocaleLowerCase()));
let suggestion ='';
if(input != ''){
result.forEach(resultItem =>
suggestion = `<div >${resultItem.name}</div>`
)
}
document.getElementById('suggestions').innerHTML=suggestion;
})
index.html
<form method="get" action="">
<input type="search" name="recherche" placeholder="code article.." id="rechercheInput"
required>
<div id="suggestions"></div>
<button type="submit">Recherche
<i >search</i>
</button>
</form>
CodePudding user response:
The following snippet does exactly what you described with JavaScript.
const articles = [{
name: 'matoss'
},
{
name: 'solution'
},
{
name: 'moloss'
},
{
name: 'KARKAN'
}
];
// DOM element handles
const input = document.getElementById('rechercheInput')
const suggestions = document.getElementById('suggestions')
const submitBtn = document.getElementById('submit')
// handling form submit
submitBtn.addEventListener('click', function(e) {
e.preventDefault() // only for the snippet - you might not need this
})
// utils
const toLowerCase = (s) => s.toLowerCase()
const strIncludes = (s1) => (s2) => s1.includes(s2)
const filterByName = (val) => ({
name
}) => strIncludes(toLowerCase(name))(toLowerCase(val))
// emptying a DOM element (#suggestions)
const empty = (element) => {
while (element.firstElementChild) {
element.firstElementChild.remove();
}
}
// getting the items from the possible articles
const getFilteredArray = (arr) => (keyword) => keyword ? arr.filter(filterByName(keyword)) : []
const getFilteredArticles = getFilteredArray(articles)
// input event handler
input.addEventListener('input', function(e) {
const filteredArticles = getFilteredArticles(e.target.value)
updateSuggestions(suggestions, this)(filteredArticles)
})
// creating suggestion item DOM element
const getSuggestionItemEl = (suggestion) => {
const suggestionItem = document.createElement('div')
suggestionItem.classList.add('suggestion-item')
suggestionItem.textContent = suggestion.name
return {
suggestionItem,
}
}
// base for handling click on suggestion items
const getListenerFn = (input, article, callback) => (e) => {
input.value = article.name
if (callback && callback instanceof Function) {
// if a callback function is defined, then it's called with
// the following args
callback(input)
}
}
// updating the suggestions list
const updateSuggestions = (container, input) => (filteredArticles) => {
// 1. emptying the container
empty(container)
// 2. generating the DOM elements; adding click handler;
// adding generated elements to the container (#suggestions)
filteredArticles.forEach((article) => {
const {
suggestionItem
} = getSuggestionItemEl(article)
suggestionItem.addEventListener('click', getListenerFn(input, article, (input) => updateSuggestions(container, input)(getFilteredArticles(input.value))))
container.append(suggestionItem)
})
}
.suggestion-item {
cursor: pointer;
transition: all 0.4s;
}
.suggestion-item:hover {
background-color: rgba(0, 0, 0, 0.3);
transition: all 0.2s;
}
<form method="get" action="">
<input type="search" name="recherche" placeholder="code article.." id="rechercheInput" required>
<button id="submit" type="submit">Recherche
<i >search</i>
</button>
<div id="suggestions"></div>
</form>