Skip to content

Commit

Permalink
Fixes #1275; Fixes #1277
Browse files Browse the repository at this point in the history
  • Loading branch information
sorvell committed Mar 10, 2015
1 parent d06d8c5 commit 1dcaf8c
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 25 deletions.
6 changes: 3 additions & 3 deletions src/expr/x-styling.html
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,15 @@
// TODO(sorvell): don't redo parsing work each time as below;
// instead create a sheet with just custom properties
for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
cssText += this._transformCss(s.textContent, this.is, b) + '\n\n';
cssText += this._transformCss(s.textContent, b) + '\n\n';
}
return cssText.trim();
},

_transformCss: function(cssText, scope, callback) {
_transformCss: function(cssText, callback) {
return Polymer.Settings.useNativeShadow ?
Polymer.StyleUtil.toCssText(cssText, callback) :
Polymer.StyleTransformer.css(cssText, scope, callback);
Polymer.StyleTransformer.css(cssText, this.is, this.extends, callback);
},

_xScopeCount: 0,
Expand Down
5 changes: 2 additions & 3 deletions src/features/standard/styling.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,8 @@
} else {
var rules = this._rulesForStyle(s);
Polymer.StyleUtil.applyCss(
Polymer.StyleTransformer.css(rules, this.is),
this.is
);
Polymer.StyleTransformer.css(rules, this.is, this.extends),
this.is, null, true);
}
}
},
Expand Down
26 changes: 15 additions & 11 deletions src/lib/style-transformer.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,29 +64,34 @@
// a string of scoped css where each selector is transformed to include
// a class created from the scope. ShadowDOM selectors are also transformed
// (e.g. :host) to use the scoping selector.
function transformCss(rules, scope, callback) {
function transformCss(rules, scope, ext, callback) {
var hostScope = calcHostScope(scope, ext);
return Polymer.StyleUtil.toCssText(rules, function(rule) {
transformRule(rule, scope);
transformRule(rule, scope, hostScope);
if (callback) {
callback(rule, scope);
callback(rule, scope, hostScope);
}
});
}

function calcHostScope(scope, ext) {
return ext ? '[is=' + scope + ']' : scope;
}

// transforms a css rule to a scoped rule.
function transformRule(rule, scope) {
function transformRule(rule, scope, hostScope) {
var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP);
for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) {
p$[i] = transformComplexSelector(p, scope);
p$[i] = transformComplexSelector(p, scope, hostScope);
}
rule.selector = p$.join(COMPLEX_SELECTOR_SEP);
}

function transformComplexSelector(selector, scope) {
function transformComplexSelector(selector, scope, hostScope) {
var stop = false;
selector = selector.replace(SIMPLE_SELECTOR_SEP, function(s) {
if (!stop) {
var o = transformCompoundSelector(s, scope);
var o = transformCompoundSelector(s, scope, hostScope);
if (o.stop) {
stop = true;
}
Expand All @@ -100,17 +105,16 @@
return selector;
}

function transformCompoundSelector(selector, scope) {
function transformCompoundSelector(selector, scope, hostScope) {
// replace :host with host scoping class
var jumpIndex = selector.search(SCOPE_JUMP);
if (selector.indexOf(HOST) >=0) {
var r = scope;
// :host(...)
selector = selector.replace(HOST_PAREN, function(m, host, paren) {
return r + paren;
return hostScope + paren;
});
// now normal :host
selector = selector.replace(HOST, r);
selector = selector.replace(HOST, hostScope);
// replace other selectors with scoping class
} else if (jumpIndex !== 0) {
selector = transformSimpleSelector(selector, scope);
Expand Down
11 changes: 6 additions & 5 deletions src/lib/style-util.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@
}

// add a string of cssText to the document.
function applyCss(cssText, moniker, target) {
function applyCss(cssText, moniker, target, lowPriority) {
var style = document.createElement('style');
if (moniker) {
style.setAttribute('scope', moniker);
}
style.textContent = cssText;
// TODO(sorvell): investigate if it's better to batch multiple
// styles, perhaps into a fragment that's appended at once? (hopefully
// this doesn't matter)
target = target || document.head;
Polymer.dom(target).appendChild(style);
if (lowPriority) {
target.insertBefore(style, target.firstChild);
} else {
target.appendChild(style);
}
return style;
}

Expand Down
31 changes: 29 additions & 2 deletions test/unit/scoped-styling-elements.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<dom-module id="x-child" encapsulate>
<dom-module id="x-child">
<template>
<div id="simple">simple</div>
<div id="complex1" class="scoped">complex1</div>
Expand All @@ -14,7 +14,7 @@
});
</script>

<dom-module id="x-styled" encapsulate>
<dom-module id="x-styled">
<style>
:host {
display: block;
Expand Down Expand Up @@ -50,6 +50,10 @@
x-child /deep/ .deepTarget {
border: 8px solid red;
}

#priority {
border: 9px solid orange;
}
</style>
<template>
<div id="simple">simple</div>
Expand All @@ -60,10 +64,33 @@
<content></content>
</div>
<x-child id="child"></x-child>
<div id="priority">priority</div>
</template>
</dom-module>
<script>
Polymer({
is: 'x-styled'
});
</script>

<dom-module id="x-button">
<style>
:host {
border: 10px solid beige;
}

:host(.special) {
border: 11px solid beige;
}

</style>
<template>
Button!
</template>
</dom-module>
<script>
Polymer({
is: 'x-button',
extends: 'button'
});
</script>
25 changes: 24 additions & 1 deletion test/unit/scoped-styling.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
<script src="../../../web-component-tester/browser.js"></script>
<link rel="import" href="../../polymer.html">
<link rel="import" href="scoped-styling-elements.html">
<style>
#priority[style-scope=x-styled] {
border: 1px solid black;
}
</style>
</head>
<body>

Expand All @@ -26,12 +31,17 @@

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

<button is="x-button"></button>
<button class="special" is="x-button"></button>

<script>

suite('scoped-styling', function() {
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');

function assertComputed(element, value) {
var computed = getComputedStyle(element);
Expand Down Expand Up @@ -84,7 +94,20 @@
Polymer.dom(styled.root).appendChild(d);
assertComputed(d, '4px');
Polymer.dom(styled.root).removeChild(d);
assert.equal(d.className, 'scoped');
assert.equal(d.getAttribute('style-scoped'), null);
Polymer.dom(styled.root).appendChild(d);
assertComputed(d, '4px');
Polymer.dom(styled.root).removeChild(d);
assert.equal(d.getAttribute('style-scoped'), null);
});

test('element style precedence below document styles', function() {
assertComputed(styledWide.$.priority, '1px');
});

test('type extension elements', function() {
assertComputed(button, '10px');
assertComputed(specialButton, '11px');
});

});
Expand Down

0 comments on commit 1dcaf8c

Please sign in to comment.