Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / polymer / components-chromium / core-style / core-style-extracted.js
1 \r
2 (function() {\r
3 \r
4 window.CoreStyle = window.CoreStyle || {\r
5   g: {},\r
6   list: {},\r
7   refMap: {}\r
8 };\r
9 \r
10 Polymer('core-style', {\r
11   /**\r
12    * The `id` property should be set if the `core-style` is a producer\r
13    * of styles. In this case, the `core-style` should have text content\r
14    * that is cssText.\r
15    *\r
16    * @attribute id\r
17    * @type string\r
18    * @default ''\r
19    */\r
20 \r
21 \r
22   publish: {\r
23     /**\r
24      * The `ref` property should be set if the `core-style` element is a \r
25      * consumer of styles. Set it to the `id` of the desired `core-style`\r
26      * element.\r
27      *\r
28      * @attribute ref\r
29      * @type string\r
30      * @default ''\r
31      */\r
32     ref: ''\r
33   },\r
34 \r
35   // static\r
36   g: CoreStyle.g,\r
37   refMap: CoreStyle.refMap,\r
38 \r
39   /**\r
40    * The `list` is a map of all `core-style` producers stored by `id`. It \r
41    * should be considered readonly. It's useful for nesting one `core-style`\r
42    * inside another.\r
43    *\r
44    * @attribute list\r
45    * @type object (readonly)\r
46    * @default {map of all `core-style` producers}\r
47    */\r
48   list: CoreStyle.list,\r
49 \r
50   // if we have an id, we provide style\r
51   // if we have a ref, we consume/require style\r
52   ready: function() {\r
53     if (this.id) {\r
54       this.provide();\r
55     } else {\r
56       this.registerRef(this.ref);\r
57       if (!window.ShadowDOMPolyfill) {\r
58         this.require();\r
59       }  \r
60     }\r
61   },\r
62 \r
63   // can't shim until attached if using SD polyfill because need to find host\r
64   attached: function() {\r
65     if (!this.id && window.ShadowDOMPolyfill) {\r
66       this.require();\r
67     }\r
68   },\r
69 \r
70   /****** producer stuff *******/\r
71 \r
72   provide: function() {\r
73     this.register();\r
74     // we want to do this asap, especially so we can do so before definitions\r
75     // that use this core-style are registered.\r
76     if (this.textContent) {\r
77       this._completeProvide();\r
78     } else {\r
79       this.async(this._completeProvide);\r
80     }\r
81   },\r
82 \r
83   register: function() {\r
84     var i = this.list[this.id];\r
85     if (i) {\r
86       if (!Array.isArray(i)) {\r
87         this.list[this.id] = [i];\r
88       }\r
89       this.list[this.id].push(this);\r
90     } else {\r
91       this.list[this.id] = this;  \r
92     }\r
93   },\r
94 \r
95   // stamp into a shadowRoot so we can monitor dom of the bound output\r
96   _completeProvide: function() {\r
97     this.createShadowRoot();\r
98     this.domObserver = new MutationObserver(this.domModified.bind(this))\r
99         .observe(this.shadowRoot, {subtree: true, \r
100         characterData: true, childList: true});\r
101     this.provideContent();\r
102   },\r
103 \r
104   provideContent: function() {\r
105     this.ensureTemplate();\r
106     this.shadowRoot.textContent = '';\r
107     this.shadowRoot.appendChild(this.instanceTemplate(this.template));\r
108     this.cssText = this.shadowRoot.textContent;\r
109   },\r
110 \r
111   ensureTemplate: function() {\r
112     if (!this.template) {\r
113       this.template = this.querySelector('template:not([repeat]):not([bind])');\r
114       // move content into the template\r
115       if (!this.template) {\r
116         this.template = document.createElement('template');\r
117         var n = this.firstChild;\r
118         while (n) {\r
119           this.template.content.appendChild(n.cloneNode(true));\r
120           n = n.nextSibling;\r
121         }\r
122       }\r
123     }\r
124   },\r
125 \r
126   domModified: function() {\r
127     this.cssText = this.shadowRoot.textContent;\r
128     this.notify();\r
129   },\r
130 \r
131   // notify instances that reference this element\r
132   notify: function() {\r
133     var s$ = this.refMap[this.id];\r
134     if (s$) {\r
135       for (var i=0, s; (s=s$[i]); i++) {\r
136         s.require();\r
137       }\r
138     }\r
139   },\r
140 \r
141   /****** consumer stuff *******/\r
142 \r
143   registerRef: function(ref) {\r
144     //console.log('register', ref);\r
145     this.refMap[this.ref] = this.refMap[this.ref] || [];\r
146     this.refMap[this.ref].push(this);\r
147   },\r
148 \r
149   applyRef: function(ref) {\r
150     this.ref = ref;\r
151     this.registerRef(this.ref);\r
152     this.require();\r
153   },\r
154 \r
155   require: function() {\r
156     var cssText = this.cssTextForRef(this.ref);\r
157     //console.log('require', this.ref, cssText);\r
158     if (cssText) {\r
159       this.ensureStyleElement();\r
160       // do nothing if cssText has not changed\r
161       if (this.styleElement._cssText === cssText) {\r
162         return;\r
163       }\r
164       this.styleElement._cssText = cssText;\r
165       if (window.ShadowDOMPolyfill) {\r
166         this.styleElement.textContent = cssText;\r
167         cssText = Platform.ShadowCSS.shimStyle(this.styleElement,\r
168             this.getScopeSelector());\r
169       }\r
170       this.styleElement.textContent = cssText;\r
171     }\r
172   },\r
173 \r
174   cssTextForRef: function(ref) {\r
175     var s$ = this.byId(ref);\r
176     var cssText = '';\r
177     if (s$) {\r
178       if (Array.isArray(s$)) {\r
179         var p = [];\r
180         for (var i=0, l=s$.length, s; (i<l) && (s=s$[i]); i++) {\r
181           p.push(s.cssText);\r
182         }\r
183         cssText = p.join('\n\n');\r
184       } else {\r
185         cssText = s$.cssText;\r
186       }\r
187     }\r
188     if (s$ && !cssText) {\r
189       console.warn('No styles provided for ref:', ref);\r
190     }\r
191     return cssText;\r
192   },\r
193 \r
194   byId: function(id) {\r
195     return this.list[id];\r
196   },\r
197 \r
198   ensureStyleElement: function() {\r
199     if (!this.styleElement) {\r
200       this.styleElement = window.ShadowDOMPolyfill ? \r
201           this.makeShimStyle() :\r
202           this.makeRootStyle();\r
203     }\r
204     if (!this.styleElement) {\r
205       console.warn(this.localName, 'could not setup style.');\r
206     }\r
207   },\r
208 \r
209   makeRootStyle: function() {\r
210     var style = document.createElement('style');\r
211     this.appendChild(style);\r
212     return style;\r
213   },\r
214 \r
215   makeShimStyle: function() {\r
216     var host = this.findHost(this);\r
217     if (host) {\r
218       var name = host.localName;\r
219       var style = document.querySelector('style[' + name + '=' + this.ref +']');\r
220       if (!style) {\r
221         style = document.createElement('style');\r
222         style.setAttribute(name, this.ref);\r
223         document.head.appendChild(style);\r
224       }\r
225       return style;\r
226     }\r
227   },\r
228 \r
229   getScopeSelector: function() {\r
230     if (!this._scopeSelector) {\r
231       var selector = '', host = this.findHost(this);\r
232       if (host) {\r
233         var typeExtension = host.hasAttribute('is');\r
234         var name = typeExtension ? host.getAttribute('is') : host.localName;\r
235         selector = Platform.ShadowCSS.makeScopeSelector(name, \r
236             typeExtension);\r
237       }\r
238       this._scopeSelector = selector;\r
239     }\r
240     return this._scopeSelector;\r
241   },\r
242 \r
243   findHost: function(node) {\r
244     while (node.parentNode) {\r
245       node = node.parentNode;\r
246     }\r
247     return node.host || wrap(document.documentElement);\r
248   },\r
249 \r
250   /* filters! */\r
251   // TODO(dfreedm): add more filters!\r
252 \r
253   cycle: function(rgb, amount) {\r
254     if (rgb.match('#')) {\r
255       var o = this.hexToRgb(rgb);\r
256       if (!o) {\r
257         return rgb;\r
258       }\r
259       rgb = 'rgb(' + o.r + ',' + o.b + ',' + o.g + ')';\r
260     }\r
261 \r
262     function cycleChannel(v) {\r
263       return Math.abs((Number(v) - amount) % 255);\r
264     }\r
265 \r
266     return rgb.replace(/rgb\(([^,]*),([^,]*),([^,]*)\)/, function(m, a, b, c) {\r
267       return 'rgb(' + cycleChannel(a) + ',' + cycleChannel(b) + ', ' \r
268           + cycleChannel(c) + ')';\r
269     });\r
270   },\r
271 \r
272   hexToRgb: function(hex) {\r
273     var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);\r
274     return result ? {\r
275         r: parseInt(result[1], 16),\r
276         g: parseInt(result[2], 16),\r
277         b: parseInt(result[3], 16)\r
278     } : null;\r
279   }\r
280 \r
281 });\r
282 \r
283 \r
284 })();\r