I'm working on a project and for that I have created a custom dropdown international country code selection section, and for that I have injected all the SVG flag icons using span tag to make the code more readable. but the problem I'm facing right now is related to search or filter function.
As I'm using span tag first in my every options of array to show the country flags, that causes a bug, when any user searches for any country, my search function tries to read the option's string from span tag or the very first character of each array, which is causing a problem to show search filtered data.
Note: In the last three options I haven't used the span tag, and here we can see the search filter function working perfectly. can you please tell me how to exclude the span tag from my search function's innerHTML.
FOR EXAMPLE: Let's take the first country Afghanistan ( 93).
I want to develop my search function to work something like this -
➤ When any user tries to search for the string or country "Afghanistan" I want to show this country (Afghanistan) in my search result, also when the user tries to search the country with country code "93" in that case also I want to show the same country (Afghanistan).
Means I want to exclude the "Span Tag" and "()" from my search filter, so that it works perfectly.
const wrapper = document.querySelector(".wrapper"),
selectBtn = wrapper.querySelector(".select-btn"),
searchInp = wrapper.querySelector("input"),
options = wrapper.querySelector(".options");
let countries = [
// With span Tag --------->
"<span class='flag-icon flag-icon-afg'></span> Afghanistan ( 93)",
"<span class='flag-icon flag-icon-bel'></span> Belgium ( 32)",
"<span class='flag-icon flag-icon-chn'></span> China ( 86)",
// Without span Tag --------->
"France ( 33)",
"India ( 91)",
"Mexico ( 52)"
];
function addCountry(selectedCountry) {
options.innerHTML = "";
countries.forEach(country => {
let isSelected = country == selectedCountry ? "selected" : "";
let li = `<li onclick="updateName(this)" >${country}</li>`;
options.insertAdjacentHTML("beforeend", li);
});
}
addCountry();
function updateName(selectedLi) {
searchInp.value = "";
addCountry(selectedLi.innerHTML);
wrapper.classList.remove("active");
filterData = /(<span\b[^<>]*><\/span>\s*)\w (?:\s \w )*\s*\((\ [\d-] )\)/g;
selectBtn.firstElementChild.innerHTML = selectedLi.innerHTML.replace(filterData, `$1$2`);;
}
//------ PLEASE CHECK HERE --------//
searchInp.addEventListener("keyup", () => {
let arr = [];
let searchWord = searchInp.value.toLowerCase();
arr = countries.filter(data => {
return data.toLowerCase().startsWith(searchWord);
}).map(data => {
let isSelected = data == selectBtn.firstElementChild.innerHTML ? "selected" : "";
return `<li onclick="updateName(this)" >${data}</li>`;
}).join("");
options.innerHTML = arr ? arr : `<p style="margin-top: 10px;">Oops! Country not found</p>`;
});
selectBtn.addEventListener("click", () => wrapper.classList.toggle("active"));
document.addEventListener('click', (event)=> {
if (!wrapper.contains(event.target)) {
wrapper.classList.remove("active");
}else{
wrapper.classList.add("active");
}
});
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
body{
background: #4285f4;
}
::selection{
color: #fff;
background: #4285f4;
}
.wrapper{
width: 370px;
margin: 85px auto 0;
}
.select-btn, li{
display: flex;
align-items: center;
cursor: pointer;
}
.select-btn{
height: 65px;
padding: 0 20px;
font-size: 22px;
background: #fff;
border-radius: 7px;
justify-content: space-between;
box-shadow: 0 10px 25px rgba(0,0,0,0.1);
}
.select-btn i{
font-size: 31px;
transition: transform 0.3s linear;
}
.wrapper.active .select-btn i{
transform: rotate(-180deg);
}
.content{
display: none;
padding: 20px;
margin-top: 15px;
background: #fff;
border-radius: 7px;
box-shadow: 0 10px 25px rgba(0,0,0,0.1);
}
.wrapper.active .content{
display: block;
}
.content .search{
position: relative;
}
.search i{
top: 50%;
left: 15px;
color: #999;
font-size: 20px;
pointer-events: none;
transform: translateY(-50%);
position: absolute;
}
.search input{
height: 50px;
width: 100%;
outline: none;
font-size: 17px;
border-radius: 5px;
padding: 0 20px 0 43px;
border: 1px solid #B3B3B3;
}
.search input:focus{
padding-left: 42px;
border: 2px solid #4285f4;
}
.search input::placeholder{
color: #bfbfbf;
}
.content .options{
margin-top: 10px;
max-height: 250px;
overflow-y: auto;
padding-right: 7px;
}
.options::-webkit-scrollbar{
width: 7px;
}
.options::-webkit-scrollbar-track{
background: #f1f1f1;
border-radius: 25px;
}
.options::-webkit-scrollbar-thumb{
background: #ccc;
border-radius: 25px;
}
.options::-webkit-scrollbar-thumb:hover{
background: #b3b3b3;
}
.options li{
height: 50px;
padding: 0 13px;
font-size: 21px;
}
.options li:hover, li.selected{
border-radius: 5px;
background: #f2f2f2;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Custom Select Menu | CodingNepal</title>
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://amitdutta.co.in/flag/css/flag-icon.css">
</head>
<body>
<div >
<div >
<span>Select Country</span>
<i ></i>
</div>
<div >
<div >
<i ></i>
<input spellcheck="false" type="text" placeholder="Search">
</div>
<ul ></ul>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
CodePudding user response:
If you replace startsWith
with includes
then the span and the parentheses have no effect on the search. You can type "Afg" or "93" and you will find Afghanistan.
return data.toLowerCase().includes(searchWord);
CodePudding user response:
Here you can use a object where you specify two keys i.e. flag and country and then while searching, search in data.country instead of data and do not use startWith rather use includes which will search thorughout your data.country and while displaying the searched data only print data.country .
let countries = [
{
flag :"<span class='flag-icon flag-icon-afg'></span>",
country : "Afghanistan ( 93)"
}
//....so on for different countries
]
// and for searching you can use
//return data.country.toLowerCase().includes(searchWord);