A reusable Javascript toggle pattern

This is a toggle pattern that can be reused multiple times on a page with options to customise parts of it. It is a very common pattern, so I've been keen to get it documented for future use.

1: Create the object


//Create the toggler object
    var Toggler = function(rootElement) {
}

The code which eventually ends up inside the curly braces will form the blueprint for every Toggler object. The value inside the parenthesis (rootElement) represents what will be parsed into the function.

2: Create a new instance of the object for each .js-toggleWrapper

//Find all of the instances of the toggler pattern on the page. 
var toggles = doc.querySelectorAll('.js-toggleWrapper');
//Store the total number of toggler patterns
var togglesTotal = toggles.length;
//Counter for the for loop
var i;
//For storing one toggle
var toggle;
//Loop through each Toggler pattern on the page
for ( i = 0; i < togglesTotal; i = i + 1 ) {
    //A new instance of the Toggler object is assigned to the toggle variable on each iteration of the loop
    toggle = new Toggler(toggles[i]);
    //Set the open class 
    toggle.setOpenClass('isOpen');
    //Set the closed class
    toggle.setClosedClass('isClosed');
    //Initialise each toggle
    toggle.init();
}

I have used a loop to find every instance of .js-toggleWrapper and create a new object for it. Without the loop, only the first .js-toggleWrapper on the page will function, which would be fine if I only needed one instance of it. Even if I only wanted to use this pattern once on each page (for now), this could change in the future. This approach means that my code has more chance of standing the test of time and will be more flexible.

toggle.setClosedClass('isClosed'); is where I can set a class to be added and removed from the toggle link as the content toggles open and closed. This is using a method called setOpenClass, which I will create shortly.

Now the objects need to do something; they need some properties and methods.

3. Set some variables

//Create the toggler object
var Toggler = function(rootElement) {
//Set a variable and store the default toggle class which hides and shows the content 
var toggleClass = 'js-toggle';
//Set a variable and store the selector for the toggle action
var toggleActionSelector = '.js-toggleAction';
//A variable to store a class that is added when the content is visible
var openClass;
//A variable to store a class that is added when the content is hidden
var closedClass;
//A variable to store all toggle links
var toggleActions;
//A variable to store a single toggle link
var toggleAction;
//A variable to store the href attribute of the toggle link
var toggleHref;
//A variable to store the content associated to the link
var target;
//A counter to use in for loops
var i;

4. Write some methods

Whilst the content is toggling, I'd like to display icons on the toggle link, which switch depending on whether the content is open or closed. I'd also like to be able to change the icons that appear on different instances of Toggler without having to rewrite the entire JavaScript pattern. I can do this by writing some methods which allow me to set the classes.

//A method for setting a class to be used when the content is open
this.setOpenClass = function(className) {
    openClass = className;
};
//A method for setting a class to be used when content is closed
this.setClosedClass = function(className) {
    closedClass = className;
};
//Method to set the toggle class
this.setToggleClass = function(className) {
    toggleClass = className;
}

As mentioned earlier, I can set the classes when I create new instances of the Toggler object like this: toggle.setClosedClass('isClosed');

5. Create an initialisation method

//Initialisation
this.init = function() {
   //Get the toggle link
   toggleAction = rootElement.querySelector(toggleActionSelector);
   //Add the closed class
   toggleAction.classList.add(closedClass);
   //Get the href attribute of the toggle action link
   toggleHref = toggleAction.getAttribute('href');
   //Get the content with an id matching the href
   target = rootElement.querySelector(toggleHref);
   //Add the toggle class to that content
   target.classList.add(toggleClass);
   //Set aria-hidden attribute to true
   target.setAttribute('aria-hidden', 'true');
   //Add a click event listener to the toggle link
   toggleAction.addEventListener('click', toggle, false);   
}

This function takes place on page load and essentially sets up the object. I've used it to apply whatever needs to happen before the toggle functionality. For example, the 'closed' class and event listeners are applied in this function.

Without JavaScript, the toggler doesn't function and the content is open all the time. I use JavaScript to add the event listener and to add and remove classes for the toggle behaviour. When the toggled content is not visible, I want the attribute aria-hidden="true" to be in the HTML. Since I use JavaScript to hide the toggled content, I also use it to set the value to "true". Without JavaScript it defaults to the HTML, which states aria-hidden="false".

5. Toggle functionality

//Toggle function
var toggle = function(ev) {
    //Toggle the toggle class (on the toggled content)
    target.classList.toggle(toggleClass);
    //if the toggle link contains the closed class
    if (toggleAction.classList.contains(closedClass)) {
        //Remove the closed class and toggle the open class
        toggleAction.classList.remove(closedClass);
        toggleAction.classList.toggle(openClass);
        //Change the aria-hidden attribute value to false
        target.setAttribute('aria-hidden', 'false');
        //Or if the toggle link does not contain the closed class
    } else {
        //Toggle the open and closed classes
        toggleAction.classList.toggle(openClass);
        toggleAction.classList.toggle(closedClass);
        //Change the aria-hidden attribute value to true
        target.setAttribute('aria-hidden', 'true');
    }
        //Prevent the default link behaviour when clicked.
        ev.preventDefault();
    }
};

The toggle function toggles a class called .js-toggle to show and hide the content. The open and closed classes are added and removed, and the aria-hidden values are changed.

The full code is available on codepen:

See the Pen Reusable toggle pattern Javascript by Lottejackson (@lottejackson) on CodePen.