Home > Enterprise >  How to keep track (write, read, update) of element states via localStorage?
How to keep track (write, read, update) of element states via localStorage?

Time:09-12

first of all, I apologize that I don't speak English, I am trying to improve in this language.

I have a problem that I don't know how to solve it, I have a web in WordPress and it creates buttons dynamically with some dynamic classes, I need to take 1 of those classes to do the following:

Let's imagine that we have 5 buttons, when I clicked on 1 of those 5 that the other 4 buttons are hidden and this is saved in the local storage, ie everything is kept in the browser.

I have this code:

 $('.dce-button').click(function(event){
      $(this).attr('data-id' , 'Next');
      localStorage.setItem("class", "noDisplay");
      localStorage.setItem("noDisplay", "true");
      $('.dce-button').not(this).each(function(){
       $(this).toggleClass("noDisplay");
      });
})

I use it to select the button I need and WORKS, it disappears the other 4 but I don't know how to keep it with the local storage, Is someone can help me?

CodePudding user response:

Something like this would work and address Peter's comment

(working JS fiddle since localStorage isnt accessible in snippets on SO https://jsfiddle.net/f7804xwc/1/)

  // on page load, get the stored value if there is one and set the buttons accordingly
  let selectedBtn = localStorage.getItem('selectedBtn');
  if (selectedBtn) {
    $('.dce-button').hide();
    $('#' selectedBtn).show()
  }


  $('.dce-button').click(function(event) {
    let selectedBtn = localStorage.getItem('selectedBtn');
    console.log(selectedBtn);
    if (selectedBtn === this.id) {
      // user clicked the selected button again, lets un-select it and re-show all the buttons
      localStorage.removeItem('selectedBtn');
      $('.dce-button').show();

    } else {
      // user clicked a button, store selection and hide the others
      localStorage.setItem("selectedBtn", this.id);
      $('.dce-button').not(this).each(function() {
        $(this).hide();
      });
    }
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button  id="btn1">Button 1</button><br>
<button  id="btn2">Button 2</button><br>
<button  id="btn3">Button 3</button><br>
<button  id="btn4">Button 4</button><br>
<button  id="btn5">Button 5</button><br>

CodePudding user response:

From the above comment ...

"Once the OP has managed to solve writing to and reading from the local storage the proper button state there will be never a chance of any other button visible than the very one which was selected at the very first time (unless one resets/erases the local storage's state(s))."

... and all code of the next provided example which relates to initStorageRelatedUIHandling (the last 3 buttons which are for logging, clearing and rendering from the local storage's current state) is going to prove the above said/commented.

Now as for a possible solution, I personally would chose an approach which stores the state(s) of any DCE related button as a JSON.stringify 'ed array. Thus one does not rely on any specific button identification but stays generic from the beginning based on just a list of queried (jquery or selector api ... it doesn't matter) DOM nodes.

One would write 2 functions writeDceState and readDceState which both take care of the storage and JSON handling.

Another function like updateDceState exclusively takes care of generating the current array representation of any buttons state based on the currently targeted/selected button. It queries a list of all DCE buttons and does map each visibility state as false except for the currently chosen. It finally forwards the updated state to writeDceState.

The render part is covered exclusively by renderDceStateFromStorage. It reads the most current state from storage and updates each button's visibility from the parsed array.

Then there is a sole handler function ... handleDceStateChange ... which on click invokes both functions one after the other ... updateDceState and renderDceStateFromStorage.

function writeDceState(state = null) {
  // `mock` is a specifc namespace which carries
  // `localStorage` behavior for SO environments.
  // - Thus the next line can be omitted later.
  const { localStorage } = mock;

  localStorage
    .setItem('dce', JSON.stringify(state)
  );
}
function readDceState() {
  // `mock` is a specifc namespace which carries
  // `localStorage` behavior for SO environments.
  // - Thus the next line can be omitted later.
  const { localStorage } = mock;

  return JSON
    .parse(
      localStorage.getItem('dce') || null
    );
}

function updateDceState(dceTarget) {
  const state = Array
    .from(
      document
        .querySelectorAll('.dce-button')
    )
    .map(elm => (elm === dceTarget));

  writeDceState(state);
}
function renderDceStateFromStorage() {
  const state = readDceState();
  document
    .querySelectorAll('.dce-button')
    .forEach((elm, idx) =>
      elm.disabled = !!state && !state[idx]
    );
}

function handleDceStateChange({ currentTarget }) {
  updateDceState(currentTarget);
  renderDceStateFromStorage();
}

function initDceHandling() {
  document
    .querySelectorAll('.dce-button')
    .forEach(elm =>
      elm.addEventListener('click', handleDceStateChange)
    );
}
function initStorageRelatedUIHandling() {
  document
    .querySelector('[data-state-display]')
    .addEventListener('click', () =>
      console.log( readDceState() )
    );
  document
    .querySelector('[data-state-clear]')
    .addEventListener('click', mock.localStorage.clear);

  document
    .querySelector('[data-state-rerender]')
    .addEventListener('click', renderDceStateFromStorage);
}

initDceHandling();
initStorageRelatedUIHandling();
body { margin: 0; }
ul { list-style: none; padding: 0; margin: 0; }
li:nth-child(6) { margin-top: 20px; }
li:nth-child(8) { margin-top: 10px; }
.as-console-wrapper { left: auto!important; width: 50%; min-height: 100%; }
<ul>
  <li>
    <button >Foo</button>
  </li>
  <li>
    <button >Bar</button>
  </li>
  <li>
    <button >Baz</button>
  </li>
  <li>
    <button >Biz</button>
  </li>
  <li>
    <button >Buzz</button>
  </li>
  <li>
    <button data-state-clear>clear storage state</button>
  </li>
  <li>
    <button data-state-display>display storage state</button>
  </li>
  <li>
    <button data-state-rerender>rerender from storage</button>
  </li>
</ul>

<script>
  // mock for the SO specific stack snippet
  // due to the policies and environment are
  // not allowing an original storage access.
  const mock = {
    localStorage: (function () {

      // https://developer.mozilla.org/en-US/docs/Web/API/Storage
      // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
      const storage = new Map;

      function key(int) {
        return [
          ...storage.keys()
        ][parseInt(int, 10)];
      }

      function setItem(key, value) {
        return storage.set(String(key), String(value));
      }
      function getItem(key) {
        return storage.get(String(key));
      }

      function removeItem(key) {
        return storage.delete(String(key));
      }

      function clear() {
        return storage.clear();
      }

      return {
        get length() {
          return storage.size;
        },
        key,
        getItem,
        setItem,
        removeItem,
        clear,      
      };

    }()),
  }
</script>

  • Related