Home > Mobile >  How to set Background Color on the selected option
How to set Background Color on the selected option

Time:12-26

I have an international custom dropdown country code selector section in my project and the code is working fine, but the problem I am facing right now is that when a user opens the dropdown list second time, then I am unable to get the first selected option highlighted using css.

That means, when a user selects an option for the first time on the dropdown, I want that option to be highlighted using the background color property. So that when user re-open the dropdown menu second time so that they should see the selected option as highlighted.

// Cache the elements
const button = document.querySelector('.telcode');
const container = document.querySelector('.container');
const input = document.querySelector('input');
const list = document.querySelector('.list');

// Add event listeners to the button, input, and list
// We use a process called "event delegation" on the list
// to catch events from its children as they "bubble up" the DOM
// https://dmitripavlutin.com/javascript-event-delegation/
button.addEventListener('click', handleButton);
input.addEventListener('input', handleInput);
list.addEventListener('click', handleListClick);
document.addEventListener('click', handleDocumentClick);

// Handles the document click - it checks to see if the clicked
// part of the document has a parent element which is either
// `null` or is the HTML element, and then closes the container
// if it's open
function handleDocumentClick(e) {
  const { parentElement } = e.target;
  if (!parentElement || parentElement.nodeName === 'HTML') {
    if (container.classList.contains('show')) {
      container.classList.remove('show');
    }  
  }
}

// All of the data held as objects within an array
const data = [
  { name: 'Afganistan', code: '69', flag: 'afg' },
  { name: 'Barbados', code: '1-246', flag: 'brb' },
  { name: 'Bolivia', code: '591', flag: 'bol' },
  { name: 'Cuba', code: '53', flag: 'cub' },
  { name: 'Fiji', code: '679', flag: 'fji' },
];

// Filters the data based on the characters
// at the start of the provided name
function filterData(data, value) {
  return data.filter(obj => {
    return (
      obj.name.toLowerCase().startsWith(value.toLowerCase())
      || obj.code.toLowerCase().startsWith(value.toLowerCase())
    );
  });
}

// Create a series of list items based on the
// data passed to it
function createListHtml(data) {
  return data.map(obj => {
    const { name, code, flag } = obj;
    return `
      <li
        
        data-name="${name}"
        data-code="${code}"
        data-flag="${flag}"
      >
        <div ></div>
        <div >${name} ( ${code})</div>
      </li>
    `;
  }).join('');
}

// Toggle the container on/off
function handleButton() {
  container.classList.toggle('show');
}

// No data available list item
function createNoDataHtml() {
  return '<li >No data available</li>';
}

// When the input is changed filter the data
// according to the current value, and then
// create some list items using that filtered data
function handleInput(e) {
  const { value } = e.target;
  if (value) {
    const filtered = filterData(data, value);
    if (filtered.length) {
      list.innerHTML = createListHtml(filtered);
    } else {
      list.innerHTML = createNoDataHtml();
    }
  } else {
    list.innerHTML = createListHtml(data);
  }
}

// Create some button HTML
function createButtonHtml(code, flag) {
  return `
    <div ></div>
    <div > ${code}</div>
  `;
}

// When an item is clicked, grab the relevant data
// attributes, create the new button HTML, and then 
// close the container
function handleListClick(e) {
  const item = e.target.closest('li') || e.target;
  if (item.classList.contains('item')) {
    const { code, flag } = item.dataset;
    button.innerHTML = createButtonHtml(code, flag);
    container.classList.remove('show');
  }
}

list.innerHTML = createListHtml(data);
.telcode { margin-bottom: 1em; display: flex;}
.telcode div.code, .item div.name { margin-left: 0.25em; }
.container { display: none; }
.show { display: block; }
.list { height: 100px; list-style: none; margin: 1em 0 0 0; padding: 0; overflow-y: scroll; border: 1px soldi darkgray; }
.item { display: flex; padding: 0.25em; border: 1px solid lightgray; }
.item:hover { cursor: pointer; background-color: lightyellow; }
<link href="https://amitdutta.co.in/flag/css/flag-icon.css" rel="stylesheet"/>
<button type="button" >Tel code</button>
<section >
  <input type="text" placeholder="Search for country" />
  <ul ></ul>
</section>

CodePudding user response:

What i changed:

The list wont be created anymore when the page is loaded, it recreates every single time, when the user clicks on the button to open the list. (line 119)

When you click on a country, it saves its "code" into a variable (line 6).

