Skip to content

Commit 89ecb5a

Browse files
committed
Merge pull request #1638 from Polymer/custom-style-fix
Custom style fix
2 parents 22daec6 + bb95be8 commit 89ecb5a

7 files changed

+91
-48
lines changed

src/lib/custom-style.html

+33-32
Original file line numberDiff line numberDiff line change
@@ -72,40 +72,57 @@
7272
var propertyUtils = Polymer.StyleProperties;
7373
var styleUtil = Polymer.StyleUtil;
7474
var styleDefaults = Polymer.StyleDefaults;
75+
var styleTransformer = Polymer.StyleTransformer;
7576

7677
Polymer({
7778

7879
is: 'custom-style',
7980
extends: 'style',
8081

8182
created: function() {
82-
this._appliesToDocument = (this.parentNode.localName !== 'dom-module');
83-
if (this._appliesToDocument) {
84-
// used applied element from HTMLImports polyfill or this
85-
var e = this.__appliedElement || this;
86-
var rules = styleUtil.rulesForStyle(e);
87-
propertyUtils.decorateStyles([e]);
88-
this._rulesToDefaultProperties(rules);
89-
// NOTE: go async to give a chance to collect properties into
90-
// the StyleDefaults before applying
91-
this.async(this._applyStyle);
83+
// NOTE: we cannot just check attached because custom elements in
84+
// HTMLImports do not get attached.
85+
this._tryApply();
86+
},
87+
88+
attached: function() {
89+
this._tryApply();
90+
},
91+
92+
_tryApply: function() {
93+
if (!this._appliesToDocument) {
94+
// only apply variables iff this style is not inside a dom-module
95+
if (this.parentNode &&
96+
(this.parentNode.localName !== 'dom-module')) {
97+
this._appliesToDocument = true;
98+
// used applied element from HTMLImports polyfill or this
99+
var e = this.__appliedElement || this;
100+
styleDefaults.addStyle(e);
101+
// we may not have any textContent yet due to parser yielding
102+
// if so, wait until we do...
103+
if (e.textContent) {
104+
this._apply();
105+
} else {
106+
var observer = new MutationObserver(function() {
107+
observer.disconnect();
108+
this._apply();
109+
}.bind(this));
110+
observer.observe(e, {childList: true});
111+
}
112+
}
92113
}
93114
},
94115

95116
// polyfill this style with root scoping and
96117
// apply custom properties!
97-
_applyStyle: function() {
118+
_apply: function() {
98119
// used applied element from HTMLImports polyfill or this
99120
var e = this.__appliedElement || this;
100121
this._computeStyleProperties();
101122
var props = this._styleProperties;
102123
var self = this;
103124
e.textContent = styleUtil.toCssText(styleUtil.rulesForStyle(e),
104125
function(rule) {
105-
// polyfill lack of support for :root
106-
if (rule.selector === ':root') {
107-
rule.selector = 'body';
108-
}
109126
var css = rule.cssText = rule.parsedCssText;
110127
if (rule.propertyInfo && rule.propertyInfo.cssText) {
111128
// TODO(sorvell): factor better
@@ -114,25 +131,9 @@
114131
// replace with reified properties, scenario is same as mixin
115132
rule.cssText = propertyUtils.valueForProperties(css, props);
116133
}
117-
if (!nativeShadow) {
118-
Polymer.StyleTransformer.rootRule(rule);
119-
}
134+
styleTransformer.documentRule(rule);
120135
}
121136
);
122-
},
123-
124-
_rulesToDefaultProperties: function(rules) {
125-
// produce css containing only property assignments.
126-
styleUtil.forEachStyleRule(rules, function(rule) {
127-
if (!rule.propertyInfo.properties) {
128-
rule.cssText = '';
129-
}
130-
});
131-
// tell parser to emit css that includes properties.
132-
var cssText = styleUtil.parser.stringify(rules, true);
133-
if (cssText) {
134-
styleDefaults.applyCss(cssText);
135-
}
136137
}
137138

138139
});

src/lib/style-defaults.html

+14-7
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,13 @@
1515
var styleProperties = Polymer.StyleProperties;
1616
var styleUtil = Polymer.StyleUtil;
1717

18-
var style = document.createElement('style')
19-
2018
var api = {
2119

22-
style: style,
23-
_styles: [style],
20+
_styles: [],
2421
_properties: null,
2522

26-
applyCss: function(cssText) {
27-
this.style.textContent += cssText;
28-
styleUtil.clearStyleRules(this.style);
23+
addStyle: function(style) {
24+
this._styles.push(style);
2925
this._properties = null;
3026
},
3127

@@ -48,6 +44,17 @@
4844

4945
_computeStyleProperties: function() {
5046
return this._styleProperties;
47+
},
48+
49+
updateStyles: function() {
50+
// invalidate the cache
51+
this._styleCache.clear();
52+
// update any custom-styles we are tracking
53+
for (var i=0, s; i < this._styles.length; i++) {
54+
s = this._styles[i];
55+
s = s.__importElement || s;
56+
s._apply();
57+
}
5158
}
5259

5360
};

src/lib/style-transformer.html

+14-2
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,19 @@
206206
return p$.join(PSEUDO_PREFIX);
207207
},
208208

209-
rootRule: function(rule) {
210-
this._transformRule(rule, this._transformRootSelector);
209+
documentRule: function(rule) {
210+
// reset selector in case this is redone.
211+
rule.selector = rule.parsedSelector;
212+
this.normalizeRootSelector(rule);
213+
if (!nativeShadow) {
214+
this._transformRule(rule, this._transformRootSelector);
215+
}
216+
},
217+
218+
normalizeRootSelector: function(rule) {
219+
if (rule.selector === ROOT) {
220+
rule.selector = 'body';
221+
}
211222
},
212223

213224
_transformRootSelector: function(selector) {
@@ -225,6 +236,7 @@
225236
var COMPLEX_SELECTOR_SEP = ',';
226237
var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g;
227238
var HOST = ':host';
239+
var ROOT = ':root';
228240
// NOTE: this supports 1 nested () pair for things like
229241
// :host(:not([selected]), more general support requires
230242
// parsing which seems like overkill

src/lib/style-util.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
},
3636

3737
rulesForStyle: function(style) {
38-
if (!style.__cssRules) {
39-
style.__cssRules = this.parser.parse(style.textContent);
38+
if (!style.__cssRules && style.textContent) {
39+
style.__cssRules = this.parser.parse(style.textContent);
4040
}
4141
return style.__cssRules;
4242
},

src/standard/x-styling.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,9 @@
234234
* to update styling.
235235
*/
236236
Polymer.updateStyles = function() {
237-
styleDefaults._styleCache.clear();
237+
// update default/custom styles
238+
styleDefaults.updateStyles();
239+
// search the document for elements to update
238240
Polymer.Base._updateRootStyles(document);
239241
};
240242

test/unit/custom-style.html

+22-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
border: 1px solid black;
3636
};
3737

38-
margin: 10px;
38+
/* mocha.css in the testing environment is hosing this test;
39+
use !important as a workaround */
40+
margin: 10px !important;
3941
width: auto;
4042

4143
--special: var(--primary);
@@ -64,13 +66,19 @@
6466
.import-var {
6567
border: var(--import-var);
6668
}
69+
70+
.dynamic {
71+
border: var(--dynamic);
72+
}
6773
</style>
6874
</head>
6975
<body>
7076
<div class="italic">italic</div>
7177
<div class="bag">bag</div>
7278
<div class="mix">mix</div>
7379

80+
<div class="dynamic">dynamic</div>
81+
7482
<div class="import-mixin">import-mixin</div>
7583
<div class="import-var">import-var</div>
7684

@@ -161,6 +169,19 @@
161169
assertComputed(m, '4px');
162170
});
163171

172+
test('dynamic custom-styles apply', function(done) {
173+
var dynamic = document.querySelector('.dynamic');
174+
assertComputed(dynamic, '0px');
175+
var ds = document.createElement('style', 'custom-style');
176+
ds.textContent = ':root { --dynamic: 11px solid orange; }';
177+
document.head.appendChild(ds);
178+
setTimeout(function() {
179+
Polymer.updateStyles();
180+
assertComputed(dynamic, '11px');
181+
done();
182+
}, 0);
183+
});
184+
164185
test('custom-styles apply normal and property values to elements', function() {
165186
var e = document.querySelector('x-foo').$.me;
166187
assertComputed(e, '1px');

test/unit/styling-cross-scope-var.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -375,16 +375,16 @@
375375

376376
test('updateStyles changes property values and using style cache', function() {
377377
styled.$.child.classList.add('special');
378-
var l = document.styleSheets.length;
378+
var l = document.querySelectorAll('style').length;
379379
styled.updateStyles();
380380
if (styled.shadyRoot) {
381-
assert.equal(document.styleSheets.length, l+4);
381+
assert.equal(document.querySelectorAll('style').length, l+4);
382382
}
383383
assertComputed(styled.$.child.$.me, '12px');
384384
styled.$.child.classList.remove('special');
385385
styled.updateStyles();
386386
if (styled.shadyRoot) {
387-
assert.equal(document.styleSheets.length, l);
387+
assert.equal(document.querySelectorAll('style').length, l);
388388
}
389389
assertComputed(styled.$.child.$.me, '2px');
390390
});

0 commit comments

Comments
 (0)