Sands QA
Sands QA

Reputation: 17

How can I remember which class was toggled after page reload using local storage

I have a list of items with the same class and a button for each that toggles offline class when clicked. I've used the for loop and forEach loop to iterate through the list using an event listener "click" then check if the item class list contains "offline".If it contains offline the button innerText changes to offline as well as the styling. Now the issue is when I reload the page everything resets. I've tried using local storage but it restores the offline class to every item.

let statusBtn = document.getElementsByClassName("statusBtn");
let status = localStorage.getItem("status");

// Array.prototype.forEach.call(statusBtn, (Btn) => {
//   Btn.addEventListener("click", () => {
//     Btn.classList.toggle("offline");
//     if (Btn.classList.contains("offline") == true) {
//       Btn.innerText = "Offline";
//       localStorage.setItem("status", "offline");
//     } else {
//       Btn.innerText = "Online";
//       Btn.classList.remove("offline");
//       localStorage.setItem("status", "online");
//     }
//   });
// });

for (let i = 0; i < statusBtn.length; i++) {
  statusBtn[i].addEventListener("click", () => {
    statusBtn[i].classList.toggle("offline");
    if (statusBtn[i].classList.contains("offline") == true) {
      statusBtn[i].innerText = "Offline";
      localStorage.setItem("status", "offline");
    } else {
      statusBtn[i].innerText = "Online";
      statusBtn[i].classList.remove("offline");
      localStorage.setItem("status", "online");
    }
  });
}

for (let i = 0; i < statusBtn.length; i++) {
  if (localStorage.getItem("status") === "offline") {
    statusBtn[i].innerText = "Offline";
    statusBtn[i].classList.add("offline");
  }
}
.offline {
  background: #f00;
  color: #fff;
}
<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
</head>

<body>
  <div class="container">
    <div id="inputContainer">
      <input type="text" name="search" id="myInput" placeholder="  Type The Store Name Here" />
    </div>
    <ul id="myUL">
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 935/932
            <button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Anthos: Gauteng, Krugersdorp
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 873<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Athlone: Westerncape, Athlone
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1067<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Arbour-Crossing: KwaZulu-Natal, Amazimtoti
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1052<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Amanzimtoti - KZN Amanzimtoti
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 927/950<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Arcadia: Gauteng, Arcadia, Arcadia
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 889/891<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Atteridgeville: Gauteng, Atteridgeville
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1106<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Avon-Wood: Western Cape, Avonwood
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1159<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Ballito: KwaZulu-Natal, Ballito
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 937<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Beaufort West: Western Cape, Beaufort West
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 968/969<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Bellville Mall: Western Cape, Kuilsriver
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 892<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Benmore: No Collection
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 828/829<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> BirchAcres Mall: Gauteng, Thembisa
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 881<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> BlueDowns: Westerncape, BlueDowns
        </a>
      </li>
    </ul>
  </div>
  <script src="popup.js"></script>
</body>

</html>

Upvotes: 0

Views: 150

Answers (3)

mplungjan
mplungjan

Reputation: 177684

Here is a vastly simplified version

This will make it easier to debug and fix whatever is wrong.

Note I have commented out the localStorage for the snippet. It is not recommended to get the status in a loop.

I store an array and use JSON.parse to read and JSON.stringify to write

const ul = document.getElementById("myUL");
const input = document.getElementById("myInput");
const statusBtn = document.querySelectorAll(".statusBtn");
let status = ["online","offline"]  // JSON.parse(localStorage.getItem("status"));


function myFunction() {
  // Declare variables
  let input, filter, ul, li, a, i, txtValue;
  filter = input.value.toUpperCase();
  lia = ul.querySelectorAll("li a");
  // Loop through all list items, and hide those who don't match the search query
  lia.forEach(a => {
    const txtValue = a.textContent.toUpperCase();
    a.closest("li")
      .classList
      .toggle("hide", input && txtValue.indexOf(filter) === -1)
  })
}
document.getElementById("myInput").addEventListener("keyup", myFunction);

// When the user scrolls the page, execute myFunction
window.onscroll = function() {
  stickySearch();
};
// Get the navbar
let search = document.getElementById("inputContainer");
// Get the offset position of the navbar
let sticky = search.offsetTop;
// Add the sticky class to the navbar when you reach its scroll position. Remove "sticky" when you leave the scroll position
function stickySearch() {
  search.classList.toggle("sticky", window.pageYOffset >= sticky);
}


ul.addEventListener("click", (e) => {
  const tgt = e.target
  tgt.classList.toggle("offline");
  const isOnline = tgt.classList.contains("online")
  tgt.textContent = isOnline ? "Offline" : "Online";
  status[+tgt.dataset.idx]=isOnline ? "offline" : "online";
  // localStorage.setItem("status", JSON.stringify(status));

});


statusBtn.forEach((btn,i) => {
  const isOnline = status[i] === "online"; 
  btn.textContent = isOnline ? "Online" : "Offline";
  btn.dataset.idx=i;
  btn.classList.add(isOnline ? "online" : "offline");
})
@import url("https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@700&display=swap");
body {
  padding: 0;
  scroll-behavior: smooth;
  background: #18202d;
}

