D.Fody
D.Fody

Reputation: 13

change element style depending on local storage

I have created a toggle input, where staff can set whether they are in or out of the office. I am using local storage to save the state of the input. When I add more than one toggle input onto the page, each input's state can be changed but when I reload the page all inputs are the same due to the local storage set on the last input ( i.e all to out ).

How do I save each toggles state and use local storage to remember this?

CSS CODE

<style type="text/css">
    .toggle {
      -webkit-appearance: none;
      appearance: none;
      width: 150px;
      height: 60px;
      display: inline-block;
      position: relative;
      border-radius: 50px;
      overflow: hidden;
      outline: none;
      border: none;
      cursor: pointer;
      background-color: red;
      transition: background-color ease 0.3s;
    }

    .toggle:before {
      content: "in out";
      display: block;
      position: absolute;
      z-index: 2;
      width: 80px;
      height: 70px;
      top: -5px;
      left: -10px;
      background: #fff;
      border-radius: 50%;
      font: 30px/70px Helvetica;
      text-transform: uppercase;
      font-weight: bold;
      text-indent: -40px;
      word-spacing: 85px;
      color: #fff;
      text-shadow: -1px -1px rgba(0,0,0,0.15);
      white-space: nowrap;
      box-shadow: 0 1px 2px rgba(0,0,0,0.2);
      transition: all cubic-bezier(0.3, 1.5, 0.7, 1) 0.3s;
    }

    .toggle:checked {
      background-color: #4CD964;
    }

    .toggle:checked:before {
      left: 75px;
    }

    .toggle.in {
        background-color: #4CD964;
    }

    .toggle.in:before {
        left: 75px;
    }

</style>

HTML CODE

<input class="toggle" type="checkbox" />
<input class="toggle" type="checkbox" />

JQUERY CODE

var toggle = $('.toggle');
toggle.on('click', function(){
    if ( $('input[type=checkbox]:checked').length === 0 ) {
        localStorage.setItem('result', 'out');
        $(this).removeClass('in');  
    } else {
        localStorage.setItem('result', 'in');
        $(this).addClass('in');
    }
})

if ( localStorage.result === 'in' ) {
    toggle.addClass('in');
} else {
    toggle.removeClass('in');
}

Upvotes: 1

Views: 901

Answers (2)

Rory McCrossan
Rory McCrossan

Reputation: 337560

Your issue is because you're only saving a single state and applying it to all checkboxes. Therefore the state applied last will be given to all on the next load of the page.

To fix this it would make far more sense to use an array. You can then store the state of every checkbox and re-apply when the page next loads, something like this:

var $toggles = $('.toggle').on('click', function() {
  var checkedStates = $toggles.map(function() {
    return this.checked;
  }).get();
  localStorage.setItem('checkedStates', JSON.stringify(checkedStates));
  $(this).toggleClass('in');
})

if (localStorage.getItem('checkedStates')) {
  JSON.parse(localStorage.getItem('checkedStates')).forEach(function(checked, i) {
    $('.toggle').eq(i).prop('checked', checked).toggleClass('in', checked)
  });
}
.toggle {
  -webkit-appearance: none;
  appearance: none;
  width: 150px;
  height: 60px;
  display: inline-block;
  position: relative;
  border-radius: 50px;
  overflow: hidden;
  outline: none;
  border: none;
  cursor: pointer;
  background-color: red;
  transition: background-color ease 0.3s;
}

.toggle:before {
  content: "in out";
  display: block;
  position: absolute;
  z-index: 2;
  width: 80px;
  height: 70px;
  top: -5px;
  left: -10px;
  background: #fff;
  border-radius: 50%;
  font: 30px/70px Helvetica;
  text-transform: uppercase;
  font-weight: bold;
  text-indent: -40px;
  word-spacing: 85px;
  color: #fff;
  text-shadow: -1px -1px rgba(0, 0, 0, 0.15);
  white-space: nowrap;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
  transition: all cubic-bezier(0.3, 1.5, 0.7, 1) 0.3s;
}

.toggle:checked {
  background-color: #4CD964;
}

.toggle:checked:before {
  left: 75px;
}

.toggle.in {
  background-color: #4CD964;
}

.toggle.in:before {
  left: 75px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<input class="toggle" type="checkbox" />
<input class="toggle" type="checkbox" />

As SO places limits on the access to localStorage in a snippet, please see this fiddle for a working example:

Example Fiddle

Upvotes: 1

Vipin Kumar
Vipin Kumar

Reputation: 6546

Yo need to add an identifier to your checkboxes. Each time a checkbox is changed overwrite the value in localStorage and retrieve on page load. Also, use an array to save it in localStorage, becasue it will be easier to work with native JS objects rather than comma separated string.

See below

HTML

<input name="chk1" class="toggle" type="checkbox" />
<input name="chk2" class="toggle" type="checkbox" />

JavaScript

var toggle = $('.toggle');

function updateStorage() {
  var storage = [];
  toggle.each(function() {
    storage.push({
      name: $(this).attr('name'),
      checked: $(this).prop('checked'),
    })
  });
  localStorage.setItem('prefix-result', JSON.stringify(storage));
}

function loadStorage() {
  var storage = localStorage.getItem('prefix-result');
  storage = storage ? JSON.parse(storage) : [];
  storage.forEach(function (item) {
    $('input[name=' + item.name + ']').prop('checked', item.checked)
  })
}

loadStorage();
toggle.on('change', updateStorage);

In your current code, you are using single key to save both values. That may work if you add both values but won't work if you overwrite previous one.

Upvotes: 0

Related Questions