Skip to content

Commit 1dcaf8c

Browse files
committed
Fixes #1275; Fixes #1277
1 parent d06d8c5 commit 1dcaf8c

File tree

6 files changed

+79
-25
lines changed

6 files changed

+79
-25
lines changed

src/expr/x-styling.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,15 @@
131131
// TODO(sorvell): don't redo parsing work each time as below;
132132
// instead create a sheet with just custom properties
133133
for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
134-
cssText += this._transformCss(s.textContent, this.is, b) + '\n\n';
134+
cssText += this._transformCss(s.textContent, b) + '\n\n';
135135
}
136136
return cssText.trim();
137137
},
138138

139-
_transformCss: function(cssText, scope, callback) {
139+
_transformCss: function(cssText, callback) {
140140
return Polymer.Settings.useNativeShadow ?
141141
Polymer.StyleUtil.toCssText(cssText, callback) :
142-
Polymer.StyleTransformer.css(cssText, scope, callback);
142+
Polymer.StyleTransformer.css(cssText, this.is, this.extends, callback);
143143
},
144144

145145
_xScopeCount: 0,

src/features/standard/styling.html

+2-3
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,8 @@
107107
} else {
108108
var rules = this._rulesForStyle(s);
109109
Polymer.StyleUtil.applyCss(
110-
Polymer.StyleTransformer.css(rules, this.is),
111-
this.is
112-
);
110+
Polymer.StyleTransformer.css(rules, this.is, this.extends),
111+
this.is, null, true);
113112
}
114113
}
115114
},

src/lib/style-transformer.html

+15-11
Original file line numberDiff line numberDiff line change
@@ -64,29 +64,34 @@
6464
// a string of scoped css where each selector is transformed to include
6565
// a class created from the scope. ShadowDOM selectors are also transformed
6666
// (e.g. :host) to use the scoping selector.
67-
function transformCss(rules, scope, callback) {
67+
function transformCss(rules, scope, ext, callback) {
68+
var hostScope = calcHostScope(scope, ext);
6869
return Polymer.StyleUtil.toCssText(rules, function(rule) {
69-
transformRule(rule, scope);
70+
transformRule(rule, scope, hostScope);
7071
if (callback) {
71-
callback(rule, scope);
72+
callback(rule, scope, hostScope);
7273
}
7374
});
7475
}
7576

77+
function calcHostScope(scope, ext) {
78+
return ext ? '[is=' + scope + ']' : scope;
79+
}
80+
7681
// transforms a css rule to a scoped rule.
77-
function transformRule(rule, scope) {
82+
function transformRule(rule, scope, hostScope) {
7883
var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP);
7984
for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) {
80-
p$[i] = transformComplexSelector(p, scope);
85+
p$[i] = transformComplexSelector(p, scope, hostScope);
8186
}
8287
rule.selector = p$.join(COMPLEX_SELECTOR_SEP);
8388
}
8489

