Skip to content

Commit

Permalink
Merge pull request #2198 from Polymer/style-sharing
Browse files Browse the repository at this point in the history
Refines how element styles are marshaled for custom elements
  • Loading branch information
kevinpschaaf committed Aug 8, 2015
2 parents bf703cb + b22f3cd commit c4a9413
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 32 deletions.
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>

0 comments on commit c4a9413

Please sign in to comment.