From 8c8ffc0a0d7985b33b5b25c4274646729c0de3b6 Mon Sep 17 00:00:00 2001 From: Phred Date: Tue, 8 Feb 2011 15:58:28 -0800 Subject: [PATCH 1/2] use subclassed array instead of just array methods removed caching (didn't work as expected) --- classList.js | 81 +++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 45 deletions(-) diff --git a/classList.js b/classList.js index 9603891..5c2d254 100644 --- a/classList.js +++ b/classList.js @@ -1,62 +1,53 @@ -(function () { +(function (global) { -if (typeof window.DOMTokenList !== 'undefined') return; +if (typeof global.DOMTokenList !== 'undefined') return; -var indexOf = [].indexOf, - slice = [].slice, - push = [].push, - splice = [].splice, - join = [].join; - -function DOMTokenList(el) { +function DOMTokenList(el) { this._element = el; - if (el.className != this.classCache) { - this._classCache = el.className; - - var classes = this._classCache.split(' '), - i; - for (i = 0; i < classes.length; i++) { - push.call(this, classes[i]); - } - } + this.push.apply(this, el.className.split(regex)); }; function setToClassName(el, classes) { el.className = classes.join(' '); } -DOMTokenList.prototype = { - add: function(token) { - push.call(this, token); - setToClassName(this._element, slice.call(this, 0)); - }, - contains: function(token) { - return indexOf.call(this, token) !== -1; - }, - item: function(index) { - return this[index] || null; - }, - remove: function(token) { - var i = indexOf.call(this, token); - splice.call(this, i, 1); - setToClassName(this._element, slice.call(this, 0)); - }, - toString: function() { - return join.call(this, ' '); - }, - toggle: function(token) { - if (indexOf.call(this, token) === -1) { - this.add(token); - } else { - this.remove(token); +var + key + ,regex = /\s+/g + ,methods = { + add: function(token) { + this.push(token); + setToClassName(this._element, this); + }, + contains: function(token) { + return this.indexOf(token) != -1; + }, + item: function(index) { + return this[index] || null; + }, + remove: function(token) { + this.splice(this.indexOf(token), 1); + setToClassName(this._element, this); + }, + toString: function() { + return this.join(' '); + }, + toggle: function(token) { + this[this.indexOf(token) == -1 ? 'add' : 'remove'](token); } } -}; +; + +// IE doesn't maintain the length of subclassed arrays but we don't need it +DOMTokenList.prototype = new Array; -window.DOMTokenList = DOMTokenList; +for (key in methods) { + DOMTokenList.prototype[key] = methods[key]; +} +global.DOMTokenList = DOMTokenList; Element.prototype.__defineGetter__('classList', function () { return new DOMTokenList(this); }); -})(); +})(this); \ No newline at end of file From 4777688285031df4bcb52e4b5f21cc310d2e6fc6 Mon Sep 17 00:00:00 2001 From: fearphage Date: Fri, 18 Feb 2011 14:55:27 -0600 Subject: [PATCH 2/2] moar caching --- classList.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/classList.js b/classList.js index 5c2d254..efabaac 100644 --- a/classList.js +++ b/classList.js @@ -5,6 +5,10 @@ if (typeof global.DOMTokenList !== 'undefined') return; function DOMTokenList(el) { this._element = el; this.push.apply(this, el.className.split(regex)); + // cache it if we can + if (mutationSupported) { + el._tokenList = this; + } }; function setToClassName(el, classes) { @@ -36,6 +40,8 @@ var this[this.indexOf(token) == -1 ? 'add' : 'remove'](token); } } + ,div = document.createElement('div') + ,mutationSupported = false ; // IE doesn't maintain the length of subclassed arrays but we don't need it @@ -47,7 +53,18 @@ for (key in methods) { global.DOMTokenList = DOMTokenList; Element.prototype.__defineGetter__('classList', function () { - return new DOMTokenList(this); + return this._tokenList || new DOMTokenList(this); }); +// detech mutation support +div.addEventListener('DOMAttrModified' + ,function detectMutation() { + mutationSupported = true; + this.removeEventListener('DOMAttrModified', detectMutation, false); + } + ,false +); +div.setAttribute('foo', 'bar'); +div = null; +document.addEventListener('DOMAttrModified', function (e) { delete e.target._tokenList; }, false); })(this); \ No newline at end of file