Added scopeSubtree(container, shouldObserve) to support element use of normal dom api under shady dom in a specific subtree.

This commit is contained in:
Steve Orvell
2015-04-14 15:00:23 -07:00
parent b9d22e6d26
commit ffd32a2851
8 changed files with 147 additions and 11 deletions

View File

@@ -245,7 +245,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
_addNodeToHost: function(node) {
var root = this._ownerShadyRootForNode(node);
var checkNode = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE ?
node.firstChild : node;
var root = this._ownerShadyRootForNode(checkNode);
if (root) {
root.host._elementAdd(node);
}

View File

@@ -20,6 +20,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var prepTemplate = Polymer.Base._prepTemplate;
var prepElement = Polymer.Base._prepElement;
var baseStampTemplate = Polymer.Base._stampTemplate;
var nativeShadow = Polymer.Settings.useNativeShadow;
Polymer.Base.addFeature({
@@ -29,11 +30,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var port = Polymer.DomModule.import(this.is);
if (this._encapsulateStyle === undefined) {
this._encapsulateStyle =
Boolean(port && !Polymer.Settings.useNativeShadow);
Boolean(port && !nativeShadow);
}
// scope css
// NOTE: dom scoped via annotations
if (Polymer.Settings.useNativeShadow || this._encapsulateStyle) {
if (nativeShadow || this._encapsulateStyle) {
this._scopeCss();
}
},
@@ -107,7 +108,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
_scopeStyles: function(styles) {
for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
// transform style if necessary and place in correct place
if (Polymer.Settings.useNativeShadow) {
if (nativeShadow) {
if (this._template) {
this._template.content.appendChild(s);
}
@@ -148,6 +149,41 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
if (this._encapsulateStyle) {
Polymer.StyleTransformer.dom(node, this.is, this._scopeCssViaAttr, true);
}
},
/**
* Apply style scoping to the specified `container` and all its
* descendants. If `shoudlObserve` is true, changes to the container are
* monitored via mutation observer and scoping is applied.
*/
scopeSubtree: function(container, shouldObserve) {
if (nativeShadow) {
return;
}
var self = this;
var scopify = function(node) {
if (node.nodeType === Node.ELEMENT_NODE) {
node.className = self._scopeElementClass(node, node.className);
var n$ = node.querySelectorAll('*');
Array.prototype.forEach.call(n$, function(n) {
n.className = self._scopeElementClass(n, n.className);
});
}
};
scopify(container);
if (shouldObserve) {
var mo = new MutationObserver(function(mxns) {
mxns.forEach(function(m) {
if (m.addedNodes) {
for (var i=0; i < m.addedNodes.length; i++) {
scopify(m.addedNodes[i]);
}
}
});
});
mo.observe(container, {childList: true, subtree: true});
return mo;
}
}
});

View File

@@ -17,6 +17,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var baseAttachedCallback = Polymer.Base.attachedCallback;
var baseSerializeValueToAttribute = Polymer.Base.serializeValueToAttribute;
var nativeShadow = Polymer.Settings.useNativeShadow;
// TODO(sorvell): consider if calculating properties and applying
// styles with properties should be separate modules.
Polymer.Base.addFeature({
@@ -133,10 +135,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
style = cssText ? this._applyCustomCss(cssText) : {};
cacheStyle(this.is, style, this._xScopeSelector,
this._styleProperties, s$);
} else if (Polymer.Settings.useNativeShadow) {
} else if (nativeShadow) {
this._applyCustomCss(style.textContent);
}
if (style.textContent /*&& !Polymer.Settings.useNativeShadow*/) {
if (style.textContent /*&& !nativeShadow*/) {
this._applyXScopeSelector(this._xScopeSelector, old);
}
}
@@ -168,7 +170,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
_transformCss: function(cssText, callback) {
return Polymer.Settings.useNativeShadow ?
return nativeShadow ?
Polymer.StyleUtil.toCssText(cssText, callback) :
Polymer.StyleTransformer.css(cssText, this.is, this.extends, callback,
this._scopeCssViaAttr);
@@ -189,13 +191,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
} else if (cssText) {
this._customStyle = Polymer.StyleUtil.applyCss(cssText,
this._xScopeSelector,
Polymer.Settings.useNativeShadow ? this.root : null);
nativeShadow ? this.root : null);
}
return this._customStyle;
},
_applyPropertiesToRule: function(properties, rule) {
if (!Polymer.Settings.useNativeShadow) {
if (!nativeShadow) {
this._scopifyRule(rule);
}
if (rule.cssText.match(CUSTOM_RULE_RX)) {
@@ -258,7 +260,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
_scopeElementClass: function(element, selector) {
if (!this._scopeCssViaAttr) {
if (!nativeShadow && !this._scopeCssViaAttr) {
selector += (selector ? ' ' : '') + SCOPE_NAME + ' ' + this.is +
(element._xScopeSelector ? ' ' + XSCOPE_NAME + ' ' +
element._xScopeSelector : '');

View File

@@ -121,4 +121,46 @@
is: 'x-button',
extends: 'button'
});
</script>
<template id="dynamic">
<div class="added">
Added
<div class="sub-added">
Sub-added
</div>
</div>
</div>
</template>
<dom-module id="x-dynamic-scope">
<style>
.added {
border: 17px solid beige;
}
.sub-added {
border: 18px solid #fafafa;
}
</style>
<template>
<div id="container"></div>
</template>
</dom-module>
<script>
(function() {
var doc = document._currentScript.ownerDocument;
var dynamic = doc.querySelector('template#dynamic');
Polymer({
is: 'x-dynamic-scope',
ready: function() {
// setup node for scope watching
this.scopeSubtree(this.$.container, true);
// simulate 3rd party action by using normal dom to add to element.
var dom = document.importNode(dynamic.content, true);
this.$.container.appendChild(dom);
}
});
})();
</script>

View File

@@ -36,6 +36,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<button is="x-button"></button>
<button class="special" is="x-button"></button>
<x-dynamic-scope></x-dynamic-scope>
<script src="styling.js"></script>
</body>
</html>

View File

@@ -148,4 +148,46 @@
is: 'x-button',
extends: 'button'
});
</script>
<template id="dynamic">
<div class="added">
Added
<div class="sub-added">
Sub-added
</div>
</div>
</div>
</template>
<dom-module id="x-dynamic-scope">
<style>
.added {
border: 17px solid beige;
}
.sub-added {
border: 18px solid #fafafa;
}
</style>
<template>
<div id="container"></div>
</template>
</dom-module>
<script>
(function() {
var doc = document._currentScript.ownerDocument;
var dynamic = doc.querySelector('template#dynamic');
Polymer({
is: 'x-dynamic-scope',
ready: function() {
// setup node for scope watching
this.scopeSubtree(this.$.container, true);
// simulate 3rd party action by using normal dom to add to element.
var dom = document.importNode(dynamic.content, true);
this.$.container.appendChild(dom);
}
});
})();
</script>

View File

@@ -36,6 +36,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
<button is="x-button"></button>
<button class="special" is="x-button"></button>
<x-dynamic-scope></x-dynamic-scope>
<script src="styling.js"></script>
</body>
</html>

View File

@@ -117,6 +117,14 @@ suite('scoped-styling', function() {
assertComputed(specialButton, '11px');
});
test('element subtree added via dom api', function() {
var container = document.querySelector('x-dynamic-scope').$.container;
var a = container.querySelector('.added');
assertComputed(a, '17px');
var b = container.querySelector('.sub-added');
assertComputed(b, '18px');
});
if (window.Polymer && !Polymer.Settings.useNativeShadow) {
suite('scoped-styling-shady-only', function() {
@@ -127,7 +135,7 @@ suite('scoped-styling', function() {
test('styles shimmed in registration order', function() {
var s$ = document.head.querySelectorAll('style[scope]');
var expected = ['x-child2', 'x-styled', 'x-button'];
var expected = ['x-child2', 'x-styled', 'x-button', 'x-dynamic-scope'];
var actual = [];
for (var i=0; i<s$.length; i++) {
actual.push(s$[i].getAttribute('scope'));