.container {
  width: 300px;
  font-family: "Roboto Condensed", sans-serif;
  max-height: 200px;
  scrollbar-width: thin;
}

input {
  height: 25px;
  width: 95%;
  margin-right: 5%;
  border: 1px solid #18202d;
  border-radius: 0.1rem;
  display: flex;
  justify-content: center;
  margin: 0 auto;
}

#myUL {
  list-style-type: none;
  padding: 0;
  margin: 0;
  max-height: 100px;
  z-index: -1;
}

#myUL li {
  border-top: solid 1px #ccc;
  z-index: -1;
}

#myUL li:nth-child(even) {
  background: #2b3546c2;
}

#myUL li a {
  padding: 5px;
  text-decoration: none;
  font-size: 13px;
  color: #fff;
  display: block;
}

#inputContainer {
  padding: 2%;
  background: #18202d;
}

#myUL .ext {
  color: #ccc;
  padding-bottom: 1%;
}

::-webkit-scrollbar {
  display: none !important;
}

.sticky {
  position: fixed;
  top: 0;
  width: 92%;
}

.backToTop {
  color: #fff;
  z-index: 1;
}

.float-end {
  float: right;
  border-radius: 0.1rem;
  border: 1px solid #ccc;
  cursor: pointer;
}

.statusBtn {
  background: #0f0;
}

.offline {
  background: #f00;
  color: #fff;
}

.hide {
  display: none
}
<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
</head>

<body>
  <div class="container">
    <div id="inputContainer">
      <input type="text" name="search" id="myInput" placeholder="  Type The Store Name Here" />
    </div>
    <ul id="myUL">
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 935/932
            <button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Anthos: Gauteng, Krugersdorp
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 873<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Athlone: Westerncape, Athlone
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1067<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Arbour-Crossing: KwaZulu-Natal, Amazimtoti
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1052<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Amanzimtoti - KZN Amanzimtoti
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 927/950<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Arcadia: Gauteng, Arcadia, Arcadia
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 889/891<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Atteridgeville: Gauteng, Atteridgeville
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1106<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Avon-Wood: Western Cape, Avonwood
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 1159<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Ballito: KwaZulu-Natal, Ballito
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 937<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Beaufort West: Western Cape, Beaufort West
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 968/969<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Bellville Mall: Western Cape, Kuilsriver
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 892<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> Benmore: No Collection
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 828/829<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> BirchAcres Mall: Gauteng, Thembisa
        </a>
      </li>
      <li>
        <a href="#">
          <div class="ext"> <i class="bi bi-arrow-right-circle"></i> Ext: 881<button class="float-end statusBtn">Online</button></div>
          <i class="bi bi-geo-alt-fill"></i> BlueDowns: Westerncape, BlueDowns
        </a>
      </li>
    </ul>
  </div>
  <script src="popup.js"></script>
</body>

</html>

Upvotes: 0

Hemera
Hemera

Reputation: 55

Note that with localStorage functions setItem(key, value) getItem(key) removeItem(key) you can only store pair of key and value from type String.
If your project grows with too much stored keys but localStorage is still fine enough another way can be parsing the values from an array by statusArray .join(' ') to one string and get them by statusValue.split(' ').

for (let i = 0; i < statusBtn.length; i++) {
    statusBtn[i].addEventListener("click", () => {
        statusBtn[i].classList.toggle("offline")
        let statusArray = localStorage.getItem("status").split(' ');
        if (statusBtn[i].classList.contains("offline") == true) {
            status[i].innerText = "Offline";
            statusArray[i] = "offline";
        } else {
            statusBtn[i].innerText = "Online";
            statusBtn[i].classList.remove("offline");
            statusArray[i] = "online";
        }
        localStorage.setItem("status", statusArray.join(' '));
    });
}

//LOAD STATE FROM STORAGE
let statusArray = localStorage.getItem("status").split(' ');
for (let i = 0; i < statusBtn.length; i++) {
    if (statusArray[i] === "offline") {
        statusBtn[i].innerText = "Offline";
        statusBtn[i].classList.add("offline");
    }
}

Upvotes: 0

Vinay
Vinay

Reputation: 7676

You can simply add an index and store the status of each button, you can think of each button as a person's name since no two persons should have the same name if you want to store the details of each one reliably

    for (let i = 0; i < statusBtn.length; i++) {
        statusBtn[i].addEventListener("click", () => {
            statusBtn[i].classList.toggle("offline")

            if (statusBtn[i].classList.contains("offline") == true) {
                statusBtn[i].innerText = "Offline";
                localStorage.setItem("status_of_"+ i , "offline");
            } else {
                statusBtn[i].innerText = "Online";
                statusBtn[i].classList.remove("offline");
                localStorage.setItem("status_of_"+i , "online");
            }
        });
    }

    //LOAD STATE FROM STORAGE
    for (let i = 0; i < statusBtn.length; i++) {
        if (localStorage.getItem("status_of_"+i) === "offline") {
            statusBtn[i].innerText = "Offline";
            statusBtn[i].classList.add("offline");
        }
    }

Upvotes: 1

Related Questions