#0006 LocalStorage State & Class Toggle

You can read more in the mozilla localStorage API

Try it

Pomodoro Session

Click on the text to mark done.

  • 25 min 1st Pomodoro
  • 5 min break
  • 25 min 2nd Pomodoro
  • 5 min break
  • 25 min 3rd Pomodoro
  • 5 min break
  • 25 min 4th Pomodoro
  • 30 min long break

Selected state is saved even when browser is closed. No cookies used.

Code

html

<!-- "checkme" class is all you need, optional a identifier -->
<span class="checkme">25 min 1st Pomodoro</span>
<span class="checkme" id="pomodoro2">25 min 2nd Pomodoro</span>

css

.checkme, .checkme.active {
    cursor: pointer;
}
.checkme.active {
    background-color: greenyellow;
}

javascript

// define a globally available JSON object
// this is used to not have to every single value in the localStorage,
// instead updating one JSON object
var lsStore = null;

const loadLSValues = () => {
    // load localStorage state into the JSON object
    lsStore = JSON.parse(localStorage.getItem('lsStore'));
    // if not yet defined, create a empty JSON object
    if (lsStore == null) lsStore = {};

    // document identifier, somewhere in the html
    let docid = document.querySelector('#docid')?.value;

    // if no doc-identifier exists, use filename/pathname
    var siteId = docid ? docid : window.location.pathname.split("/").pop();

    // select all elements containing a "checkme" class
    let allel = document.querySelectorAll('.checkme');
    var elcount = 0;
    allel?.forEach(el => {
        // if checkme elements have id's, use those, otherwise 'ch' + counter
        let add = el.id ? el.id : "ch" + elcount;
        // create a hash of the siteID make it hex add the element-id
        let elid = Math.abs(siteId.hashCode()).toString(16) + add;

        // set for current element
        el.setAttribute("id", elid);
        // set toggleFunction for current element
        el.setAttribute('onclick', "toggleLSVal(this)");

        // if value is defined
        if(lsStore[elid] == true) {
            el.classList.contains('active') ? '' : el.classList.toggle('active');
        } else {
            lsStore[elid] = false;
        }

        elcount++;
    });

    // write local lsStore JSON object into browser LocalStorage
    localStorage.setItem('lsStore', JSON.stringify(lsStore));
};

// clear storage & remove active class
const clearLSValues = () => {
    localStorage.setItem('lsStore',JSON.stringify({}));
    let elem = document.querySelectorAll('.active');
    elem.forEach(el => {
        el.classList.remove('active');
    })
};

// toggle active class and save new state to localStorage
const toggleLSVal = (el) => {
    let curVal = el.classList.toggle('active');
    lsStore[el.id] = curVal;
    localStorage.setItem('lsStore', JSON.stringify(lsStore));
};

// used to create a identifier for the stored values
String.prototype.hashCode = function() {
    var hash = 0, i, chr;
    if (this.length === 0) return hash;
    for (i = 0; i < this.length; i++) {
        chr   = this.charCodeAt(i);
        hash  = ((hash << 5) - hash) + chr;
        hash |= 0; // Convert to 32bit integer
    }
    return hash;
};