inside function createListHtml() it matches the saved code with every single county, if match, then it gives the entry an id named "selected" (i gave it a yellow background in the css)

I hope you can understand what i wrote :)

Heres the code (i didnt changed the html file) : Css:

.telcode { margin-bottom: 1em; display: flex;}
.telcode div.code, .item div.name { margin-left: 0.25em; }
.container { display: none; }
.show { display: block; }
.list { height: 100px; list-style: none; margin: 1em 0 0 0; padding: 0; overflow-y: scroll; border: 1px soldi darkgray; }
.item { display: flex; padding: 0.25em; border: 1px solid lightgray; }
.item:hover { cursor: pointer; background-color: lightyellow; }
#selected { cursor: pointer; background-color: yellow; }

Js:

// Cache the elements
const button = document.querySelector(".telcode");
const container = document.querySelector(".container");
const input = document.querySelector("input");
const list = document.querySelector(".list");
var selectedCountry = ""; // saved by "code"

// Add event listeners to the button, input, and list
// We use a process called "event delegation" on the list
// to catch events from its children as they "bubble up" the DOM
// https://dmitripavlutin.com/javascript-event-delegation/
button.addEventListener("click", handleButton);
input.addEventListener("input", handleInput);
list.addEventListener("click", handleListClick);
document.addEventListener("click", handleDocumentClick);

// Handles the document click - it checks to see if the clicked
// part of the document has a parent element which is either
// `null` or is the HTML element, and then closes the container
// if it's open
function handleDocumentClick(e) {
  const { parentElement } = e.target;
  if (!parentElement || parentElement.nodeName === "HTML") {
    if (container.classList.contains("show")) {
      container.classList.remove("show");
    }
  }
}

// All of the data held as objects within an array
const data = [
  { name: "Afganistan", code: "69", flag: "afg" },
  { name: "Barbados", code: "1-246", flag: "brb" },
  { name: "Bolivia", code: "591", flag: "bol" },
  { name: "Cuba", code: "53", flag: "cub" },
  { name: "Fiji", code: "679", flag: "fji" },
];

// Filters the data based on the characters
// at the start of the provided name
function filterData(data, value) {
  return data.filter((obj) => {
    return (
      obj.name.toLowerCase().startsWith(value.toLowerCase()) ||
      obj.code.toLowerCase().startsWith(value.toLowerCase())
    );
  });
}

// Create a series of list items based on the
// data passed to it
function createListHtml(data) {
  return data
    .map((obj) => {
      const { name, code, flag } = obj;
      let isSelected = "";
      if (obj.code == selectedCountry) isSelected = "selected";
      console.log(isSelected,obj.code,selectedCountry);
      return `
      <li
        
        data-name="${name}"
        data-code="${code}"
        data-flag="${flag}"
        id="${isSelected}"
      >
        <div ></div>
        <div >${name} ( ${code})</div>
      </li>
    `;
    })
    .join("");
}

// Toggle the container on/off
function handleButton() {
  container.classList.toggle("show");
  list.innerHTML = createListHtml(data);
}

// No data available list item
function createNoDataHtml() {
  return '<li >No data available</li>';
}

// When the input is changed filter the data
// according to the current value, and then
// create some list items using that filtered data
function handleInput(e) {
  const { value } = e.target;
  if (value) {
    const filtered = filterData(data, value);
    if (filtered.length) {
      list.innerHTML = createListHtml(filtered);
    } else {
      list.innerHTML = createNoDataHtml();
    }
  } else {
    list.innerHTML = createListHtml(data);
  }
}

// Create some button HTML
function createButtonHtml(code, flag) {
  return `
    <div ></div>
    <div > ${code}</div>
  `;
}

// When an item is clicked, grab the relevant data
// attributes, create the new button HTML, and then
// close the container
function handleListClick(e) {
  const item = e.target.closest("li") || e.target;
  if (item.classList.contains("item")) {
    const { code, flag } = item.dataset;
    selectedCountry = item.dataset.code;
    button.innerHTML = createButtonHtml(code, flag);
    container.classList.remove("show");
  }
}

Hope this helps! Enjoy coding!

CodePudding user response:

You could use the .setAttribute() method to apply an inline style to the selected li element.

Like this:

item.setAttribute("style", "background-color: lightyellow;");

Before, you'll need to reset any previously highlighted element with this method:

function resetSelection() {
  let items = document.querySelectorAll("li[style]"), item;
  for (let i = 0; i < items.length; i  ) {
    item = items[i];
    item.removeAttribute("style");
  }
}

