JSFiddle - React, Tailwind, and code Playground

sets the data-state attr of elements on the page as they are clicked

by moob

HTML

<div>
  <p>paragraph</p>
  <p>paragraph <strong>strong</strong> <span>span</span></p>
  <a href='#'>link</a><a href='#'>link</a><a href='#'>link</a><a href='#'>link</a><a href='#'>link</a><a href='#'>link</a>
</div>

<ul>
  <li>one</li>
  <li>two</li>
  <li>three</li>
  <li>four</li>
</ul>

<section id="eg1">
  <div>divone<div>divonechild</div></div>
  <div>divtwo<div>divtwochild</div></div>
  <div>divthree<div>divthreechild</div></div>
  <div>divfour<div>divfourchild</div></div>
</section>

<section id="eg2">
  <div>divone<div>divonechild</div></div>
  <div>divtwo<div>divtwochild</div></div>
  <div>divthree<div>divthreechild</div></div>
  <div>divfour<div>divfourchild</div></div>
</section>

CSS

body * {
  background: white;
  border: 1px solid #eee;
  margin: 10px;
}

body *[data-state~="clicked"] {
  border: 1px solid #666;
}

body *[data-state~="on"] {
  outline: 3px solid rgba(255, 155, 155, .5);
}

body *[data-state~="active"] {
  background: rgba(0, 255, 0, 0.2);
}

body *[data-state~="current"] {
  color: red;
  text-decoration:underline;
}

/* eg1 */
section#eg1 > div > div {display:none;}
section#eg1 > div[data-state~="on"] > div {
  display:block;
}
/* eg2 */
section#eg2 > div > div {display:none;}
section#eg2 > div[data-state~="active"] > div {
  display:block;
}

JavaScript

/*
clicked (every element clicked is recorded as such) 
on (every element clicked is marked as on) 
active (only 1 child can be active)
current (the very last element that been clicked)
*/
var state = {
  add: function (el, str) {
    if (!!el.dataset.state) {
      state.remove(el, str);
      el.dataset.state = el.dataset.state+" "+str;
    } else {
      el.dataset.state = str;
    }
  },
  remove: function (el, str) {
    if (!!el.dataset && !!el.dataset.state) {     
      var re = new RegExp(str,"g");
      el.dataset.state = el.dataset.state.replace(re,"");
    }
  },
  toggle: function (el, str) {
    if (state.is(el, str)) {
      state.remove(el, str);
    } else {
      state.add(el, str);
    }
  },
  is: function (el, str) {
    if (!!el.dataset.state) {
      var states = el.dataset.state.split(' ');
      var index = states.indexOf(str); //IE >=9
      if (index > -1) {
        return true
      }
    }
    return false;
  },
  onclick: function (e) {
    //console.log(e.target,e.currentTarget);
    //clicked (every element clicked is recorded as such) 
    state.add(e.target, "clicked");
    //on (every element clicked is marked as on) 
    state.toggle(e.target, "on");
    //active (only 1 child can be active);
    var children = e.target.parentNode.childNodes;
    var n = children.length - 1;
    while (n--) {
      console.log(children[n]);
      state.remove(children[n], "active");
    }
    state.add(e.target, "active");
    //current (the very last element that been clicked)
    var current = document.querySelectorAll('*[data-state~="current"]'),
      i;
    for (i = 0; i < current.length; ++i) {
      state.remove(current[i], "current");
    }
    state.add(e.target, "current");
    
    //
  }
}
document.addEventListener("click", state.onclick, false);


/* perf test */
if(0>1){
var start = performance.now();
for(i=0; i<1000; i++){ 
    
    var str = 'omega iota kappa';
/*
    var items = str.split(' ');
    var index =...