Little knowledge: introduction to the usage of classList and compatibility with IE8

Posted by jeppers on Tue, 15 Oct 2019 17:24:21 +0200

Preface

Question: how can I use native js instead of element.addClass/removeClass("") to add a class name to the current element?

Answer: you can use the classList in js. It has several callable methods > > > add, remove, toggle, contains, replace, item, among which add / remove can solve your problem.

Introduction usage

add( String [, String] )
Adds the specified class value. If these classes already exist in an element's attributes, they are ignored.
remove( String [,String] )
Deletes the specified class value.
toggle ( String [, force] )
When there is only one parameter: switch class value; that is, if the class exists, delete it and return false; if not, add it and return true.
When there is a second parameter: if the result of the second parameter is true, add the specified class value, and if the result is false, delete it.
contains( String )
Checks whether the specified class value exists in the class attribute of the element.
replace( oldClass, newClass )
Replace an existing class with a new one.
item ( Number )
Returns the class value by the index in the collection.

Small example:

div.classList.add("foo"); //Add a CSS class
div.classList.add("foo","bar"); //Add multiple CSS classes

var list = ["foo","bar"];
div.classList.remove("foo"); //Remove a CSS class
div.classList.remove(...list); //Remove the css class contained in the array list

div.classList.toggle("head"); // That is, if the css class exists in the class, delete it and return false; if not, add it and return true

console.log(div.classList.contains("foo")); // Checks whether the specified class value exists in the class attribute of the element

div.classList.replace("candy", "bar"); // Replace the existing class of bar with the new class of candy.

Compatibility issues

IE browser compatibility issues:

However, it's a pity that some methods in the classList are not compatible below IE10, but we can make a compatibility, which can only be compatible to ie8 at present.

Compatibility Code:

if (!("classList" in document.documentElement)) {
  Object.defineProperty(window.Element.prototype, 'classList', {
    get: function () {
      var self = this
 
      function update(fn) {
        return function () {
          var className = self.className.replace(/^\s+|\s+$/g, ''),
            valArr = arguments
 
          return fn(className, valArr)
        }
      }
 
      function add_rmv (className, valArr, tag) {
        for (var i in valArr) {
          if(typeof valArr[i] !== 'string' || !!~valArr[i].search(/\s+/g)) throw TypeError('the type of value is error')
          var temp = valArr[i]
          var flag = !!~className.search(new RegExp('(\\s+)?'+temp+'(\\s+)?'))
          if (tag === 1) {
            !flag ? className += ' ' + temp : ''
          } else if (tag === 2) {
            flag ? className = className.replace(new RegExp('(\\s+)?'+temp),'') : ''
          }
        }
        self.className = className
        return tag
      }
 
      return {
        add: update(function (className, valArr) {
          add_rmv(className, valArr, 1)
        }),
 
        remove: update(function (className, valArr) {
          add_rmv(className, valArr, 2)
        }),
 
        toggle: function (value) {
          if(typeof value !== 'string' || arguments.length === 0) throw TypeError("Failed to execute 'toggle' on 'DOMTokenList': 1 argument(string) required, but only 0 present.")
          if (arguments.length === 1) {
            this.contains(value) ? this.remove(value) : this.add(value)
            return
          }
          !arguments[1] ? this.remove(value) : this.add(value)
        },
 
        contains: update(function (className, valArr) {
          if (valArr.length === 0) throw TypeError("Failed to execute 'contains' on 'DOMTokenList': 1 argument required, but only 0 present.")
          if (typeof valArr[0] !== 'string' || !!~valArr[0].search(/\s+/g)) return false
          return !!~className.search(new RegExp(valArr[0]))
        }),
 
        item: function (index) {
          typeof index === 'string' ? index = parseInt(index) : ''
          if (arguments.length === 0 || typeof index !== 'number') throw TypeError("Failed to execute 'toggle' on 'DOMTokenList': 1 argument required, but only 0 present.")
          var claArr = self.className.replace(/^\s+|\s+$/, '').split(/\s+/)
          var len = claArr.length
          if (index < 0 || index >= len) return null
          return claArr[index]
        }
      }
    }
  })
}

Topics: Attribute IE