skip to Main Content

I need to make reservation system for test with HTML, CSS, JS. i need to change color of border from li’s. But i need to select only one li if i select one it must be add class, when i click to other one it need to delete class from first li.

const staff = [
    {
        "id": 1,
        "name": "Alex Rosetta",
        "email": "[email protected]",
        "image": "https://i.ibb.co/LJnNhRF/unsplash-279x-IHym-PYY.png",
    },
    {
        "id": 2,
        "name": "Maria July",
        "email": "[email protected]",
        "image": "https://i.ibb.co/3FhkswY/unsplash-IF9-TK5-Uy-KI.png",
    }
];



staff.map(({ id, name, email, image }) => {

    const list = document.querySelector('.myUl');

    list.innerHTML += `<li class="repoFolder" data-value="${id}">

    <div class="doc-photo">
        <img src="${image}" />
    </div>
    <div class="doc-infos">
        <p class="name">${name}</p>
        <p class="mail">${email}</p>
    </div>
</li>`;
});

var items = document.querySelectorAll(".myUl li");
var tab = [], index;

// function rootFolder() {
//     alert(items.getAttribute('data-value'));
// }

// for (var i = 0; i < items.length; i++) {
//     items[i].onclick = function (e) {
//         alert(e.getAttribute('data-value'));
//     };
// }


for (var i = 0; i < items.length; i++) {
    items[i].onclick = function () {
        console.log(this.getAttribute('data-value'));
        if (this.classList.contains('my-class')) {
            this.classList.remove('my-class');
          } else {
            this.classList.add('my-class');
          }
        

    };
}

i tried this, but didnt work

for (var i = 0; i < items.length; i++) {
    items[i].onclick = function () {
        console.log(this.getAttribute('data-value'));
        if (document.querySelector(".myUl li").classList.contains('my-class')) {
            document.querySelector(".myUl li").classList.remove('my-class');
            this.classList.add('my-class');
          } else {
            this.classList.add('my-class');
          }
        

    };
}

Can someone help please?
Thanks!

2

Answers


  1. You can use toggle instead of add and remove. As second argument you can pass a boolean: let it be true when the iterated item is the clicked one:

    for (const clickedItem of items) {
        clickedItem.addEventListener("click", function () {
            for (const item of items) {
                item.classList.toggle('my-class', item === clickedItem);
            }
        });
    }
    

    Not related, but don’t use .map for iteration when you don’t use its return value. Then use .forEach.

    Login or Signup to reply.
  2. map returns a new array of transformed elements. Since you’re also working with template strings you may as well use that to your advantage. map over the data and return a new (joined) array of HTML strings, and join that up into one HTML string. You can use insertAdjacentHTML to add that to the list element.

    The next step is to use event delegation – attach one listener to the list element and have that watch for events as they bubble up the DOM from its child elements (ie its list items).

    Once it catches an event it first checks that the event occurred within a list item, removes the "active" class from all the list items, and then adds one to the item that fired the event.

    const staff=[{id:1,name:"Alex Rosetta",email:"[email protected]",image:"https://i.ibb.co/LJnNhRF/unsplash-279x-IHym-PYY.png"},{id:2,name:"Maria July",email:"[email protected]",image:"https://i.ibb.co/3FhkswY/unsplash-IF9-TK5-Uy-KI.png"}];
    
    // Returns a joined array of HTML strings
    function getHTML(data) {
      return staff.map(obj => {
        const { id, name, email, image } = obj;
        return `
          <li class="repoFolder" data-value="${id}">
            <div class="doc-photo">
              <img src="${image}" alt="Image of ${name}" />
            </div>
            <div class="doc-infos">
              <p class="name">${name}</p>
              <p class="mail">${email}</p>
            </div>
          </li>
        `;
      }).join('');
    }
    
    // Select the list element and add a listener to it
    const list = document.querySelector('ul');
    list.addEventListener('click', handleList);
    
    // Call `getHTML` with the staff data and insert it
    // into the list element
    list.insertAdjacentHTML('beforeend', getHTML(staff));
    
    // Use the list element to grab all its list items
    const items = list.querySelectorAll('li');
    
    // When the listener on the list element catches an
    // event check that it's a descendant of a list item,
    // remove the "active" classes from the list items,
    // and then add one the list item that caught the event
    function handleList(e) {
      if (e.target.closest('li')) {
        const parent = e.target.closest('li');
        items.forEach(item => item.classList.remove('active'));
        parent.classList.add('active');
      }
    }
    ul { list-style: none; margin: 0; padding: 0; }
    .active { background-color: lightgreen; }
    <ul></ul>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search