From 07261e4b8ef797b9916ced21b718390fe2a79c61 Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Thu, 13 Aug 2015 15:31:29 -0700 Subject: [PATCH] Add `Polymer.dom().notifyObservers` method to 'kick' observers, for example, when attributes change under Shadow DOM. --- src/lib/dom-api-mutation-content.html | 4 +- src/lib/dom-api-mutation.html | 18 +++- src/lib/dom-api.html | 62 ++++--------- src/mini/shady.html | 34 ++++--- test/smoke/observeReNodes.html | 29 +++++- test/smoke/observeReNodes2.html | 126 ++++++++++++++++++++++++++ 6 files changed, 203 insertions(+), 70 deletions(-) create mode 100644 test/smoke/observeReNodes2.html diff --git a/src/lib/dom-api-mutation-content.html b/src/lib/dom-api-mutation-content.html index bf13de0130..b603d91ca8 100644 --- a/src/lib/dom-api-mutation-content.html +++ b/src/lib/dom-api-mutation-content.html @@ -30,7 +30,7 @@ return h; }, - notifyIfNeeded: function() { + notify: function() { if (this._hasListeners()) { this._scheduleNotify(); } @@ -82,7 +82,7 @@ var host = root && root.host; if (host) { this._observer = Polymer.dom(host).observeNodes( - this.notifyIfNeeded.bind(this)); + this.notify.bind(this)); } }, diff --git a/src/lib/dom-api-mutation.html b/src/lib/dom-api-mutation.html index 5d0f6dc47c..1d3b16fd8f 100644 --- a/src/lib/dom-api-mutation.html +++ b/src/lib/dom-api-mutation.html @@ -14,6 +14,7 @@ var DomApi = Polymer.DomApi.ctor; var Settings = Polymer.Settings; + var hasDomApi = Polymer.DomApi.hasDomApi; DomApi.Mutation = function(domApi) { this.domApi = domApi; @@ -100,7 +101,7 @@ _observeContentElements: function(elements) { for (var i=0, h, n; (i < elements.length) && (n=elements[i]); i++) { - if (n.localName === 'content') { + if (this._isContent(n)) { n.__observeNodesMap = n.__observeNodesMap || new WeakMap(); if (n.__observeNodesMap.get(this) === undefined) { h = Polymer.dom(n).observeNodes( @@ -113,7 +114,7 @@ _unobserveContentElements: function(elements) { for (var i=0, n, h; (i < elements.length) && (n=elements[i]); i++) { - if (n.localName === 'content') { + if (this._isContent(n)) { h = n.__observeNodesMap.get(this); if (h) { Polymer.dom(n).unobserveNodes(h); @@ -122,6 +123,10 @@ } }, + _isContent: function(node) { + return (node.localName === 'content'); + }, + _callListeners: function(info) { var o$ = this._listeners; for (var i=0, o; (i < o$.length) && (o=o$[i]); i++) { @@ -151,10 +156,13 @@ this._debouncer.context = this; Polymer.dom.addDebouncer(this._debouncer); this._preflush = this._flush.bind(this); - Polymer.dom.addPreflush(this._preflush); + + } + if (!this._hasListeners()) { + Polymer.dom.addPreflush(this._preflush); + // note: doing this > 1x is a no-op + this._observer.observe(this.node, {childList: true}); } - // note: doing this > 1x is a no-op - this._observer.observe(this.node, {childList: true}); }, _cleanupObserver: function() { diff --git a/src/lib/dom-api.html b/src/lib/dom-api.html index 906ca167dc..91b8e92db2 100644 --- a/src/lib/dom-api.html +++ b/src/lib/dom-api.html @@ -538,7 +538,10 @@ if (this.observer) { this.observer.removeListener(handle); } - } + }, + + // abstract, intended as public 'kick' mehanism + notifyObservers: function() {} }; @@ -744,58 +747,25 @@ DomApi.prototype._distributeParent = function() {}; - DomApi.prototype.observeChildren = function(callback) { - if (!this._mo) { - this._mo = new MutationObserver(this._notifyObservers.bind(this)); - this._mo.observe(this.node, {childList: true}); - // make sure to notify initial state... - this._mutationDebouncer = Polymer.Debounce(this._mutationDebouncer, - function() { - this._notifyObservers([{ - target: this.node, - addedNodes: this.childNodes.slice() - }]); - } - ); - this._mutationDebouncer.context = this; - Polymer.dom.addDebouncer(this._mutationDebouncer); - } - return this._observers.push(callback); - }; - - DomApi.prototype._notifyObservers = function(mxns) { - var info = { - target: this.node, - addedNodes: [], - removedNodes: [] - }; - mxns.forEach(function(m) { - if (m.addedNodes) { - for (var i=0; i < m.addedNodes.length; i++) { - info.addedNodes.push(m.addedNodes[i]); + DomApi.prototype.notifyObservers = function() { + if (this.node.shadowRoot) { + var ip$ = this.node.shadowRoot.querySelectorAll('content'); + for (var i=0, c; (i @@ -68,8 +78,8 @@ Polymer.dom.flush(); - - // setTimeout(function() { + + function test() { console.group('test dynamic'); var d = makeNode('dynamic!'); Polymer.dom.flush(); @@ -91,7 +101,18 @@ Polymer.dom(content).removeChild(Polymer.dom(content).lastChild); Polymer.dom.flush(); console.groupEnd('test dynamic'); - // }, 1000); + } + test(); + content.$.inner.unobserve(); + test(); + content.$.inner.observe(); + test(); + content.$.inner.unobserve(); + test(); + content.$.inner.observe(); + test(); + + diff --git a/test/smoke/observeReNodes2.html b/test/smoke/observeReNodes2.html new file mode 100644 index 0000000000..e9477e1fc2 --- /dev/null +++ b/test/smoke/observeReNodes2.html @@ -0,0 +1,126 @@ + + + + + observeReNodes + + + + + + + + + + + + + + + + + + + + + +
content A
+
content B
+
+ +

+ + + + +