85-
function transformComplexSelector(selector, scope) {
90+
function transformComplexSelector(selector, scope, hostScope) {
8691
var stop = false;
8792
selector = selector.replace(SIMPLE_SELECTOR_SEP, function(s) {
8893
if (!stop) {
89-
var o = transformCompoundSelector(s, scope);
94+
var o = transformCompoundSelector(s, scope, hostScope);
9095
if (o.stop) {
9196
stop = true;
9297
}
@@ -100,17 +105,16 @@
100105
return selector;
101106
}
102107

103-
function transformCompoundSelector(selector, scope) {
108+
function transformCompoundSelector(selector, scope, hostScope) {
104109
// replace :host with host scoping class
105110
var jumpIndex = selector.search(SCOPE_JUMP);
106111
if (selector.indexOf(HOST) >=0) {
107-
var r = scope;
108112
// :host(...)
109113
selector = selector.replace(HOST_PAREN, function(m, host, paren) {
110-
return r + paren;
114+
return hostScope + paren;
111115
});
112116
// now normal :host
113-
selector = selector.replace(HOST, r);
117+
selector = selector.replace(HOST, hostScope);
114118
// replace other selectors with scoping class
115119
} else if (jumpIndex !== 0) {
116120
selector = transformSimpleSelector(selector, scope);

src/lib/style-util.html

+6-5
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,18 @@
4343
}
4444

4545
// add a string of cssText to the document.
46-
function applyCss(cssText, moniker, target) {
46+
function applyCss(cssText, moniker, target, lowPriority) {
4747
var style = document.createElement('style');
4848
if (moniker) {
4949
style.setAttribute('scope', moniker);
5050
}
5151
style.textContent = cssText;
52-
// TODO(sorvell): investigate if it's better to batch multiple
53-
// styles, perhaps into a fragment that's appended at once? (hopefully
54-
// this doesn't matter)
5552
target = target || document.head;
56-
Polymer.dom(target).appendChild(style);
53+
if (lowPriority) {
54+
target.insertBefore(style, target.firstChild);
55+
} else {
56+
target.appendChild(style);
57+
}
5758
return style;
5859
}
5960

test/unit/scoped-styling-elements.html

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<dom-module id="x-child" encapsulate>
1+
<dom-module id="x-child">
22
<template>
33
<div id="simple">simple</div>
44
<div id="complex1" class="scoped">complex1</div>
@@ -14,7 +14,7 @@
1414
});
1515
</script>
1616

17-
<dom-module id="x-styled" encapsulate>
17+
<dom-module id="x-styled">
1818
<style>
1919
:host {
2020
display: block;
@@ -50,6 +50,10 @@
5050
x-child /deep/ .deepTarget {
5151
border: 8px solid red;
5252
}
53+
54+
#priority {
55+
border: 9px solid orange;
56+
}
5357
</style>
5458
<template>
5559
<div id="simple">simple</div>
@@ -60,10 +64,33 @@
6064
<content></content>
6165
</div>
6266
<x-child id="child"></x-child>
67+
<div id="priority">priority</div>
6368
</template>
6469
</dom-module>
6570
<script>
6671
Polymer({
6772
is: 'x-styled'
6873
});
74+
</script>
75+
76+
<dom-module id="x-button">
77+
<style>
78+
:host {
79+
border: 10px solid beige;
80+
}
81+
82+
:host(.special) {
83+
border: 11px solid beige;
84+
}
85+
86+
</style>
87+
<template>
88+
Button!
89+
</template>
90+
</dom-module>
91+
<script>
92+
Polymer({
93+
is: 'x-button',
94+
extends: 'button'
95+
});
6996
</script>

test/unit/scoped-styling.html

+24-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
<script src="../../../web-component-tester/browser.js"></script>
1616
<link rel="import" href="../../polymer.html">
1717
<link rel="import" href="scoped-styling-elements.html">
18+
<style>
19+
#priority[style-scope=x-styled] {
20+
border: 1px solid black;
21+
}
22+
</style>
1823
</head>
1924
<body>
2025

@@ -26,12 +31,17 @@
2631

2732
<x-styled class="wide"></x-styled>
2833

34+
<button is="x-button"></button>
35+
<button class="special" is="x-button"></button>
36+
2937
<script>
3038

3139
suite('scoped-styling', function() {
3240
var styled = document.querySelector('x-styled');
3341
var styledWide = document.querySelector('x-styled.wide');
3442
var unscoped = document.querySelector('.scoped');
43+
var button = document.querySelector('[is=x-button]');
44+
var specialButton = document.querySelector('[is=x-button].special');
3545

3646
function assertComputed(element, value) {
3747
var computed = getComputedStyle(element);
@@ -84,7 +94,20 @@
8494
Polymer.dom(styled.root).appendChild(d);
8595
assertComputed(d, '4px');
8696
Polymer.dom(styled.root).removeChild(d);
87-
assert.equal(d.className, 'scoped');
97+
assert.equal(d.getAttribute('style-scoped'), null);
98+
Polymer.dom(styled.root).appendChild(d);
99+
assertComputed(d, '4px');
100+
Polymer.dom(styled.root).removeChild(d);
101+
assert.equal(d.getAttribute('style-scoped'), null);
102+
});
103+
104+
test('element style precedence below document styles', function() {
105+
assertComputed(styledWide.$.priority, '1px');
106+
});
107+
108+
test('type extension elements', function() {
109+
assertComputed(button, '10px');
110+
assertComputed(specialButton, '11px');
88111
});
89112

90113
});

0 commit comments

Comments
 (0)