Written by Hamilton Cline
Last updated on April 3, 2019, 12:40 pm

Activating Things

It turns out that lots of simple interaction can be added to your app or website with a tiny bit of javascript, and... well a lot of css. But more importantly, the little bit of javascript can be abstracted, and then only css is will be necessary to make new interactions.

Activating things can be seen as the process of adding the class of .active to an element. What does this do? Nothing, until you use that class with css or javascript.

data-activate

For the next few examples, I'll break them down into jQuery, qdelegate, and vanilla javascript examples. Understand that this concept will work perfectly fine without delegation, but not if the elements are being created dynamically after page load.

// jQuery $(document).on("click","[data-activate]",e=>{ $($(e.target).data("activate")) .addClass("active"); }); // qdelegate qdelegate("body")("click","[data-activate]",e=>{ document.querySelectorAll(e.target.dataset.activate) .forEach(o=>o.classList.add("active")); }); // no delegation, vanilla javascript document.querySelectorAll("[data-activate]").forEach(o=>{ o.addEventListener("click",e=>{ document.querySelectorAll(e.target.dataset.activate) .forEach(o=>o.classList.add("active")); }); });

So what is this? This is something where we use the data- attribute concept of html and javascript to add a selector to an element, so that when one element is clicked, it adds a class of active to some other element. Let's see an example.

Activate this.
<div id="activate-1">Activate this.</div> <button type="button" data-activate="#activate-1">Click me to activate that</button>

To be perfectly honest, that probably looked like it didn't work. But it did. The javascript worked. In fact, if you were to browser inspect that "activate this" element, you would notice that, after having clicked the button, it was given an .active class.

Let's add some css to our example to make it change when activated.

Activate this.
<div class="select" id="activate-2">Activate this.</div> <button type="button" data-activate="#activate-2">Click me to activate that</button> .select.active { color:white; background-color:blue; }

Did you catch that? It only happens once. So this is the basic premise of everything that comes after this. Adding or removing a class of active to an element. Everything else is some variation of that, and it all revolves around setting up some one time javascript, and then designing everything else with html and css.

But only being able to activate is not very useful. So let's add a deactivate.

data-deactivate

// jQuery $(document).on("click","[data-deactivate]",e=>{ $($(e.target).data("deactivate")) .removeClass("active"); }); // qdelegate qdelegate("body")("click","[data-deactivate]",e=>{ document.querySelectorAll(e.target.dataset.deactivate) .forEach(o=>o.classList.remove("active")); }); // no delegation, vanilla javascript document.querySelectorAll("[data-deactivate]").forEach(o=>{ o.addEventListener("click",e=>{ document.querySelectorAll(e.target.dataset.deactivate) .forEach(o=>o.classList.remove("active")); }); });

It's the exact same concept. And it's basically got to be duplicated but different. It might be possible to do these all from one concept, but I don't think it's worth your time to explore. They're really small, but they do enough differently.

Activate this.
<div class="select active" id="activate-3">Activate this.</div> <button type="button" data-activate="#activate-3">Activate that</button> <button type="button" data-deactivate="#activate-3">De-activate that</button>

So let's take the previous example and add in our new deactivate button. It works in the exact same way. But this example seems tedious, if we have to switch buttons each time we toggle the value, so let's take it to the next step.

data-toggle

// jQuery $(document).on("click","[data-toggle]",e=>{ $($(e.target).data("toggle")) .toggleClass("active"); }); // qdelegate qdelegate("body")("click","[data-toggle]",e=>{ document.querySelectorAll(e.target.dataset.toggle) .forEach(o=>o.classList.toggle("active")); }); // no delegation, vanilla javascript document.querySelectorAll("[data-toggle]").forEach(o=>{ o.addEventListener("click",e=>{ document.querySelectorAll(e.target.dataset.toggle) .forEach(o=>o.classList.toggle("active")); }); });
Toggle this.
<div class="select" id="activate-4">Toggle this.</div> <button type="button" data-toggle="#activate-4">Toggle that</button>

Same implementation. You should be getting the idea now.

