Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refines how element styles are marshaled for custom elements #2198

Merged
merged 8 commits into from
Aug 8, 2015
20 changes: 18 additions & 2 deletions src/lib/custom-style.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
browsers without non-native Shadow DOM.
* Custom properties used by Polymer's shim for cross-scope styling
may be defined in an `custom-style`.
* An `include` attribute may be specified to pull in style data from a
`dom-module` matching the include attribute. By using `include`, style data
can be shared between multiple `custom-style` elements.
Example:
Expand Down Expand Up @@ -80,7 +83,17 @@
is: 'custom-style',
extends: 'style',

created: function() {
properties: {
// include is a property so that it deserializes
/**
* Specify `include` to identify a `dom-module` containing style data which
* should be used within the `custom-style`. By using `include` style data
* may be shared between multiple different `custom-style` elements.
*/
include: String
},

ready: function() {
// NOTE: we cannot just check attached because custom elements in
// HTMLImports do not get attached.
this._tryApply();
Expand All @@ -101,7 +114,7 @@
styleDefaults.addStyle(e);
// we may not have any textContent yet due to parser yielding
// if so, wait until we do...
if (e.textContent) {
if (e.textContent || this.include) {
this._apply();
} else {
var observer = new MutationObserver(function() {
Expand All @@ -119,6 +132,9 @@
_apply: function() {
// used applied element from HTMLImports polyfill or this
var e = this.__appliedElement || this;
if (this.include) {
e.textContent += styleUtil.cssFromModules(this.include);
}
this._computeStyleProperties();
var props = this._styleProperties;
var self = this;
Expand Down
16 changes: 7 additions & 9 deletions src/lib/dom-module.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
this.getAttribute('name') || this.getAttribute('is');
if (id) {
this.id = id;
// store id separate from lowercased id so that
// in all cases mixedCase id will stored distinctly
// and lowercase version is a fallback
modules[id] = this;
lcModules[id.toLowerCase()] = this;
}
Expand Down Expand Up @@ -87,20 +90,15 @@
// loaded by this point. In addition the HTMLImports polyfill should be
// changed to upgrade elements prior to running any scripts.)
var cePolyfill = window.CustomElements && !CustomElements.useNative;
if (cePolyfill) {
var ready = CustomElements.ready;
CustomElements.ready = true;
}
document.registerElement('dom-module', DomModule);
if (cePolyfill) {
CustomElements.ready = ready;
}

function forceDocumentUpgrade() {
if (cePolyfill) {
var script = document._currentScript || document.currentScript;
if (script) {
CustomElements.upgradeAll(script.ownerDocument);
var doc = script && script.ownerDocument;
if (doc && !doc.__customElementsForceUpgraded) {
doc.__customElementsForceUpgraded = true;
CustomElements.upgradeAll(doc);
}
}
}
Expand Down
55 changes: 44 additions & 11 deletions src/lib/style-util.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

return {

MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css]',
MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css], template',
INCLUDE_ATTR: 'include',

toCssText: function(rules, callback, preserveProperties) {
if (typeof rules === 'string') {
Expand Down Expand Up @@ -81,37 +82,69 @@
return style;
},

cssFromModules: function(moduleIds) {
var modules = moduleIds.trim().split(' ');
var cssText = '';
for (var i=0; i < modules.length; i++) {
cssText += this.cssFromModule(modules[i]);
}
return cssText;
},

// returns cssText of styles in a given module; also un-applies any
// styles that apply to the document.
cssFromModule: function(moduleId) {
var m = Polymer.DomModule.import(moduleId);
if (m && !m._cssText) {
var cssText = '';
var e$ = Array.prototype.slice.call(
m.querySelectorAll(this.MODULE_STYLES_SELECTOR));
for (var i=0, e; i < e$.length; i++) {
e = e$[i];
m._cssText = this._cssFromElement(m);
}
return m && m._cssText || '';
},

// support lots of ways to discover css...
_cssFromElement: function(element) {
var cssText = '';
// if element is a template, get content from its .content
var content = element.content || element;
var sourceDoc = element.ownerDocument;
var e$ = Array.prototype.slice.call(
content.querySelectorAll(this.MODULE_STYLES_SELECTOR));
for (var i=0, e, resolveDoc, addModule; i < e$.length; i++) {
e = e$[i];
resolveDoc = sourceDoc;
addModule = null;
// look inside templates for elements
if (e.localName === 'template') {
cssText += this._cssFromElement(e);
} else {
// style elements inside dom-modules will apply to the main document
// we don't want this, so we remove them here.
if (e.localName === 'style') {
addModule = e.getAttribute(this.INCLUDE_ATTR);
// get style element applied to main doc via HTMLImports polyfill
e = e.__appliedElement || e;
e.parentNode.removeChild(e);
// it's an import, assume this is a text file of css content.
} else {
// TODO(sorvell): plan is to deprecate this way to get styles;
// remember to add deprecation warning when this is done.
e = e.import && e.import.body;
resolveDoc = e.import;
}
// adjust paths in css.
if (e) {
cssText +=
Polymer.ResolveUrl.resolveCss(e.textContent, e.ownerDocument);
cssText += this.resolveCss(e.textContent, resolveDoc);
}
}
m._cssText = cssText;
// now support module refs on 'styling' elements
if (addModule) {
cssText += this.cssFromModules(addModule);
}
}
return m && m._cssText || '';
return cssText;
},


resolveCss: Polymer.ResolveUrl.resolveCss,
parser: Polymer.CssParse,
ruleTypes: Polymer.CssParse.types

Expand Down
35 changes: 35 additions & 0 deletions test/smoke/style-sharing/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!doctype html>
<html>
<head>

<title></title>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<script src="../../../../webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../../../polymer.html">
<link rel="import" href="shared-styles.html">
<link rel="import" href="x-foo.html">
</head>
<body unresolved>

<style is="custom-style" module="shared-styles"></style>

<style is="custom-style">
.zot {
background-color: var(--zot);
}
</style>

<div class="bar">.bar from custom-style with module shared-styles</div>
<div class="foo">.foo should not be colored</div>
<div class="zot">.zot from custom-style using var in custom-style with module shared-styles</div>

<hr>

<x-foo></x-foo>


</body>
</html>
11 changes: 11 additions & 0 deletions test/smoke/style-sharing/shared-styles.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<dom-module id="shared-styles">
<style type="polymer">
.bar {
background-color: steelblue;
}

:root {
--zot: seagreen;
}
</style>
</dom-module>
31 changes: 31 additions & 0 deletions test/smoke/style-sharing/x-foo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<link rel="import" href="shared-styles.html">

<dom-module id="x-foo">
<template>
<style module="shared-styles"></style>
<style>
.foo {
background-color: tomato;
}

:host {
display: block;
border: 1px dashed orange;
padding: 4px;
}

.zot {
background-color: var(--zot);
}
</style>
<h4>x-foo</h4>
<div class="bar">.bar from shared-styles.html</div>
<div class="foo">.foo from local stylesheet</div>
<div class="zot">.zot from var in shared-styles.html</div>
</template>
<script>
Polymer({

});
</script>
</dom-module>
19 changes: 15 additions & 4 deletions test/unit/custom-style-import.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
<style is="custom-style">
:root {
<dom-module id="shared-style">
<template>
<style>
:root {
--import-var: 3px solid orange;
}
</style>
</template>
</dom-module>

<link rel="import" href="sub/style-import.html">

--import-var: 3px solid orange;
<style is="custom-style" include="shared-style style-import">
:root {

--import-mixin: {
border: 4px solid blue;
};

padding: 10px;
}
</style>
</style>

8 changes: 8 additions & 0 deletions test/unit/custom-style.html
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@
<br><br>
<div id="after"></div>

<div class="foo"></div>


<dom-module id="x-baz">
<style>
Expand Down Expand Up @@ -253,6 +255,12 @@
assertComputed(document.body, '12px');
});

test('style paths in included dom-modules loaded in import', function() {
var foo = document.querySelector('.foo');
var url = getComputedStyle(foo).backgroundImage;
assert.include(url, 'sub/google.png');
});

});


Expand Down
4 changes: 3 additions & 1 deletion test/unit/styling-remote-elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@

</style>
<template>
<!-- style in template using module! -->
<style include="remote-styles"></style>
<content select=".blank"></content>
<div id="simple">simple</div>
<div id="complex1" class="scoped">complex1</div>
Expand All @@ -106,12 +108,12 @@
<x-child2 class="wide" id="child2"></x-child2>
<div id="computed" class$="{{computeClass(aClass)}}">Computed</div>
<content></content>
<div id="url" class="foo"></div>
</template>
</dom-module>
<script>
Polymer({
is: 'x-styled',
styleModules: ['remote-styles'],

computeClass: function(className) {
return className;
Expand Down
4 changes: 4 additions & 0 deletions test/unit/styling-remote-module-sheet.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<link rel="import" href="sub/style-import.html">
<dom-module id="remote-styles">
<template>
<style include="style-import"></style>
<style>
#simple {
border: 3px solid orange;
Expand All @@ -8,4 +11,5 @@
border: 4px solid pink;
}
</style>
</template>
</dom-module>
6 changes: 6 additions & 0 deletions test/unit/styling-remote.html
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,12 @@
assertComputed(order.$.me, '10px');
});

test('style paths in included dom-modules loaded in import', function() {
var el = styled.$.url;
var url = getComputedStyle(el).backgroundImage;
assert.include(url, 'sub/google.png');
});

// weird check allows testing under HTMLImports polyfill
if (!window.Polymer || !Polymer.Settings.useNativeShadow) {

Expand Down
11 changes: 6 additions & 5 deletions test/unit/styling-scoped-elements.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<dom-module id="x-gchild">
<style>
:host-context(.wide) #target {
border: 10px solid orange;
}
</style>
<template>
<!-- styles can be in templates -->
<style>
:host-context(.wide) #target {
border: 10px solid orange;
}
</style>
<div id="target">x-gchild</div>
</template>
</dom-module>
Expand Down
11 changes: 11 additions & 0 deletions test/unit/sub/style-import.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<dom-module id="style-import">
<template>
<style>
.foo {
height: 2px;
border: 1px solid orange;
background: url(google.png);
}
</style>
</template>
</dom-module>