mirror of
https://github.com/Polymer/polymer.git
synced 2025-02-25 18:55:30 -06:00
Fixes style scoping when elements are stamped inside repeats.
Removes `element.host` which was used by the platform (e.g. <a>.host), in favor of `element.domHost`. This is just a shorthand for `Polymer.dom(element).getOwnerRoot().host`
This commit is contained in:
@@ -45,6 +45,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
// boilerplate code
|
||||
archetype._notifyPath = this._notifyPathImpl;
|
||||
archetype._scopeElementClass = this._scopeElementClassImpl;
|
||||
// boilerplate code
|
||||
var _constructor = this._constructorImpl;
|
||||
var ctor = function TemplateInstance(model, host) {
|
||||
@@ -208,6 +209,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
this._tryReady();
|
||||
},
|
||||
|
||||
_scopeElementClassImpl: function(node, value) {
|
||||
var host = this._rootDataHost;
|
||||
if (host) {
|
||||
return host._scopeElementClass(node, value);
|
||||
}
|
||||
},
|
||||
|
||||
stamp: function(model) {
|
||||
model = model || {};
|
||||
if (this._parentProps) {
|
||||
@@ -236,7 +244,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
// },
|
||||
|
||||
// stamp: function(model) {
|
||||
// return new this.ctor(model, this.host);
|
||||
// return new this.ctor(model, this.dataHost);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
(function() {
|
||||
|
||||
var baseAttachedCallback = Polymer.Base.attachedCallback;
|
||||
var baseDetachedCallback = Polymer.Base.detachedCallback;
|
||||
|
||||
Polymer.Base._addFeature({
|
||||
|
||||
@@ -42,23 +41,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
ready: function() {
|
||||
},
|
||||
|
||||
/**
|
||||
Returns the host of the local dom in which this element exists.
|
||||
This is a shorthand for Polymer.dom(this).getOwnerRoot().host
|
||||
*/
|
||||
get host() {
|
||||
return this._host || (this._host = this._queryHost());
|
||||
},
|
||||
|
||||
set host(value) {
|
||||
this._host = value;
|
||||
},
|
||||
|
||||
_queryHost: function(node) {
|
||||
var ownerRoot = Polymer.dom(this).getOwnerRoot();
|
||||
return ownerRoot && ownerRoot.host;
|
||||
},
|
||||
|
||||
// NOTE: The concept of 'host' is overloaded. There are two different
|
||||
// notions:
|
||||
// 1. an element hosts the elements in its local dom root.
|
||||
@@ -73,16 +55,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
// 2. establish this element as the current hosting element (allows
|
||||
// any elements we stamp to easily set host to us).
|
||||
_pushHost: function(host) {
|
||||
// this.host reflects the parent element whose "local DOM"
|
||||
// this element is contained within. This may change if the element
|
||||
// is appended to a different parent.
|
||||
this.host = host = host ||
|
||||
// NOTE: The `dataHost` of an element never changes.
|
||||
this.dataHost = host = host ||
|
||||
Polymer.Base.hostStack[Polymer.Base.hostStack.length-1];
|
||||
// this.dataHost reflects the parent element who manages
|
||||
// any bindings for the element. Only elements originally
|
||||
// stamped from Polymer templates have a dataHost, and this
|
||||
// never changes
|
||||
this.dataHost = host;
|
||||
if (host && host._clients) {
|
||||
host._clients.push(this);
|
||||
}
|
||||
@@ -138,8 +117,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
// if (!Polymer.Settings.useNativeCustomElements) {
|
||||
// CustomElements.takeRecords();
|
||||
// }
|
||||
//
|
||||
this._clientsReadied = true;
|
||||
this._clients = null;
|
||||
},
|
||||
|
||||
// mark readied and call `ready`
|
||||
@@ -151,10 +130,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
this._attachedPending = false;
|
||||
this.attachedCallback();
|
||||
}
|
||||
// reset _host as it needs to be established by local dom after data
|
||||
// configuration
|
||||
this.host = null;
|
||||
this._clients = null;
|
||||
},
|
||||
|
||||
// for system overriding
|
||||
@@ -168,12 +143,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
} else {
|
||||
this._attachedPending = true;
|
||||
}
|
||||
},
|
||||
|
||||
detachedCallback: function() {
|
||||
// uncache host so it will be calculated again.
|
||||
this.host = null;
|
||||
baseDetachedCallback.call(this);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -58,6 +58,16 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
this.shadyRoot.host = this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the element whose local dom within which this element
|
||||
* is contained. This is a shorthand for
|
||||
* `Polymer.dom(this).getOwnerRoot().host`.
|
||||
*/
|
||||
get domHost() {
|
||||
var root = Polymer.dom(this).getOwnerRoot();
|
||||
return root && root.host;
|
||||
},
|
||||
|
||||
/**
|
||||
* Force this element to distribute its children to its local dom.
|
||||
* A user should call `distributeContent` if distribution has been
|
||||
|
||||
@@ -48,16 +48,17 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
_computeStylePropertiesFromHost: function() {
|
||||
// TODO(sorvell): experimental feature, global defaults!
|
||||
var props = {}, styles = [Polymer.StyleDefaults.defaultSheet];
|
||||
if (this.host) {
|
||||
var host = this.domHost;
|
||||
if (host) {
|
||||
// enable finding styles in hosts without `enableStyleCustomProperties`
|
||||
if (!this.host._styleProperties) {
|
||||
this.host._styleProperties = this.host._computeStyleProperties();
|
||||
if (!host._styleProperties) {
|
||||
host._styleProperties = host._computeStyleProperties();
|
||||
}
|
||||
props = Object.create(this.host._styleProperties);
|
||||
styles = this.host._styles;
|
||||
props = Object.create(host._styleProperties);
|
||||
styles = host._styles;
|
||||
}
|
||||
this.simpleMixin(props,
|
||||
this._customPropertiesFromStyles(styles, this.host));
|
||||
this._customPropertiesFromStyles(styles, host));
|
||||
return props;
|
||||
|
||||
},
|
||||
@@ -271,11 +272,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
serializeValueToAttribute: function(value, attribute, node) {
|
||||
if (attribute === 'class') {
|
||||
// host needed to scope styling.
|
||||
var host = node.host;
|
||||
if (!host) {
|
||||
var root = Polymer.dom(node).getOwnerRoot();
|
||||
host = root && root.host;
|
||||
}
|
||||
var host = node === this ?
|
||||
Polymer.dom(this).getOwnerRoot() || this.dataHost :
|
||||
this;
|
||||
if (host) {
|
||||
value = host._scopeElementClass(node, value);
|
||||
}
|
||||
@@ -289,8 +288,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
},
|
||||
|
||||
updateHostStyles: function() {
|
||||
if (this.host) {
|
||||
this.host.updateStyles();
|
||||
var host = Polymer.dom(this).getOwnerRoot() || this.dataHost;
|
||||
if (host) {
|
||||
host.updateStyles();
|
||||
} else {
|
||||
this._updateRootStyles(document);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,156 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
<x-dynamic-scope></x-dynamic-scope>
|
||||
|
||||
<script src="styling.js"></script>
|
||||
<script>
|
||||
suite('scoped-styling', function() {
|
||||
|
||||
function assertComputed(element, value) {
|
||||
var computed = getComputedStyle(element);
|
||||
assert.equal(computed['border-top-width'], value, 'computed style incorrect');
|
||||
}
|
||||
|
||||
var styled = document.querySelector('x-styled');
|
||||
var styledWide = document.querySelector('x-styled.wide');
|
||||
var unscoped = document.querySelector('.scoped');
|
||||
var button = document.querySelector('[is=x-button]');
|
||||
var specialButton = document.querySelector('[is=x-button].special');
|
||||
|
||||
test(':host, :host(...)', function() {
|
||||
assertComputed(styled, '1px');
|
||||
assertComputed(styledWide, '2px');
|
||||
|
||||
});
|
||||
|
||||
test('scoped selectors, simple and complex', function() {
|
||||
assertComputed(styled.$.simple, '3px');
|
||||
assertComputed(styled.$.complex1, '4px');
|
||||
assertComputed(styled.$.complex2, '4px');
|
||||
});
|
||||
|
||||
test('media query scoped selectors', function() {
|
||||
assertComputed(styled.$.media, '5px');
|
||||
});
|
||||
|
||||
test('upper bound encapsulation', function() {
|
||||
assertComputed(unscoped, '0px');
|
||||
});
|
||||
|
||||
test('lower bound encapsulation', function() {
|
||||
assertComputed(styled.$.child.$.simple, '0px');
|
||||
assertComputed(styled.$.child.$.complex1, '0px');
|
||||
assertComputed(styled.$.child.$.complex2, '0px');
|
||||
assertComputed(styled.$.child.$.media, '0px');
|
||||
});
|
||||
|
||||
test('::content selectors', function() {
|
||||
var content = document.querySelector('.content');
|
||||
var content1 = document.querySelector('.content1');
|
||||
var content2 = document.querySelector('.content2');
|
||||
assertComputed(content, '6px');
|
||||
assertComputed(content1, '13px');
|
||||
assertComputed(content2, '14px');
|
||||
});
|
||||
|
||||
test('::shadow selectors', function() {
|
||||
assertComputed(styled.$.child.$.shadow, '7px');
|
||||
});
|
||||
|
||||
test('/deep/ selectors', function() {
|
||||
assertComputed(styled.$.child.$.deep, '8px');
|
||||
});
|
||||
|
||||
test('elements dynamically added/removed from root', function() {
|
||||
var d = document.createElement('div');
|
||||
d.classList.add('scoped');
|
||||
d.textContent = 'Dynamically... Scoped!';
|
||||
Polymer.dom(styled.root).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '4px');
|
||||
Polymer.dom(document.body).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when added to other root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when added to other root');
|
||||
Polymer.dom(styled.root).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '4px');
|
||||
Polymer.dom(styled.root).removeChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when removed from root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when removed from root');
|
||||
Polymer.dom(styled.root).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '4px');
|
||||
});
|
||||
|
||||
test('elements dynamically added/removed from host', function() {
|
||||
var d = document.createElement('div');
|
||||
d.classList.add('scoped');
|
||||
d.classList.add('blank');
|
||||
d.textContent = 'Dynamically... unScoped!';
|
||||
Polymer.dom(styled).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '0px');
|
||||
Polymer.dom(document.body).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when added to other root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when added to other root');
|
||||
Polymer.dom(styled).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '0px');
|
||||
Polymer.dom(styled).removeChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when removed from root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when removed from root');
|
||||
Polymer.dom(styled).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '0px');
|
||||
});
|
||||
|
||||
test('elements with computed classes', function() {
|
||||
assertComputed(styled.$.computed, '0px');
|
||||
styled.aClass = 'computed';
|
||||
assertComputed(styled.$.computed, '15px');
|
||||
});
|
||||
|
||||
test('elements with hostAttributes: class', function() {
|
||||
assertComputed(styled.$.child, '16px');
|
||||
});
|
||||
|
||||
test('type extension elements', function() {
|
||||
assertComputed(button, '10px');
|
||||
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() {
|
||||
|
||||
test('element style precedence below document styles', function() {
|
||||
assertComputed(styledWide.$.priority, '1px');
|
||||
});
|
||||
|
||||
test('styles shimmed in registration order', function() {
|
||||
var s$ = document.head.querySelectorAll('style[scope]');
|
||||
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'));
|
||||
}
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -91,6 +91,10 @@
|
||||
border: 15px solid orange;
|
||||
}
|
||||
|
||||
.computeda {
|
||||
border: 20px solid orange;
|
||||
}
|
||||
|
||||
#child {
|
||||
border: 16px solid tomato;
|
||||
display: block;
|
||||
@@ -115,12 +119,21 @@
|
||||
<div id="priority">priority</div>
|
||||
<x-child2 class="wide" id="child2"></x-child2>
|
||||
<div id="computed" class$="{{computeClass(aClass)}}">Computed</div>
|
||||
<div id="repeatContainer">
|
||||
<template id="repeat" is="x-repeat" items="{{items}}">
|
||||
<a class$="{{parent.aaClass}}">A Computed</a>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</dom-module>
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'x-styled',
|
||||
|
||||
properties: {
|
||||
items: {value: [{}]}
|
||||
},
|
||||
|
||||
computeClass: function(className) {
|
||||
return className;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,162 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
<x-dynamic-scope></x-dynamic-scope>
|
||||
|
||||
<script src="styling.js"></script>
|
||||
<script>
|
||||
suite('scoped-styling', function() {
|
||||
|
||||
function assertComputed(element, value) {
|
||||
var computed = getComputedStyle(element);
|
||||
assert.equal(computed['border-top-width'], value, 'computed style incorrect');
|
||||
}
|
||||
|
||||
var styled = document.querySelector('x-styled');
|
||||
var styledWide = document.querySelector('x-styled.wide');
|
||||
var unscoped = document.querySelector('.scoped');
|
||||
var button = document.querySelector('[is=x-button]');
|
||||
var specialButton = document.querySelector('[is=x-button].special');
|
||||
|
||||
test(':host, :host(...)', function() {
|
||||
assertComputed(styled, '1px');
|
||||
assertComputed(styledWide, '2px');
|
||||
|
||||
});
|
||||
|
||||
test('scoped selectors, simple and complex', function() {
|
||||
assertComputed(styled.$.simple, '3px');
|
||||
assertComputed(styled.$.complex1, '4px');
|
||||
assertComputed(styled.$.complex2, '4px');
|
||||
});
|
||||
|
||||
test('media query scoped selectors', function() {
|
||||
assertComputed(styled.$.media, '5px');
|
||||
});
|
||||
|
||||
test('upper bound encapsulation', function() {
|
||||
assertComputed(unscoped, '0px');
|
||||
});
|
||||
|
||||
test('lower bound encapsulation', function() {
|
||||
assertComputed(styled.$.child.$.simple, '0px');
|
||||
assertComputed(styled.$.child.$.complex1, '0px');
|
||||
assertComputed(styled.$.child.$.complex2, '0px');
|
||||
assertComputed(styled.$.child.$.media, '0px');
|
||||
});
|
||||
|
||||
test('::content selectors', function() {
|
||||
var content = document.querySelector('.content');
|
||||
var content1 = document.querySelector('.content1');
|
||||
var content2 = document.querySelector('.content2');
|
||||
assertComputed(content, '6px');
|
||||
assertComputed(content1, '13px');
|
||||
assertComputed(content2, '14px');
|
||||
});
|
||||
|
||||
test('::shadow selectors', function() {
|
||||
assertComputed(styled.$.child.$.shadow, '7px');
|
||||
});
|
||||
|
||||
test('/deep/ selectors', function() {
|
||||
assertComputed(styled.$.child.$.deep, '8px');
|
||||
});
|
||||
|
||||
test('elements dynamically added/removed from root', function() {
|
||||
var d = document.createElement('div');
|
||||
d.classList.add('scoped');
|
||||
d.textContent = 'Dynamically... Scoped!';
|
||||
Polymer.dom(styled.root).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '4px');
|
||||
Polymer.dom(document.body).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when added to other root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when added to other root');
|
||||
Polymer.dom(styled.root).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '4px');
|
||||
Polymer.dom(styled.root).removeChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when removed from root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when removed from root');
|
||||
Polymer.dom(styled.root).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '4px');
|
||||
});
|
||||
|
||||
test('elements dynamically added/removed from host', function() {
|
||||
var d = document.createElement('div');
|
||||
d.classList.add('scoped');
|
||||
d.classList.add('blank');
|
||||
d.textContent = 'Dynamically... unScoped!';
|
||||
Polymer.dom(styled).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '0px');
|
||||
Polymer.dom(document.body).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when added to other root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when added to other root');
|
||||
Polymer.dom(styled).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '0px');
|
||||
Polymer.dom(styled).removeChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when removed from root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when removed from root');
|
||||
Polymer.dom(styled).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '0px');
|
||||
});
|
||||
|
||||
test('elements with computed classes', function() {
|
||||
assertComputed(styled.$.computed, '0px');
|
||||
styled.aClass = 'computed';
|
||||
assertComputed(styled.$.computed, '15px');
|
||||
});
|
||||
|
||||
test('<a> with computed classes dynamically added', function() {
|
||||
assertComputed(styled.$.repeatContainer.firstElementChild, '0px');
|
||||
styled.aaClass = 'computeda';
|
||||
assertComputed(styled.$.repeatContainer.firstElementChild, '20px');
|
||||
});
|
||||
|
||||
test('elements with hostAttributes: class', function() {
|
||||
assertComputed(styled.$.child, '16px');
|
||||
});
|
||||
|
||||
test('type extension elements', function() {
|
||||
assertComputed(button, '10px');
|
||||
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() {
|
||||
|
||||
test('element style precedence below document styles', function() {
|
||||
assertComputed(styledWide.$.priority, '1px');
|
||||
});
|
||||
|
||||
test('styles shimmed in registration order', function() {
|
||||
var s$ = document.head.querySelectorAll('style[scope]');
|
||||
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'));
|
||||
}
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
suite('scoped-styling', function() {
|
||||
|
||||
function assertComputed(element, value) {
|
||||
var computed = getComputedStyle(element);
|
||||
assert.equal(computed['border-top-width'], value, 'computed style incorrect');
|
||||
}
|
||||
|
||||
var styled = document.querySelector('x-styled');
|
||||
var styledWide = document.querySelector('x-styled.wide');
|
||||
var unscoped = document.querySelector('.scoped');
|
||||
var button = document.querySelector('[is=x-button]');
|
||||
var specialButton = document.querySelector('[is=x-button].special');
|
||||
|
||||
test(':host, :host(...)', function() {
|
||||
assertComputed(styled, '1px');
|
||||
assertComputed(styledWide, '2px');
|
||||
|
||||
});
|
||||
|
||||
test('scoped selectors, simple and complex', function() {
|
||||
assertComputed(styled.$.simple, '3px');
|
||||
assertComputed(styled.$.complex1, '4px');
|
||||
assertComputed(styled.$.complex2, '4px');
|
||||
});
|
||||
|
||||
test('media query scoped selectors', function() {
|
||||
assertComputed(styled.$.media, '5px');
|
||||
});
|
||||
|
||||
test('upper bound encapsulation', function() {
|
||||
assertComputed(unscoped, '0px');
|
||||
});
|
||||
|
||||
test('lower bound encapsulation', function() {
|
||||
assertComputed(styled.$.child.$.simple, '0px');
|
||||
assertComputed(styled.$.child.$.complex1, '0px');
|
||||
assertComputed(styled.$.child.$.complex2, '0px');
|
||||
assertComputed(styled.$.child.$.media, '0px');
|
||||
});
|
||||
|
||||
test('::content selectors', function() {
|
||||
var content = document.querySelector('.content');
|
||||
var content1 = document.querySelector('.content1');
|
||||
var content2 = document.querySelector('.content2');
|
||||
assertComputed(content, '6px');
|
||||
assertComputed(content1, '13px');
|
||||
assertComputed(content2, '14px');
|
||||
});
|
||||
|
||||
test('::shadow selectors', function() {
|
||||
assertComputed(styled.$.child.$.shadow, '7px');
|
||||
});
|
||||
|
||||
test('/deep/ selectors', function() {
|
||||
assertComputed(styled.$.child.$.deep, '8px');
|
||||
});
|
||||
|
||||
test('elements dynamically added/removed from root', function() {
|
||||
var d = document.createElement('div');
|
||||
d.classList.add('scoped');
|
||||
d.textContent = 'Dynamically... Scoped!';
|
||||
Polymer.dom(styled.root).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '4px');
|
||||
Polymer.dom(document.body).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when added to other root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when added to other root');
|
||||
Polymer.dom(styled.root).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '4px');
|
||||
Polymer.dom(styled.root).removeChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when removed from root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when removed from root');
|
||||
Polymer.dom(styled.root).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '4px');
|
||||
});
|
||||
|
||||
test('elements dynamically added/removed from host', function() {
|
||||
var d = document.createElement('div');
|
||||
d.classList.add('scoped');
|
||||
d.classList.add('blank');
|
||||
d.textContent = 'Dynamically... unScoped!';
|
||||
Polymer.dom(styled).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '0px');
|
||||
Polymer.dom(document.body).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when added to other root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when added to other root');
|
||||
Polymer.dom(styled).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '0px');
|
||||
Polymer.dom(styled).removeChild(d);
|
||||
Polymer.dom.flush();
|
||||
assert.notInclude(d.getAttribute('style-scoped'), styled.is, 'scoping attribute not removed when removed from root');
|
||||
assert.notInclude(d.className, styled.is, 'scoping class not removed when removed from root');
|
||||
Polymer.dom(styled).appendChild(d);
|
||||
Polymer.dom.flush();
|
||||
assertComputed(d, '0px');
|
||||
});
|
||||
|
||||
test('elements with computed classes', function() {
|
||||
assertComputed(styled.$.computed, '0px');
|
||||
styled.aClass = 'computed';
|
||||
assertComputed(styled.$.computed, '15px');
|
||||
});
|
||||
|
||||
test('elements with hostAttributes: class', function() {
|
||||
assertComputed(styled.$.child, '16px');
|
||||
});
|
||||
|
||||
test('type extension elements', function() {
|
||||
assertComputed(button, '10px');
|
||||
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() {
|
||||
|
||||
test('element style precedence below document styles', function() {
|
||||
assertComputed(styledWide.$.priority, '1px');
|
||||
});
|
||||
|
||||
test('styles shimmed in registration order', function() {
|
||||
var s$ = document.head.querySelectorAll('style[scope]');
|
||||
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'));
|
||||
}
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user