data-activateone

// jQuery $(document).on("click","[data-activateone]",e=>{ $($(e.target).data("activateone")) .addClass("active") .siblings().removeClass("active"); }); // qdelegate qdelegate("body")("click","[data-activateone]",e=>{ document.querySelectorAll(e.target.dataset.activateone) .forEach(o=>Array.from(o.parentElement.children) .forEach(c=>c.classList[o==c?'add':'remove']("active"))); }); // no delegation, vanilla javascript document.querySelectorAll("[data-activateone]").forEach(o=>{ o.addEventListener("click",e=>{ document.querySelectorAll(e.target.dataset.activateone) .forEach(o=>Array.from(o.parentElement.children) .forEach(c=>c.classList[o==c?'add':'remove']("active"))); }); });

Ok, this one is a little different in its idea, and the code got a bit more complicated without jQuery. jQuery has an easy way to select siblings of an element, and do something to them, but in javascript, we have to go to the parent element, get it's children, and then check the children against whether or not the current one is the original one.

So what even is the point of this one. Well sometimes what you want to do is add active to one element, and turn off active on all of its siblings. This gives us a handy way to activate only one item in a list. Let's see it in action.

thing thing thing
<div> <span class="select" id="activate-5-1">thing</span> <span class="select" id="activate-5-2">thing</span> <span class="select" id="activate-5-3">thing</span> </div> <div> <button type="button" data-activateone="#activate-5-1">1</button> <button type="button" data-activateone="#activate-5-2">2</button> <button type="button" data-activateone="#activate-5-3">3</button> </div>

That's it. That's the whole thing. With these four tools, we can make all kinds of interactions. It's possible you can improve these, or add something useful to them. I'd love to hear your ideas, but for now, let's gather them together.

All Together

// jQuery $(document) .on("click","[data-activate]",e=>$($(e.target).data("activate")).addClass("active")); .on("click","[data-deactivate]",e=>$($(e.target).data("deactivate")).removeClass("active")); .on("click","[data-toggle]",e=>$($(e.target).data("toggle")).toggleClass("active")); .on("click","[data-activateone]",e=>$($(e.target).data("activateone")).addClass("active").siblings().removeClass("active")); // qdelegate qdelegate("body") ("click","[data-activate]",e=>{ document.querySelectorAll(e.target.dataset.activate) .forEach(o=>o.classList.add("active")); }) ("click","[data-deactivate]",e=>{ document.querySelectorAll(e.target.dataset.deactivate) .forEach(o=>o.classList.remove("active")); }) ("click","[data-toggle]",e=>{ document.querySelectorAll(e.target.dataset.toggle) .forEach(o=>o.classList.toggle("active")); }) ("click","[data-activateone]",e=>{ document.querySelectorAll(e.target.dataset.activateone) .forEach(o=>Array.from(o.parentElement.children).forEach(c=>c.classList[o==c?'add':'remove']("active"))); }); // no delegation, vanilla javascript document.querySelectorAll("[data-activate]").forEach(o=>{ o.addEventListener("click",e=>{ document.querySelectorAll(e.target.dataset.activate) .forEach(o=>o.classList.add("active")); }); }); document.querySelectorAll("[data-deactivate]").forEach(o=>{ o.addEventListener("click",e=>{ document.querySelectorAll(e.target.dataset.deactivate) .forEach(o=>o.classList.remove("active")); }); }); document.querySelectorAll("[data-toggle]").forEach(o=>{ o.addEventListener("click",e=>{ document.querySelectorAll(e.target.dataset.toggle) .forEach(o=>o.classList.toggle("active")); }); }); document.querySelectorAll("[data-activateone]").forEach(o=>{ o.addEventListener("click",e=>{ document.querySelectorAll(e.target.dataset.activateone) .forEach(o=>Array.from(o.parentElement.children) .forEach(c=>c.classList[o==c?'add':'remove']("active"))); }); });

Examples

Here are some examples that use the data-activate concept here on tutsos.

Written by Hamilton Cline
Last updated on April 3, 2019, 12:40 pm