Last active
October 28, 2020 01:25
-
-
Save krmgns/c2ea7c49edf7b757fe9561ba37cb19ca to your computer and use it in GitHub Desktop.
Polyfill: Element.prototype.classList for IE8/9, Safari.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Element.prototype.classList for IE8/9, Safari. | |
* @author Kerem Güneş <[email protected]> | |
* @copyright Released under the MIT License <https://opensource.org/licenses/MIT> | |
* @version 1.2 | |
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/classList | |
*/ | |
;(function() { | |
// Helpers. | |
var trim = function(s) { | |
return s.replace(/^\s+|\s+$/g, ''); | |
}, | |
regExp = function(name) { | |
return new RegExp('(^|\\s+)'+ name +'(\\s+|$)'); | |
}, | |
forEach = function(list, fn, scope) { | |
for (var i = 0; i < list.length; i++) { | |
fn.call(scope, list[i]); | |
} | |
}; | |
// Class list object with basic methods. | |
function ClassList(element) { | |
this.element = element; | |
} | |
ClassList.prototype = { | |
add: function() { | |
forEach(arguments, function(name) { | |
if (!this.contains(name)) { | |
this.element.className = trim(this.element.className +' '+ name); | |
} | |
}, this); | |
}, | |
remove: function() { | |
forEach(arguments, function(name) { | |
this.element.className = trim(this.element.className.replace(regExp(name), ' ')); | |
}, this); | |
}, | |
toggle: function(name) { | |
return this.contains(name) ? (this.remove(name), false) : (this.add(name), true); | |
}, | |
contains: function(name) { | |
return regExp(name).test(this.element.className); | |
}, | |
item: function(i) { | |
return this.element.className.split(/\s+/)[i] || null; | |
}, | |
// bonus | |
replace: function(oldName, newName) { | |
this.remove(oldName), this.add(newName); | |
} | |
}; | |
// IE8/9, Safari | |
// Remove this if statements to override native classList. | |
if (!('classList' in Element.prototype)) { | |
// Use this if statement to override native classList that does not have for example replace() method. | |
// See browser compatibility: https://developer.mozilla.org/en-US/docs/Web/API/Element/classList#Browser_compatibility. | |
// if (!('classList' in Element.prototype) || | |
// !('classList' in Element.prototype && Element.prototype.classList.replace)) { | |
Object.defineProperty(Element.prototype, 'classList', { | |
get: function() { | |
return new ClassList(this); | |
} | |
}); | |
} | |
// For others replace() support. | |
if (window.DOMTokenList && !DOMTokenList.prototype.replace) { | |
DOMTokenList.prototype.replace = ClassList.prototype.replace; | |
} | |
})(); |
Also on line 28, for the remove()
, if the class being removed is in the middle of two other classes rather than an end (and if classes are delimited by only a single space), it loses the space and the surrounding class names get combined into one.
@ballercat; even it is not worth to deal with empty class, fixed it.
@desjardinsm; that was a good catch, thank you, fixed.
And added item()
and other trivial stuff, comments etc.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Please fix line 21. There should be no extra space if className is already empty.