Reputation: 77
I want to add the International country code selection field in my phone number field for my project. for that I have created a beautiful custom dropdown option selector code with search option. But there's a problem on it and the problem is when someone selects any option "Country Name + Country Code", the exact same value gets updated on the field.
I want only Country code to be selected or updated on the field not the County name. Means want to extract the country's telephone code only not the name. For this purpose I need help of JS experts to implement the functionality.
// Get dropdowns and form
const dropdowns = document.querySelectorAll('[data-dropdown]');
const form = document.querySelector('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);
// 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('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('dropdown__selected');
selected.textContent = optionsArr[0].textContent;
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('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...';
search.type = 'text';
search.classList.add('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('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('dropdown__menu_item');
item.dataset.value = option.value;
item.textContent = option.textContent;
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.textContent;
// Change the text on selected element
// Change the value on select field
selected.textContent = label;
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('.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
itemsArr.forEach(option => {
if(!indexesArr.includes(itemsArr.indexOf(option))) {
customOptions[itemsArr.indexOf(option)].style.display = 'none';
}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('.dropdown') === null && e.target !== this && menu.offsetParent !== null) {
menu.style.display = 'none';
}
}
@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap');
:root {
--primary-color: #009e6c;
--border-color: #eee;
}
* {
box-sizing: border-box;
margin: 0;
}
body {
font-family: 'Roboto', sans-serif;
font-size: 16px;
line-height: 1.5;
}
header {
background-color: var(--primary-color);
color: #fff;
text-align: center;
padding: 50px 0;
margin-bottom: 50px;
}
.container {
max-width: 600px;
margin: 0 auto;
padding-bottom: 50px;
}
.form {
border: 1px solid var(--border-color);
padding: 40px;
}
.form__group {
margin-bottom: 20px;
}
.form__group label {
display: block;
font-size: 14px;
margin-bottom: 5px;
}
.dropdown {
position: relative;
}
.dropdown__selected {
display: flex;
align-items: center;
width: 100%;
height: 40px;
padding: 0 20px 0 10px;
font-size: 14px;
border: 1px solid var(--border-color);
position: relative;
cursor: pointer;
transition: box-shadow .3s ease;
}
.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;
}
.dropdown__selected:hover {
box-shadow: 0 0 5px rgba(0,0,0,0.1);
}
.dropdown__menu {
position: absolute;
top: 100%;
left: 0;
width: 100%;
border: 1px solid var(--border-color);
border-top: 0;
background-color: #fff;
z-index: 5;
display: none;
}
.dropdown__menu_items {
max-height: 210px;
overflow-y: auto;
}
.dropdown__menu_search {
display: block;
width: 100%;
border: 0;
border-bottom: 1px solid var(--border-color);
padding: 12px;
outline: 0;
background-color: #f9f9f9;
}
.dropdown__menu_item {
padding: 10px;
border-bottom: 1px solid var(--border-color);
font-size: 14px;
cursor: pointer;
}
.dropdown__menu_item:last-child {
border-bottom: 0;
}
.dropdown__menu_item:hover {
background-color: var(--border-color);
}
.dropdown__menu_item.selected,
.dropdown__menu_item.selected:hover {
background-color: var(--primary-color);
color: #fff;
}
.btn {
display: inline-flex;
align-items: center;
padding: 10px 20px;
background-color: var(--primary-color);
color: #fff;
border: 0;
outline: 0;
cursor: pointer;
}
<div class="container">
<form class="form">
<div class="form__group">
<label for="country">Select Country Code</label>
<select id="country" name="country" data-dropdown>
<option value="AFG">Afganistan (<span>+93</span>)</option>
<option value="CHN">China (<span>+86</span>)</option>
<option value="FRA">France (<span>+33</span>)</option>
<option value="KOR">South Korea (<span>+82</span>)</option>
<option value="IND">India (<span>+91</span>)</option>
<!-- <option value="PAK">Pakistan (+92)</option>
<option value="BGD">Bangladesh (+880)</option>
<option value="RUS">Russia (+7)</option>
<option value="DEU">Germany (+49)</option> -->
</select>
</div>
<button type="submit" class="btn">Submit</button>
</form>
</div>
Upvotes: 0
Views: 210
Reputation: 496
One option is to use the javascript match()
method to match against a regular expression of the +
character followed by two digits.
\+
matches the +
character and \d{2}
matches exactly two digits together each between 0 and 9.
This is the line I would change in your code to set the field to the country code value:
selected.textContent = label.match(/\+\d{2}/).toString();
Upvotes: 1