Index: third_party/polymer/components/core-style/core-style.html |
diff --git a/third_party/polymer/components/core-style/core-style.html b/third_party/polymer/components/core-style/core-style.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d0aaf5295faebe39fd2ea2747783086194ed4991 |
--- /dev/null |
+++ b/third_party/polymer/components/core-style/core-style.html |
@@ -0,0 +1,387 @@ |
+<!-- |
+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 |
+--> |
+<!-- |
+ |
+The `core-style` element helps manage styling inside other elements and can |
+be used to make themes. The `core-style` element can be either a producer |
+or consumer of styling. If it has its `id` property set, it's a producer. |
+Elements that are producers should include css styling as their text content. |
+If a `core-style` has its `ref` property set, it's a consumer. A `core-style` |
+typically sets its `ref` property to the value of the `id` property of the |
+`core-style` it wants to use. This allows a single producer to be used in |
+multiple places, for example, in many different elements. |
+ |
+It's common to place `core-style` producer elements inside HTMLImports. |
+Remote stylesheets should be included this way, the @import css mechanism is |
+not currently supported. |
+ |
+Here's a basic example: |
+ |
+ <polymer-element name="x-test" noscript> |
+ <template> |
+ <core-style ref="x-test"></core-style> |
+ <content></content> |
+ </template> |
+ </polymer-element> |
+ |
+The `x-test` element above will be styled by any `core-style` elements that have |
+`id` set to `x-test`. These `core-style` producers are separate from the element |
+definition, allowing a user of the element to style it independent of the author's |
+styling. For example: |
+ |
+ <core-style id="x-test"> |
+ :host { |
+ backgound-color: steelblue; |
+ } |
+ </core-style> |
+ |
+The content of the `x-test` `core-style` producer gets included inside the |
+shadowRoot of the `x-test` element. If the content of the `x-test` producer |
+`core-style` changes, all consumers of it are automatically kept in sync. This |
+allows updating styling on the fly. |
+ |
+The `core-style` element also supports bindings and it is the producer |
+`core-style` element is the model for its content. Here's an example: |
+ |
+ <core-style id="x-test"> |
+ :host { |
+ background-color: {{myColor}}; |
+ } |
+ </core-style> |
+ <script> |
+ document._currentScript.ownerDocument.getElementById('x-test').myColor = 'orange'; |
+ </script> |
+ |
+Finally, to facilitate sharing data between `core-style` elements, all |
+`core-style` elements have a `g` property which is set to the global |
+`CoreStyle.g`. Here's an example: |
+ |
+ <core-style id="x-test"> |
+ :host { |
+ background-color: {{g.myColor}}; |
+ } |
+ </core-style> |
+ <script> |
+ CoreStyle.g.myColor = 'tomato'; |
+ </script> |
+ |
+Finally, one `core-style` can be nested inside another. The `core-style` |
+element has a `list` property which is a map of all the `core-style` producers. |
+A `core-style` producer's content is available via its `cssText` property. |
+Putting this together: |
+ |
+ <core-style id="common"> |
+ :host { |
+ font-family: sans-serif; |
+ } |
+ </core-style> |
+ |
+ <core-style id="x-test"> |
+ {{list.common.cssText}} |
+ |
+ :host { |
+ background-color: {{g.myColor}}; |
+ } |
+ </core-style> |
+ |
+ |
+@group Polymer Core Elements |
+@element core-style |
+@homepage github.io |
+--> |
+ |
+<link rel="import" href="../polymer/polymer.html"> |
+ |
+<polymer-element name="core-style" hidden> |
+<script> |
+(function() { |
+ |
+window.CoreStyle = window.CoreStyle || { |
+ g: {}, |
+ list: {}, |
+ refMap: {} |
+}; |
+ |
+Polymer('core-style', { |
+ /** |
+ * The `id` property should be set if the `core-style` is a producer |
+ * of styles. In this case, the `core-style` should have text content |
+ * that is cssText. |
+ * |
+ * @attribute id |
+ * @type string |
+ * @default '' |
+ */ |
+ |
+ |
+ publish: { |
+ /** |
+ * The `ref` property should be set if the `core-style` element is a |
+ * consumer of styles. Set it to the `id` of the desired `core-style` |
+ * element. |
+ * |
+ * @attribute ref |
+ * @type string |
+ * @default '' |
+ */ |
+ ref: '' |
+ }, |
+ |
+ // static |
+ g: CoreStyle.g, |
+ refMap: CoreStyle.refMap, |
+ |
+ /** |
+ * The `list` is a map of all `core-style` producers stored by `id`. It |
+ * should be considered readonly. It's useful for nesting one `core-style` |
+ * inside another. |
+ * |
+ * @attribute list |
+ * @type object (readonly) |
+ * @default {map of all `core-style` producers} |
+ */ |
+ list: CoreStyle.list, |
+ |
+ // if we have an id, we provide style |
+ // if we have a ref, we consume/require style |
+ ready: function() { |
+ if (this.id) { |
+ this.provide(); |
+ } else { |
+ this.registerRef(this.ref); |
+ if (!window.ShadowDOMPolyfill) { |
+ this.require(); |
+ } |
+ } |
+ }, |
+ |
+ // can't shim until attached if using SD polyfill because need to find host |
+ attached: function() { |
+ if (!this.id && window.ShadowDOMPolyfill) { |
+ this.require(); |
+ } |
+ }, |
+ |
+ /****** producer stuff *******/ |
+ |
+ provide: function() { |
+ this.register(); |
+ // we want to do this asap, especially so we can do so before definitions |
+ // that use this core-style are registered. |
+ if (this.textContent) { |
+ this._completeProvide(); |
+ } else { |
+ this.async(this._completeProvide); |
+ } |
+ }, |
+ |
+ register: function() { |
+ var i = this.list[this.id]; |
+ if (i) { |
+ if (!Array.isArray(i)) { |
+ this.list[this.id] = [i]; |
+ } |
+ this.list[this.id].push(this); |
+ } else { |
+ this.list[this.id] = this; |
+ } |
+ }, |
+ |
+ // stamp into a shadowRoot so we can monitor dom of the bound output |
+ _completeProvide: function() { |
+ this.createShadowRoot(); |
+ this.domObserver = new MutationObserver(this.domModified.bind(this)) |
+ .observe(this.shadowRoot, {subtree: true, |
+ characterData: true, childList: true}); |
+ this.provideContent(); |
+ }, |
+ |
+ provideContent: function() { |
+ this.ensureTemplate(); |
+ this.shadowRoot.textContent = ''; |
+ this.shadowRoot.appendChild(this.instanceTemplate(this.template)); |
+ this.cssText = this.shadowRoot.textContent; |
+ }, |
+ |
+ ensureTemplate: function() { |
+ if (!this.template) { |
+ this.template = this.querySelector('template:not([repeat]):not([bind])'); |
+ // move content into the template |
+ if (!this.template) { |
+ this.template = document.createElement('template'); |
+ var n = this.firstChild; |
+ while (n) { |
+ this.template.content.appendChild(n.cloneNode(true)); |
+ n = n.nextSibling; |
+ } |
+ } |
+ } |
+ }, |
+ |
+ domModified: function() { |
+ this.cssText = this.shadowRoot.textContent; |
+ this.notify(); |
+ }, |
+ |
+ // notify instances that reference this element |
+ notify: function() { |
+ var s$ = this.refMap[this.id]; |
+ if (s$) { |
+ for (var i=0, s; (s=s$[i]); i++) { |
+ s.require(); |
+ } |
+ } |
+ }, |
+ |
+ /****** consumer stuff *******/ |
+ |
+ registerRef: function(ref) { |
+ //console.log('register', ref); |
+ this.refMap[this.ref] = this.refMap[this.ref] || []; |
+ this.refMap[this.ref].push(this); |
+ }, |
+ |
+ applyRef: function(ref) { |
+ this.ref = ref; |
+ this.registerRef(this.ref); |
+ this.require(); |
+ }, |
+ |
+ require: function() { |
+ var cssText = this.cssTextForRef(this.ref); |
+ //console.log('require', this.ref, cssText); |
+ if (cssText) { |
+ this.ensureStyleElement(); |
+ // do nothing if cssText has not changed |
+ if (this.styleElement._cssText === cssText) { |
+ return; |
+ } |
+ this.styleElement._cssText = cssText; |
+ if (window.ShadowDOMPolyfill) { |
+ this.styleElement.textContent = cssText; |
+ cssText = Platform.ShadowCSS.shimStyle(this.styleElement, |
+ this.getScopeSelector()); |
+ } |
+ this.styleElement.textContent = cssText; |
+ } |
+ }, |
+ |
+ cssTextForRef: function(ref) { |
+ var s$ = this.byId(ref); |
+ var cssText = ''; |
+ if (s$) { |
+ if (Array.isArray(s$)) { |
+ var p = []; |
+ for (var i=0, l=s$.length, s; (i<l) && (s=s$[i]); i++) { |
+ p.push(s.cssText); |
+ } |
+ cssText = p.join('\n\n'); |
+ } else { |
+ cssText = s$.cssText; |
+ } |
+ } |
+ if (s$ && !cssText) { |
+ console.warn('No styles provided for ref:', ref); |
+ } |
+ return cssText; |
+ }, |
+ |
+ byId: function(id) { |
+ return this.list[id]; |
+ }, |
+ |
+ ensureStyleElement: function() { |
+ if (!this.styleElement) { |
+ this.styleElement = window.ShadowDOMPolyfill ? |
+ this.makeShimStyle() : |
+ this.makeRootStyle(); |
+ } |
+ if (!this.styleElement) { |
+ console.warn(this.localName, 'could not setup style.'); |
+ } |
+ }, |
+ |
+ makeRootStyle: function() { |
+ var style = document.createElement('style'); |
+ this.appendChild(style); |
+ return style; |
+ }, |
+ |
+ makeShimStyle: function() { |
+ var host = this.findHost(this); |
+ if (host) { |
+ var name = host.localName; |
+ var style = document.querySelector('style[' + name + '=' + this.ref +']'); |
+ if (!style) { |
+ style = document.createElement('style'); |
+ style.setAttribute(name, this.ref); |
+ document.head.appendChild(style); |
+ } |
+ return style; |
+ } |
+ }, |
+ |
+ getScopeSelector: function() { |
+ if (!this._scopeSelector) { |
+ var selector = '', host = this.findHost(this); |
+ if (host) { |
+ var typeExtension = host.hasAttribute('is'); |
+ var name = typeExtension ? host.getAttribute('is') : host.localName; |
+ selector = Platform.ShadowCSS.makeScopeSelector(name, |
+ typeExtension); |
+ } |
+ this._scopeSelector = selector; |
+ } |
+ return this._scopeSelector; |
+ }, |
+ |
+ findHost: function(node) { |
+ while (node.parentNode) { |
+ node = node.parentNode; |
+ } |
+ return node.host || wrap(document.documentElement); |
+ }, |
+ |
+ /* filters! */ |
+ // TODO(dfreedm): add more filters! |
+ |
+ cycle: function(rgb, amount) { |
+ if (rgb.match('#')) { |
+ var o = this.hexToRgb(rgb); |
+ if (!o) { |
+ return rgb; |
+ } |
+ rgb = 'rgb(' + o.r + ',' + o.b + ',' + o.g + ')'; |
+ } |
+ |
+ function cycleChannel(v) { |
+ return Math.abs((Number(v) - amount) % 255); |
+ } |
+ |
+ return rgb.replace(/rgb\(([^,]*),([^,]*),([^,]*)\)/, function(m, a, b, c) { |
+ return 'rgb(' + cycleChannel(a) + ',' + cycleChannel(b) + ', ' |
+ + cycleChannel(c) + ')'; |
+ }); |
+ }, |
+ |
+ hexToRgb: function(hex) { |
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); |
+ return result ? { |
+ r: parseInt(result[1], 16), |
+ g: parseInt(result[2], 16), |
+ b: parseInt(result[3], 16) |
+ } : null; |
+ } |
+ |
+}); |
+ |
+ |
+})(); |
+</script> |
+</polymer-element> |