3
\$\begingroup\$

I wrote this function that will toggle a class of a targeted element. Applying the class js_class_toggle to any element will trigger the function when clicking on it.

To define what the target element is and the class you want to toggle is, you have to add data-class-toggle="target_element_id.className" to the element. You can also add this to any element on the page and it will work the same since its targeting the element by its id.

For example:

<div id="test_element" class="js_class_toggle" data-class-toggle="test_element.className">
    This element will have a class toggled
</div>

JS:

$(document).on("click", ".js_class_toggle", function(e){

    //Set variables
    var element = $(e.currentTarget),
        elementsClasses = element.attr('data-class-toggle'),
        elementsClassesSplit = elementsClasses.split('.'),
        targetElement = elementsClassesSplit[0],
        targetClass = elementsClassesSplit[1];


    //Toggle the class
    $("#"+targetElement).toggleClass(targetClass);
});

Here is a working example of it: https://jsfiddle.net/fxo1a5w3/2/

What i will work on next is to be able to have multiple toggles in the same request, for example:

<div id="test_element" class="js_class_toggle" data-class-toggle="element1.className2,element2.className2">
    This element will have its class toggled
</div>

But before that i want to know if there is a better way of doing what i have done so far. The goal is for it to be a function that can be used in any project.

\$\endgroup\$
  • \$\begingroup\$ I like the idea but I wonder what added value a small framework around toggleClass could provide. Maybe your extended framework would clarify this. \$\endgroup\$ – dfhwze Jun 3 at 17:34
  • \$\begingroup\$ Sorry i don't understand exactly what you mean, are you asking how i am using this code in my actual project? \$\endgroup\$ – K.D Jun 3 at 17:58
  • \$\begingroup\$ I am more interested to see your extended API with support for multiple class toggles. This simple API you have so far doesn't show me the potential of your API yet :) \$\endgroup\$ – dfhwze Jun 3 at 18:00
4
\$\begingroup\$

You can access the data element via dataset property and camelCase data name

const data = element.dataset.classToggle;

You can add a click event to the document as follows that will only do something if the target is class js_class_toggle

const togClass = `.js_class_toggle`;

addEventListener("click", e => {
    if (e.target.classList.contains(togClass)) {
        /* ...do stuff... */
    }
}

Or you can add a click to each element containing the class.

document.querySelectorAll(togClass).forEach(el => el.addEventListener("click", toggleClick));

By the looks you are toggling the class on the element that is clicked so there is no need to add the reference

<div class="js_class_toggle toggle-me" data-class-toggle="toggle-me">
    This element will have a class toggled
</div>

making the function to toggle very simple

function toggleClick(e) {
     e.target.classList.toggle(e.target.dataset.classToggle);
}

To include the reference id you can make the data JSON like

<div id = "foo" class="js_class_toggle toggle-me" 
    data-class-toggle='{"query": "#foo", "toggleClass": "toggle-me"}'>
    This element will have a class toggled
</div>

Then the function becomes

function toggleClick(e) {
     const data = JSON.parse(e.target.dataset.classToggle);
     const el = document.querySelector(data.query);
     if (el) { el.classList.toggle(data.toggleClass) }
}
\$\endgroup\$
  • \$\begingroup\$ Thanks for the feedback! I actually use this code for toggling other elements classes too. For example, i have a button that when you click on it, a form loads on to the page, the form loads in place of another element that says "start typing". clicking on either the button or the "start typing" element, will give the "start typing" element a class that will show a loading indicator. So when i click on either that element, or on the button, i want that loader to show. I also add another class to the actual button when clicking on it. So i toggle 2 classes for 2 different elements. \$\endgroup\$ – K.D Jun 4 at 18:08
  • \$\begingroup\$ And i actually did just convert the code to use JSON instead of what i had before, and with the suggestions of some i managed to reduce the amount of code in the function as well as make it simpler. So yes to the JSON suggestion! \$\endgroup\$ – K.D Jun 4 at 18:10
2
\$\begingroup\$

Suggestions for simplifying

elementsClasses = element.attr('data-class-toggle'),

There's a jQuery method for simplifying that: .data(). It only allows typing five fewer characters:

elementsClasses = element.data('class-toggle')

The click handler registration could be simplified from

$(document).on("click", ".js_class_toggle", function(e){

to:

$('.js_class_toggle').click(function(e){

If you utilize Array destructuring assignment, then the following three lines could be simplified:

elementsClassesSplit = elementsClasses.split('.'),
targetElement = elementsClassesSplit[0],
targetClass = elementsClassesSplit[1];

To a single line:

[targetElement, targetClass] = elementsClasses.split('.')

Though make sure you are aware of the Browser support.

\$\endgroup\$
  • \$\begingroup\$ Right, i forgot about .data()! I used the .on() function because if an element is loaded through ajax that should have this functionality, this function wont work on it (as far as i know and have tested) because that element would have been loaded after the document has loaded. Anywhere i read about this says to use .on instead of .click, but maybe i'm/they`re wrong. And i didn't know that last suggestion exists! I'll update my code and see how its going after that. Thanks! \$\endgroup\$ – K.D Jun 3 at 17:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.