OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The Polymer Authors. All rights reserved. | 2 * Copyright 2012 The Polymer Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style | 3 * Use of this source code is governed by a BSD-style |
4 * license that can be found in the LICENSE file. | 4 * license that can be found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 if (typeof WeakMap === 'undefined') { | 7 if (typeof WeakMap === 'undefined') { |
8 (function() { | 8 (function() { |
9 var defineProperty = Object.defineProperty; | 9 var defineProperty = Object.defineProperty; |
10 var counter = Date.now() % 1e9; | 10 var counter = Date.now() % 1e9; |
(...skipping 6889 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6900 | 6900 |
6901 /* | 6901 /* |
6902 * Copyright 2012 The Polymer Authors. All rights reserved. | 6902 * Copyright 2012 The Polymer Authors. All rights reserved. |
6903 * Use of this source code is governed by a BSD-style | 6903 * Use of this source code is governed by a BSD-style |
6904 * license that can be found in the LICENSE file. | 6904 * license that can be found in the LICENSE file. |
6905 */ | 6905 */ |
6906 | 6906 |
6907 /* | 6907 /* |
6908 This is a limited shim for ShadowDOM css styling. | 6908 This is a limited shim for ShadowDOM css styling. |
6909 https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#style
s | 6909 https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#style
s |
6910 | 6910 |
6911 The intention here is to support only the styling features which can be | 6911 The intention here is to support only the styling features which can be |
6912 relatively simply implemented. The goal is to allow users to avoid the | 6912 relatively simply implemented. The goal is to allow users to avoid the |
6913 most obvious pitfalls and do so without compromising performance significantly
. | 6913 most obvious pitfalls and do so without compromising performance significantly
. |
6914 For ShadowDOM styling that's not covered here, a set of best practices | 6914 For ShadowDOM styling that's not covered here, a set of best practices |
6915 can be provided that should allow users to accomplish more complex styling. | 6915 can be provided that should allow users to accomplish more complex styling. |
6916 | 6916 |
6917 The following is a list of specific ShadowDOM styling features and a brief | 6917 The following is a list of specific ShadowDOM styling features and a brief |
6918 discussion of the approach used to shim. | 6918 discussion of the approach used to shim. |
6919 | 6919 |
6920 Shimmed features: | 6920 Shimmed features: |
6921 | 6921 |
6922 * :host, :ancestor: ShadowDOM allows styling of the shadowRoot's host | 6922 * :host, :ancestor: ShadowDOM allows styling of the shadowRoot's host |
6923 element using the :host rule. To shim this feature, the :host styles are | 6923 element using the :host rule. To shim this feature, the :host styles are |
6924 reformatted and prefixed with a given scope name and promoted to a | 6924 reformatted and prefixed with a given scope name and promoted to a |
6925 document level stylesheet. | 6925 document level stylesheet. |
6926 For example, given a scope name of .foo, a rule like this: | 6926 For example, given a scope name of .foo, a rule like this: |
6927 | 6927 |
6928 :host { | 6928 :host { |
6929 background: red; | 6929 background: red; |
6930 } | 6930 } |
6931 } | 6931 } |
6932 | 6932 |
6933 becomes: | 6933 becomes: |
6934 | 6934 |
6935 .foo { | 6935 .foo { |
6936 background: red; | 6936 background: red; |
6937 } | 6937 } |
6938 | 6938 |
6939 * encapsultion: Styles defined within ShadowDOM, apply only to | 6939 * encapsultion: Styles defined within ShadowDOM, apply only to |
6940 dom inside the ShadowDOM. Polymer uses one of two techniques to imlement | 6940 dom inside the ShadowDOM. Polymer uses one of two techniques to imlement |
6941 this feature. | 6941 this feature. |
6942 | 6942 |
6943 By default, rules are prefixed with the host element tag name | 6943 By default, rules are prefixed with the host element tag name |
6944 as a descendant selector. This ensures styling does not leak out of the 'top' | 6944 as a descendant selector. This ensures styling does not leak out of the 'top' |
6945 of the element's ShadowDOM. For example, | 6945 of the element's ShadowDOM. For example, |
6946 | 6946 |
6947 div { | 6947 div { |
6948 font-weight: bold; | 6948 font-weight: bold; |
6949 } | 6949 } |
6950 | 6950 |
6951 becomes: | 6951 becomes: |
6952 | 6952 |
6953 x-foo div { | 6953 x-foo div { |
6954 font-weight: bold; | 6954 font-weight: bold; |
6955 } | 6955 } |
6956 | 6956 |
6957 becomes: | 6957 becomes: |
6958 | 6958 |
6959 | 6959 |
6960 Alternatively, if Platform.ShadowCSS.strictStyling is set to true then | 6960 Alternatively, if Platform.ShadowCSS.strictStyling is set to true then |
6961 selectors are scoped by adding an attribute selector suffix to each | 6961 selectors are scoped by adding an attribute selector suffix to each |
6962 simple selector that contains the host element tag name. Each element | 6962 simple selector that contains the host element tag name. Each element |
6963 in the element's ShadowDOM template is also given the scope attribute. | 6963 in the element's ShadowDOM template is also given the scope attribute. |
6964 Thus, these rules match only elements that have the scope attribute. | 6964 Thus, these rules match only elements that have the scope attribute. |
6965 For example, given a scope name of x-foo, a rule like this: | 6965 For example, given a scope name of x-foo, a rule like this: |
6966 | 6966 |
6967 div { | 6967 div { |
6968 font-weight: bold; | 6968 font-weight: bold; |
6969 } | 6969 } |
6970 | 6970 |
6971 becomes: | 6971 becomes: |
6972 | 6972 |
6973 div[x-foo] { | 6973 div[x-foo] { |
6974 font-weight: bold; | 6974 font-weight: bold; |
6975 } | 6975 } |
6976 | 6976 |
6977 Note that elements that are dynamically added to a scope must have the scope | 6977 Note that elements that are dynamically added to a scope must have the scope |
6978 selector added to them manually. | 6978 selector added to them manually. |
6979 | 6979 |
6980 * upper/lower bound encapsulation: Styles which are defined outside a | 6980 * upper/lower bound encapsulation: Styles which are defined outside a |
6981 shadowRoot should not cross the ShadowDOM boundary and should not apply | 6981 shadowRoot should not cross the ShadowDOM boundary and should not apply |
6982 inside a shadowRoot. | 6982 inside a shadowRoot. |
6983 | 6983 |
6984 This styling behavior is not emulated. Some possible ways to do this that | 6984 This styling behavior is not emulated. Some possible ways to do this that |
6985 were rejected due to complexity and/or performance concerns include: (1) reset | 6985 were rejected due to complexity and/or performance concerns include: (1) reset |
6986 every possible property for every possible selector for a given scope name; | 6986 every possible property for every possible selector for a given scope name; |
6987 (2) re-implement css in javascript. | 6987 (2) re-implement css in javascript. |
6988 | 6988 |
6989 As an alternative, users should make sure to use selectors | 6989 As an alternative, users should make sure to use selectors |
6990 specific to the scope in which they are working. | 6990 specific to the scope in which they are working. |
6991 | 6991 |
6992 * ::distributed: This behavior is not emulated. It's often not necessary | 6992 * ::distributed: This behavior is not emulated. It's often not necessary |
6993 to style the contents of a specific insertion point and instead, descendants | 6993 to style the contents of a specific insertion point and instead, descendants |
6994 of the host element can be styled selectively. Users can also create an | 6994 of the host element can be styled selectively. Users can also create an |
6995 extra node around an insertion point and style that node's contents | 6995 extra node around an insertion point and style that node's contents |
6996 via descendent selectors. For example, with a shadowRoot like this: | 6996 via descendent selectors. For example, with a shadowRoot like this: |
6997 | 6997 |
6998 <style> | 6998 <style> |
6999 ::content(div) { | 6999 ::content(div) { |
7000 background: red; | 7000 background: red; |
7001 } | 7001 } |
7002 </style> | 7002 </style> |
7003 <content></content> | 7003 <content></content> |
7004 | 7004 |
7005 could become: | 7005 could become: |
7006 | 7006 |
7007 <style> | 7007 <style> |
7008 / *@polyfill .content-container div * / | 7008 / *@polyfill .content-container div * / |
7009 ::content(div) { | 7009 ::content(div) { |
7010 background: red; | 7010 background: red; |
7011 } | 7011 } |
7012 </style> | 7012 </style> |
7013 <div class="content-container"> | 7013 <div class="content-container"> |
7014 <content></content> | 7014 <content></content> |
7015 </div> | 7015 </div> |
7016 | 7016 |
7017 Note the use of @polyfill in the comment above a ShadowDOM specific style | 7017 Note the use of @polyfill in the comment above a ShadowDOM specific style |
7018 declaration. This is a directive to the styling shim to use the selector | 7018 declaration. This is a directive to the styling shim to use the selector |
7019 in comments in lieu of the next selector when running under polyfill. | 7019 in comments in lieu of the next selector when running under polyfill. |
7020 */ | 7020 */ |
7021 (function(scope) { | 7021 (function(scope) { |
7022 | 7022 |
7023 var ShadowCSS = { | 7023 var ShadowCSS = { |
7024 strictStyling: false, | 7024 strictStyling: false, |
7025 registry: {}, | 7025 registry: {}, |
7026 // Shim styles for a given root associated with a name and extendsName | 7026 // Shim styles for a given root associated with a name and extendsName |
7027 // 1. cache root styles by name | 7027 // 1. cache root styles by name |
7028 // 2. optionally tag root nodes with scope name | 7028 // 2. optionally tag root nodes with scope name |
7029 // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */ | 7029 // 3. shim polyfill directives /* @polyfill */ and /* @polyfill-rule */ |
7030 // 4. shim :host and scoping | 7030 // 4. shim :host and scoping |
7031 shimStyling: function(root, name, extendsName) { | 7031 shimStyling: function(root, name, extendsName) { |
7032 var typeExtension = this.isTypeExtension(extendsName); | 7032 var typeExtension = this.isTypeExtension(extendsName); |
7033 // use caching to make working with styles nodes easier and to facilitate | 7033 // use caching to make working with styles nodes easier and to facilitate |
7034 // lookup of extendee | 7034 // lookup of extendee |
7035 var def = this.registerDefinition(root, name, extendsName); | 7035 var def = this.registerDefinition(root, name, extendsName); |
7036 // find styles and apply shimming... | 7036 // find styles and apply shimming... |
7037 if (this.strictStyling) { | 7037 if (this.strictStyling) { |
7038 this.applyScopeToContent(root, name); | 7038 this.applyScopeToContent(root, name); |
7039 } | 7039 } |
7040 var cssText = this.stylesToShimmedCssText(def.rootStyles, def.scopeStyles, | 7040 var cssText = this.stylesToShimmedCssText(def.rootStyles, def.scopeStyles, |
7041 name, typeExtension); | 7041 name, typeExtension); |
7042 // provide shimmedStyle for user extensibility | 7042 // provide shimmedStyle for user extensibility |
7043 def.shimmedStyle = cssTextToStyle(cssText); | 7043 def.shimmedStyle = cssTextToStyle(cssText); |
7044 if (root) { | 7044 if (root) { |
7045 root.shimmedStyle = def.shimmedStyle; | 7045 root.shimmedStyle = def.shimmedStyle; |
7046 } | 7046 } |
7047 // remove existing style elements | 7047 // remove existing style elements |
7048 for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); | 7048 for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); |
7049 i++) { | 7049 i++) { |
7050 s.parentNode.removeChild(s); | 7050 s.parentNode.removeChild(s); |
7051 } | 7051 } |
7052 // add style to document | 7052 // add style to document |
7053 addCssToDocument(cssText); | 7053 addCssToDocument(cssText); |
7054 }, | 7054 }, |
7055 // apply @polyfill rules + :host and scope shimming | 7055 // apply @polyfill rules + :host and scope shimming |
7056 stylesToShimmedCssText: function(rootStyles, scopeStyles, name, | 7056 stylesToShimmedCssText: function(rootStyles, scopeStyles, name, |
7057 typeExtension) { | 7057 typeExtension) { |
7058 name = name || ''; | 7058 name = name || ''; |
7059 // insert @polyfill and @polyfill-rule rules into style elements | 7059 // insert @polyfill and @polyfill-rule rules into style elements |
7060 // scoping process takes care of shimming these | 7060 // scoping process takes care of shimming these |
7061 this.insertPolyfillDirectives(rootStyles); | 7061 this.insertPolyfillDirectives(rootStyles); |
7062 this.insertPolyfillRules(rootStyles); | 7062 this.insertPolyfillRules(rootStyles); |
7063 var cssText = this.shimScoping(scopeStyles, name, typeExtension); | 7063 var cssText = this.shimScoping(scopeStyles, name, typeExtension); |
7064 // note: we only need to do rootStyles since these are unscoped. | 7064 // note: we only need to do rootStyles since these are unscoped. |
7065 cssText += this.extractPolyfillUnscopedRules(rootStyles); | 7065 cssText += this.extractPolyfillUnscopedRules(rootStyles); |
7066 return cssText; | 7066 return cssText.trim(); |
7067 }, | 7067 }, |
7068 registerDefinition: function(root, name, extendsName) { | 7068 registerDefinition: function(root, name, extendsName) { |
7069 var def = this.registry[name] = { | 7069 var def = this.registry[name] = { |
7070 root: root, | 7070 root: root, |
7071 name: name, | 7071 name: name, |
7072 extendsName: extendsName | 7072 extendsName: extendsName |
7073 } | 7073 } |
7074 var styles = root ? root.querySelectorAll('style') : []; | 7074 var styles = root ? root.querySelectorAll('style') : []; |
7075 styles = styles ? Array.prototype.slice.call(styles, 0) : []; | 7075 styles = styles ? Array.prototype.slice.call(styles, 0) : []; |
7076 def.rootStyles = styles; | 7076 def.rootStyles = styles; |
(...skipping 18 matching lines...) Expand all Loading... |
7095 Array.prototype.forEach.call(root.querySelectorAll('template'), | 7095 Array.prototype.forEach.call(root.querySelectorAll('template'), |
7096 function(template) { | 7096 function(template) { |
7097 this.applyScopeToContent(template.content, name); | 7097 this.applyScopeToContent(template.content, name); |
7098 }, | 7098 }, |
7099 this); | 7099 this); |
7100 } | 7100 } |
7101 }, | 7101 }, |
7102 /* | 7102 /* |
7103 * Process styles to convert native ShadowDOM rules that will trip | 7103 * Process styles to convert native ShadowDOM rules that will trip |
7104 * up the css parser; we rely on decorating the stylesheet with comments. | 7104 * up the css parser; we rely on decorating the stylesheet with comments. |
7105 * | 7105 * |
7106 * For example, we convert this rule: | 7106 * For example, we convert this rule: |
7107 * | 7107 * |
7108 * (comment start) @polyfill :host menu-item (comment end) | 7108 * (comment start) @polyfill :host menu-item (comment end) |
7109 * shadow::-webkit-distributed(menu-item) { | 7109 * shadow::-webkit-distributed(menu-item) { |
7110 * | 7110 * |
7111 * to this: | 7111 * to this: |
7112 * | 7112 * |
7113 * scopeName menu-item { | 7113 * scopeName menu-item { |
7114 * | 7114 * |
7115 **/ | 7115 **/ |
7116 insertPolyfillDirectives: function(styles) { | 7116 insertPolyfillDirectives: function(styles) { |
7117 if (styles) { | 7117 if (styles) { |
7118 Array.prototype.forEach.call(styles, function(s) { | 7118 Array.prototype.forEach.call(styles, function(s) { |
7119 s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent); | 7119 s.textContent = this.insertPolyfillDirectivesInCssText(s.textContent); |
7120 }, this); | 7120 }, this); |
7121 } | 7121 } |
7122 }, | 7122 }, |
7123 insertPolyfillDirectivesInCssText: function(cssText) { | 7123 insertPolyfillDirectivesInCssText: function(cssText) { |
7124 return cssText.replace(cssPolyfillCommentRe, function(match, p1) { | 7124 return cssText.replace(cssPolyfillCommentRe, function(match, p1) { |
7125 // remove end comment delimiter and add block start | 7125 // remove end comment delimiter and add block start |
7126 return p1.slice(0, -2) + '{'; | 7126 return p1.slice(0, -2) + '{'; |
7127 }); | 7127 }); |
7128 }, | 7128 }, |
7129 /* | 7129 /* |
7130 * Process styles to add rules which will only apply under the polyfill | 7130 * Process styles to add rules which will only apply under the polyfill |
7131 * | 7131 * |
7132 * For example, we convert this rule: | 7132 * For example, we convert this rule: |
7133 * | 7133 * |
7134 * (comment start) @polyfill-rule :host menu-item { | 7134 * (comment start) @polyfill-rule :host menu-item { |
7135 * ... } (comment end) | 7135 * ... } (comment end) |
7136 * | 7136 * |
7137 * to this: | 7137 * to this: |
7138 * | 7138 * |
7139 * scopeName menu-item {...} | 7139 * scopeName menu-item {...} |
7140 * | 7140 * |
7141 **/ | 7141 **/ |
7142 insertPolyfillRules: function(styles) { | 7142 insertPolyfillRules: function(styles) { |
7143 if (styles) { | 7143 if (styles) { |
7144 Array.prototype.forEach.call(styles, function(s) { | 7144 Array.prototype.forEach.call(styles, function(s) { |
7145 s.textContent = this.insertPolyfillRulesInCssText(s.textContent); | 7145 s.textContent = this.insertPolyfillRulesInCssText(s.textContent); |
7146 }, this); | 7146 }, this); |
7147 } | 7147 } |
7148 }, | 7148 }, |
7149 insertPolyfillRulesInCssText: function(cssText) { | 7149 insertPolyfillRulesInCssText: function(cssText) { |
7150 return cssText.replace(cssPolyfillRuleCommentRe, function(match, p1) { | 7150 return cssText.replace(cssPolyfillRuleCommentRe, function(match, p1) { |
7151 // remove end comment delimiter | 7151 // remove end comment delimiter |
7152 return p1.slice(0, -1); | 7152 return p1.slice(0, -1); |
7153 }); | 7153 }); |
7154 }, | 7154 }, |
7155 /* | 7155 /* |
7156 * Process styles to add rules which will only apply under the polyfill | 7156 * Process styles to add rules which will only apply under the polyfill |
7157 * and do not process via CSSOM. (CSSOM is destructive to rules on rare | 7157 * and do not process via CSSOM. (CSSOM is destructive to rules on rare |
7158 * occasions, e.g. -webkit-calc on Safari.) | 7158 * occasions, e.g. -webkit-calc on Safari.) |
7159 * For example, we convert this rule: | 7159 * For example, we convert this rule: |
7160 * | 7160 * |
7161 * (comment start) @polyfill-unscoped-rule menu-item { | 7161 * (comment start) @polyfill-unscoped-rule menu-item { |
7162 * ... } (comment end) | 7162 * ... } (comment end) |
7163 * | 7163 * |
7164 * to this: | 7164 * to this: |
7165 * | 7165 * |
7166 * menu-item {...} | 7166 * menu-item {...} |
7167 * | 7167 * |
7168 **/ | 7168 **/ |
7169 extractPolyfillUnscopedRules: function(styles) { | 7169 extractPolyfillUnscopedRules: function(styles) { |
7170 var cssText = ''; | 7170 var cssText = ''; |
7171 if (styles) { | 7171 if (styles) { |
7172 Array.prototype.forEach.call(styles, function(s) { | 7172 Array.prototype.forEach.call(styles, function(s) { |
7173 cssText += this.extractPolyfillUnscopedRulesFromCssText( | 7173 cssText += this.extractPolyfillUnscopedRulesFromCssText( |
7174 s.textContent) + '\n\n'; | 7174 s.textContent) + '\n\n'; |
7175 }, this); | 7175 }, this); |
7176 } | 7176 } |
7177 return cssText; | 7177 return cssText; |
7178 }, | 7178 }, |
7179 extractPolyfillUnscopedRulesFromCssText: function(cssText) { | 7179 extractPolyfillUnscopedRulesFromCssText: function(cssText) { |
7180 var r = '', matches; | 7180 var r = '', matches; |
7181 while (matches = cssPolyfillUnscopedRuleCommentRe.exec(cssText)) { | 7181 while (matches = cssPolyfillUnscopedRuleCommentRe.exec(cssText)) { |
7182 r += matches[1].slice(0, -1) + '\n\n'; | 7182 r += matches[1].slice(0, -1) + '\n\n'; |
7183 } | 7183 } |
7184 return r; | 7184 return r; |
7185 }, | 7185 }, |
7186 /* Ensure styles are scoped. Pseudo-scoping takes a rule like: | 7186 /* Ensure styles are scoped. Pseudo-scoping takes a rule like: |
7187 * | 7187 * |
7188 * .foo {... } | 7188 * .foo {... } |
7189 * | 7189 * |
7190 * and converts this to | 7190 * and converts this to |
7191 * | 7191 * |
7192 * scopeName .foo { ... } | 7192 * scopeName .foo { ... } |
7193 */ | 7193 */ |
7194 shimScoping: function(styles, name, typeExtension) { | 7194 shimScoping: function(styles, name, typeExtension) { |
7195 if (styles) { | 7195 if (styles) { |
7196 return this.convertScopedStyles(styles, name, typeExtension); | 7196 return this.convertScopedStyles(styles, name, typeExtension); |
7197 } | 7197 } |
7198 }, | 7198 }, |
7199 convertScopedStyles: function(styles, name, typeExtension) { | 7199 convertScopedStyles: function(styles, name, typeExtension) { |
7200 var cssText = stylesToCssText(styles); | 7200 var cssText = stylesToCssText(styles); |
7201 cssText = this.insertPolyfillHostInCssText(cssText); | 7201 cssText = this.insertPolyfillHostInCssText(cssText); |
7202 cssText = this.convertColonHost(cssText); | 7202 cssText = this.convertColonHost(cssText); |
7203 cssText = this.convertColonAncestor(cssText); | 7203 cssText = this.convertColonAncestor(cssText); |
7204 cssText = this.convertCombinators(cssText); | 7204 cssText = this.convertCombinators(cssText); |
7205 var rules = cssToRules(cssText); | |
7206 if (name) { | 7205 if (name) { |
| 7206 var rules = cssToRules(cssText); |
7207 cssText = this.scopeRules(rules, name, typeExtension); | 7207 cssText = this.scopeRules(rules, name, typeExtension); |
7208 } | 7208 } |
7209 return cssText; | 7209 return cssText; |
7210 }, | 7210 }, |
7211 /* | 7211 /* |
7212 * convert a rule like :host(.foo) > .bar { } | 7212 * convert a rule like :host(.foo) > .bar { } |
7213 * | 7213 * |
7214 * to | 7214 * to |
7215 * | 7215 * |
7216 * scopeName.foo > .bar | 7216 * scopeName.foo > .bar |
7217 */ | 7217 */ |
7218 convertColonHost: function(cssText) { | 7218 convertColonHost: function(cssText) { |
7219 return this.convertColonRule(cssText, cssColonHostRe, | 7219 return this.convertColonRule(cssText, cssColonHostRe, |
7220 this.colonHostPartReplacer); | 7220 this.colonHostPartReplacer); |
7221 }, | 7221 }, |
7222 /* | 7222 /* |
7223 * convert a rule like :ancestor(.foo) > .bar { } | 7223 * convert a rule like :ancestor(.foo) > .bar { } |
7224 * | 7224 * |
7225 * to | 7225 * to |
7226 * | 7226 * |
7227 * scopeName.foo > .bar, .foo scopeName > .bar { } | 7227 * scopeName.foo > .bar, .foo scopeName > .bar { } |
7228 * | 7228 * |
7229 * and | 7229 * and |
7230 * | 7230 * |
7231 * :ancestor(.foo:host) .bar { ... } | 7231 * :ancestor(.foo:host) .bar { ... } |
7232 * | 7232 * |
7233 * to | 7233 * to |
7234 * | 7234 * |
7235 * scopeName.foo .bar { ... } | 7235 * scopeName.foo .bar { ... } |
7236 */ | 7236 */ |
7237 convertColonAncestor: function(cssText) { | 7237 convertColonAncestor: function(cssText) { |
7238 return this.convertColonRule(cssText, cssColonAncestorRe, | 7238 return this.convertColonRule(cssText, cssColonAncestorRe, |
7239 this.colonAncestorPartReplacer); | 7239 this.colonAncestorPartReplacer); |
7240 }, | 7240 }, |
7241 convertColonRule: function(cssText, regExp, partReplacer) { | 7241 convertColonRule: function(cssText, regExp, partReplacer) { |
7242 // p1 = :host, p2 = contents of (), p3 rest of rule | 7242 // p1 = :host, p2 = contents of (), p3 rest of rule |
7243 return cssText.replace(regExp, function(m, p1, p2, p3) { | 7243 return cssText.replace(regExp, function(m, p1, p2, p3) { |
7244 p1 = polyfillHostNoCombinator; | 7244 p1 = polyfillHostNoCombinator; |
(...skipping 23 matching lines...) Expand all Loading... |
7268 * Convert ^ and ^^ combinators by replacing with space. | 7268 * Convert ^ and ^^ combinators by replacing with space. |
7269 */ | 7269 */ |
7270 convertCombinators: function(cssText) { | 7270 convertCombinators: function(cssText) { |
7271 return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' '); | 7271 return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' '); |
7272 }, | 7272 }, |
7273 // change a selector like 'div' to 'name div' | 7273 // change a selector like 'div' to 'name div' |
7274 scopeRules: function(cssRules, name, typeExtension) { | 7274 scopeRules: function(cssRules, name, typeExtension) { |
7275 var cssText = ''; | 7275 var cssText = ''; |
7276 Array.prototype.forEach.call(cssRules, function(rule) { | 7276 Array.prototype.forEach.call(cssRules, function(rule) { |
7277 if (rule.selectorText && (rule.style && rule.style.cssText)) { | 7277 if (rule.selectorText && (rule.style && rule.style.cssText)) { |
7278 cssText += this.scopeSelector(rule.selectorText, name, typeExtension, | 7278 cssText += this.scopeSelector(rule.selectorText, name, typeExtension, |
7279 this.strictStyling) + ' {\n\t'; | 7279 this.strictStyling) + ' {\n\t'; |
7280 cssText += this.propertiesFromRule(rule) + '\n}\n\n'; | 7280 cssText += this.propertiesFromRule(rule) + '\n}\n\n'; |
7281 } else if (rule.media) { | 7281 } else if (rule.media) { |
7282 cssText += '@media ' + rule.media.mediaText + ' {\n'; | 7282 cssText += '@media ' + rule.media.mediaText + ' {\n'; |
7283 cssText += this.scopeRules(rule.cssRules, name, typeExtension); | 7283 cssText += this.scopeRules(rule.cssRules, name, typeExtension); |
7284 cssText += '\n}\n\n'; | 7284 cssText += '\n}\n\n'; |
7285 } else if (rule.cssText) { | 7285 } else if (rule.cssText) { |
7286 cssText += rule.cssText + '\n\n'; | 7286 cssText += rule.cssText + '\n\n'; |
7287 } | 7287 } |
7288 }, this); | 7288 }, this); |
7289 return cssText; | 7289 return cssText; |
7290 }, | 7290 }, |
7291 scopeSelector: function(selector, name, typeExtension, strict) { | 7291 scopeSelector: function(selector, name, typeExtension, strict) { |
7292 var r = [], parts = selector.split(','); | 7292 var r = [], parts = selector.split(','); |
7293 parts.forEach(function(p) { | 7293 parts.forEach(function(p) { |
7294 p = p.trim(); | 7294 p = p.trim(); |
7295 if (this.selectorNeedsScoping(p, name, typeExtension)) { | 7295 if (this.selectorNeedsScoping(p, name, typeExtension)) { |
7296 p = (strict && !p.match(polyfillHostNoCombinator)) ? | 7296 p = (strict && !p.match(polyfillHostNoCombinator)) ? |
7297 this.applyStrictSelectorScope(p, name) : | 7297 this.applyStrictSelectorScope(p, name) : |
7298 this.applySimpleSelectorScope(p, name, typeExtension); | 7298 this.applySimpleSelectorScope(p, name, typeExtension); |
7299 } | 7299 } |
7300 r.push(p); | 7300 r.push(p); |
7301 }, this); | 7301 }, this); |
7302 return r.join(', '); | 7302 return r.join(', '); |
7303 }, | 7303 }, |
7304 selectorNeedsScoping: function(selector, name, typeExtension) { | 7304 selectorNeedsScoping: function(selector, name, typeExtension) { |
7305 var re = this.makeScopeMatcher(name, typeExtension); | 7305 var re = this.makeScopeMatcher(name, typeExtension); |
7306 return !selector.match(re); | 7306 return !selector.match(re); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7339 return scoped; | 7339 return scoped; |
7340 }, | 7340 }, |
7341 insertPolyfillHostInCssText: function(selector) { | 7341 insertPolyfillHostInCssText: function(selector) { |
7342 return selector.replace(hostRe, polyfillHost).replace(colonHostRe, | 7342 return selector.replace(hostRe, polyfillHost).replace(colonHostRe, |
7343 polyfillHost).replace(colonAncestorRe, polyfillAncestor); | 7343 polyfillHost).replace(colonAncestorRe, polyfillAncestor); |
7344 }, | 7344 }, |
7345 propertiesFromRule: function(rule) { | 7345 propertiesFromRule: function(rule) { |
7346 // TODO(sorvell): Safari cssom incorrectly removes quotes from the content | 7346 // TODO(sorvell): Safari cssom incorrectly removes quotes from the content |
7347 // property. (https://bugs.webkit.org/show_bug.cgi?id=118045) | 7347 // property. (https://bugs.webkit.org/show_bug.cgi?id=118045) |
7348 if (rule.style.content && !rule.style.content.match(/['"]+/)) { | 7348 if (rule.style.content && !rule.style.content.match(/['"]+/)) { |
7349 return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + | 7349 return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + |
7350 rule.style.content + '\';'); | 7350 rule.style.content + '\';'); |
7351 } | 7351 } |
7352 return rule.style.cssText; | 7352 return rule.style.cssText; |
7353 } | 7353 } |
7354 }; | 7354 }; |
7355 | 7355 |
7356 var selectorRe = /([^{]*)({[\s\S]*?})/gim, | 7356 var selectorRe = /([^{]*)({[\s\S]*?})/gim, |
7357 cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, | 7357 cssCommentRe = /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, |
7358 cssPolyfillCommentRe = /\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?
){/gim, | 7358 cssPolyfillCommentRe = /\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?
){/gim, |
7359 cssPolyfillRuleCommentRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\/
/gim, | 7359 cssPolyfillRuleCommentRe = /\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\/
/gim, |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7434 if (window.ShadowDOMPolyfill) { | 7434 if (window.ShadowDOMPolyfill) { |
7435 addCssToDocument('style { display: none !important; }\n'); | 7435 addCssToDocument('style { display: none !important; }\n'); |
7436 var doc = wrap(document); | 7436 var doc = wrap(document); |
7437 var head = doc.querySelector('head'); | 7437 var head = doc.querySelector('head'); |
7438 head.insertBefore(getSheet(), head.childNodes[0]); | 7438 head.insertBefore(getSheet(), head.childNodes[0]); |
7439 | 7439 |
7440 // TODO(sorvell): monkey-patching HTMLImports is abusive; | 7440 // TODO(sorvell): monkey-patching HTMLImports is abusive; |
7441 // consider a better solution. | 7441 // consider a better solution. |
7442 document.addEventListener('DOMContentLoaded', function() { | 7442 document.addEventListener('DOMContentLoaded', function() { |
7443 var urlResolver = scope.urlResolver; | 7443 var urlResolver = scope.urlResolver; |
7444 | 7444 |
7445 if (window.HTMLImports && !HTMLImports.useNative) { | 7445 if (window.HTMLImports && !HTMLImports.useNative) { |
7446 var SHIM_SHEET_SELECTOR = 'link[rel=stylesheet]' + | 7446 var SHIM_SHEET_SELECTOR = 'link[rel=stylesheet]' + |
7447 '[' + SHIM_ATTRIBUTE + ']'; | 7447 '[' + SHIM_ATTRIBUTE + ']'; |
7448 var SHIM_STYLE_SELECTOR = 'style[' + SHIM_ATTRIBUTE + ']'; | 7448 var SHIM_STYLE_SELECTOR = 'style[' + SHIM_ATTRIBUTE + ']'; |
7449 HTMLImports.importer.documentPreloadSelectors += ',' + SHIM_SHEET_SELECTOR
; | 7449 HTMLImports.importer.documentPreloadSelectors += ',' + SHIM_SHEET_SELECTOR
; |
7450 HTMLImports.importer.importsPreloadSelectors += ',' + SHIM_SHEET_SELECTOR; | 7450 HTMLImports.importer.importsPreloadSelectors += ',' + SHIM_SHEET_SELECTOR; |
7451 | 7451 |
7452 HTMLImports.parser.documentSelectors = [ | 7452 HTMLImports.parser.documentSelectors = [ |
7453 HTMLImports.parser.documentSelectors, | 7453 HTMLImports.parser.documentSelectors, |
7454 SHIM_SHEET_SELECTOR, | 7454 SHIM_SHEET_SELECTOR, |
7455 SHIM_STYLE_SELECTOR | 7455 SHIM_STYLE_SELECTOR |
7456 ].join(','); | 7456 ].join(','); |
| 7457 |
| 7458 var originalParseGeneric = HTMLImports.parser.parseGeneric; |
7457 | 7459 |
7458 HTMLImports.parser.parseGeneric = function(elt) { | 7460 HTMLImports.parser.parseGeneric = function(elt) { |
7459 if (elt[SHIMMED_ATTRIBUTE]) { | 7461 if (elt[SHIMMED_ATTRIBUTE]) { |
7460 return; | 7462 return; |
7461 } | 7463 } |
7462 var style = elt.__importElement || elt; | 7464 var style = elt.__importElement || elt; |
| 7465 if (!style.hasAttribute(SHIM_ATTRIBUTE)) { |
| 7466 originalParseGeneric.call(this, elt); |
| 7467 return; |
| 7468 } |
7463 if (elt.__resource) { | 7469 if (elt.__resource) { |
7464 style = elt.ownerDocument.createElement('style'); | 7470 style = elt.ownerDocument.createElement('style'); |
7465 style.textContent = urlResolver.resolveCssText( | 7471 style.textContent = urlResolver.resolveCssText( |
7466 elt.__resource, elt.href); | 7472 elt.__resource, elt.href); |
7467 } else { | 7473 } else { |
7468 urlResolver.resolveStyles(style); | 7474 urlResolver.resolveStyle(style); |
7469 } | 7475 } |
7470 var styles = [style]; | 7476 var styles = [style]; |
7471 style.textContent = ShadowCSS.stylesToShimmedCssText(styles, styles); | 7477 style.textContent = ShadowCSS.stylesToShimmedCssText(styles, styles); |
7472 style.removeAttribute(SHIM_ATTRIBUTE, ''); | 7478 style.removeAttribute(SHIM_ATTRIBUTE, ''); |
7473 style.setAttribute(SHIMMED_ATTRIBUTE, ''); | 7479 style.setAttribute(SHIMMED_ATTRIBUTE, ''); |
7474 style[SHIMMED_ATTRIBUTE] = true; | 7480 style[SHIMMED_ATTRIBUTE] = true; |
7475 // place in document | 7481 // place in document |
7476 if (style.parentNode !== head) { | 7482 if (style.parentNode !== head) { |
7477 // replace links in head | 7483 // replace links in head |
7478 if (elt.parentNode === head) { | 7484 if (elt.parentNode === head) { |
7479 head.replaceChild(style, elt); | 7485 head.replaceChild(style, elt); |
7480 } else { | 7486 } else { |
7481 head.appendChild(style); | 7487 head.appendChild(style); |
7482 } | 7488 } |
7483 } | 7489 } |
7484 style.__importParsed = true | 7490 style.__importParsed = true; |
7485 this.markParsingComplete(elt); | 7491 this.markParsingComplete(elt); |
7486 } | 7492 } |
7487 | 7493 |
7488 var hasResource = HTMLImports.parser.hasResource; | 7494 var hasResource = HTMLImports.parser.hasResource; |
7489 HTMLImports.parser.hasResource = function(node) { | 7495 HTMLImports.parser.hasResource = function(node) { |
7490 if (node.localName === 'link' && node.rel === 'stylesheet' && | 7496 if (node.localName === 'link' && node.rel === 'stylesheet' && |
7491 node.hasAttribute(SHIM_ATTRIBUTE)) { | 7497 node.hasAttribute(SHIM_ATTRIBUTE)) { |
7492 return (node.__resource); | 7498 return (node.__resource); |
7493 } else { | 7499 } else { |
7494 return hasResource.call(this, node); | 7500 return hasResource.call(this, node); |
(...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8286 | 8292 |
8287 // TODO(sorvell): workaround for bug: | 8293 // TODO(sorvell): workaround for bug: |
8288 // https://code.google.com/p/chromium/issues/detail?id=229142 | 8294 // https://code.google.com/p/chromium/issues/detail?id=229142 |
8289 // remove when this bug is addressed | 8295 // remove when this bug is addressed |
8290 // give main document templates a base that allows them to fetch eagerly | 8296 // give main document templates a base that allows them to fetch eagerly |
8291 // resolved paths relative to the main document | 8297 // resolved paths relative to the main document |
8292 var template = document.createElement('template'); | 8298 var template = document.createElement('template'); |
8293 var base = document.createElement('base'); | 8299 var base = document.createElement('base'); |
8294 base.href = document.baseURI; | 8300 base.href = document.baseURI; |
8295 template.content.ownerDocument.appendChild(base); | 8301 template.content.ownerDocument.appendChild(base); |
8296 | 8302 |
8297 | 8303 |
8298 // utility | 8304 // utility |
8299 | 8305 |
8300 function createDOM(inTagOrNode, inHTML, inAttrs) { | 8306 function createDOM(inTagOrNode, inHTML, inAttrs) { |
8301 var dom = typeof inTagOrNode == 'string' ? | 8307 var dom = typeof inTagOrNode == 'string' ? |
8302 document.createElement(inTagOrNode) : inTagOrNode.cloneNode(true); | 8308 document.createElement(inTagOrNode) : inTagOrNode.cloneNode(true); |
8303 dom.innerHTML = inHTML; | 8309 dom.innerHTML = inHTML; |
8304 if (inAttrs) { | 8310 if (inAttrs) { |
8305 for (var n in inAttrs) { | 8311 for (var n in inAttrs) { |
8306 dom.setAttribute(n, inAttrs[n]); | 8312 dom.setAttribute(n, inAttrs[n]); |
(...skipping 20 matching lines...) Expand all Loading... |
8327 return elementDeclarations; | 8333 return elementDeclarations; |
8328 } | 8334 } |
8329 | 8335 |
8330 // Once DOMContent has loaded, any main document scripts that depend on | 8336 // Once DOMContent has loaded, any main document scripts that depend on |
8331 // Polymer() should have run. Calling Polymer() now is an error until | 8337 // Polymer() should have run. Calling Polymer() now is an error until |
8332 // polymer is imported. | 8338 // polymer is imported. |
8333 window.addEventListener('DOMContentLoaded', function() { | 8339 window.addEventListener('DOMContentLoaded', function() { |
8334 if (window.Polymer === polymerStub) { | 8340 if (window.Polymer === polymerStub) { |
8335 window.Polymer = function() { | 8341 window.Polymer = function() { |
8336 console.error('You tried to use polymer without loading it first. To ' + | 8342 console.error('You tried to use polymer without loading it first. To ' + |
8337 'load polymer, <link rel="import" href="' + | 8343 'load polymer, <link rel="import" href="' + |
8338 'components/polymer/polymer.html">'); | 8344 'components/polymer/polymer.html">'); |
8339 }; | 8345 }; |
8340 } | 8346 } |
8341 }); | 8347 }); |
8342 | 8348 |
8343 // exports | 8349 // exports |
8344 scope.createDOM = createDOM; | 8350 scope.createDOM = createDOM; |
8345 | 8351 |
8346 })(window.Platform); | 8352 })(window.Platform); |
8347 | 8353 |
8348 /* | 8354 /* |
8349 * Copyright 2013 The Polymer Authors. All rights reserved. | 8355 * Copyright 2013 The Polymer Authors. All rights reserved. |
8350 * Use of this source code is governed by a BSD-style | 8356 * Use of this source code is governed by a BSD-style |
8351 * license that can be found in the LICENSE file. | 8357 * license that can be found in the LICENSE file. |
8352 */ | 8358 */ |
8353 | 8359 |
8354 // poor man's adapter for template.content on various platform scenarios | 8360 // poor man's adapter for template.content on various platform scenarios |
8355 window.templateContent = window.templateContent || function(inTemplate) { | 8361 window.templateContent = window.templateContent || function(inTemplate) { |
8356 return inTemplate.content; | 8362 return inTemplate.content; |
8357 }; | 8363 }; |
8358 (function(scope) { | 8364 (function(scope) { |
8359 | 8365 |
8360 scope = scope || (window.Inspector = {}); | 8366 scope = scope || (window.Inspector = {}); |
8361 | 8367 |
8362 var inspector; | 8368 var inspector; |
8363 | 8369 |
8364 window.sinspect = function(inNode, inProxy) { | 8370 window.sinspect = function(inNode, inProxy) { |
8365 if (!inspector) { | 8371 if (!inspector) { |
8366 inspector = window.open('', 'ShadowDOM Inspector', null, true); | 8372 inspector = window.open('', 'ShadowDOM Inspector', null, true); |
8367 inspector.document.write(inspectorHTML); | 8373 inspector.document.write(inspectorHTML); |
8368 //inspector.document.close(); | 8374 //inspector.document.close(); |
8369 inspector.api = { | 8375 inspector.api = { |
8370 shadowize: shadowize | 8376 shadowize: shadowize |
8371 }; | 8377 }; |
(...skipping 30 matching lines...) Expand all Loading... |
8402 ' }', | 8408 ' }', |
8403 ' </style>', | 8409 ' </style>', |
8404 ' </head>', | 8410 ' </head>', |
8405 ' <body>', | 8411 ' <body>', |
8406 ' <ul id="crumbs">', | 8412 ' <ul id="crumbs">', |
8407 ' </ul>', | 8413 ' </ul>', |
8408 ' <div id="tree"></div>', | 8414 ' <div id="tree"></div>', |
8409 ' </body>', | 8415 ' </body>', |
8410 '</html>' | 8416 '</html>' |
8411 ].join('\n'); | 8417 ].join('\n'); |
8412 | 8418 |
8413 var crumbs = []; | 8419 var crumbs = []; |
8414 | 8420 |
8415 var displayCrumbs = function() { | 8421 var displayCrumbs = function() { |
8416 // alias our document | 8422 // alias our document |
8417 var d = inspector.document; | 8423 var d = inspector.document; |
8418 // get crumbbar | 8424 // get crumbbar |
8419 var cb = d.querySelector('#crumbs'); | 8425 var cb = d.querySelector('#crumbs'); |
8420 // clear crumbs | 8426 // clear crumbs |
8421 cb.textContent = ''; | 8427 cb.textContent = ''; |
8422 // build new crumbs | 8428 // build new crumbs |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8530 var idx = Number(this.attributes.idx.value); | 8536 var idx = Number(this.attributes.idx.value); |
8531 //alert(idx); | 8537 //alert(idx); |
8532 var node = drillable[idx]; | 8538 var node = drillable[idx]; |
8533 if (node) { | 8539 if (node) { |
8534 inspect(node.webkitShadowRoot || node.shadowRoot, node) | 8540 inspect(node.webkitShadowRoot || node.shadowRoot, node) |
8535 } else { | 8541 } else { |
8536 console.log("bad shadowize node"); | 8542 console.log("bad shadowize node"); |
8537 console.dir(this); | 8543 console.dir(this); |
8538 } | 8544 } |
8539 }; | 8545 }; |
8540 | 8546 |
8541 // export | 8547 // export |
8542 | 8548 |
8543 scope.output = output; | 8549 scope.output = output; |
8544 | 8550 |
8545 })(window.Inspector); | 8551 })(window.Inspector); |
8546 | 8552 |
8547 | 8553 |
8548 | 8554 |
8549 /* | 8555 /* |
8550 * Copyright 2013 The Polymer Authors. All rights reserved. | 8556 * Copyright 2013 The Polymer Authors. All rights reserved. |
8551 * Use of this source code is governed by a BSD-style | 8557 * Use of this source code is governed by a BSD-style |
8552 * license that can be found in the LICENSE file. | 8558 * license that can be found in the LICENSE file. |
8553 */ | 8559 */ |
8554 (function(scope) { | 8560 (function(scope) { |
8555 | 8561 |
8556 // TODO(sorvell): It's desireable to provide a default stylesheet | 8562 // TODO(sorvell): It's desireable to provide a default stylesheet |
8557 // that's convenient for styling unresolved elements, but | 8563 // that's convenient for styling unresolved elements, but |
8558 // it's cumbersome to have to include this manually in every page. | 8564 // it's cumbersome to have to include this manually in every page. |
8559 // It would make sense to put inside some HTMLImport but | 8565 // It would make sense to put inside some HTMLImport but |
8560 // the HTMLImports polyfill does not allow loading of stylesheets | 8566 // the HTMLImports polyfill does not allow loading of stylesheets |
8561 // that block rendering. Therefore this injection is tolerated here. | 8567 // that block rendering. Therefore this injection is tolerated here. |
8562 | 8568 |
8563 var style = document.createElement('style'); | 8569 var style = document.createElement('style'); |
8564 style.textContent = '' | 8570 style.textContent = '' |
8565 + 'body {' | 8571 + 'body {' |
8566 + 'transition: opacity ease-in 0.2s;' | 8572 + 'transition: opacity ease-in 0.2s;' |
8567 + ' } \n' | 8573 + ' } \n' |
8568 + 'body[unresolved] {' | 8574 + 'body[unresolved] {' |
8569 + 'opacity: 0; display: block; overflow: hidden;' | 8575 + 'opacity: 0; display: block; overflow: hidden;' |
8570 + ' } \n' | 8576 + ' } \n' |
8571 ; | 8577 ; |
8572 var head = document.querySelector('head'); | 8578 var head = document.querySelector('head'); |
8573 head.insertBefore(style, head.firstChild); | 8579 head.insertBefore(style, head.firstChild); |
8574 | 8580 |
8575 })(Platform); | 8581 })(Platform); |
8576 | 8582 |
8577 (function(scope) { | 8583 (function(scope) { |
8578 | 8584 |
8579 function withDependencies(task, depends) { | 8585 function withDependencies(task, depends) { |
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9476 * Use of this source code is governed by a BSD-style | 9482 * Use of this source code is governed by a BSD-style |
9477 * license that can be found in the LICENSE file. | 9483 * license that can be found in the LICENSE file. |
9478 */ | 9484 */ |
9479 | 9485 |
9480 (function(scope) { | 9486 (function(scope) { |
9481 | 9487 |
9482 var IMPORT_LINK_TYPE = 'import'; | 9488 var IMPORT_LINK_TYPE = 'import'; |
9483 var flags = scope.flags; | 9489 var flags = scope.flags; |
9484 var isIe = /Trident/.test(navigator.userAgent); | 9490 var isIe = /Trident/.test(navigator.userAgent); |
9485 // TODO(sorvell): SD polyfill intrusion | 9491 // TODO(sorvell): SD polyfill intrusion |
9486 var mainDoc = window.ShadowDOMPolyfill ? | 9492 var mainDoc = window.ShadowDOMPolyfill ? |
9487 window.ShadowDOMPolyfill.wrapIfNeeded(document) : document; | 9493 window.ShadowDOMPolyfill.wrapIfNeeded(document) : document; |
9488 | 9494 |
9489 // importParser | 9495 // importParser |
9490 // highlander object to manage parsing of imports | 9496 // highlander object to manage parsing of imports |
9491 // parses import related elements | 9497 // parses import related elements |
9492 // and ensures proper parse order | 9498 // and ensures proper parse order |
9493 // parse order is enforced by crawling the tree and monitoring which elements | 9499 // parse order is enforced by crawling the tree and monitoring which elements |
9494 // have been parsed; async parsing is also supported. | 9500 // have been parsed; async parsing is also supported. |
9495 | 9501 |
9496 // highlander object for parsing a document tree | 9502 // highlander object for parsing a document tree |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9547 parseImport: function(elt) { | 9553 parseImport: function(elt) { |
9548 elt.import.__importParsed = true; | 9554 elt.import.__importParsed = true; |
9549 // TODO(sorvell): consider if there's a better way to do this; | 9555 // TODO(sorvell): consider if there's a better way to do this; |
9550 // expose an imports parsing hook; this is needed, for example, by the | 9556 // expose an imports parsing hook; this is needed, for example, by the |
9551 // CustomElements polyfill. | 9557 // CustomElements polyfill. |
9552 if (HTMLImports.__importsParsingHook) { | 9558 if (HTMLImports.__importsParsingHook) { |
9553 HTMLImports.__importsParsingHook(elt); | 9559 HTMLImports.__importsParsingHook(elt); |
9554 } | 9560 } |
9555 // fire load event | 9561 // fire load event |
9556 if (elt.__resource) { | 9562 if (elt.__resource) { |
9557 elt.dispatchEvent(new CustomEvent('load', {bubbles: false})); | 9563 elt.dispatchEvent(new CustomEvent('load', {bubbles: false})); |
9558 } else { | 9564 } else { |
9559 elt.dispatchEvent(new CustomEvent('error', {bubbles: false})); | 9565 elt.dispatchEvent(new CustomEvent('error', {bubbles: false})); |
9560 } | 9566 } |
9561 // TODO(sorvell): workaround for Safari addEventListener not working | 9567 // TODO(sorvell): workaround for Safari addEventListener not working |
9562 // for elements not in the main document. | 9568 // for elements not in the main document. |
9563 if (elt.__pending) { | 9569 if (elt.__pending) { |
9564 var fn; | 9570 var fn; |
9565 while (elt.__pending.length) { | 9571 while (elt.__pending.length) { |
9566 fn = elt.__pending.shift(); | 9572 fn = elt.__pending.shift(); |
9567 if (fn) { | 9573 if (fn) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9629 parseScript: function(scriptElt) { | 9635 parseScript: function(scriptElt) { |
9630 // acquire code to execute | 9636 // acquire code to execute |
9631 var code = (scriptElt.__resource || scriptElt.textContent).trim(); | 9637 var code = (scriptElt.__resource || scriptElt.textContent).trim(); |
9632 if (code) { | 9638 if (code) { |
9633 // calculate source map hint | 9639 // calculate source map hint |
9634 var moniker = scriptElt.__nodeUrl; | 9640 var moniker = scriptElt.__nodeUrl; |
9635 if (!moniker) { | 9641 if (!moniker) { |
9636 moniker = scriptElt.ownerDocument.baseURI; | 9642 moniker = scriptElt.ownerDocument.baseURI; |
9637 // there could be more than one script this url | 9643 // there could be more than one script this url |
9638 var tag = '[' + Math.floor((Math.random()+1)*1000) + ']'; | 9644 var tag = '[' + Math.floor((Math.random()+1)*1000) + ']'; |
9639 // TODO(sjmiles): Polymer hack, should be pluggable if we need to allow | 9645 // TODO(sjmiles): Polymer hack, should be pluggable if we need to allow |
9640 // this sort of thing | 9646 // this sort of thing |
9641 var matches = code.match(/Polymer\(['"]([^'"]*)/); | 9647 var matches = code.match(/Polymer\(['"]([^'"]*)/); |
9642 tag = matches && matches[1] || tag; | 9648 tag = matches && matches[1] || tag; |
9643 // tag the moniker | 9649 // tag the moniker |
9644 moniker += '/' + tag + '.js'; | 9650 moniker += '/' + tag + '.js'; |
9645 } | 9651 } |
9646 // source map hint | 9652 // source map hint |
9647 code += "\n//# sourceURL=" + moniker + "\n"; | 9653 code += "\n//# sourceURL=" + moniker + "\n"; |
9648 // evaluate the code | 9654 // evaluate the code |
9649 scope.currentScript = scriptElt; | 9655 scope.currentScript = scriptElt; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9697 | 9703 |
9698 // clone style with proper path resolution for main document | 9704 // clone style with proper path resolution for main document |
9699 // NOTE: styles are the only elements that require direct path fixup. | 9705 // NOTE: styles are the only elements that require direct path fixup. |
9700 function cloneStyle(style) { | 9706 function cloneStyle(style) { |
9701 var clone = style.ownerDocument.createElement('style'); | 9707 var clone = style.ownerDocument.createElement('style'); |
9702 clone.textContent = style.textContent; | 9708 clone.textContent = style.textContent; |
9703 path.resolveUrlsInStyle(clone); | 9709 path.resolveUrlsInStyle(clone); |
9704 return clone; | 9710 return clone; |
9705 } | 9711 } |
9706 | 9712 |
9707 // path fixup: style elements in imports must be made relative to the main | 9713 // path fixup: style elements in imports must be made relative to the main |
9708 // document. We fixup url's in url() and @import. | 9714 // document. We fixup url's in url() and @import. |
9709 var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g; | 9715 var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g; |
9710 var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g; | 9716 var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g; |
9711 | 9717 |
9712 var path = { | 9718 var path = { |
9713 resolveUrlsInStyle: function(style) { | 9719 resolveUrlsInStyle: function(style) { |
9714 var doc = style.ownerDocument; | 9720 var doc = style.ownerDocument; |
9715 var resolver = doc.createElement('a'); | 9721 var resolver = doc.createElement('a'); |
9716 style.textContent = this.resolveUrlsInCssText(style.textContent, resolver); | 9722 style.textContent = this.resolveUrlsInCssText(style.textContent, resolver); |
9717 return style; | 9723 return style; |
9718 }, | 9724 }, |
9719 resolveUrlsInCssText: function(cssText, urlObj) { | 9725 resolveUrlsInCssText: function(cssText, urlObj) { |
9720 var r = this.replaceUrls(cssText, urlObj, CSS_URL_REGEXP); | 9726 var r = this.replaceUrls(cssText, urlObj, CSS_URL_REGEXP); |
9721 r = this.replaceUrls(r, urlObj, CSS_IMPORT_REGEXP); | 9727 r = this.replaceUrls(r, urlObj, CSS_IMPORT_REGEXP); |
9722 return r; | 9728 return r; |
9723 }, | 9729 }, |
9724 replaceUrls: function(text, urlObj, regexp) { | 9730 replaceUrls: function(text, urlObj, regexp) { |
9725 return text.replace(regexp, function(m, pre, url, post) { | 9731 return text.replace(regexp, function(m, pre, url, post) { |
9726 var urlPath = url.replace(/["']/g, ''); | 9732 var urlPath = url.replace(/["']/g, ''); |
9727 urlObj.href = urlPath; | 9733 urlObj.href = urlPath; |
9728 urlPath = urlObj.href; | 9734 urlPath = urlObj.href; |
9729 return pre + '\'' + urlPath + '\'' + post; | 9735 return pre + '\'' + urlPath + '\'' + post; |
9730 }); | 9736 }); |
9731 } | 9737 } |
9732 } | 9738 } |
9733 | 9739 |
9734 // exports | 9740 // exports |
9735 scope.parser = importParser; | 9741 scope.parser = importParser; |
9736 scope.path = path; | 9742 scope.path = path; |
9737 scope.isIE = isIe; | 9743 scope.isIE = isIe; |
9738 | 9744 |
9739 })(HTMLImports); | 9745 })(HTMLImports); |
9740 | 9746 |
9741 /* | 9747 /* |
9742 * Copyright 2013 The Polymer Authors. All rights reserved. | 9748 * Copyright 2013 The Polymer Authors. All rights reserved. |
9743 * Use of this source code is governed by a BSD-style | 9749 * Use of this source code is governed by a BSD-style |
9744 * license that can be found in the LICENSE file. | 9750 * license that can be found in the LICENSE file. |
9745 */ | 9751 */ |
9746 | 9752 |
9747 (function(scope) { | 9753 (function(scope) { |
9748 | 9754 |
9749 var hasNative = ('import' in document.createElement('link')); | 9755 var hasNative = ('import' in document.createElement('link')); |
9750 var useNative = hasNative; | 9756 var useNative = hasNative; |
9751 var flags = scope.flags; | 9757 var flags = scope.flags; |
9752 var IMPORT_LINK_TYPE = 'import'; | 9758 var IMPORT_LINK_TYPE = 'import'; |
9753 | 9759 |
9754 // TODO(sorvell): SD polyfill intrusion | 9760 // TODO(sorvell): SD polyfill intrusion |
9755 var mainDoc = window.ShadowDOMPolyfill ? | 9761 var mainDoc = window.ShadowDOMPolyfill ? |
9756 ShadowDOMPolyfill.wrapIfNeeded(document) : document; | 9762 ShadowDOMPolyfill.wrapIfNeeded(document) : document; |
9757 | 9763 |
9758 if (!useNative) { | 9764 if (!useNative) { |
9759 | 9765 |
9760 // imports | 9766 // imports |
9761 var xhr = scope.xhr; | 9767 var xhr = scope.xhr; |
9762 var Loader = scope.Loader; | 9768 var Loader = scope.Loader; |
9763 var parser = scope.parser; | 9769 var parser = scope.parser; |
9764 | 9770 |
9765 // importer | 9771 // importer |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9828 this.loadSubtree(doc); | 9834 this.loadSubtree(doc); |
9829 this.observe(doc); | 9835 this.observe(doc); |
9830 parser.parseNext(); | 9836 parser.parseNext(); |
9831 }, | 9837 }, |
9832 loadedAll: function() { | 9838 loadedAll: function() { |
9833 parser.parseNext(); | 9839 parser.parseNext(); |
9834 } | 9840 } |
9835 }; | 9841 }; |
9836 | 9842 |
9837 // loader singleton | 9843 // loader singleton |
9838 var importLoader = new Loader(importer.loaded.bind(importer), | 9844 var importLoader = new Loader(importer.loaded.bind(importer), |
9839 importer.loadedAll.bind(importer)); | 9845 importer.loadedAll.bind(importer)); |
9840 | 9846 |
9841 function isDocumentLink(elt) { | 9847 function isDocumentLink(elt) { |
9842 return isLinkRel(elt, IMPORT_LINK_TYPE); | 9848 return isLinkRel(elt, IMPORT_LINK_TYPE); |
9843 } | 9849 } |
9844 | 9850 |
9845 function isLinkRel(elt, rel) { | 9851 function isLinkRel(elt, rel) { |
9846 return elt.localName === 'link' && elt.getAttribute('rel') === rel; | 9852 return elt.localName === 'link' && elt.getAttribute('rel') === rel; |
9847 } | 9853 } |
9848 | 9854 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9909 }, | 9915 }, |
9910 configurable: true | 9916 configurable: true |
9911 }; | 9917 }; |
9912 | 9918 |
9913 Object.defineProperty(document, 'baseURI', baseURIDescriptor); | 9919 Object.defineProperty(document, 'baseURI', baseURIDescriptor); |
9914 Object.defineProperty(mainDoc, 'baseURI', baseURIDescriptor); | 9920 Object.defineProperty(mainDoc, 'baseURI', baseURIDescriptor); |
9915 } | 9921 } |
9916 | 9922 |
9917 // call a callback when all HTMLImports in the document at call (or at least | 9923 // call a callback when all HTMLImports in the document at call (or at least |
9918 // document ready) time have loaded. | 9924 // document ready) time have loaded. |
9919 // 1. ensure the document is in a ready state (has dom), then | 9925 // 1. ensure the document is in a ready state (has dom), then |
9920 // 2. watch for loading of imports and call callback when done | 9926 // 2. watch for loading of imports and call callback when done |
9921 function whenImportsReady(callback, doc) { | 9927 function whenImportsReady(callback, doc) { |
9922 doc = doc || mainDoc; | 9928 doc = doc || mainDoc; |
9923 // if document is loading, wait and try again | 9929 // if document is loading, wait and try again |
9924 whenDocumentReady(function() { | 9930 whenDocumentReady(function() { |
9925 watchImportsLoad(callback, doc); | 9931 watchImportsLoad(callback, doc); |
9926 }, doc); | 9932 }, doc); |
9927 } | 9933 } |
9928 | 9934 |
9929 // call the callback when the document is in a ready state (has dom) | 9935 // call the callback when the document is in a ready state (has dom) |
9930 var requiredReadyState = HTMLImports.isIE ? 'complete' : 'interactive'; | 9936 var requiredReadyState = HTMLImports.isIE ? 'complete' : 'interactive'; |
9931 var READY_EVENT = 'readystatechange'; | 9937 var READY_EVENT = 'readystatechange'; |
9932 function isDocumentReady(doc) { | 9938 function isDocumentReady(doc) { |
9933 return (doc.readyState === 'complete' || | 9939 return (doc.readyState === 'complete' || |
9934 doc.readyState === requiredReadyState); | 9940 doc.readyState === requiredReadyState); |
9935 } | 9941 } |
9936 | 9942 |
9937 // call <callback> when we ensure the document is in a ready state | 9943 // call <callback> when we ensure the document is in a ready state |
9938 function whenDocumentReady(callback, doc) { | 9944 function whenDocumentReady(callback, doc) { |
9939 if (!isDocumentReady(doc)) { | 9945 if (!isDocumentReady(doc)) { |
9940 var checkReady = function() { | 9946 var checkReady = function() { |
9941 if (doc.readyState === 'complete' || | 9947 if (doc.readyState === 'complete' || |
9942 doc.readyState === requiredReadyState) { | 9948 doc.readyState === requiredReadyState) { |
9943 doc.removeEventListener(READY_EVENT, checkReady); | 9949 doc.removeEventListener(READY_EVENT, checkReady); |
9944 whenDocumentReady(callback, doc); | 9950 whenDocumentReady(callback, doc); |
9945 } | 9951 } |
9946 } | 9952 } |
9947 doc.addEventListener(READY_EVENT, checkReady); | 9953 doc.addEventListener(READY_EVENT, checkReady); |
9948 } else if (callback) { | 9954 } else if (callback) { |
9949 callback(); | 9955 callback(); |
9950 } | 9956 } |
9951 } | 9957 } |
9952 | 9958 |
9953 // call <callback> when we ensure all imports have loaded | 9959 // call <callback> when we ensure all imports have loaded |
9954 function watchImportsLoad(callback, doc) { | 9960 function watchImportsLoad(callback, doc) { |
9955 var imports = doc.querySelectorAll('link[rel=import]'); | 9961 var imports = doc.querySelectorAll('link[rel=import]'); |
9956 var loaded = 0, l = imports.length; | 9962 var loaded = 0, l = imports.length; |
9957 function checkDone(d) { | 9963 function checkDone(d) { |
9958 if (loaded == l) { | 9964 if (loaded == l) { |
9959 // go async to ensure parser isn't stuck on a script tag | 9965 // go async to ensure parser isn't stuck on a script tag |
9960 requestAnimationFrame(callback); | 9966 requestAnimationFrame(callback); |
9961 } | 9967 } |
9962 } | 9968 } |
9963 function loadedImport(e) { | 9969 function loadedImport(e) { |
9964 loaded++; | 9970 loaded++; |
9965 checkDone(); | 9971 checkDone(); |
9966 } | 9972 } |
9967 if (l) { | 9973 if (l) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10026 } | 10032 } |
10027 } | 10033 } |
10028 } | 10034 } |
10029 | 10035 |
10030 function shouldLoadNode(node) { | 10036 function shouldLoadNode(node) { |
10031 return (node.nodeType === 1) && matches.call(node, | 10037 return (node.nodeType === 1) && matches.call(node, |
10032 importer.loadSelectorsForNode(node)); | 10038 importer.loadSelectorsForNode(node)); |
10033 } | 10039 } |
10034 | 10040 |
10035 // x-plat matches | 10041 // x-plat matches |
10036 var matches = HTMLElement.prototype.matches || | 10042 var matches = HTMLElement.prototype.matches || |
10037 HTMLElement.prototype.matchesSelector || | 10043 HTMLElement.prototype.matchesSelector || |
10038 HTMLElement.prototype.webkitMatchesSelector || | 10044 HTMLElement.prototype.webkitMatchesSelector || |
10039 HTMLElement.prototype.mozMatchesSelector || | 10045 HTMLElement.prototype.mozMatchesSelector || |
10040 HTMLElement.prototype.msMatchesSelector; | 10046 HTMLElement.prototype.msMatchesSelector; |
10041 | 10047 |
10042 var observer = new MutationObserver(handler); | 10048 var observer = new MutationObserver(handler); |
10043 | 10049 |
10044 // observe the given root for loadable elements | 10050 // observe the given root for loadable elements |
10045 function observe(root) { | 10051 function observe(root) { |
10046 observer.observe(root, {childList: true, subtree: true}); | 10052 observer.observe(root, {childList: true, subtree: true}); |
10047 } | 10053 } |
(...skipping 20 matching lines...) Expand all Loading... |
10068 var e = document.createEvent('HTMLEvents'); | 10074 var e = document.createEvent('HTMLEvents'); |
10069 e.initEvent(inType, | 10075 e.initEvent(inType, |
10070 dictionary.bubbles === false ? false : true, | 10076 dictionary.bubbles === false ? false : true, |
10071 dictionary.cancelable === false ? false : true, | 10077 dictionary.cancelable === false ? false : true, |
10072 dictionary.detail); | 10078 dictionary.detail); |
10073 return e; | 10079 return e; |
10074 }; | 10080 }; |
10075 } | 10081 } |
10076 | 10082 |
10077 // TODO(sorvell): SD polyfill intrusion | 10083 // TODO(sorvell): SD polyfill intrusion |
10078 var doc = window.ShadowDOMPolyfill ? | 10084 var doc = window.ShadowDOMPolyfill ? |
10079 window.ShadowDOMPolyfill.wrapIfNeeded(document) : document; | 10085 window.ShadowDOMPolyfill.wrapIfNeeded(document) : document; |
10080 | 10086 |
10081 // Fire the 'HTMLImportsLoaded' event when imports in document at load time | 10087 // Fire the 'HTMLImportsLoaded' event when imports in document at load time |
10082 // have loaded. This event is required to simulate the script blocking | 10088 // have loaded. This event is required to simulate the script blocking |
10083 // behavior of native imports. A main document script that needs to be sure | 10089 // behavior of native imports. A main document script that needs to be sure |
10084 // imports have loaded should wait for this event. | 10090 // imports have loaded should wait for this event. |
10085 HTMLImports.whenImportsReady(function() { | 10091 HTMLImports.whenImportsReady(function() { |
10086 HTMLImports.ready = true; | 10092 HTMLImports.ready = true; |
10087 HTMLImports.readyTime = new Date().getTime(); | 10093 HTMLImports.readyTime = new Date().getTime(); |
10088 doc.dispatchEvent( | 10094 doc.dispatchEvent( |
10089 new CustomEvent('HTMLImportsLoaded', {bubbles: true}) | 10095 new CustomEvent('HTMLImportsLoaded', {bubbles: true}) |
10090 ); | 10096 ); |
10091 }); | 10097 }); |
10092 | 10098 |
10093 | 10099 |
10094 // no need to bootstrap the polyfill when native imports is available. | 10100 // no need to bootstrap the polyfill when native imports is available. |
10095 if (!HTMLImports.useNative) { | 10101 if (!HTMLImports.useNative) { |
10096 function bootstrap() { | 10102 function bootstrap() { |
10097 HTMLImports.importer.bootDocument(doc); | 10103 HTMLImports.importer.bootDocument(doc); |
10098 } | 10104 } |
10099 | 10105 |
10100 // TODO(sorvell): SD polyfill does *not* generate mutations for nodes added | 10106 // TODO(sorvell): SD polyfill does *not* generate mutations for nodes added |
10101 // by the parser. For this reason, we must wait until the dom exists to | 10107 // by the parser. For this reason, we must wait until the dom exists to |
10102 // bootstrap. | 10108 // bootstrap. |
10103 if (document.readyState === 'complete' || | 10109 if (document.readyState === 'complete' || |
10104 (document.readyState === 'interactive' && !window.attachEvent)) { | 10110 (document.readyState === 'interactive' && !window.attachEvent)) { |
10105 bootstrap(); | 10111 bootstrap(); |
10106 } else { | 10112 } else { |
10107 document.addEventListener('DOMContentLoaded', bootstrap); | 10113 document.addEventListener('DOMContentLoaded', bootstrap); |
10108 } | 10114 } |
10109 } | 10115 } |
10110 | 10116 |
10111 })(); | 10117 })(); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10209 | 10215 |
10210 function insertedNode(node) { | 10216 function insertedNode(node) { |
10211 inserted(node); | 10217 inserted(node); |
10212 if (inDocument(node)) { | 10218 if (inDocument(node)) { |
10213 forSubtree(node, function(e) { | 10219 forSubtree(node, function(e) { |
10214 inserted(e); | 10220 inserted(e); |
10215 }); | 10221 }); |
10216 } | 10222 } |
10217 } | 10223 } |
10218 | 10224 |
10219 | |
10220 // TODO(sorvell): on platforms without MutationObserver, mutations may not be | 10225 // TODO(sorvell): on platforms without MutationObserver, mutations may not be |
10221 // reliable and therefore attached/detached are not reliable. | 10226 // reliable and therefore attached/detached are not reliable. |
10222 // To make these callbacks less likely to fail, we defer all inserts and removes | 10227 // To make these callbacks less likely to fail, we defer all inserts and removes |
10223 // to give a chance for elements to be inserted into dom. | 10228 // to give a chance for elements to be inserted into dom. |
10224 // This ensures attachedCallback fires for elements that are created and | 10229 // This ensures attachedCallback fires for elements that are created and |
10225 // immediately added to dom. | 10230 // immediately added to dom. |
10226 var hasPolyfillMutations = (!window.MutationObserver || | 10231 var hasPolyfillMutations = (!window.MutationObserver || |
10227 (window.MutationObserver === window.JsMutationObserver)); | 10232 (window.MutationObserver === window.JsMutationObserver)); |
10228 scope.hasPolyfillMutations = hasPolyfillMutations; | 10233 scope.hasPolyfillMutations = hasPolyfillMutations; |
10229 | 10234 |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10446 } | 10451 } |
10447 } | 10452 } |
10448 } | 10453 } |
10449 | 10454 |
10450 // exports | 10455 // exports |
10451 scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE; | 10456 scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE; |
10452 scope.watchShadow = watchShadow; | 10457 scope.watchShadow = watchShadow; |
10453 scope.upgradeDocumentTree = upgradeDocumentTree; | 10458 scope.upgradeDocumentTree = upgradeDocumentTree; |
10454 scope.upgradeAll = addedNode; | 10459 scope.upgradeAll = addedNode; |
10455 scope.upgradeSubtree = addedSubtree; | 10460 scope.upgradeSubtree = addedSubtree; |
| 10461 scope.insertedNode = insertedNode; |
10456 | 10462 |
10457 scope.observeDocument = observeDocument; | 10463 scope.observeDocument = observeDocument; |
10458 scope.upgradeDocument = upgradeDocument; | 10464 scope.upgradeDocument = upgradeDocument; |
10459 | 10465 |
10460 scope.takeRecords = takeRecords; | 10466 scope.takeRecords = takeRecords; |
10461 | 10467 |
10462 })(window.CustomElements); | 10468 })(window.CustomElements); |
10463 | 10469 |
10464 /* | 10470 /* |
10465 * Copyright 2013 The Polymer Authors. All rights reserved. | 10471 * Copyright 2013 The Polymer Authors. All rights reserved. |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10682 element.setAttribute('is', definition.is); | 10688 element.setAttribute('is', definition.is); |
10683 } | 10689 } |
10684 // remove 'unresolved' attr, which is a standin for :unresolved. | 10690 // remove 'unresolved' attr, which is a standin for :unresolved. |
10685 element.removeAttribute('unresolved'); | 10691 element.removeAttribute('unresolved'); |
10686 // make 'element' implement definition.prototype | 10692 // make 'element' implement definition.prototype |
10687 implement(element, definition); | 10693 implement(element, definition); |
10688 // flag as upgraded | 10694 // flag as upgraded |
10689 element.__upgraded__ = true; | 10695 element.__upgraded__ = true; |
10690 // lifecycle management | 10696 // lifecycle management |
10691 created(element); | 10697 created(element); |
| 10698 // attachedCallback fires in tree order, call before recursing |
| 10699 scope.insertedNode(element); |
10692 // there should never be a shadow root on element at this point | 10700 // there should never be a shadow root on element at this point |
10693 // we require child nodes be upgraded before `created` | |
10694 scope.upgradeSubtree(element); | 10701 scope.upgradeSubtree(element); |
10695 // OUTPUT | 10702 // OUTPUT |
10696 return element; | 10703 return element; |
10697 } | 10704 } |
10698 | 10705 |
10699 function implement(element, definition) { | 10706 function implement(element, definition) { |
10700 // prototype swizzling is best | 10707 // prototype swizzling is best |
10701 if (Object.__proto__) { | 10708 if (Object.__proto__) { |
10702 element.__proto__ = definition.prototype; | 10709 element.__proto__ = definition.prototype; |
10703 } else { | 10710 } else { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10776 | 10783 |
10777 var registry = {}; | 10784 var registry = {}; |
10778 | 10785 |
10779 function getRegisteredDefinition(name) { | 10786 function getRegisteredDefinition(name) { |
10780 if (name) { | 10787 if (name) { |
10781 return registry[name.toLowerCase()]; | 10788 return registry[name.toLowerCase()]; |
10782 } | 10789 } |
10783 } | 10790 } |
10784 | 10791 |
10785 function registerDefinition(name, definition) { | 10792 function registerDefinition(name, definition) { |
10786 if (registry[name]) { | |
10787 throw new Error('a type with that name is already registered.'); | |
10788 } | |
10789 registry[name] = definition; | 10793 registry[name] = definition; |
10790 } | 10794 } |
10791 | 10795 |
10792 function generateConstructor(definition) { | 10796 function generateConstructor(definition) { |
10793 return function() { | 10797 return function() { |
10794 return instantiate(definition); | 10798 return instantiate(definition); |
10795 }; | 10799 }; |
10796 } | 10800 } |
10797 | 10801 |
10798 function createElement(tag, typeExtension) { | 10802 function createElement(tag, typeExtension) { |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10953 */ | 10957 */ |
10954 (function(scope){ | 10958 (function(scope){ |
10955 | 10959 |
10956 // bootstrap parsing | 10960 // bootstrap parsing |
10957 function bootstrap() { | 10961 function bootstrap() { |
10958 // parse document | 10962 // parse document |
10959 CustomElements.parser.parse(document); | 10963 CustomElements.parser.parse(document); |
10960 // one more pass before register is 'live' | 10964 // one more pass before register is 'live' |
10961 CustomElements.upgradeDocument(document); | 10965 CustomElements.upgradeDocument(document); |
10962 // choose async | 10966 // choose async |
10963 var async = window.Platform && Platform.endOfMicrotask ? | 10967 var async = window.Platform && Platform.endOfMicrotask ? |
10964 Platform.endOfMicrotask : | 10968 Platform.endOfMicrotask : |
10965 setTimeout; | 10969 setTimeout; |
10966 async(function() { | 10970 async(function() { |
10967 // set internal 'ready' flag, now document.registerElement will trigger | 10971 // set internal 'ready' flag, now document.registerElement will trigger |
10968 // synchronous upgrades | 10972 // synchronous upgrades |
10969 CustomElements.ready = true; | 10973 CustomElements.ready = true; |
10970 // capture blunt profiling data | 10974 // capture blunt profiling data |
10971 CustomElements.readyTime = Date.now(); | 10975 CustomElements.readyTime = Date.now(); |
10972 if (window.HTMLImports) { | 10976 if (window.HTMLImports) { |
10973 CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime; | 10977 CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime; |
10974 } | 10978 } |
10975 // notify the system that we are bootstrapped | 10979 // notify the system that we are bootstrapped |
10976 document.dispatchEvent( | 10980 document.dispatchEvent( |
10977 new CustomEvent('WebComponentsReady', {bubbles: true}) | 10981 new CustomEvent('WebComponentsReady', {bubbles: true}) |
(...skipping 20 matching lines...) Expand all Loading... |
10998 // When loading at readyState complete time (or via flag), boot custom elements | 11002 // When loading at readyState complete time (or via flag), boot custom elements |
10999 // immediately. | 11003 // immediately. |
11000 // If relevant, HTMLImports must already be loaded. | 11004 // If relevant, HTMLImports must already be loaded. |
11001 if (document.readyState === 'complete' || scope.flags.eager) { | 11005 if (document.readyState === 'complete' || scope.flags.eager) { |
11002 bootstrap(); | 11006 bootstrap(); |
11003 // When loading at readyState interactive time, bootstrap only if HTMLImports | 11007 // When loading at readyState interactive time, bootstrap only if HTMLImports |
11004 // are not pending. Also avoid IE as the semantics of this state are unreliable. | 11008 // are not pending. Also avoid IE as the semantics of this state are unreliable. |
11005 } else if (document.readyState === 'interactive' && !window.attachEvent && | 11009 } else if (document.readyState === 'interactive' && !window.attachEvent && |
11006 (!window.HTMLImports || window.HTMLImports.ready)) { | 11010 (!window.HTMLImports || window.HTMLImports.ready)) { |
11007 bootstrap(); | 11011 bootstrap(); |
11008 // When loading at other readyStates, wait for the appropriate DOM event to | 11012 // When loading at other readyStates, wait for the appropriate DOM event to |
11009 // bootstrap. | 11013 // bootstrap. |
11010 } else { | 11014 } else { |
11011 var loadEvent = window.HTMLImports && !HTMLImports.ready ? | 11015 var loadEvent = window.HTMLImports && !HTMLImports.ready ? |
11012 'HTMLImportsLoaded' : 'DOMContentLoaded'; | 11016 'HTMLImportsLoaded' : 'DOMContentLoaded'; |
11013 window.addEventListener(loadEvent, bootstrap); | 11017 window.addEventListener(loadEvent, bootstrap); |
11014 } | 11018 } |
11015 | 11019 |
11016 })(window.CustomElements); | 11020 })(window.CustomElements); |
11017 | 11021 |
11018 /* | 11022 /* |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11103 | 11107 |
11104 function createStyleElement(cssText, scope) { | 11108 function createStyleElement(cssText, scope) { |
11105 scope = scope || document; | 11109 scope = scope || document; |
11106 scope = scope.createElement ? scope : scope.ownerDocument; | 11110 scope = scope.createElement ? scope : scope.ownerDocument; |
11107 var style = scope.createElement('style'); | 11111 var style = scope.createElement('style'); |
11108 style.textContent = cssText; | 11112 style.textContent = cssText; |
11109 return style; | 11113 return style; |
11110 } | 11114 } |
11111 | 11115 |
11112 // TODO(sorvell): use a common loader shared with HTMLImports polyfill | 11116 // TODO(sorvell): use a common loader shared with HTMLImports polyfill |
11113 // currently, this just loads the first @import per style element | 11117 // currently, this just loads the first @import per style element |
11114 // and does not recurse into loaded elements; we'll address this with a | 11118 // and does not recurse into loaded elements; we'll address this with a |
11115 // generalized loader that's built out of the one in the HTMLImports polyfill. | 11119 // generalized loader that's built out of the one in the HTMLImports polyfill. |
11116 // polyfill the loading of a style element's @import via xhr | 11120 // polyfill the loading of a style element's @import via xhr |
11117 function xhrLoadStyle(style, callback) { | 11121 function xhrLoadStyle(style, callback) { |
11118 HTMLImports.xhr.load(atImportUrlFromStyle(style), function (err, resource, | 11122 HTMLImports.xhr.load(atImportUrlFromStyle(style), function (err, resource, |
11119 url) { | 11123 url) { |
11120 replaceAtImportWithCssText(this, url, resource); | 11124 replaceAtImportWithCssText(this, url, resource); |
11121 this.textContent = urlResolver.resolveCssText(this.textContent, url); | 11125 this.textContent = urlResolver.resolveCssText(this.textContent, url); |
11122 callback && callback(this); | 11126 callback && callback(this); |
11123 }, style); | 11127 }, style); |
11124 } | 11128 } |
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12071 var DEDUP_TIMEOUT = 2500; | 12075 var DEDUP_TIMEOUT = 2500; |
12072 var CLICK_COUNT_TIMEOUT = 200; | 12076 var CLICK_COUNT_TIMEOUT = 200; |
12073 var ATTRIB = 'touch-action'; | 12077 var ATTRIB = 'touch-action'; |
12074 var INSTALLER; | 12078 var INSTALLER; |
12075 // The presence of touch event handlers blocks scrolling, and so we must be ca
reful to | 12079 // The presence of touch event handlers blocks scrolling, and so we must be ca
reful to |
12076 // avoid adding handlers unnecessarily. Chrome plans to add a touch-action-de
lay property | 12080 // avoid adding handlers unnecessarily. Chrome plans to add a touch-action-de
lay property |
12077 // (crbug.com/329559) to address this, and once we have that we can opt-in to
a simpler | 12081 // (crbug.com/329559) to address this, and once we have that we can opt-in to
a simpler |
12078 // handler registration mechanism. Rather than try to predict how exactly to
opt-in to | 12082 // handler registration mechanism. Rather than try to predict how exactly to
opt-in to |
12079 // that we'll just leave this disabled until there is a build of Chrome to tes
t. | 12083 // that we'll just leave this disabled until there is a build of Chrome to tes
t. |
12080 var HAS_TOUCH_ACTION_DELAY = false; | 12084 var HAS_TOUCH_ACTION_DELAY = false; |
12081 | 12085 |
12082 // handler block for native touch events | 12086 // handler block for native touch events |
12083 var touchEvents = { | 12087 var touchEvents = { |
12084 scrollType: new WeakMap(), | 12088 scrollType: new WeakMap(), |
12085 events: [ | 12089 events: [ |
12086 'touchstart', | 12090 'touchstart', |
12087 'touchmove', | 12091 'touchmove', |
12088 'touchend', | 12092 'touchend', |
12089 'touchcancel' | 12093 'touchcancel' |
12090 ], | 12094 ], |
12091 register: function(target) { | 12095 register: function(target) { |
(...skipping 2291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14383 content.appendChild(el); | 14387 content.appendChild(el); |
14384 return; | 14388 return; |
14385 } | 14389 } |
14386 | 14390 |
14387 var child; | 14391 var child; |
14388 while (child = el.firstChild) { | 14392 while (child = el.firstChild) { |
14389 content.appendChild(child); | 14393 content.appendChild(child); |
14390 } | 14394 } |
14391 } | 14395 } |
14392 | 14396 |
| 14397 var templateObserver; |
| 14398 if (typeof MutationObserver == 'function') { |
| 14399 templateObserver = new MutationObserver(function(records) { |
| 14400 for (var i = 0; i < records.length; i++) { |
| 14401 records[i].target.refChanged_(); |
| 14402 } |
| 14403 }); |
| 14404 } |
| 14405 |
14393 /** | 14406 /** |
14394 * Ensures proper API and content model for template elements. | 14407 * Ensures proper API and content model for template elements. |
14395 * @param {HTMLTemplateElement} opt_instanceRef The template element which | 14408 * @param {HTMLTemplateElement} opt_instanceRef The template element which |
14396 * |el| template element will return as the value of its ref(), and whose | 14409 * |el| template element will return as the value of its ref(), and whose |
14397 * content will be used as source when createInstance() is invoked. | 14410 * content will be used as source when createInstance() is invoked. |
14398 */ | 14411 */ |
14399 HTMLTemplateElement.decorate = function(el, opt_instanceRef) { | 14412 HTMLTemplateElement.decorate = function(el, opt_instanceRef) { |
14400 if (el.templateIsDecorated_) | 14413 if (el.templateIsDecorated_) |
14401 return false; | 14414 return false; |
14402 | 14415 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14486 }; | 14499 }; |
14487 } | 14500 } |
14488 | 14501 |
14489 if (!template.setModelFnScheduled_) { | 14502 if (!template.setModelFnScheduled_) { |
14490 template.setModelFnScheduled_ = true; | 14503 template.setModelFnScheduled_ = true; |
14491 Observer.runEOM_(template.setModelFn_); | 14504 Observer.runEOM_(template.setModelFn_); |
14492 } | 14505 } |
14493 } | 14506 } |
14494 | 14507 |
14495 mixin(HTMLTemplateElement.prototype, { | 14508 mixin(HTMLTemplateElement.prototype, { |
| 14509 bind: function(name, value, oneTime) { |
| 14510 if (name != 'ref') |
| 14511 return Element.prototype.bind.call(this, name, value, oneTime); |
| 14512 |
| 14513 var self = this; |
| 14514 var ref = oneTime ? value : value.open(function(ref) { |
| 14515 self.setAttribute('ref', ref); |
| 14516 self.refChanged_(); |
| 14517 }); |
| 14518 |
| 14519 this.setAttribute('ref', ref); |
| 14520 this.refChanged_(); |
| 14521 if (oneTime) |
| 14522 return; |
| 14523 |
| 14524 this.unbind('ref'); |
| 14525 return this.bindings.ref = value; |
| 14526 }, |
| 14527 |
14496 processBindingDirectives_: function(directives) { | 14528 processBindingDirectives_: function(directives) { |
14497 if (this.iterator_) | 14529 if (this.iterator_) |
14498 this.iterator_.closeDeps(); | 14530 this.iterator_.closeDeps(); |
14499 | 14531 |
14500 if (!directives.if && !directives.bind && !directives.repeat) { | 14532 if (!directives.if && !directives.bind && !directives.repeat) { |
14501 if (this.iterator_) { | 14533 if (this.iterator_) { |
14502 this.iterator_.close(); | 14534 this.iterator_.close(); |
14503 this.iterator_ = undefined; | 14535 this.iterator_ = undefined; |
14504 this.bindings.iterator = undefined; | 14536 this.bindings.iterator = undefined; |
14505 } | 14537 } |
14506 | 14538 |
14507 return; | 14539 return; |
14508 } | 14540 } |
14509 | 14541 |
14510 if (!this.iterator_) { | 14542 if (!this.iterator_) { |
14511 this.iterator_ = new TemplateIterator(this); | 14543 this.iterator_ = new TemplateIterator(this); |
14512 this.bindings = this.bindings || {}; | 14544 this.bindings = this.bindings || {}; |
14513 this.bindings.iterator = this.iterator_; | 14545 this.bindings.iterator = this.iterator_; |
14514 } | 14546 } |
14515 | 14547 |
14516 this.iterator_.updateDependencies(directives, this.model_); | 14548 this.iterator_.updateDependencies(directives, this.model_); |
| 14549 |
| 14550 if (templateObserver) { |
| 14551 templateObserver.observe(this, { attributes: true, |
| 14552 attributeFilter: ['ref'] }); |
| 14553 } |
| 14554 |
14517 return this.iterator_; | 14555 return this.iterator_; |
14518 }, | 14556 }, |
14519 | 14557 |
14520 createInstance: function(model, bindingDelegate, delegate_, | 14558 createInstance: function(model, bindingDelegate, delegate_, |
14521 instanceBindings_) { | 14559 instanceBindings_) { |
14522 if (bindingDelegate) | 14560 if (bindingDelegate) |
14523 delegate_ = this.newDelegate_(bindingDelegate); | 14561 delegate_ = this.newDelegate_(bindingDelegate); |
14524 | 14562 |
14525 var content = this.ref.content; | 14563 if (!this.refContent_) |
| 14564 this.refContent_ = this.ref_.content; |
| 14565 var content = this.refContent_; |
14526 var map = this.bindingMap_; | 14566 var map = this.bindingMap_; |
14527 if (!map || map.content !== content) { | 14567 if (!map || map.content !== content) { |
14528 // TODO(rafaelw): Setup a MutationObserver on content to detect | 14568 // TODO(rafaelw): Setup a MutationObserver on content to detect |
14529 // when the instanceMap is invalid. | 14569 // when the instanceMap is invalid. |
14530 map = createInstanceBindingMap(content, | 14570 map = createInstanceBindingMap(content, |
14531 delegate_ && delegate_.prepareBinding) || []; | 14571 delegate_ && delegate_.prepareBinding) || []; |
14532 map.content = content; | 14572 map.content = content; |
14533 this.bindingMap_ = map; | 14573 this.bindingMap_ = map; |
14534 } | 14574 } |
14535 | 14575 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14567 | 14607 |
14568 set model(model) { | 14608 set model(model) { |
14569 this.model_ = model; | 14609 this.model_ = model; |
14570 ensureSetModelScheduled(this); | 14610 ensureSetModelScheduled(this); |
14571 }, | 14611 }, |
14572 | 14612 |
14573 get bindingDelegate() { | 14613 get bindingDelegate() { |
14574 return this.delegate_ && this.delegate_.raw; | 14614 return this.delegate_ && this.delegate_.raw; |
14575 }, | 14615 }, |
14576 | 14616 |
| 14617 refChanged_: function() { |
| 14618 if (!this.iterator_ || this.refContent_ === this.ref_.content) |
| 14619 return; |
| 14620 |
| 14621 this.refContent_ = undefined; |
| 14622 this.iterator_.valueChanged(); |
| 14623 this.iterator_.updateIteratedValue(); |
| 14624 }, |
| 14625 |
| 14626 clear: function() { |
| 14627 this.model_ = undefined; |
| 14628 this.delegate_ = undefined; |
| 14629 this.bindings_ = undefined; |
| 14630 this.refContent_ = undefined; |
| 14631 if (!this.iterator_) |
| 14632 return; |
| 14633 this.iterator_.valueChanged(); |
| 14634 this.iterator_.close() |
| 14635 this.iterator_ = undefined; |
| 14636 }, |
| 14637 |
14577 setDelegate_: function(delegate) { | 14638 setDelegate_: function(delegate) { |
14578 this.delegate_ = delegate; | 14639 this.delegate_ = delegate; |
14579 this.bindingMap_ = undefined; | 14640 this.bindingMap_ = undefined; |
14580 if (this.iterator_) { | 14641 if (this.iterator_) { |
14581 this.iterator_.instancePositionChangedFn_ = undefined; | 14642 this.iterator_.instancePositionChangedFn_ = undefined; |
14582 this.iterator_.instanceModelFn_ = undefined; | 14643 this.iterator_.instanceModelFn_ = undefined; |
14583 } | 14644 } |
14584 }, | 14645 }, |
14585 | 14646 |
14586 newDelegate_: function(bindingDelegate) { | 14647 newDelegate_: function(bindingDelegate) { |
(...skipping 16 matching lines...) Expand all Loading... |
14603 prepareInstanceModel: delegateFn('prepareInstanceModel'), | 14664 prepareInstanceModel: delegateFn('prepareInstanceModel'), |
14604 prepareInstancePositionChanged: | 14665 prepareInstancePositionChanged: |
14605 delegateFn('prepareInstancePositionChanged') | 14666 delegateFn('prepareInstancePositionChanged') |
14606 }; | 14667 }; |
14607 }, | 14668 }, |
14608 | 14669 |
14609 // TODO(rafaelw): Assigning .bindingDelegate always succeeds. It may | 14670 // TODO(rafaelw): Assigning .bindingDelegate always succeeds. It may |
14610 // make sense to issue a warning or even throw if the template is already | 14671 // make sense to issue a warning or even throw if the template is already |
14611 // "activated", since this would be a strange thing to do. | 14672 // "activated", since this would be a strange thing to do. |
14612 set bindingDelegate(bindingDelegate) { | 14673 set bindingDelegate(bindingDelegate) { |
| 14674 if (this.delegate_) { |
| 14675 throw Error('Template must be cleared before a new bindingDelegate ' + |
| 14676 'can be assigned'); |
| 14677 } |
| 14678 |
14613 this.setDelegate_(this.newDelegate_(bindingDelegate)); | 14679 this.setDelegate_(this.newDelegate_(bindingDelegate)); |
14614 }, | 14680 }, |
14615 | 14681 |
14616 get ref() { | 14682 get ref_() { |
14617 var ref = searchRefId(this, this.getAttribute('ref')); | 14683 var ref = searchRefId(this, this.getAttribute('ref')); |
14618 if (!ref) | 14684 if (!ref) |
14619 ref = this.instanceRef_; | 14685 ref = this.instanceRef_; |
14620 | 14686 |
14621 if (!ref) | 14687 if (!ref) |
14622 return this; | 14688 return this; |
14623 | 14689 |
14624 var nextRef = ref.ref; | 14690 var nextRef = ref.ref_; |
14625 return nextRef ? nextRef : ref; | 14691 return nextRef ? nextRef : ref; |
14626 } | 14692 } |
14627 }); | 14693 }); |
14628 | 14694 |
14629 // Returns | 14695 // Returns |
14630 // a) undefined if there are no mustaches. | 14696 // a) undefined if there are no mustaches. |
14631 // b) [TEXT, (ONE_TIME?, PATH, DELEGATE_FN, TEXT)+] if there is at least one
mustache. | 14697 // b) [TEXT, (ONE_TIME?, PATH, DELEGATE_FN, TEXT)+] if there is at least one
mustache. |
14632 function parseMustaches(s, name, node, prepareBindingFn) { | 14698 function parseMustaches(s, name, node, prepareBindingFn) { |
14633 if (!s || !s.length) | 14699 if (!s || !s.length) |
14634 return; | 14700 return; |
(...skipping 1715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16350 observer.addPath(model, path); | 16416 observer.addPath(model, path); |
16351 | 16417 |
16352 return path.getValueFrom(model); | 16418 return path.getValueFrom(model); |
16353 } | 16419 } |
16354 } | 16420 } |
16355 | 16421 |
16356 return this.valueFn_; | 16422 return this.valueFn_; |
16357 }, | 16423 }, |
16358 | 16424 |
16359 setValue: function(model, newValue) { | 16425 setValue: function(model, newValue) { |
| 16426 if (this.path.length == 1); |
| 16427 model = findScope(model, this.path[0]); |
| 16428 |
16360 return this.path.setValueFrom(model, newValue); | 16429 return this.path.setValueFrom(model, newValue); |
16361 } | 16430 } |
16362 }; | 16431 }; |
16363 | 16432 |
16364 function MemberExpression(object, property, accessor) { | 16433 function MemberExpression(object, property, accessor) { |
16365 // convert literal computed property access where literal value is a value | 16434 // convert literal computed property access where literal value is a value |
16366 // path to ident dot-access. | 16435 // path to ident dot-access. |
16367 if (accessor == '[' && | 16436 if (accessor == '[' && |
16368 property instanceof Literal && | 16437 property instanceof Literal && |
16369 Path.get(property.value).valid) { | 16438 Path.get(property.value).valid) { |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16743 'webkitAnimationStart', | 16812 'webkitAnimationStart', |
16744 'webkitAnimationEnd', | 16813 'webkitAnimationEnd', |
16745 'webkitTransitionEnd', | 16814 'webkitTransitionEnd', |
16746 'DOMFocusOut', | 16815 'DOMFocusOut', |
16747 'DOMFocusIn', | 16816 'DOMFocusIn', |
16748 'DOMMouseScroll' | 16817 'DOMMouseScroll' |
16749 ].forEach(function(e) { | 16818 ].forEach(function(e) { |
16750 mixedCaseEventTypes[e.toLowerCase()] = e; | 16819 mixedCaseEventTypes[e.toLowerCase()] = e; |
16751 }); | 16820 }); |
16752 | 16821 |
16753 function prepareEventBinding(path, name) { | 16822 var parentScopeName = '@' + Math.random().toString(36).slice(2); |
| 16823 |
| 16824 // Single ident paths must bind directly to the appropriate scope object. |
| 16825 // I.e. Pushed values in two-bindings need to be assigned to the actual model |
| 16826 // object. |
| 16827 function findScope(model, prop) { |
| 16828 while (model[parentScopeName] && |
| 16829 !Object.prototype.hasOwnProperty.call(model, prop)) { |
| 16830 model = model[parentScopeName]; |
| 16831 } |
| 16832 |
| 16833 return model; |
| 16834 } |
| 16835 |
| 16836 function resolveEventReceiver(model, path, node) { |
| 16837 if (path.length == 0) |
| 16838 return undefined; |
| 16839 |
| 16840 if (path.length == 1) |
| 16841 return findScope(model, path[0]); |
| 16842 |
| 16843 for (var i = 0; model != null && i < path.length - 1; i++) { |
| 16844 model = model[path[i]]; |
| 16845 } |
| 16846 |
| 16847 return model; |
| 16848 } |
| 16849 |
| 16850 function prepareEventBinding(path, name, polymerExpressions) { |
16754 var eventType = name.substring(3); | 16851 var eventType = name.substring(3); |
16755 eventType = mixedCaseEventTypes[eventType] || eventType; | 16852 eventType = mixedCaseEventTypes[eventType] || eventType; |
16756 | 16853 |
16757 return function(model, node, oneTime) { | 16854 return function(model, node, oneTime) { |
16758 var fn = path.getValueFrom(model); | 16855 var fn, receiver, handler; |
| 16856 if (typeof polymerExpressions.resolveEventHandler == 'function') { |
| 16857 handler = function(e) { |
| 16858 fn = fn || polymerExpressions.resolveEventHandler(model, path, node); |
| 16859 fn(e, e.detail, e.currentTarget); |
16759 | 16860 |
16760 function handler(e) { | 16861 if (Platform && typeof Platform.flush == 'function') |
16761 if (!oneTime) | 16862 Platform.flush(); |
16762 fn = path.getValueFrom(model); | 16863 }; |
| 16864 } else { |
| 16865 handler = function(e) { |
| 16866 fn = fn || path.getValueFrom(model); |
| 16867 receiver = receiver || resolveEventReceiver(model, path, node); |
16763 | 16868 |
16764 fn.apply(model, [e, e.detail, e.currentTarget]); | 16869 fn.apply(receiver, [e, e.detail, e.currentTarget]); |
16765 | 16870 |
16766 if (Platform && typeof Platform.flush == 'function') | 16871 if (Platform && typeof Platform.flush == 'function') |
16767 Platform.flush(); | 16872 Platform.flush(); |
| 16873 }; |
16768 } | 16874 } |
16769 | 16875 |
16770 node.addEventListener(eventType, handler); | 16876 node.addEventListener(eventType, handler); |
16771 | 16877 |
16772 if (oneTime) | 16878 if (oneTime) |
16773 return; | 16879 return; |
16774 | 16880 |
16775 function bindingValue() { | 16881 function bindingValue() { |
16776 return '{{ ' + path + ' }}'; | 16882 return '{{ ' + path + ' }}'; |
16777 } | 16883 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16812 var indexIdent = template.polymerExpressionIndexIdent_; | 16918 var indexIdent = template.polymerExpressionIndexIdent_; |
16813 if (!indexIdent) | 16919 if (!indexIdent) |
16814 return; | 16920 return; |
16815 | 16921 |
16816 return function(templateInstance, index) { | 16922 return function(templateInstance, index) { |
16817 templateInstance.model[indexIdent] = index; | 16923 templateInstance.model[indexIdent] = index; |
16818 }; | 16924 }; |
16819 }, | 16925 }, |
16820 | 16926 |
16821 prepareBinding: function(pathString, name, node) { | 16927 prepareBinding: function(pathString, name, node) { |
| 16928 var path = Path.get(pathString); |
16822 if (isEventHandler(name)) { | 16929 if (isEventHandler(name)) { |
16823 var path = Path.get(pathString); | |
16824 if (!path.valid) { | 16930 if (!path.valid) { |
16825 console.error('on-* bindings must be simple path expressions'); | 16931 console.error('on-* bindings must be simple path expressions'); |
16826 return; | 16932 return; |
16827 } | 16933 } |
16828 | 16934 |
16829 return prepareEventBinding(path, name); | 16935 return prepareEventBinding(path, name, this); |
16830 } | 16936 } |
16831 | 16937 |
16832 if (Path.get(pathString).valid) | 16938 if (path.valid) { |
| 16939 if (path.length == 1) { |
| 16940 return function(model, node, oneTime) { |
| 16941 if (oneTime) |
| 16942 return path.getValueFrom(model); |
| 16943 |
| 16944 var scope = findScope(model, path[0]); |
| 16945 return new PathObserver(scope, path); |
| 16946 } |
| 16947 } |
| 16948 |
16833 return; // bail out early if pathString is simple path. | 16949 return; // bail out early if pathString is simple path. |
| 16950 } |
16834 | 16951 |
16835 return prepareBinding(pathString, name, node, this); | 16952 return prepareBinding(pathString, name, node, this); |
16836 }, | 16953 }, |
16837 | 16954 |
16838 prepareInstanceModel: function(template) { | 16955 prepareInstanceModel: function(template) { |
16839 var scopeName = template.polymerExpressionScopeIdent_; | 16956 var scopeName = template.polymerExpressionScopeIdent_; |
16840 if (!scopeName) | 16957 if (!scopeName) |
16841 return; | 16958 return; |
16842 | 16959 |
16843 var parentScope = template.templateInstance ? | 16960 var parentScope = template.templateInstance ? |
16844 template.templateInstance.model : | 16961 template.templateInstance.model : |
16845 template.model; | 16962 template.model; |
16846 | 16963 |
| 16964 var indexName = template.polymerExpressionIndexIdent_; |
| 16965 |
16847 return function(model) { | 16966 return function(model) { |
16848 var scope = Object.create(parentScope); | 16967 var scope = Object.create(parentScope); |
16849 scope[scopeName] = model; | 16968 scope[scopeName] = model; |
| 16969 scope[indexName] = undefined; |
| 16970 scope[parentScopeName] = parentScope; |
16850 return scope; | 16971 return scope; |
16851 }; | 16972 }; |
16852 } | 16973 } |
16853 }; | 16974 }; |
16854 | 16975 |
16855 global.PolymerExpressions = PolymerExpressions; | 16976 global.PolymerExpressions = PolymerExpressions; |
16856 if (global.exposeGetExpression) | 16977 if (global.exposeGetExpression) |
16857 global.getExpression_ = getExpression; | 16978 global.getExpression_ = getExpression; |
16858 | 16979 |
16859 global.PolymerExpressions.prepareEventBinding = prepareEventBinding; | 16980 global.PolymerExpressions.prepareEventBinding = prepareEventBinding; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16905 } | 17026 } |
16906 } | 17027 } |
16907 | 17028 |
16908 // exports | 17029 // exports |
16909 scope.flush = flush; | 17030 scope.flush = flush; |
16910 | 17031 |
16911 })(window.Platform); | 17032 })(window.Platform); |
16912 | 17033 |
16913 | 17034 |
16914 //# sourceMappingURL=platform.concat.js.map | 17035 //# sourceMappingURL=platform.concat.js.map |
OLD | NEW |