Merge pull request #81 from mysticatea/fixes-70

Fixes #70
This commit is contained in:
John Messerly
2014-12-18 10:17:37 -08:00
2 changed files with 67 additions and 9 deletions

View File

@@ -7,34 +7,61 @@
* Code distributed by Google as part of the polymer project is also
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/
// NOTE: Set the 'ownerElement_' property on a DOMTokenList to make invalidation
// happen. This is pretty hacky but we only have to do it in one place
// (Element.js) currently so it seems like the least bad option.
(function(scope) {
'use strict';
var unsafeUnwrap = scope.unsafeUnwrap;
var enqueueMutation = scope.enqueueMutation;
function getClass (el) {
return unsafeUnwrap(el).getAttribute('class');
}
function enqueueClassAttributeChange(el, oldValue) {
enqueueMutation(el, 'attributes', {
name: 'class',
namespace: null,
oldValue: oldValue
});
}
function invalidateClass(el) {
scope.invalidateRendererBasedOnAttribute(el, 'class');
}
function changeClass(tokenList, method, args) {
var ownerElement = tokenList.ownerElement_;
if (ownerElement == null) {
return method.apply(tokenList, args);
}
var oldValue = getClass(ownerElement);
var retv = method.apply(tokenList, args);
if (getClass(ownerElement) !== oldValue) {
enqueueClassAttributeChange(ownerElement, oldValue);
invalidateClass(ownerElement);
}
return retv;
}
var oldAdd = DOMTokenList.prototype.add;
DOMTokenList.prototype.add = function() {
oldAdd.apply(this, arguments);
this.ownerElement_ && invalidateClass(this.ownerElement_);
changeClass(this, oldAdd, arguments);
};
var oldRemove = DOMTokenList.prototype.remove;
DOMTokenList.prototype.remove = function() {
oldRemove.apply(this, arguments);
this.ownerElement_ && invalidateClass(this.ownerElement_);
changeClass(this, oldRemove, arguments);
};
var oldToggle = DOMTokenList.prototype.toggle;
DOMTokenList.prototype.toggle = function(token) {
var rv = oldToggle.apply(this, arguments);
this.ownerElement_ && invalidateClass(this.ownerElement_);
return rv;
DOMTokenList.prototype.toggle = function() {
return changeClass(this, oldToggle, arguments);
};
})(window.ShadowDOMPolyfill);

View File

@@ -279,6 +279,37 @@ suite('MutationObserver', function() {
});
});
test('should notify changes by target\'s classList property', function() {
var div = document.createElement('div');
var observer = new MutationObserver(function() {});
observer.observe(div, {
attributes: true,
attributeOldValue: true
});
div.classList.add('A');
div.classList.add('A'); //< Should be ignored
div.classList.remove('A');
div.classList.remove('A'); //< Should be ignored
var records = observer.takeRecords();
assert.equal(records.length, 2);
expectMutationRecord(records[0], {
type: 'attributes',
target: div,
attributeName: 'class',
attributeNamespace: null,
oldValue: null
});
expectMutationRecord(records[1], {
type: 'attributes',
target: div,
attributeName: 'class',
attributeNamespace: null,
oldValue: 'A'
});
});
});
});