-
-
Save bryanerayner/8be2ff8353bf33a0f3ec to your computer and use it in GitHub Desktop.
Change jQuery to use the more performant classList over string concatenation methods, when ClassList is available
This file contains hidden or 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
/** | |
* jQuery extension, add support `classList`. | |
* | |
* @author RubaXa <[email protected]>, bryanerayner <[email protected]> | |
* @license MIT | |
*/ | |
(function ($) { | |
var | |
_rspace = /\s+/ | |
, _$cache = $('<div/>') | |
, _div = _$cache[0] | |
, _classList = _div.classList | |
, _supportsArgs | |
; | |
var _each = function ($el, method, callback) { | |
$el.each(function (i) { | |
_$cache[0] = this; | |
_$cache[method](callback.call(this, i, _$cache.attr('class'))); | |
}); | |
} | |
var _factory = function (method) { | |
return function (value) { | |
var typeOf = typeof value, i = this.length; | |
if ('string' === typeOf) { | |
value = $.trim(value); | |
if ("" !== value) { | |
value = value.split(_rspace); | |
var j, n = value.length, list; | |
while (i--) { | |
list = this[i].classList; | |
if (1 === n) { | |
list[method](value[0]); | |
} | |
else if (_supportsArgs) { | |
list[method].apply(list, value); | |
} | |
else { | |
for (j = 0; j < n; j++) { | |
list[method](value[j]); | |
} | |
} | |
} | |
} | |
} | |
else if ((void 0 === value) && ('remove' === method)) { | |
while (i--) { | |
this[i].className = ''; | |
} | |
} | |
else if ('function' === typeOf) { | |
_each(this, method + 'Class', value); | |
} | |
return this; | |
} | |
} | |
if (_classList) { | |
_classList.add('-a', 'b-'); | |
_supportsArgs = /-a/.test(_div.className) && /b-/.test(_div.className); | |
/** | |
* Has class | |
* | |
* @param {string} className | |
* @returns {boolean} | |
*/ | |
$.fn.hasClass = function (className) { | |
className = $.trim(className); | |
var splitClassNames = className.split(_rspace); | |
var s = splitClassNames.length; | |
var i = this.length; | |
var numContained = 0; | |
while (i--) { | |
numContained = 0; | |
for (var q = 0; q < s; q++) { | |
if (this[i].classList.contains(splitClassNames[q])) { | |
numContained++; | |
} | |
} | |
if (numContained === s) | |
{ | |
return true; | |
} | |
} | |
return false; | |
}; | |
/** | |
* Add class | |
* | |
* @param {string|function} value | |
* @returns {jQuery} | |
*/ | |
$.fn.addClass = _factory('add'); | |
/** | |
* Remove class | |
* | |
* @param {string|function} value | |
* @returns {jQuery} | |
*/ | |
$.fn.removeClass = _factory('remove'); | |
} | |
// Cleanup | |
_$cache[0] = _div = _classList = null; | |
})(jQuery); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Revised the file to properly declare nested functions (they should be variables) and support cases where 'hasClass' is queried by user input with a space separated string