diff --git a/src/features/mini/content.html b/src/features/mini/content.html index 094444757b..0990cda902 100644 --- a/src/features/mini/content.html +++ b/src/features/mini/content.html @@ -285,7 +285,13 @@ node = node || this; var list = node.querySelectorAll(selector); return list; - } + }, + + // system override point + _elementAdd: function() {}, + + // system override point + _elementRemove: function() {} }); @@ -440,6 +446,7 @@ }, appendChild: function(node, container) { + this.host._elementAdd(node); container = container || this.node; if (this.host._useContent) { saveLightChildrenIfNeeded(container); @@ -475,6 +482,7 @@ insertBefore: function(node, ref_node, container) { container = container || this.node; if (ref_node) { + this.host._elementAdd(node); if (this.host._useContent) { saveLightChildrenIfNeeded(container); var children = this.children(container); @@ -520,6 +528,7 @@ This method also performs dom composition. */ removeChild: function(node, container) { + this.host._elementRemove(node); container = container || this.node; if (this.host._useContent) { var children = this.children(container); diff --git a/src/features/standard/styling.html b/src/features/standard/styling.html index 32d9fb9077..2a0d103f00 100644 --- a/src/features/standard/styling.html +++ b/src/features/standard/styling.html @@ -125,6 +125,20 @@ transformer.host(this, this.is); } stampTemplate.call(this); + }, + + // add scoping class whenever an element is added to localDOM + _elementAdd: function(node) { + if (this._encapsulateStyle && !node.__styleScoped) { + transformer.dom(node, this.is); + } + }, + + // remove scoping class whenever an element is removed from localDOM + _elementRemove: function(node) { + if (this._encapsulateStyle) { + transformer.dom(node, ''); + } } }); diff --git a/src/lib/style-transformer.html b/src/lib/style-transformer.html index 044f82fba6..cdaaef1df6 100644 --- a/src/lib/style-transformer.html +++ b/src/lib/style-transformer.html @@ -38,12 +38,15 @@ // Given a node and scope name, add a scoping class to each node // in the tree. This facilitates transforming css into scoped rules. function transformDom(node, scope) { - _transformDom(node, scope + SCOPE_SUFFIX); + _transformDom(node, scope ? scope + SCOPE_SUFFIX : ''); } function _transformDom(node, selector) { if (node.classList) { - node.classList.add(selector); + node.className = node.className.replace(SCOPING_CLASS, ''); + if (selector) { + node.classList.add(selector); + } } // NOTE: it'd be better to use *Element* but Safari does not support // this api for document fragments. @@ -141,6 +144,7 @@ var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//; var CLASS_PREFIX = '.'; var PSEUDO_PREFIX = ':'; + var SCOPING_CLASS = /(?:^|\s)([\S]*?-x)(?:$|\s)/; // exports return { diff --git a/src/lib/template/x-repeat.html b/src/lib/template/x-repeat.html index 4f3e531ec5..4c137f1dbe 100644 --- a/src/lib/template/x-repeat.html +++ b/src/lib/template/x-repeat.html @@ -330,6 +330,7 @@ var beforeNode = beforeRow ? beforeRow._children[0] : this; var parentNode = this.lightDom.elementParent(); if (this._domTarget) { + row.root.__styleScoped = true; this._domTarget.insertBefore(row.root, beforeNode, parentNode); } else { parentNode.insertBefore(row.root, beforeNode); diff --git a/test/unit/scoped-styling.html b/test/unit/scoped-styling.html index b07c4dd98c..c15fe1ca32 100644 --- a/test/unit/scoped-styling.html +++ b/test/unit/scoped-styling.html @@ -77,6 +77,15 @@ test('/deep/ selectors', function() { assertComputed(styled.$.child.$.deep, '8px'); }); + + test('dynamically added elements', function() { + var d = document.createElement('div'); + d.classList.add('scoped'); + styled.localDom.appendChild(d); + assertComputed(d, '4px'); + styled.localDom.removeChild(d); + assert.equal(d.className, 'scoped'); + }); });