|
9 | 9 | // imports
|
10 | 10 | var log = window.logFlags || {};
|
11 | 11 |
|
12 |
| - var doc = window.ShadowDOMPolyfill ? ShadowDOMPolyfill.wrap(document) : document; |
| 12 | + var doc = wrap(document); |
13 | 13 |
|
14 | 14 | /**
|
15 | 15 | * Install external stylesheets loaded in <element> elements into the
|
16 | 16 | * element's template.
|
17 | 17 | * @param inElementElement The <element> element to style.
|
18 | 18 | */
|
19 |
| - function installSheets(inElementElement) { |
20 |
| - installLocalSheets(inElementElement); |
21 |
| - installGlobalStyles(inElementElement); |
| 19 | + function installSheets(elementElement) { |
| 20 | + installLocalSheets(elementElement); |
| 21 | + installGlobalStyles(elementElement); |
22 | 22 | }
|
23 | 23 |
|
24 | 24 | /**
|
|
30 | 30 | * Note, ignores sheets with the attribute 'polymer-scope'.
|
31 | 31 | * @param inElementElement The <element> element to style.
|
32 | 32 | */
|
33 |
| - function installLocalSheets(inElementElement) { |
34 |
| - var sheets = inElementElement.querySelectorAll('[rel=stylesheet]'); |
35 |
| - var template = inElementElement.querySelector('template'); |
36 |
| - if (template) { |
37 |
| - var content = templateContent(template); |
38 |
| - } |
| 33 | + function installLocalSheets(elementElement) { |
| 34 | + var sheets = findInElement(elementElement, SHEET_SELECTOR, function(s) { |
| 35 | + return !s.hasAttribute(SCOPE_ATTR); |
| 36 | + }); |
| 37 | + var content = elementTemplateContent(elementElement); |
39 | 38 | if (content) {
|
40 |
| - forEach(sheets, function(sheet) { |
41 |
| - if (!sheet.hasAttribute(SCOPE_ATTR)) { |
42 |
| - // in case we're in document, remove from element |
43 |
| - sheet.parentNode.removeChild(sheet); |
44 |
| - var style = createStyleElementFromSheet(sheet); |
45 |
| - if (style) { |
46 |
| - content.insertBefore(style, content.firstChild); |
47 |
| - } |
| 39 | + // in case we're in document, remove from element |
| 40 | + sheets.forEach(function(sheet) { |
| 41 | + sheet.parentNode.removeChild(sheet); |
| 42 | + }); |
| 43 | + var fragment = document.createDocumentFragment(); |
| 44 | + sheets.forEach(function(sheet) { |
| 45 | + var style = createStyleElementFromSheet(sheet); |
| 46 | + if (style) { |
| 47 | + fragment.appendChild(style); |
48 | 48 | }
|
49 | 49 | });
|
| 50 | + content.insertBefore(fragment, content.firstChild); |
50 | 51 | }
|
51 | 52 | }
|
52 | 53 |
|
|
59 | 60 | * @param inElementElement The <element> element to style.
|
60 | 61 | */
|
61 | 62 | // TODO(sorvell): remove when wkb.ug/72462 is addressed.
|
62 |
| - function installGlobalStyles(inElementElement) { |
63 |
| - var styles = inElementElement.globalStyles || |
64 |
| - (inElementElement.globalStyles = findStyles(inElementElement, 'global')); |
65 |
| - applyStylesToScope(styles, doc.head); |
| 63 | + function installGlobalStyles(elementElement) { |
| 64 | + applyStylesToScope(findStyles(elementElement, 'global'), doc.head); |
66 | 65 | }
|
67 | 66 |
|
68 |
| - |
69 | 67 | /**
|
70 | 68 | * Installs external stylesheets and <style> elements with the attribute
|
71 | 69 | * polymer-scope='controller' into the scope of inElement. This is intended
|
|
83 | 81 | * @param inElementElement The <element> containing controller styles.
|
84 | 82 | */
|
85 | 83 | // TODO(sorvell): remove when spec issues are addressed
|
86 |
| - function installControllerStyles(inElement, inElementElement) { |
87 |
| - var styles = inElementElement.controllerStyles || |
88 |
| - (inElementElement.controllerStyles = findStyles(inElementElement, 'controller')); |
| 84 | + function installControllerStyles(element, elementElement) { |
| 85 | + if (!elementElement.controllerStyles) { |
| 86 | + elementElement.controllerStyles = findStyles(elementElement, |
| 87 | + 'controller'); |
| 88 | + } |
| 89 | + var styles = elementElement.controllerStyles; |
89 | 90 | async.queue(function() {
|
90 |
| - var scope = findStyleController(inElement); |
| 91 | + var scope = findStyleController(element); |
91 | 92 | if (scope) {
|
92 |
| - Polymer.shimPolyfillDirectives(styles, inElement.localName); |
| 93 | + Polymer.shimPolyfillDirectives(styles, element.localName); |
93 | 94 | applyStylesToScope(styles, scope);
|
94 | 95 | }
|
95 | 96 | });
|
|
120 | 121 |
|
121 | 122 | }
|
122 | 123 |
|
123 |
| - function findStyleController(inNode) { |
| 124 | + function findStyleController(node) { |
124 | 125 | // find the shadow root that contains inNode
|
125 |
| - var n = inNode; |
| 126 | + var n = node; |
126 | 127 | while (n.parentNode && n.localName != 'shadow-root') {
|
127 | 128 | n = n.parentNode;
|
128 | 129 | }
|
129 | 130 | return n == doc ? doc.head : n;
|
130 | 131 | };
|
131 | 132 |
|
132 |
| - function createStyleElementFromSheet(inSheet) { |
133 |
| - if (inSheet.__resource) { |
| 133 | + function createStyleElementFromSheet(sheet) { |
| 134 | + if (sheet.__resource) { |
134 | 135 | var style = doc.createElement('style');
|
135 |
| - style.textContent = inSheet.__resource; |
| 136 | + style.textContent = sheet.__resource; |
136 | 137 | return style;
|
137 | 138 | } else {
|
138 |
| - console.warn('Could not find content for stylesheet', inSheet); |
| 139 | + console.warn('Could not find content for stylesheet', sheet); |
139 | 140 | }
|
140 | 141 | }
|
141 | 142 |
|
142 |
| - function applyStylesToScope(inStyles, inScope) { |
143 |
| - inStyles.forEach(function(style) { |
144 |
| - inScope.appendChild(style.cloneNode(true)); |
| 143 | + function applyStylesToScope(styles, scope) { |
| 144 | + styles.forEach(function(style) { |
| 145 | + scope.appendChild(style.cloneNode(true)); |
145 | 146 | });
|
146 | 147 | }
|
147 | 148 |
|
148 | 149 | var eltProto = HTMLElement.prototype;
|
149 | 150 | var matches = eltProto.matches || eltProto.matchesSelector ||
|
150 | 151 | eltProto.webkitMatchesSelector || eltProto.mozMatchesSelector;
|
151 |
| - function matchesSelector(inNode, inSelector) { |
| 152 | + function matchesSelector(node, inSelector) { |
152 | 153 | if (matches) {
|
153 |
| - return matches.call(inNode, inSelector); |
| 154 | + return matches.call(node, inSelector); |
154 | 155 | }
|
155 | 156 | }
|
156 | 157 |
|
157 | 158 | // TODO(sorvell): it would be better to identify blocks of rules within
|
158 | 159 | // style declarations than require different style/link elements.
|
159 |
| - function findStyles(inElementElement, inDescriptor) { |
| 160 | + function findStyles(elementElement, descriptor) { |
160 | 161 | var styleList = [];
|
161 | 162 | // handle stylesheets
|
162 |
| - var sheets = inElementElement.querySelectorAll('[rel=stylesheet]'); |
163 |
| - var selector = '[' + SCOPE_ATTR + '=' + inDescriptor + ']'; |
164 |
| - Array.prototype.forEach.call(sheets, function(sheet) { |
165 |
| - if (matchesSelector(sheet, selector)) { |
166 |
| - // in case we're in document, remove from element |
167 |
| - sheet.parentNode.removeChild(sheet); |
168 |
| - styleList.push(createStyleElementFromSheet(sheet)); |
169 |
| - } |
| 163 | + var selector = '[' + SCOPE_ATTR + '=' + descriptor + ']'; |
| 164 | + var matcher = function(s) { |
| 165 | + return matchesSelector(s, selector); |
| 166 | + }; |
| 167 | + var sheets = findInElement(elementElement, SHEET_SELECTOR, matcher); |
| 168 | + sheets.forEach(function(sheet) { |
| 169 | + // in case we're in document, remove from element |
| 170 | + sheet.parentNode.removeChild(sheet); |
| 171 | + styleList.push(createStyleElementFromSheet(sheet)); |
170 | 172 | });
|
171 | 173 | // handle style elements
|
172 |
| - var styles = inElementElement.querySelectorAll('style'); |
173 |
| - Array.prototype.forEach.call(styles, function(style) { |
174 |
| - if (matchesSelector(style, selector)) { |
175 |
| - // in case we're in document, remove from element |
176 |
| - style.parentNode.removeChild(style); |
177 |
| - styleList.push(style); |
178 |
| - } |
| 174 | + var styles = findInElement(elementElement, STYLE_SELECTOR, matcher); |
| 175 | + styles.forEach(function(style) { |
| 176 | + // in case we're in document, remove from element |
| 177 | + style.parentNode.removeChild(style); |
| 178 | + styleList.push(style); |
179 | 179 | });
|
180 | 180 | return styleList;
|
181 | 181 | }
|
182 | 182 |
|
| 183 | + |
| 184 | + function findInElement(elementElement, selector, matcher) { |
| 185 | + var nodes = arrayFromNodeList(elementElement |
| 186 | + .querySelectorAll(selector)); |
| 187 | + var content = elementTemplateContent(elementElement); |
| 188 | + if (content) { |
| 189 | + var templateNodes = arrayFromNodeList(content |
| 190 | + .querySelectorAll(selector)); |
| 191 | + nodes = nodes.concat(templateNodes); |
| 192 | + } |
| 193 | + return nodes.filter(matcher); |
| 194 | + } |
| 195 | + |
| 196 | + function elementTemplateContent(elementElement) { |
| 197 | + var template = elementElement.querySelector('template'); |
| 198 | + return template && templateContent(template); |
| 199 | + } |
| 200 | + |
| 201 | + var STYLE_SELECTOR = 'style'; |
| 202 | + var SHEET_SELECTOR = '[rel=stylesheet]'; |
183 | 203 | var SCOPE_ATTR = 'polymer-scope';
|
184 |
| - var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); |
| 204 | + function arrayFromNodeList(nodeList) { |
| 205 | + return Array.prototype.slice.call(nodeList || [], 0); |
| 206 | + } |
185 | 207 |
|
186 | 208 | // exports
|
187 | 209 | Polymer.installSheets = installSheets;
|
|
0 commit comments