See the full example below:

// Cache the elements
const button = document.querySelector('.telcode');
const container = document.querySelector('.container');
const input = document.querySelector('input');
const list = document.querySelector('.list');

// Add event listeners to the button, input, and list
// We use a process called "event delegation" on the list
// to catch events from its children as they "bubble up" the DOM
// https://dmitripavlutin.com/javascript-event-delegation/
button.addEventListener('click', handleButton);
input.addEventListener('input', handleInput);
list.addEventListener('click', handleListClick);
document.addEventListener('click', handleDocumentClick);

// Handles the document click - it checks to see if the clicked
// part of the document has a parent element which is either
// `null` or is the HTML element, and then closes the container
// if it's open
function handleDocumentClick(e) {
  const {
    parentElement
  } = e.target;
  if (!parentElement || parentElement.nodeName === 'HTML') {
    if (container.classList.contains('show')) {
      container.classList.remove('show');
    }
  }
}

// All of the data held as objects within an array
const data = [{
    name: 'Afganistan',
    code: '69',
    flag: 'afg'
  },
  {
    name: 'Barbados',
    code: '1-246',
    flag: 'brb'
  },
  {
    name: 'Bolivia',
    code: '591',
    flag: 'bol'
  },
  {
    name: 'Cuba',
    code: '53',
    flag: 'cub'
  },
  {
    name: 'Fiji',
    code: '679',
    flag: 'fji'
  },
];

// Filters the data based on the characters
// at the start of the provided name
function filterData(data, value) {
  return data.filter(obj => {
    return (
      obj.name.toLowerCase().startsWith(value.toLowerCase()) ||
      obj.code.toLowerCase().startsWith(value.toLowerCase())
    );
  });
}

// Create a series of list items based on the
// data passed to it
function createListHtml(data) {
  return data.map(obj => {
    const {
      name,
      code,
      flag
    } = obj;
    return `
      <li
        
        data-name="${name}"
        data-code="${code}"
        data-flag="${flag}"
      >
        <div ></div>
        <div >${name} ( ${code})</div>
      </li>
    `;
  }).join('');
}

// Toggle the container on/off
function handleButton() {
  container.classList.toggle('show');
}

// No data available list item
function createNoDataHtml() {
  return '<li >No data available</li>';
}

// When the input is changed filter the data
// according to the current value, and then
// create some list items using that filtered data
function handleInput(e) {
  const {
    value
  } = e.target;
  if (value) {
    const filtered = filterData(data, value);
    if (filtered.length) {
      list.innerHTML = createListHtml(filtered);
    } else {
      list.innerHTML = createNoDataHtml();
    }
  } else {
    list.innerHTML = createListHtml(data);
  }
}

// Create some button HTML
function createButtonHtml(code, flag) {
  return `
    <div ></div>
    <div > ${code}</div>
  `;
}

// When an item is clicked, grab the relevant data
// attributes, create the new button HTML, and then 
// close the container
function handleListClick(e) {
  const item = e.target.closest('li') || e.target;
  if (item.classList.contains('item')) {
    const {
      code,
      flag
    } = item.dataset;
    button.innerHTML = createButtonHtml(code, flag);
    container.classList.remove('show');
    resetSelection();
    item.setAttribute("style", "background-color: lightyellow;");
  }
}

function resetSelection() {
  let items = document.querySelectorAll("li[style]"), item;
  for (let i = 0; i < items.length; i  ) {
    item = items[i];
    item.removeAttribute("style");
  }
}

list.innerHTML = createListHtml(data);
.telcode {
  margin-bottom: 1em;
  display: flex;
}

.telcode div.code,
.item div.name {
  margin-left: 0.25em;
}

.container {
  display: none;
}

.show {
  display: block;
}

.list {
  height: 100px;
  list-style: none;
  margin: 1em 0 0 0;
  padding: 0;
  overflow-y: scroll;
  border: 1px soldi darkgray;
}

.item {
  display: flex;
  padding: 0.25em;
  border: 1px solid lightgray;
}

.item:hover {
  cursor: pointer;
  background-color: lightyellow;
}
<link href="https://amitdutta.co.in/flag/css/flag-icon.css" rel="stylesheet" />
<button type="button" >Tel code</button>
<section >
  <input type="text" placeholder="Search for country" />
  <ul ></ul>
</section>

Hope this helps!

Merry Christmas! ✨❤✨

  • Related