mirror of
https://github.com/Polymer/polymer.git
synced 2025-02-25 18:55:30 -06:00
201 lines
7.0 KiB
HTML
201 lines
7.0 KiB
HTML
<!--
|
|
@license
|
|
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
|
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
Code distributed by Google as part of the polymer project is also
|
|
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
-->
|
|
<link rel="import" href="style-util.html">
|
|
<link rel="import" href="style-transformer.html">
|
|
<link rel="import" href="style-defaults.html">
|
|
|
|
<!--
|
|
|
|
The `custom-style` extension of the native `<style>` element allows defining styles
|
|
in the main document that can take advantage of several special features of
|
|
Polymer's styling system:
|
|
|
|
* Document styles defined in a `custom-style` will be shimmed to ensure they do
|
|
not leak into local DOM when running on browsers without non-native Shadow DOM.
|
|
* Shadow DOM-specific `/deep/` and `::shadow` combinators will be shimmed on
|
|
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:
|
|
|
|
```html
|
|
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<script src="components/webcomponentsjs/webcomponents-lite.js"></script>
|
|
<link rel="import" href="components/polymer/polymer.html">
|
|
|
|
<style is="custom-style">
|
|
|
|
/* Will be prevented from affecting local DOM of Polymer elements */
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
/* Can use /deep/ and ::shadow combinators */
|
|
body /deep/ .my-special-view::shadow #thing-inside {
|
|
background: yellow;
|
|
}
|
|
|
|
/* Custom properties that inherit down the document tree may be defined */
|
|
body {
|
|
--my-toolbar-title-color: green;
|
|
}
|
|
|
|
</style>
|
|
|
|
</head>
|
|
<body>
|
|
|
|
...
|
|
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
Note, all features of `custom-style` are available when defining styles as part of Polymer elements (e.g. `<style>` elements within `<dom-module>`'s used for defining Polymer elements. The `custom-style` extension should only be used for defining document styles, outside of a custom element's local DOM.
|
|
|
|
-->
|
|
|
|
<script>
|
|
(function() {
|
|
|
|
var nativeShadow = Polymer.Settings.useNativeShadow;
|
|
var propertyUtils = Polymer.StyleProperties;
|
|
var styleUtil = Polymer.StyleUtil;
|
|
var cssParse = Polymer.CssParse;
|
|
var styleDefaults = Polymer.StyleDefaults;
|
|
var styleTransformer = Polymer.StyleTransformer;
|
|
|
|
Polymer({
|
|
|
|
is: 'custom-style',
|
|
extends: 'style',
|
|
_template: null,
|
|
|
|
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();
|
|
},
|
|
|
|
attached: function() {
|
|
this._tryApply();
|
|
},
|
|
|
|
_tryApply: function() {
|
|
if (!this._appliesToDocument) {
|
|
// only apply variables iff this style is not inside a dom-module
|
|
if (this.parentNode &&
|
|
(this.parentNode.localName !== 'dom-module')) {
|
|
this._appliesToDocument = true;
|
|
// used applied element from HTMLImports polyfill or this
|
|
var e = this.__appliedElement || this;
|
|
styleDefaults.addStyle(e);
|
|
// we may not have any textContent yet due to parser yielding
|
|
// if so, wait until we do...
|
|
if (e.textContent || this.include) {
|
|
this._apply(true);
|
|
} else {
|
|
var self = this;
|
|
var observer = new MutationObserver(function() {
|
|
observer.disconnect();
|
|
self._apply(true);
|
|
});
|
|
observer.observe(e, {childList: true});
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
// polyfill this style with root scoping and
|
|
// apply custom properties!
|
|
_apply: function(deferProperties) {
|
|
// used applied element from HTMLImports polyfill or this
|
|
var e = this.__appliedElement || this;
|
|
if (this.include) {
|
|
e.textContent = styleUtil.cssFromModules(this.include, true) +
|
|
e.textContent;
|
|
}
|
|
if (e.textContent) {
|
|
styleUtil.forEachStyleRule(styleUtil.rulesForStyle(e), function(rule) {
|
|
styleTransformer.documentRule(rule);
|
|
});
|
|
// Allow all custom-styles defined in this turn to register
|
|
// before applying any properties. This helps ensure that all properties
|
|
// are defined before any are consumed.
|
|
// Premature application of properties can occur in 2 cases:
|
|
// (1) A property `--foo` is consumed in a custom-style
|
|
// before another custom-style produces `--foo`.
|
|
// In general, we require custom properties to be defined before being
|
|
// used in elements so supporting this for custom-style
|
|
// is dubious but is slightly more like native properties where this
|
|
// is supported.
|
|
// (2) A set of in order styles (A, B) are re-ordered due to a parser
|
|
// yield that makes A wait for textContent. This reorders its
|
|
// `_apply` after B.
|
|
// This case should only occur with native webcomponents.
|
|
var self = this;
|
|
var fn = function fn() {
|
|
self._applyCustomProperties(e);
|
|
}
|
|
if (this._pendingApplyProperties) {
|
|
cancelAnimationFrame(this._pendingApplyProperties);
|
|
this._pendingApplyProperties = null;
|
|
}
|
|
if (deferProperties) {
|
|
this._pendingApplyProperties = requestAnimationFrame(fn);
|
|
} else {
|
|
fn();
|
|
}
|
|
}
|
|
},
|
|
|
|
_applyCustomProperties: function(element) {
|
|
this._computeStyleProperties();
|
|
var props = this._styleProperties;
|
|
var rules = styleUtil.rulesForStyle(element);
|
|
element.textContent = styleUtil.toCssText(rules, function(rule) {
|
|
var css = rule.cssText = rule.parsedCssText;
|
|
if (rule.propertyInfo && rule.propertyInfo.cssText) {
|
|
// remove property assignments
|
|
// so next function isn't confused
|
|
// NOTE: we have 3 categories of css:
|
|
// (1) normal properties,
|
|
// (2) custom property assignments (--foo: red;),
|
|
// (3) custom property usage: border: var(--foo); @apply(--foo);
|
|
// In elements, 1 and 3 are separated for efficiency; here they
|
|
// are not and this makes this case unique.
|
|
css = cssParse.removeCustomPropAssignment(css);
|
|
// replace with reified properties, scenario is same as mixin
|
|
rule.cssText = propertyUtils.valueForProperties(css, props);
|
|
}
|
|
});
|
|
}
|
|
|
|
});
|
|
|
|
})();
|
|
</script>
|