I'm working on a project and for that project I have created a custom dropdown international country code selection section, and for that I have injected all the SVG flag icons using innerHTML and I have noticed that after using the 240 lines of innerHTML the performance/ loading speed of my website is being negatively affected by the innerHTML.
Because, the Option tag doesn't support any other HTML tag that why I have to manually inject the span tag to every custom div using innerHTML which makes my site slower. is there any alternate way available to do the same thing using JS. or can we use the innerHTML to inject span tag's for all 240 countries at once by using loops or something.
I need JS solution only. CSS is not working for mine problems.
// Autoclick on the parent div to hide the Dropdown after loading a page (Bug)
window.addEventListener('load', () => {
document.querySelector(".country-code-selector").click();
});
document.addEventListener('DOMContentLoaded', () => {
const head = document.getElementsByTagName('head')[0];
const link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'https://amitdutta.co.in/flag/css/flag-icon.css';
head.appendChild(link);
// Get dropdowns and form
const dropdowns = document.querySelectorAll('[cc-data-dropdown]');
const form = document.querySelector('.country-code-selector form');
// Check if dropdowns exist on page
if (dropdowns.length > 0) {
// Loop through dropdowns and create custom dropdown for each select element
dropdowns.forEach(dropdown => {
createCustomDropdown(dropdown);
});
}
// Check if form element exist on page
if (form !== null) {
// When form is submitted console log the value of the select field
form.addEventListener('submit', (e) => {
e.preventDefault();
console.log('Selected country:', form.querySelector('[name="country"]').value);
});
}
// Create custom dropdown
function createCustomDropdown(dropdown) {
// Get all options and convert them from nodelist to array
const options = dropdown.querySelectorAll('option');
const optionsArr = Array.prototype.slice.call(options);
optionsArr[0].innerHTML = '<span ></span> Afganistan ( 69)';
optionsArr[1].innerHTML = '<span ></span> Albania ( 355)';
optionsArr[2].innerHTML = '<span ></span> Algeria ( 213)';
optionsArr[3].innerHTML = '<span ></span> American Samoa ( 1-684)';
optionsArr[4].innerHTML = '<span ></span> Andorra ( 376)';
optionsArr[5].innerHTML = '<span ></span> Angola ( 244)';
optionsArr[6].innerHTML = '<span ></span> Anguilla ( 1-264)';
optionsArr[7].innerHTML = '<span ></span> Antarctica ( 672)';
optionsArr[8].innerHTML = '<span ></span> Antigua and Barbuda ( 1-268)';
optionsArr[9].innerHTML = '<span ></span> Argentina ( 54)';
optionsArr[10].innerHTML = '<span ></span> Armenia ( 374)';
optionsArr[11].innerHTML = '<span ></span> Aruba ( 297)';
optionsArr[12].innerHTML = '<span ></span> Australia ( 61)';
optionsArr[13].innerHTML = '<span ></span> Austria ( 43)';
optionsArr[14].innerHTML = '<span ></span> Azerbaijan ( 994)';
optionsArr[15].innerHTML = '<span ></span> Bahamas ( 1-242)';
optionsArr[16].innerHTML = '<span ></span> Bahrain ( 973)';
optionsArr[17].innerHTML = '<span ></span> Bangladesh ( 880)';
optionsArr[18].innerHTML = '<span ></span> Barbados ( 1-246)';
optionsArr[19].innerHTML = '<span ></span> Belarus ( 375)';
optionsArr[20].innerHTML = '<span ></span> Belgium ( 32)';
optionsArr[21].innerHTML = '<span ></span> Belize ( 501)';
optionsArr[22].innerHTML = '<span ></span> Benin ( 229)';
optionsArr[23].innerHTML = '<span ></span> Bermuda ( 1-441)';
optionsArr[24].innerHTML = '<span ></span> Bhutan ( 975)';
optionsArr[25].innerHTML = '<span ></span> Bolivia ( 591)';
optionsArr[26].innerHTML = '<span ></span> Bosnia and Herzegovina ( 387)';
optionsArr[27].innerHTML = '<span ></span> Botswana ( 267)';
optionsArr[28].innerHTML = '<span ></span> Brazil ( 55)';
optionsArr[29].innerHTML = '<span ></span> British Indian Ocean Territory ( 246)';
optionsArr[30].innerHTML = '<span ></span> British Virgin Islands ( 1-284)';
optionsArr[31].innerHTML = '<span ></span> Brunei ( 673)';
optionsArr[32].innerHTML = '<span ></span> Bulgaria ( 359)';
optionsArr[33].innerHTML = '<span ></span> Burkina Faso ( 226)';
optionsArr[34].innerHTML = '<span ></span> Burundi ( 257)';
optionsArr[35].innerHTML = '<span ></span> Cambodia ( 855)';
optionsArr[36].innerHTML = '<span ></span> Cameroon ( 237)';
optionsArr[37].innerHTML = '<span ></span> Canada ( 1)';
optionsArr[38].innerHTML = '<span ></span> Cape Verde ( 238)';
optionsArr[39].innerHTML = '<span ></span> Cayman Islands ( 1-345)';
optionsArr[40].innerHTML = '<span ></span> Central African Republic ( 236)';
optionsArr[41].innerHTML = '<span ></span> Chad ( 235)';
optionsArr[42].innerHTML = '<span ></span> Chile ( 56)';
optionsArr[43].innerHTML = '<span ></span> China ( 86)';
optionsArr[44].innerHTML = '<span ></span> Christmas Island ( 61)';
optionsArr[45].innerHTML = '<span ></span> Cocos Islands ( 61)';
optionsArr[46].innerHTML = '<span ></span> Colombia ( 57)';
optionsArr[47].innerHTML = '<span ></span> Comoros ( 269)';
optionsArr[48].innerHTML = '<span ></span> Cook Islands ( 682)';
optionsArr[49].innerHTML = '<span ></span> Costa Rica ( 506)';
optionsArr[50].innerHTML = '<span ></span> Croatia ( 385)';
optionsArr[51].innerHTML = '<span ></span> Cuba ( 53)';
optionsArr[52].innerHTML = '<span ></span> Curacao ( 599)';
optionsArr[53].innerHTML = '<span ></span> Cyprus ( 357)';
optionsArr[54].innerHTML = '<span ></span> Czech Republic ( 420)';
optionsArr[55].innerHTML = '<span ></span> Democratic Republic of the Congo ( 243)';
optionsArr[56].innerHTML = '<span ></span> Denmark ( 45)';
optionsArr[57].innerHTML = '<span ></span> Djibouti ( 253)';
optionsArr[58].innerHTML = '<span ></span> Dominica ( 1-767)';
optionsArr[59].innerHTML = '<span ></span> Dominican Republic ( 1-809)';
optionsArr[60].innerHTML = '<span ></span> East Timor ( 670)';
optionsArr[61].innerHTML = '<span ></span> Ecuador ( 593)';
optionsArr[62].innerHTML = '<span ></span> Egypt ( 20)';
optionsArr[63].innerHTML = '<span ></span> El Salvador ( 503)';
optionsArr[64].innerHTML = '<span ></span> Equatorial Guinea ( 240)';
optionsArr[65].innerHTML = '<span ></span> Eritrea ( 291)';
optionsArr[66].innerHTML = '<span ></span> Estonia ( 372)';
optionsArr[67].innerHTML = '<span ></span> Ethiopia ( 251)';
optionsArr[68].innerHTML = '<span ></span> Falkland Islands ( 500)';
optionsArr[69].innerHTML = '<span ></span> Faroe Islands ( 298)';
optionsArr[70].innerHTML = '<span ></span> Fiji ( 679)';
// More 169 Countries (Currently not added here) -
optionsArr[71].innerHTML = 'No Data Found';
// Create custom dropdown element and add class dropdown to it
// Insert it in the DOM after the select field
const customDropdown = document.createElement('div');
customDropdown.classList.add('cc-dropdown');
dropdown.insertAdjacentElement('afterend', customDropdown);
// Create element for selected option
// Add class to this element, text from the first option in select field and append it to custom dropdown
const selected = document.createElement('div');
selected.classList.add('cc-dropdown-selected');
selected.innerHTML = 'Tel-Code';
customDropdown.appendChild(selected);
// Create element for dropdown menu, add class to it and append it to custom dropdown
// Add click event to selected element to toggle dropdown menu
const menu = document.createElement('div');
menu.classList.add('cc-dropdown-menu');
customDropdown.appendChild(menu);
selected.addEventListener('click', toggleDropdown.bind(menu));
// Create serach input element
// Add class, type and placeholder to this element and append it to menu element
const search = document.createElement('input');
search.placeholder = 'Search Your Country...';
search.type = 'text';
search.classList.add('cc-dropdown-menu-search');
menu.appendChild(search);
// Create wrapper element for menu items, add class to it and append to menu element
const menuItemsWrapper = document.createElement('div');
menuItemsWrapper.classList.add('cc-dropdown-menu-items');
menu.appendChild(menuItemsWrapper);
// Loop through all options and create custom option for each option and append it to items wrapper element
// Add click event for each custom option to set clicked option as selected option
optionsArr.forEach(option => {
const item = document.createElement('div');
item.classList.add('cc-dropdown-menu-item');
item.dataset.value = option.value;
item.innerHTML = option.innerHTML;
menuItemsWrapper.appendChild(item);
item.addEventListener('click', setSelected.bind(item, selected, dropdown, menu));
});
// Add selected class to first custom option
// menuItemsWrapper.querySelector('div').classList.add('selected');
// Add input event to search input element to filter items
// Add click event to document element to close custom dropdown if clicked outside of it
// Hide original dropdown(select)
search.addEventListener('input', filterItems.bind(search, optionsArr, menu));
document.addEventListener('click', closeIfClickedOutside.bind(customDropdown, menu));
dropdown.style.display = 'none';
}
// Toggle dropdown
function toggleDropdown() {
// Check if dropdown is opened and if it is close it, otherwise open it and focus search input
if (this.offsetParent !== null) {
this.style.display = 'none';
} else {
this.style.display = 'block';
this.querySelector('input').focus();
}
}
// Set selected option
function setSelected(selected, dropdown, menu) {
// Get value and label from clicked custom option
const value = this.dataset.value;
const label = this.innerHTML;
// Change the text on selected element
// Change the value on select field
filterDate = /(<span\b[^<>]*><\/span>\s*)\w (?:\s \w )*\s*\((\ [\d-] )\)/g;
selected.innerHTML = label.replace(filterDate, `$1$2`);
dropdown.value = value;
// Close the menu
// Reset search input value
// Remove selected class from previously selected option and show all divs if they were filtered
// Add selected class to clicked option
menu.style.display = 'none';
menu.querySelector('input').value = '';
menu.querySelectorAll('div').forEach(div => {
if (div.classList.contains('selected')) {
div.classList.remove('selected');
}
if (div.offsetParent === null) {
div.style.display = 'block';
}
});
this.classList.add('selected');
}
// Filter items
function filterItems(itemsArr, menu) {
// Get all custom options
// Get the value of search input and convert it to all lowercase characters
// Get filtered items
// Get the indexes of filtered items
const customOptions = menu.querySelectorAll('.cc-dropdown-menu-items div');
const value = this.value.toLowerCase();
const filteredItems = itemsArr.filter(item => item.value.toLowerCase().includes(value));
const indexesArr = filteredItems.map(item => itemsArr.indexOf(item));
// Check if option is not inside indexes array and hide it and if it is inside indexes array and it is hidden show it
var options = itemsArr.length;
itemsArr.forEach(option => {
if (!indexesArr.includes(itemsArr.indexOf(option))) {
customOptions[itemsArr.indexOf(option)].style.display = 'none';
options -= 1;
if (options <= 0) {
customOptions[itemsArr.length - 1].style.display = 'block';
}
} else {
if (customOptions[itemsArr.indexOf(option)].offsetParent === null) {
customOptions[itemsArr.indexOf(option)].style.display = 'block';
}
}
});
}
// Close dropdown if clicked outside dropdown element
function closeIfClickedOutside(menu, e) {
if (e.target.closest('.cc-dropdown') === null && e.target !== this && menu.offsetParent !== null) {
menu.style.display = 'none';
}
}
});
.cc-dropdown-menu-items::-webkit-scrollbar-track {
background-color: #323757;
width: 2px;
}
.cc-dropdown-menu-items::-webkit-scrollbar {
background-color: #323757;
width: 14px;
}
.cc-dropdown-menu-items::-webkit-scrollbar-thumb {
background-color: #e8576f;
border: 4px solid #323757;
z-index: -1;
width: 2px;
min-height: 50px;
}
#phone-number {
width: calc(100% - 120px);
margin-left: 120px;
}
.frm div:nth-child(3) .inputBox .tx {
margin-left: 120px;
}
.frm div:nth-child(3) .inputBox {
display: flex;
}
.frm div:nth-child(3) .inputBox .ln {
margin-left: 120px;
width: calc(100% - 120px);
}
.cc-dropdown {
position: relative;
}
.cc-dropdown-selected {
display: flex;
align-items: center;
justify-content: center;
width: 116px;
height: 40px;
padding: 0 20px 0 10px;
position: relative;
cursor: pointer;
transition: box-shadow .3s ease;
background-color: #323757;
border-radius: 3px;
font-size: 15px;
color: #fff;
}
.cc-dropdown-selected::after {
top: calc(50% - 2px);
right: 10px;
border: solid transparent;
content: '';
height: 0;
width: 0;
position: absolute;
border-top-color:#000;
border-width: 4px;
margin-left: -4px;
}
.cc-dropdown-selected:hover {
box-shadow: 0 0 5px rgba(0,0,0,0.1);
}
.cc-dropdown-menu {
position: absolute;
top: 100%;
left: 0;
width: 273px;
border: 3px solid #323757;
margin-right: -2px;
border-top: 0;
background-color: #fff;
z-index: 9;
margin-top: 10px;
}
.cc-dropdown-menu-items {
max-height: 200px;
width: 270px;
overflow-y: auto;
overflow-x: hidden;
z-index: 9;
}
.cc-dropdown-menu-search {
display: block;
width: 270px;
border: 0;
border-right: 3px solid #323757;
padding: 14px 0px 14px 10px;
font-size: 15px;
font-weight: 550;
color: #fff;
outline: 0;
background-color: #323757;
}
.cc-dropdown-menu-search::placeholder {
color: rgb(214, 214, 214)!important;
}
.cc-dropdown-menu-item {
width: 267px;
border-bottom: 1px solid #323757a6;
font-size: 14px;
font-weight: 550;
cursor: pointer;
z-index: 9;
user-select: none;
padding: 10px 18px 10px 10px;
}
.cc-dropdown-menu-items .flag-icon {
height: 15px;
width: 26px;
margin-right: 3px;
}
.cc-dropdown-menu-item:last-child {
border-bottom: 0;
}
.cc-dropdown-menu-item:hover {
background-color: rgb(228, 228, 228);
}
.cc-dropdown-menu-item.selected {
border: none;
}
.cc-dropdown-selected .flag-icon {
margin-right: 5px!important;
}
.cc-dropdown-menu-item.selected, .cc-dropdown-menu-item.selected:hover {
background-color: #323757c2;
color: #ffffff;
}
.cc-dropdown-menu-item:last-child {
pointer-events: none;
}
<div >
<form >
<div >
<select id="country" name="country" cc-data-dropdown>
<option value="Afganistan"></option>
<option value="Albania"></option>
<option value="Algeria"></option>
<option value="American Samoa"></option>
<option value="Andorra"></option>
<option value="Angola"></option>
<option value="Anguilla"></option>
<option value="Antarctica"></option>
<option value="Antigua and Barbuda"></option>
<option value="Argentina"></option>
<option value="Armenia"></option>
<option value="Aruba"></option>
<option value="Australia"></option>
<option value="Austria"></option>
<option value="Azerbaijan"></option>
<option value="Bahamas"></option>
<option value="Bahrain"></option>
<option value="Bangladesh"></option>
<option value="Barbados"></option>
<option value="Belarus"></option>
<option value="Belgium"></option>
<option value="Belize"></option>
<option value="Benin"></option>
<option value="Bermuda"></option>
<option value="Bhutan"></option>
<option value="Bolivia"></option>
<option value="Bosnia and Herzegovina"></option>
<option value="Botswana"></option>
<option value="Brazil"></option>
<option value="British Indian Ocean Territory"></option>
<option value="British Virgin Islands"></option>
<option value="Brunei"></option>
<option value="Bulgaria"></option>
<option value="Burkina Faso"></option>
<option value="Burundi"></option>
<option value="Cambodia"></option>
<option value="Cameroon"></option>
<option value="Canada"></option>
<option value="Cape Verde"></option>
<option value="Cayman Islands"></option>
<option value="Central African Republic"></option>
<option value="Chad"></option>
<option value="Chile"></option>
<option value="China"></option>
<option value="Christmas Island"></option>
<option value="Cocos Islands"></option>
<option value="Colombia"></option>
<option value="Comoros"></option>
<option value="Cook Islands"></option>
<option value="Costa Rica"></option>
<option value="Croatia"></option>
<option value="Cuba"></option>
<option value="Curacao"></option>
<option value="Cyprus"></option>
<option value="Czech Republic"></option>
<option value="Democratic Republic of the Congo"></option>
<option value="Denmark"></option>
<option value="Djibouti"></option>
<option value="Dominica"></option>
<option value="Dominican Republic"></option>
<option value="East Timor"></option>
<option value="Ecuador"></option>
<option value="Egypt"></option>
<option value="El Salvador"></option>
<option value="Equatorial Guinea"></option>
<option value="Eritrea"></option>
<option value="Estonia"></option>
<option value="Ethiopia"></option>
<option value="Falkland Islands"></option>
<option value="Faroe Islands"></option>
<option value="Fiji"></option>
<option></option>
</select>
</div>
</form>
</div>
CodePudding user response:
One alternative to using the innerHTML property to modify the content of an element is to use DOM manipulation methods to modify the element's content. These methods are generally more efficient and can improve performance, especially when modifying a large number of elements or when working with a large DOM.
An alternative to innerHTML (not the solution, you should try and then discover