Add, remove or toggle classes with vanilla Javascript

in javascript

The Javascript on my site is fairly basic - controlling the mobile menu toggle and adding a class if Javascript is enabled - so it seemed silly to use jQuery just for a couple of lines. I rewrote the script in plain (or vanilla) Javascript instead of jQuery - here's a couple of key things I came across:

querySelector and querySelectorAll

Finds either the first (querySelector) or every (querySelectorAll) element which matches the selector.

classList

Calling classList returns a list of classes on the element:

<p class="text clearfix">Lorem ipsum</p>
document.querySelectorAll("p").classList;
//-> text clearfix

element.classList has four functions to access or change classes on an element:

querySelector and classList allowed me to replace essentially all of the jQuery code in my script - examples below. It feels good to remove an entire library from my site! (although I am using it on the blog and project pages :P)

Original - using jQuery

// namespace code to prevent collisions or global variables leaking
var jt = jt || {};

// once the page has loaded, fire everything
$(document).ready(function () {
  jt.helpers.jsCheck();
  jt.nav.mobileMenu();
});

// navigation functions
// uses the revealing module pattern
jt.nav = (function () {
  // this hides or shows the mobile menu when the nav button is pressed
  function mobileMenu() {
    $(".nav__mobile-menu").click(function (e) {
      e.preventDefault();

      $(".nav").toggleClass("nav--active");
    });
  }

  return {
    mobileMenu: mobileMenu,
  };
})();

// helper functions
jt.helpers = (function () {
  // this adds a class to the document if JS is enabled in the browser
  function jsCheck() {
    $("html").removeClass("no-js").addClass("js");
  }

  return {
    jsCheck: jsCheck,
  };
})();

Updated version - plain Javascript

var jt = jt || {};

// same functions as above
jt.nav = (function () {
  function mobileMenu() {
    // querySelector returns the first element it finds with the correct selector
    // addEventListener is roughly analogous to $.on()
    document
      .querySelector(".nav__mobile-menu")
      .addEventListener("click", function (e) {
        e.preventDefault();

        // querySelectorAll returns all the nodes it finds with the selector
        // however, you can't iterate over querySelectorAll results (!!)
        // so this is a workaround - call Array.map and pass in the
        // list of nodes along with a function
        // technically querySelectorAll returns a NodeList not an Array so
        /// doesn't have standard array functions
        [].map.call(document.querySelectorAll(".nav"), function (el) {
          // classList is the key here - contains functions to manipulate
          // classes on an element
          el.classList.toggle("nav--active");
        });
      });
  }

  return {
    mobileMenu: mobileMenu,
  };
})();

jt.helpers = (function () {
  function jsCheck() {
    // again, use classList to manipulate classes on elements
    var bodyClass = document.querySelector("html").classList;
    bodyClass.remove("no-js");
    bodyClass.add("js");
  }

  return {
    jsCheck: jsCheck,
  };
})();

// start everything
// this isn't in a doc.ready - loaded at the bottom of the page so the DOM is already ready
jt.helpers.jsCheck();
jt.nav.mobileMenu();