Index: pkg/web_components/lib/platform.concat.js |
diff --git a/pkg/web_components/lib/platform.concat.js b/pkg/web_components/lib/platform.concat.js |
index b1e80668ad486024b5432cae1dfe30600cd5bd3b..293c435aee306e4f9ae4adc6131324832b64a3ce 100644 |
--- a/pkg/web_components/lib/platform.concat.js |
+++ b/pkg/web_components/lib/platform.concat.js |
@@ -1649,61 +1649,61 @@ if (typeof WeakMap === 'undefined') { |
}; |
})(typeof global !== 'undefined' && global && typeof module !== 'undefined' && module ? global : this || window); |
-// prepoulate window.Platform.flags for default controls |
-window.Platform = window.Platform || {}; |
-// prepopulate window.logFlags if necessary |
-window.logFlags = window.logFlags || {}; |
-// process flags |
-(function(scope){ |
- // import |
- var flags = scope.flags || {}; |
- // populate flags from location |
- location.search.slice(1).split('&').forEach(function(o) { |
- o = o.split('='); |
- o[0] && (flags[o[0]] = o[1] || true); |
- }); |
- var entryPoint = document.currentScript || document.querySelector('script[src*="platform.js"]'); |
- if (entryPoint) { |
- var a = entryPoint.attributes; |
- for (var i = 0, n; i < a.length; i++) { |
- n = a[i]; |
- if (n.name !== 'src') { |
- flags[n.name] = n.value || true; |
- } |
- } |
- } |
- if (flags.log) { |
- flags.log.split(',').forEach(function(f) { |
- window.logFlags[f] = true; |
- }); |
- } |
- // If any of these flags match 'native', then force native ShadowDOM; any |
- // other truthy value, or failure to detect native |
- // ShadowDOM, results in polyfill |
- flags.shadow = (flags.shadow || flags.shadowdom || flags.polyfill); |
- if (flags.shadow === 'native') { |
- flags.shadow = false; |
- } else { |
- flags.shadow = flags.shadow || !HTMLElement.prototype.createShadowRoot; |
- } |
- |
- // CustomElements polyfill flag |
- if (flags.register) { |
- window.CustomElements = window.CustomElements || {flags: {}}; |
- window.CustomElements.flags.register = flags.register; |
- } |
- |
- if (flags.imports) { |
- window.HTMLImports = window.HTMLImports || {flags: {}}; |
- window.HTMLImports.flags.imports = flags.imports; |
- } |
- |
- // export |
- scope.flags = flags; |
-})(Platform); |
- |
-// select ShadowDOM impl |
-if (Platform.flags.shadow) { |
+// prepoulate window.Platform.flags for default controls |
+window.Platform = window.Platform || {}; |
+// prepopulate window.logFlags if necessary |
+window.logFlags = window.logFlags || {}; |
+// process flags |
+(function(scope){ |
+ // import |
+ var flags = scope.flags || {}; |
+ // populate flags from location |
+ location.search.slice(1).split('&').forEach(function(o) { |
+ o = o.split('='); |
+ o[0] && (flags[o[0]] = o[1] || true); |
+ }); |
+ var entryPoint = document.currentScript || document.querySelector('script[src*="platform.js"]'); |
+ if (entryPoint) { |
+ var a = entryPoint.attributes; |
+ for (var i = 0, n; i < a.length; i++) { |
+ n = a[i]; |
+ if (n.name !== 'src') { |
+ flags[n.name] = n.value || true; |
+ } |
+ } |
+ } |
+ if (flags.log) { |
+ flags.log.split(',').forEach(function(f) { |
+ window.logFlags[f] = true; |
+ }); |
+ } |
+ // If any of these flags match 'native', then force native ShadowDOM; any |
+ // other truthy value, or failure to detect native |
+ // ShadowDOM, results in polyfill |
+ flags.shadow = (flags.shadow || flags.shadowdom || flags.polyfill); |
+ if (flags.shadow === 'native') { |
+ flags.shadow = false; |
+ } else { |
+ flags.shadow = flags.shadow || !HTMLElement.prototype.createShadowRoot; |
+ } |
+ |
+ // CustomElements polyfill flag |
+ if (flags.register) { |
+ window.CustomElements = window.CustomElements || {flags: {}}; |
+ window.CustomElements.flags.register = flags.register; |
+ } |
+ |
+ if (flags.imports) { |
+ window.HTMLImports = window.HTMLImports || {flags: {}}; |
+ window.HTMLImports.flags.imports = flags.imports; |
+ } |
+ |
+ // export |
+ scope.flags = flags; |
+})(Platform); |
+ |
+// select ShadowDOM impl |
+if (Platform.flags.shadow) { |
// Copyright 2012 The Polymer Authors. All rights reserved. |
// Use of this source code is goverened by a BSD-style |
@@ -6907,10 +6907,10 @@ window.ShadowDOMPolyfill = {}; |
/* |
This is a limited shim for ShadowDOM css styling. |
https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles |
- |
- The intention here is to support only the styling features which can be |
- relatively simply implemented. The goal is to allow users to avoid the |
- most obvious pitfalls and do so without compromising performance significantly. |
+ |
+ The intention here is to support only the styling features which can be |
+ relatively simply implemented. The goal is to allow users to avoid the |
+ most obvious pitfalls and do so without compromising performance significantly. |
For ShadowDOM styling that's not covered here, a set of best practices |
can be provided that should allow users to accomplish more complex styling. |
@@ -6920,56 +6920,56 @@ window.ShadowDOMPolyfill = {}; |
Shimmed features: |
* :host, :ancestor: ShadowDOM allows styling of the shadowRoot's host |
- element using the :host rule. To shim this feature, the :host styles are |
- reformatted and prefixed with a given scope name and promoted to a |
+ element using the :host rule. To shim this feature, the :host styles are |
+ reformatted and prefixed with a given scope name and promoted to a |
document level stylesheet. |
For example, given a scope name of .foo, a rule like this: |
- |
+ |
:host { |
background: red; |
} |
} |
- |
+ |
becomes: |
- |
+ |
.foo { |
background: red; |
} |
- |
- * encapsultion: Styles defined within ShadowDOM, apply only to |
+ |
+ * encapsultion: Styles defined within ShadowDOM, apply only to |
dom inside the ShadowDOM. Polymer uses one of two techniques to imlement |
this feature. |
- |
- By default, rules are prefixed with the host element tag name |
+ |
+ By default, rules are prefixed with the host element tag name |
as a descendant selector. This ensures styling does not leak out of the 'top' |
of the element's ShadowDOM. For example, |
div { |
font-weight: bold; |
} |
- |
+ |
becomes: |
x-foo div { |
font-weight: bold; |
} |
- |
+ |
becomes: |
- Alternatively, if Platform.ShadowCSS.strictStyling is set to true then |
+ Alternatively, if Platform.ShadowCSS.strictStyling is set to true then |
selectors are scoped by adding an attribute selector suffix to each |
- simple selector that contains the host element tag name. Each element |
- in the element's ShadowDOM template is also given the scope attribute. |
+ simple selector that contains the host element tag name. Each element |
+ in the element's ShadowDOM template is also given the scope attribute. |
Thus, these rules match only elements that have the scope attribute. |
For example, given a scope name of x-foo, a rule like this: |
- |
+ |
div { |
font-weight: bold; |
} |
- |
+ |
becomes: |
- |
+ |
div[x-foo] { |
font-weight: bold; |
} |
@@ -6981,31 +6981,31 @@ window.ShadowDOMPolyfill = {}; |
shadowRoot should not cross the ShadowDOM boundary and should not apply |
inside a shadowRoot. |
- This styling behavior is not emulated. Some possible ways to do this that |
+ This styling behavior is not emulated. Some possible ways to do this that |
were rejected due to complexity and/or performance concerns include: (1) reset |
every possible property for every possible selector for a given scope name; |
(2) re-implement css in javascript. |
- |
+ |
As an alternative, users should make sure to use selectors |
specific to the scope in which they are working. |
- |
+ |
* ::distributed: This behavior is not emulated. It's often not necessary |
to style the contents of a specific insertion point and instead, descendants |
- of the host element can be styled selectively. Users can also create an |
+ of the host element can be styled selectively. Users can also create an |
extra node around an insertion point and style that node's contents |
via descendent selectors. For example, with a shadowRoot like this: |
- |
+ |
<style> |
::content(div) { |
background: red; |
} |
</style> |
<content></content> |
- |
+ |
could become: |
- |
+ |
<style> |
- / *@polyfill .content-container div * / |
+ / *@polyfill .content-container div * / |
::content(div) { |
background: red; |
} |
@@ -7013,9 +7013,9 @@ window.ShadowDOMPolyfill = {}; |
<div class="content-container"> |
<content></content> |
</div> |
- |
+ |
Note the use of @polyfill in the comment above a ShadowDOM specific style |
- declaration. This is a directive to the styling shim to use the selector |
+ declaration. This is a directive to the styling shim to use the selector |
in comments in lieu of the next selector when running under polyfill. |
*/ |
(function(scope) { |
@@ -7045,7 +7045,7 @@ var ShadowCSS = { |
root.shimmedStyle = def.shimmedStyle; |
} |
// remove existing style elements |
- for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); |
+ for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]); |
i++) { |
s.parentNode.removeChild(s); |
} |
@@ -7063,7 +7063,7 @@ var ShadowCSS = { |
var cssText = this.shimScoping(scopeStyles, name, typeExtension); |
// note: we only need to do rootStyles since these are unscoped. |
cssText += this.extractPolyfillUnscopedRules(rootStyles); |
- return cssText; |
+ return cssText.trim(); |
}, |
registerDefinition: function(root, name, extendsName) { |
var def = this.registry[name] = { |
@@ -7102,14 +7102,14 @@ var ShadowCSS = { |
/* |
* Process styles to convert native ShadowDOM rules that will trip |
* up the css parser; we rely on decorating the stylesheet with comments. |
- * |
+ * |
* For example, we convert this rule: |
- * |
+ * |
* (comment start) @polyfill :host menu-item (comment end) |
* shadow::-webkit-distributed(menu-item) { |
- * |
+ * |
* to this: |
- * |
+ * |
* scopeName menu-item { |
* |
**/ |
@@ -7128,14 +7128,14 @@ var ShadowCSS = { |
}, |
/* |
* Process styles to add rules which will only apply under the polyfill |
- * |
+ * |
* For example, we convert this rule: |
- * |
- * (comment start) @polyfill-rule :host menu-item { |
+ * |
+ * (comment start) @polyfill-rule :host menu-item { |
* ... } (comment end) |
- * |
+ * |
* to this: |
- * |
+ * |
* scopeName menu-item {...} |
* |
**/ |
@@ -7154,15 +7154,15 @@ var ShadowCSS = { |
}, |
/* |
* Process styles to add rules which will only apply under the polyfill |
- * and do not process via CSSOM. (CSSOM is destructive to rules on rare |
+ * and do not process via CSSOM. (CSSOM is destructive to rules on rare |
* occasions, e.g. -webkit-calc on Safari.) |
* For example, we convert this rule: |
- * |
- * (comment start) @polyfill-unscoped-rule menu-item { |
+ * |
+ * (comment start) @polyfill-unscoped-rule menu-item { |
* ... } (comment end) |
- * |
+ * |
* to this: |
- * |
+ * |
* menu-item {...} |
* |
**/ |
@@ -7184,11 +7184,11 @@ var ShadowCSS = { |
return r; |
}, |
/* Ensure styles are scoped. Pseudo-scoping takes a rule like: |
- * |
- * .foo {... } |
- * |
+ * |
+ * .foo {... } |
+ * |
* and converts this to |
- * |
+ * |
* scopeName .foo { ... } |
*/ |
shimScoping: function(styles, name, typeExtension) { |
@@ -7202,8 +7202,8 @@ var ShadowCSS = { |
cssText = this.convertColonHost(cssText); |
cssText = this.convertColonAncestor(cssText); |
cssText = this.convertCombinators(cssText); |
- var rules = cssToRules(cssText); |
if (name) { |
+ var rules = cssToRules(cssText); |
cssText = this.scopeRules(rules, name, typeExtension); |
} |
return cssText; |
@@ -7225,13 +7225,13 @@ var ShadowCSS = { |
* to |
* |
* scopeName.foo > .bar, .foo scopeName > .bar { } |
- * |
+ * |
* and |
* |
* :ancestor(.foo:host) .bar { ... } |
- * |
+ * |
* to |
- * |
+ * |
* scopeName.foo .bar { ... } |
*/ |
convertColonAncestor: function(cssText) { |
@@ -7275,7 +7275,7 @@ var ShadowCSS = { |
var cssText = ''; |
Array.prototype.forEach.call(cssRules, function(rule) { |
if (rule.selectorText && (rule.style && rule.style.cssText)) { |
- cssText += this.scopeSelector(rule.selectorText, name, typeExtension, |
+ cssText += this.scopeSelector(rule.selectorText, name, typeExtension, |
this.strictStyling) + ' {\n\t'; |
cssText += this.propertiesFromRule(rule) + '\n}\n\n'; |
} else if (rule.media) { |
@@ -7293,7 +7293,7 @@ var ShadowCSS = { |
parts.forEach(function(p) { |
p = p.trim(); |
if (this.selectorNeedsScoping(p, name, typeExtension)) { |
- p = (strict && !p.match(polyfillHostNoCombinator)) ? |
+ p = (strict && !p.match(polyfillHostNoCombinator)) ? |
this.applyStrictSelectorScope(p, name) : |
this.applySimpleSelectorScope(p, name, typeExtension); |
} |
@@ -7346,7 +7346,7 @@ var ShadowCSS = { |
// TODO(sorvell): Safari cssom incorrectly removes quotes from the content |
// property. (https://bugs.webkit.org/show_bug.cgi?id=118045) |
if (rule.style.content && !rule.style.content.match(/['"]+/)) { |
- return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + |
+ return rule.style.cssText.replace(/content:[^;]*;/g, 'content: \'' + |
rule.style.content + '\';'); |
} |
return rule.style.cssText; |
@@ -7441,7 +7441,7 @@ if (window.ShadowDOMPolyfill) { |
// consider a better solution. |
document.addEventListener('DOMContentLoaded', function() { |
var urlResolver = scope.urlResolver; |
- |
+ |
if (window.HTMLImports && !HTMLImports.useNative) { |
var SHIM_SHEET_SELECTOR = 'link[rel=stylesheet]' + |
'[' + SHIM_ATTRIBUTE + ']'; |
@@ -7454,18 +7454,24 @@ if (window.ShadowDOMPolyfill) { |
SHIM_SHEET_SELECTOR, |
SHIM_STYLE_SELECTOR |
].join(','); |
+ |
+ var originalParseGeneric = HTMLImports.parser.parseGeneric; |
HTMLImports.parser.parseGeneric = function(elt) { |
if (elt[SHIMMED_ATTRIBUTE]) { |
return; |
} |
var style = elt.__importElement || elt; |
+ if (!style.hasAttribute(SHIM_ATTRIBUTE)) { |
+ originalParseGeneric.call(this, elt); |
+ return; |
+ } |
if (elt.__resource) { |
style = elt.ownerDocument.createElement('style'); |
style.textContent = urlResolver.resolveCssText( |
elt.__resource, elt.href); |
} else { |
- urlResolver.resolveStyles(style); |
+ urlResolver.resolveStyle(style); |
} |
var styles = [style]; |
style.textContent = ShadowCSS.stylesToShimmedCssText(styles, styles); |
@@ -7481,7 +7487,7 @@ if (window.ShadowDOMPolyfill) { |
head.appendChild(style); |
} |
} |
- style.__importParsed = true |
+ style.__importParsed = true; |
this.markParsingComplete(elt); |
} |
@@ -8293,7 +8299,7 @@ scope.mixin = mixin; |
var base = document.createElement('base'); |
base.href = document.baseURI; |
template.content.ownerDocument.appendChild(base); |
- |
+ |
// utility |
@@ -8334,7 +8340,7 @@ scope.mixin = mixin; |
if (window.Polymer === polymerStub) { |
window.Polymer = function() { |
console.error('You tried to use polymer without loading it first. To ' + |
- 'load polymer, <link rel="import" href="' + |
+ 'load polymer, <link rel="import" href="' + |
'components/polymer/polymer.html">'); |
}; |
} |
@@ -8356,9 +8362,9 @@ window.templateContent = window.templateContent || function(inTemplate) { |
return inTemplate.content; |
}; |
(function(scope) { |
- |
+ |
scope = scope || (window.Inspector = {}); |
- |
+ |
var inspector; |
window.sinspect = function(inNode, inProxy) { |
@@ -8409,7 +8415,7 @@ window.templateContent = window.templateContent || function(inTemplate) { |
' </body>', |
'</html>' |
].join('\n'); |
- |
+ |
var crumbs = []; |
var displayCrumbs = function() { |
@@ -8537,11 +8543,11 @@ window.templateContent = window.templateContent || function(inTemplate) { |
console.dir(this); |
} |
}; |
- |
+ |
// export |
- |
+ |
scope.output = output; |
- |
+ |
})(window.Inspector); |
@@ -8553,20 +8559,20 @@ window.templateContent = window.templateContent || function(inTemplate) { |
*/ |
(function(scope) { |
- // TODO(sorvell): It's desireable to provide a default stylesheet |
+ // TODO(sorvell): It's desireable to provide a default stylesheet |
// that's convenient for styling unresolved elements, but |
// it's cumbersome to have to include this manually in every page. |
- // It would make sense to put inside some HTMLImport but |
- // the HTMLImports polyfill does not allow loading of stylesheets |
+ // It would make sense to put inside some HTMLImport but |
+ // the HTMLImports polyfill does not allow loading of stylesheets |
// that block rendering. Therefore this injection is tolerated here. |
var style = document.createElement('style'); |
style.textContent = '' |
+ 'body {' |
- + 'transition: opacity ease-in 0.2s;' |
+ + 'transition: opacity ease-in 0.2s;' |
+ ' } \n' |
+ 'body[unresolved] {' |
- + 'opacity: 0; display: block; overflow: hidden;' |
+ + 'opacity: 0; display: block; overflow: hidden;' |
+ ' } \n' |
; |
var head = document.querySelector('head'); |
@@ -9483,7 +9489,7 @@ var IMPORT_LINK_TYPE = 'import'; |
var flags = scope.flags; |
var isIe = /Trident/.test(navigator.userAgent); |
// TODO(sorvell): SD polyfill intrusion |
-var mainDoc = window.ShadowDOMPolyfill ? |
+var mainDoc = window.ShadowDOMPolyfill ? |
window.ShadowDOMPolyfill.wrapIfNeeded(document) : document; |
// importParser |
@@ -9554,7 +9560,7 @@ var importParser = { |
} |
// fire load event |
if (elt.__resource) { |
- elt.dispatchEvent(new CustomEvent('load', {bubbles: false})); |
+ elt.dispatchEvent(new CustomEvent('load', {bubbles: false})); |
} else { |
elt.dispatchEvent(new CustomEvent('error', {bubbles: false})); |
} |
@@ -9636,7 +9642,7 @@ var importParser = { |
moniker = scriptElt.ownerDocument.baseURI; |
// there could be more than one script this url |
var tag = '[' + Math.floor((Math.random()+1)*1000) + ']'; |
- // TODO(sjmiles): Polymer hack, should be pluggable if we need to allow |
+ // TODO(sjmiles): Polymer hack, should be pluggable if we need to allow |
// this sort of thing |
var matches = code.match(/Polymer\(['"]([^'"]*)/); |
tag = matches && matches[1] || tag; |
@@ -9704,7 +9710,7 @@ function cloneStyle(style) { |
return clone; |
} |
-// path fixup: style elements in imports must be made relative to the main |
+// path fixup: style elements in imports must be made relative to the main |
// document. We fixup url's in url() and @import. |
var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g; |
var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g; |
@@ -9714,7 +9720,7 @@ var path = { |
var doc = style.ownerDocument; |
var resolver = doc.createElement('a'); |
style.textContent = this.resolveUrlsInCssText(style.textContent, resolver); |
- return style; |
+ return style; |
}, |
resolveUrlsInCssText: function(cssText, urlObj) { |
var r = this.replaceUrls(cssText, urlObj, CSS_URL_REGEXP); |
@@ -9727,7 +9733,7 @@ var path = { |
urlObj.href = urlPath; |
urlPath = urlObj.href; |
return pre + '\'' + urlPath + '\'' + post; |
- }); |
+ }); |
} |
} |
@@ -9752,7 +9758,7 @@ var flags = scope.flags; |
var IMPORT_LINK_TYPE = 'import'; |
// TODO(sorvell): SD polyfill intrusion |
-var mainDoc = window.ShadowDOMPolyfill ? |
+var mainDoc = window.ShadowDOMPolyfill ? |
ShadowDOMPolyfill.wrapIfNeeded(document) : document; |
if (!useNative) { |
@@ -9835,7 +9841,7 @@ if (!useNative) { |
}; |
// loader singleton |
- var importLoader = new Loader(importer.loaded.bind(importer), |
+ var importLoader = new Loader(importer.loaded.bind(importer), |
importer.loadedAll.bind(importer)); |
function isDocumentLink(elt) { |
@@ -9916,7 +9922,7 @@ if (!document.baseURI) { |
// call a callback when all HTMLImports in the document at call (or at least |
// document ready) time have loaded. |
-// 1. ensure the document is in a ready state (has dom), then |
+// 1. ensure the document is in a ready state (has dom), then |
// 2. watch for loading of imports and call callback when done |
function whenImportsReady(callback, doc) { |
doc = doc || mainDoc; |
@@ -9938,7 +9944,7 @@ function isDocumentReady(doc) { |
function whenDocumentReady(callback, doc) { |
if (!isDocumentReady(doc)) { |
var checkReady = function() { |
- if (doc.readyState === 'complete' || |
+ if (doc.readyState === 'complete' || |
doc.readyState === requiredReadyState) { |
doc.removeEventListener(READY_EVENT, checkReady); |
whenDocumentReady(callback, doc); |
@@ -9954,7 +9960,7 @@ function whenDocumentReady(callback, doc) { |
function watchImportsLoad(callback, doc) { |
var imports = doc.querySelectorAll('link[rel=import]'); |
var loaded = 0, l = imports.length; |
- function checkDone(d) { |
+ function checkDone(d) { |
if (loaded == l) { |
// go async to ensure parser isn't stuck on a script tag |
requestAnimationFrame(callback); |
@@ -10033,8 +10039,8 @@ function shouldLoadNode(node) { |
} |
// x-plat matches |
-var matches = HTMLElement.prototype.matches || |
- HTMLElement.prototype.matchesSelector || |
+var matches = HTMLElement.prototype.matches || |
+ HTMLElement.prototype.matchesSelector || |
HTMLElement.prototype.webkitMatchesSelector || |
HTMLElement.prototype.mozMatchesSelector || |
HTMLElement.prototype.msMatchesSelector; |
@@ -10075,11 +10081,11 @@ if (typeof window.CustomEvent !== 'function') { |
} |
// TODO(sorvell): SD polyfill intrusion |
-var doc = window.ShadowDOMPolyfill ? |
+var doc = window.ShadowDOMPolyfill ? |
window.ShadowDOMPolyfill.wrapIfNeeded(document) : document; |
-// Fire the 'HTMLImportsLoaded' event when imports in document at load time |
-// have loaded. This event is required to simulate the script blocking |
+// Fire the 'HTMLImportsLoaded' event when imports in document at load time |
+// have loaded. This event is required to simulate the script blocking |
// behavior of native imports. A main document script that needs to be sure |
// imports have loaded should wait for this event. |
HTMLImports.whenImportsReady(function() { |
@@ -10096,9 +10102,9 @@ if (!HTMLImports.useNative) { |
function bootstrap() { |
HTMLImports.importer.bootDocument(doc); |
} |
- |
+ |
// TODO(sorvell): SD polyfill does *not* generate mutations for nodes added |
- // by the parser. For this reason, we must wait until the dom exists to |
+ // by the parser. For this reason, we must wait until the dom exists to |
// bootstrap. |
if (document.readyState === 'complete' || |
(document.readyState === 'interactive' && !window.attachEvent)) { |
@@ -10116,350 +10122,350 @@ if (!HTMLImports.useNative) { |
* license that can be found in the LICENSE file. |
*/ |
window.CustomElements = window.CustomElements || {flags:{}}; |
- /* |
-Copyright 2013 The Polymer Authors. All rights reserved. |
-Use of this source code is governed by a BSD-style |
-license that can be found in the LICENSE file. |
-*/ |
- |
-(function(scope){ |
- |
-var logFlags = window.logFlags || {}; |
-var IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : 'none'; |
- |
-// walk the subtree rooted at node, applying 'find(element, data)' function |
-// to each element |
-// if 'find' returns true for 'element', do not search element's subtree |
-function findAll(node, find, data) { |
- var e = node.firstElementChild; |
- if (!e) { |
- e = node.firstChild; |
- while (e && e.nodeType !== Node.ELEMENT_NODE) { |
- e = e.nextSibling; |
- } |
- } |
- while (e) { |
- if (find(e, data) !== true) { |
- findAll(e, find, data); |
- } |
- e = e.nextElementSibling; |
- } |
- return null; |
-} |
- |
-// walk all shadowRoots on a given node. |
-function forRoots(node, cb) { |
- var root = node.shadowRoot; |
- while(root) { |
- forSubtree(root, cb); |
- root = root.olderShadowRoot; |
- } |
-} |
- |
-// walk the subtree rooted at node, including descent into shadow-roots, |
-// applying 'cb' to each element |
-function forSubtree(node, cb) { |
- //logFlags.dom && node.childNodes && node.childNodes.length && console.group('subTree: ', node); |
- findAll(node, function(e) { |
- if (cb(e)) { |
- return true; |
- } |
- forRoots(e, cb); |
- }); |
- forRoots(node, cb); |
- //logFlags.dom && node.childNodes && node.childNodes.length && console.groupEnd(); |
-} |
- |
-// manage lifecycle on added node |
-function added(node) { |
- if (upgrade(node)) { |
- insertedNode(node); |
- return true; |
- } |
- inserted(node); |
-} |
- |
-// manage lifecycle on added node's subtree only |
-function addedSubtree(node) { |
- forSubtree(node, function(e) { |
- if (added(e)) { |
- return true; |
- } |
- }); |
-} |
- |
-// manage lifecycle on added node and it's subtree |
-function addedNode(node) { |
- return added(node) || addedSubtree(node); |
-} |
- |
-// upgrade custom elements at node, if applicable |
-function upgrade(node) { |
- if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) { |
- var type = node.getAttribute('is') || node.localName; |
- var definition = scope.registry[type]; |
- if (definition) { |
- logFlags.dom && console.group('upgrade:', node.localName); |
- scope.upgrade(node); |
- logFlags.dom && console.groupEnd(); |
- return true; |
- } |
- } |
-} |
- |
-function insertedNode(node) { |
- inserted(node); |
- if (inDocument(node)) { |
- forSubtree(node, function(e) { |
- inserted(e); |
- }); |
- } |
-} |
- |
- |
-// TODO(sorvell): on platforms without MutationObserver, mutations may not be |
-// reliable and therefore attached/detached are not reliable. |
-// To make these callbacks less likely to fail, we defer all inserts and removes |
-// to give a chance for elements to be inserted into dom. |
-// This ensures attachedCallback fires for elements that are created and |
-// immediately added to dom. |
-var hasPolyfillMutations = (!window.MutationObserver || |
- (window.MutationObserver === window.JsMutationObserver)); |
-scope.hasPolyfillMutations = hasPolyfillMutations; |
- |
-var isPendingMutations = false; |
-var pendingMutations = []; |
-function deferMutation(fn) { |
- pendingMutations.push(fn); |
- if (!isPendingMutations) { |
- isPendingMutations = true; |
- var async = (window.Platform && window.Platform.endOfMicrotask) || |
- setTimeout; |
- async(takeMutations); |
- } |
-} |
- |
-function takeMutations() { |
- isPendingMutations = false; |
- var $p = pendingMutations; |
- for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) { |
- p(); |
- } |
- pendingMutations = []; |
-} |
- |
-function inserted(element) { |
- if (hasPolyfillMutations) { |
- deferMutation(function() { |
- _inserted(element); |
- }); |
- } else { |
- _inserted(element); |
- } |
-} |
- |
-// TODO(sjmiles): if there are descents into trees that can never have inDocument(*) true, fix this |
-function _inserted(element) { |
- // TODO(sjmiles): it's possible we were inserted and removed in the space |
- // of one microtask, in which case we won't be 'inDocument' here |
- // But there are other cases where we are testing for inserted without |
- // specific knowledge of mutations, and must test 'inDocument' to determine |
- // whether to call inserted |
- // If we can factor these cases into separate code paths we can have |
- // better diagnostics. |
- // TODO(sjmiles): when logging, do work on all custom elements so we can |
- // track behavior even when callbacks not defined |
- //console.log('inserted: ', element.localName); |
- if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) { |
- logFlags.dom && console.group('inserted:', element.localName); |
- if (inDocument(element)) { |
- element.__inserted = (element.__inserted || 0) + 1; |
- // if we are in a 'removed' state, bluntly adjust to an 'inserted' state |
- if (element.__inserted < 1) { |
- element.__inserted = 1; |
- } |
- // if we are 'over inserted', squelch the callback |
- if (element.__inserted > 1) { |
- logFlags.dom && console.warn('inserted:', element.localName, |
- 'insert/remove count:', element.__inserted) |
- } else if (element.attachedCallback) { |
- logFlags.dom && console.log('inserted:', element.localName); |
- element.attachedCallback(); |
- } |
- } |
- logFlags.dom && console.groupEnd(); |
- } |
-} |
- |
-function removedNode(node) { |
- removed(node); |
- forSubtree(node, function(e) { |
- removed(e); |
- }); |
-} |
- |
-function removed(element) { |
- if (hasPolyfillMutations) { |
- deferMutation(function() { |
- _removed(element); |
- }); |
- } else { |
- _removed(element); |
- } |
-} |
- |
-function _removed(element) { |
- // TODO(sjmiles): temporary: do work on all custom elements so we can track |
- // behavior even when callbacks not defined |
- if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) { |
- logFlags.dom && console.group('removed:', element.localName); |
- if (!inDocument(element)) { |
- element.__inserted = (element.__inserted || 0) - 1; |
- // if we are in a 'inserted' state, bluntly adjust to an 'removed' state |
- if (element.__inserted > 0) { |
- element.__inserted = 0; |
- } |
- // if we are 'over removed', squelch the callback |
- if (element.__inserted < 0) { |
- logFlags.dom && console.warn('removed:', element.localName, |
- 'insert/remove count:', element.__inserted) |
- } else if (element.detachedCallback) { |
- element.detachedCallback(); |
- } |
- } |
- logFlags.dom && console.groupEnd(); |
- } |
-} |
- |
-// SD polyfill intrustion due mainly to the fact that 'document' |
-// is not entirely wrapped |
-function wrapIfNeeded(node) { |
- return window.ShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node) |
- : node; |
-} |
- |
-function inDocument(element) { |
- var p = element; |
- var doc = wrapIfNeeded(document); |
- while (p) { |
- if (p == doc) { |
- return true; |
- } |
- p = p.parentNode || p.host; |
- } |
-} |
- |
-function watchShadow(node) { |
- if (node.shadowRoot && !node.shadowRoot.__watched) { |
- logFlags.dom && console.log('watching shadow-root for: ', node.localName); |
- // watch all unwatched roots... |
- var root = node.shadowRoot; |
- while (root) { |
- watchRoot(root); |
- root = root.olderShadowRoot; |
- } |
- } |
-} |
- |
-function watchRoot(root) { |
- if (!root.__watched) { |
- observe(root); |
- root.__watched = true; |
- } |
-} |
- |
-function handler(mutations) { |
- // |
- if (logFlags.dom) { |
- var mx = mutations[0]; |
- if (mx && mx.type === 'childList' && mx.addedNodes) { |
- if (mx.addedNodes) { |
- var d = mx.addedNodes[0]; |
- while (d && d !== document && !d.host) { |
- d = d.parentNode; |
- } |
- var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || ''; |
- u = u.split('/?').shift().split('/').pop(); |
- } |
- } |
- console.group('mutations (%d) [%s]', mutations.length, u || ''); |
- } |
- // |
- mutations.forEach(function(mx) { |
- //logFlags.dom && console.group('mutation'); |
- if (mx.type === 'childList') { |
- forEach(mx.addedNodes, function(n) { |
- //logFlags.dom && console.log(n.localName); |
- if (!n.localName) { |
- return; |
- } |
- // nodes added may need lifecycle management |
- addedNode(n); |
- }); |
- // removed nodes may need lifecycle management |
- forEach(mx.removedNodes, function(n) { |
- //logFlags.dom && console.log(n.localName); |
- if (!n.localName) { |
- return; |
- } |
- removedNode(n); |
- }); |
- } |
- //logFlags.dom && console.groupEnd(); |
- }); |
- logFlags.dom && console.groupEnd(); |
-}; |
- |
-var observer = new MutationObserver(handler); |
- |
-function takeRecords() { |
- // TODO(sjmiles): ask Raf why we have to call handler ourselves |
- handler(observer.takeRecords()); |
- takeMutations(); |
-} |
- |
-var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); |
- |
-function observe(inRoot) { |
- observer.observe(inRoot, {childList: true, subtree: true}); |
-} |
- |
-function observeDocument(doc) { |
- observe(doc); |
-} |
- |
-function upgradeDocument(doc) { |
- logFlags.dom && console.group('upgradeDocument: ', (doc.baseURI).split('/').pop()); |
- addedNode(doc); |
- logFlags.dom && console.groupEnd(); |
-} |
- |
-function upgradeDocumentTree(doc) { |
- doc = wrapIfNeeded(doc); |
- upgradeDocument(doc); |
- //console.log('upgradeDocumentTree: ', (doc.baseURI).split('/').pop()); |
- // upgrade contained imported documents |
- var imports = doc.querySelectorAll('link[rel=' + IMPORT_LINK_TYPE + ']'); |
- for (var i=0, l=imports.length, n; (i<l) && (n=imports[i]); i++) { |
- if (n.import && n.import.__parsed) { |
- upgradeDocumentTree(n.import); |
- } |
- } |
-} |
- |
-// exports |
-scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE; |
-scope.watchShadow = watchShadow; |
-scope.upgradeDocumentTree = upgradeDocumentTree; |
-scope.upgradeAll = addedNode; |
-scope.upgradeSubtree = addedSubtree; |
- |
-scope.observeDocument = observeDocument; |
-scope.upgradeDocument = upgradeDocument; |
- |
-scope.takeRecords = takeRecords; |
- |
-})(window.CustomElements); |
+ /* |
+Copyright 2013 The Polymer Authors. All rights reserved. |
+Use of this source code is governed by a BSD-style |
+license that can be found in the LICENSE file. |
+*/ |
+ |
+(function(scope){ |
+ |
+var logFlags = window.logFlags || {}; |
+var IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : 'none'; |
+ |
+// walk the subtree rooted at node, applying 'find(element, data)' function |
+// to each element |
+// if 'find' returns true for 'element', do not search element's subtree |
+function findAll(node, find, data) { |
+ var e = node.firstElementChild; |
+ if (!e) { |
+ e = node.firstChild; |
+ while (e && e.nodeType !== Node.ELEMENT_NODE) { |
+ e = e.nextSibling; |
+ } |
+ } |
+ while (e) { |
+ if (find(e, data) !== true) { |
+ findAll(e, find, data); |
+ } |
+ e = e.nextElementSibling; |
+ } |
+ return null; |
+} |
+ |
+// walk all shadowRoots on a given node. |
+function forRoots(node, cb) { |
+ var root = node.shadowRoot; |
+ while(root) { |
+ forSubtree(root, cb); |
+ root = root.olderShadowRoot; |
+ } |
+} |
+ |
+// walk the subtree rooted at node, including descent into shadow-roots, |
+// applying 'cb' to each element |
+function forSubtree(node, cb) { |
+ //logFlags.dom && node.childNodes && node.childNodes.length && console.group('subTree: ', node); |
+ findAll(node, function(e) { |
+ if (cb(e)) { |
+ return true; |
+ } |
+ forRoots(e, cb); |
+ }); |
+ forRoots(node, cb); |
+ //logFlags.dom && node.childNodes && node.childNodes.length && console.groupEnd(); |
+} |
+ |
+// manage lifecycle on added node |
+function added(node) { |
+ if (upgrade(node)) { |
+ insertedNode(node); |
+ return true; |
+ } |
+ inserted(node); |
+} |
+ |
+// manage lifecycle on added node's subtree only |
+function addedSubtree(node) { |
+ forSubtree(node, function(e) { |
+ if (added(e)) { |
+ return true; |
+ } |
+ }); |
+} |
+ |
+// manage lifecycle on added node and it's subtree |
+function addedNode(node) { |
+ return added(node) || addedSubtree(node); |
+} |
+ |
+// upgrade custom elements at node, if applicable |
+function upgrade(node) { |
+ if (!node.__upgraded__ && node.nodeType === Node.ELEMENT_NODE) { |
+ var type = node.getAttribute('is') || node.localName; |
+ var definition = scope.registry[type]; |
+ if (definition) { |
+ logFlags.dom && console.group('upgrade:', node.localName); |
+ scope.upgrade(node); |
+ logFlags.dom && console.groupEnd(); |
+ return true; |
+ } |
+ } |
+} |
+ |
+function insertedNode(node) { |
+ inserted(node); |
+ if (inDocument(node)) { |
+ forSubtree(node, function(e) { |
+ inserted(e); |
+ }); |
+ } |
+} |
+ |
+// TODO(sorvell): on platforms without MutationObserver, mutations may not be |
+// reliable and therefore attached/detached are not reliable. |
+// To make these callbacks less likely to fail, we defer all inserts and removes |
+// to give a chance for elements to be inserted into dom. |
+// This ensures attachedCallback fires for elements that are created and |
+// immediately added to dom. |
+var hasPolyfillMutations = (!window.MutationObserver || |
+ (window.MutationObserver === window.JsMutationObserver)); |
+scope.hasPolyfillMutations = hasPolyfillMutations; |
+ |
+var isPendingMutations = false; |
+var pendingMutations = []; |
+function deferMutation(fn) { |
+ pendingMutations.push(fn); |
+ if (!isPendingMutations) { |
+ isPendingMutations = true; |
+ var async = (window.Platform && window.Platform.endOfMicrotask) || |
+ setTimeout; |
+ async(takeMutations); |
+ } |
+} |
+ |
+function takeMutations() { |
+ isPendingMutations = false; |
+ var $p = pendingMutations; |
+ for (var i=0, l=$p.length, p; (i<l) && (p=$p[i]); i++) { |
+ p(); |
+ } |
+ pendingMutations = []; |
+} |
+ |
+function inserted(element) { |
+ if (hasPolyfillMutations) { |
+ deferMutation(function() { |
+ _inserted(element); |
+ }); |
+ } else { |
+ _inserted(element); |
+ } |
+} |
+ |
+// TODO(sjmiles): if there are descents into trees that can never have inDocument(*) true, fix this |
+function _inserted(element) { |
+ // TODO(sjmiles): it's possible we were inserted and removed in the space |
+ // of one microtask, in which case we won't be 'inDocument' here |
+ // But there are other cases where we are testing for inserted without |
+ // specific knowledge of mutations, and must test 'inDocument' to determine |
+ // whether to call inserted |
+ // If we can factor these cases into separate code paths we can have |
+ // better diagnostics. |
+ // TODO(sjmiles): when logging, do work on all custom elements so we can |
+ // track behavior even when callbacks not defined |
+ //console.log('inserted: ', element.localName); |
+ if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) { |
+ logFlags.dom && console.group('inserted:', element.localName); |
+ if (inDocument(element)) { |
+ element.__inserted = (element.__inserted || 0) + 1; |
+ // if we are in a 'removed' state, bluntly adjust to an 'inserted' state |
+ if (element.__inserted < 1) { |
+ element.__inserted = 1; |
+ } |
+ // if we are 'over inserted', squelch the callback |
+ if (element.__inserted > 1) { |
+ logFlags.dom && console.warn('inserted:', element.localName, |
+ 'insert/remove count:', element.__inserted) |
+ } else if (element.attachedCallback) { |
+ logFlags.dom && console.log('inserted:', element.localName); |
+ element.attachedCallback(); |
+ } |
+ } |
+ logFlags.dom && console.groupEnd(); |
+ } |
+} |
+ |
+function removedNode(node) { |
+ removed(node); |
+ forSubtree(node, function(e) { |
+ removed(e); |
+ }); |
+} |
+ |
+function removed(element) { |
+ if (hasPolyfillMutations) { |
+ deferMutation(function() { |
+ _removed(element); |
+ }); |
+ } else { |
+ _removed(element); |
+ } |
+} |
+ |
+function _removed(element) { |
+ // TODO(sjmiles): temporary: do work on all custom elements so we can track |
+ // behavior even when callbacks not defined |
+ if (element.attachedCallback || element.detachedCallback || (element.__upgraded__ && logFlags.dom)) { |
+ logFlags.dom && console.group('removed:', element.localName); |
+ if (!inDocument(element)) { |
+ element.__inserted = (element.__inserted || 0) - 1; |
+ // if we are in a 'inserted' state, bluntly adjust to an 'removed' state |
+ if (element.__inserted > 0) { |
+ element.__inserted = 0; |
+ } |
+ // if we are 'over removed', squelch the callback |
+ if (element.__inserted < 0) { |
+ logFlags.dom && console.warn('removed:', element.localName, |
+ 'insert/remove count:', element.__inserted) |
+ } else if (element.detachedCallback) { |
+ element.detachedCallback(); |
+ } |
+ } |
+ logFlags.dom && console.groupEnd(); |
+ } |
+} |
+ |
+// SD polyfill intrustion due mainly to the fact that 'document' |
+// is not entirely wrapped |
+function wrapIfNeeded(node) { |
+ return window.ShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node) |
+ : node; |
+} |
+ |
+function inDocument(element) { |
+ var p = element; |
+ var doc = wrapIfNeeded(document); |
+ while (p) { |
+ if (p == doc) { |
+ return true; |
+ } |
+ p = p.parentNode || p.host; |
+ } |
+} |
+ |
+function watchShadow(node) { |
+ if (node.shadowRoot && !node.shadowRoot.__watched) { |
+ logFlags.dom && console.log('watching shadow-root for: ', node.localName); |
+ // watch all unwatched roots... |
+ var root = node.shadowRoot; |
+ while (root) { |
+ watchRoot(root); |
+ root = root.olderShadowRoot; |
+ } |
+ } |
+} |
+ |
+function watchRoot(root) { |
+ if (!root.__watched) { |
+ observe(root); |
+ root.__watched = true; |
+ } |
+} |
+ |
+function handler(mutations) { |
+ // |
+ if (logFlags.dom) { |
+ var mx = mutations[0]; |
+ if (mx && mx.type === 'childList' && mx.addedNodes) { |
+ if (mx.addedNodes) { |
+ var d = mx.addedNodes[0]; |
+ while (d && d !== document && !d.host) { |
+ d = d.parentNode; |
+ } |
+ var u = d && (d.URL || d._URL || (d.host && d.host.localName)) || ''; |
+ u = u.split('/?').shift().split('/').pop(); |
+ } |
+ } |
+ console.group('mutations (%d) [%s]', mutations.length, u || ''); |
+ } |
+ // |
+ mutations.forEach(function(mx) { |
+ //logFlags.dom && console.group('mutation'); |
+ if (mx.type === 'childList') { |
+ forEach(mx.addedNodes, function(n) { |
+ //logFlags.dom && console.log(n.localName); |
+ if (!n.localName) { |
+ return; |
+ } |
+ // nodes added may need lifecycle management |
+ addedNode(n); |
+ }); |
+ // removed nodes may need lifecycle management |
+ forEach(mx.removedNodes, function(n) { |
+ //logFlags.dom && console.log(n.localName); |
+ if (!n.localName) { |
+ return; |
+ } |
+ removedNode(n); |
+ }); |
+ } |
+ //logFlags.dom && console.groupEnd(); |
+ }); |
+ logFlags.dom && console.groupEnd(); |
+}; |
+ |
+var observer = new MutationObserver(handler); |
+ |
+function takeRecords() { |
+ // TODO(sjmiles): ask Raf why we have to call handler ourselves |
+ handler(observer.takeRecords()); |
+ takeMutations(); |
+} |
+ |
+var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); |
+ |
+function observe(inRoot) { |
+ observer.observe(inRoot, {childList: true, subtree: true}); |
+} |
+ |
+function observeDocument(doc) { |
+ observe(doc); |
+} |
+ |
+function upgradeDocument(doc) { |
+ logFlags.dom && console.group('upgradeDocument: ', (doc.baseURI).split('/').pop()); |
+ addedNode(doc); |
+ logFlags.dom && console.groupEnd(); |
+} |
+ |
+function upgradeDocumentTree(doc) { |
+ doc = wrapIfNeeded(doc); |
+ upgradeDocument(doc); |
+ //console.log('upgradeDocumentTree: ', (doc.baseURI).split('/').pop()); |
+ // upgrade contained imported documents |
+ var imports = doc.querySelectorAll('link[rel=' + IMPORT_LINK_TYPE + ']'); |
+ for (var i=0, l=imports.length, n; (i<l) && (n=imports[i]); i++) { |
+ if (n.import && n.import.__parsed) { |
+ upgradeDocumentTree(n.import); |
+ } |
+ } |
+} |
+ |
+// exports |
+scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE; |
+scope.watchShadow = watchShadow; |
+scope.upgradeDocumentTree = upgradeDocumentTree; |
+scope.upgradeAll = addedNode; |
+scope.upgradeSubtree = addedSubtree; |
+scope.insertedNode = insertedNode; |
+ |
+scope.observeDocument = observeDocument; |
+scope.upgradeDocument = upgradeDocument; |
+ |
+scope.takeRecords = takeRecords; |
+ |
+})(window.CustomElements); |
/* |
* Copyright 2013 The Polymer Authors. All rights reserved. |
@@ -10689,8 +10695,9 @@ if (useNative) { |
element.__upgraded__ = true; |
// lifecycle management |
created(element); |
+ // attachedCallback fires in tree order, call before recursing |
+ scope.insertedNode(element); |
// there should never be a shadow root on element at this point |
- // we require child nodes be upgraded before `created` |
scope.upgradeSubtree(element); |
// OUTPUT |
return element; |
@@ -10783,9 +10790,6 @@ if (useNative) { |
} |
function registerDefinition(name, definition) { |
- if (registry[name]) { |
- throw new Error('a type with that name is already registered.'); |
- } |
registry[name] = definition; |
} |
@@ -10960,11 +10964,11 @@ function bootstrap() { |
// one more pass before register is 'live' |
CustomElements.upgradeDocument(document); |
// choose async |
- var async = window.Platform && Platform.endOfMicrotask ? |
+ var async = window.Platform && Platform.endOfMicrotask ? |
Platform.endOfMicrotask : |
setTimeout; |
async(function() { |
- // set internal 'ready' flag, now document.registerElement will trigger |
+ // set internal 'ready' flag, now document.registerElement will trigger |
// synchronous upgrades |
CustomElements.ready = true; |
// capture blunt profiling data |
@@ -11005,7 +11009,7 @@ if (document.readyState === 'complete' || scope.flags.eager) { |
} else if (document.readyState === 'interactive' && !window.attachEvent && |
(!window.HTMLImports || window.HTMLImports.ready)) { |
bootstrap(); |
-// When loading at other readyStates, wait for the appropriate DOM event to |
+// When loading at other readyStates, wait for the appropriate DOM event to |
// bootstrap. |
} else { |
var loadEvent = window.HTMLImports && !HTMLImports.ready ? |
@@ -11110,8 +11114,8 @@ function createStyleElement(cssText, scope) { |
} |
// TODO(sorvell): use a common loader shared with HTMLImports polyfill |
-// currently, this just loads the first @import per style element |
-// and does not recurse into loaded elements; we'll address this with a |
+// currently, this just loads the first @import per style element |
+// and does not recurse into loaded elements; we'll address this with a |
// generalized loader that's built out of the one in the HTMLImports polyfill. |
// polyfill the loading of a style element's @import via xhr |
function xhrLoadStyle(style, callback) { |
@@ -12078,7 +12082,7 @@ scope.loader = loader; |
// handler registration mechanism. Rather than try to predict how exactly to opt-in to |
// that we'll just leave this disabled until there is a build of Chrome to test. |
var HAS_TOUCH_ACTION_DELAY = false; |
- |
+ |
// handler block for native touch events |
var touchEvents = { |
scrollType: new WeakMap(), |
@@ -14390,6 +14394,15 @@ PointerGestureEvent.prototype.preventTap = function() { |
} |
} |
+ var templateObserver; |
+ if (typeof MutationObserver == 'function') { |
+ templateObserver = new MutationObserver(function(records) { |
+ for (var i = 0; i < records.length; i++) { |
+ records[i].target.refChanged_(); |
+ } |
+ }); |
+ } |
+ |
/** |
* Ensures proper API and content model for template elements. |
* @param {HTMLTemplateElement} opt_instanceRef The template element which |
@@ -14493,6 +14506,25 @@ PointerGestureEvent.prototype.preventTap = function() { |
} |
mixin(HTMLTemplateElement.prototype, { |
+ bind: function(name, value, oneTime) { |
+ if (name != 'ref') |
+ return Element.prototype.bind.call(this, name, value, oneTime); |
+ |
+ var self = this; |
+ var ref = oneTime ? value : value.open(function(ref) { |
+ self.setAttribute('ref', ref); |
+ self.refChanged_(); |
+ }); |
+ |
+ this.setAttribute('ref', ref); |
+ this.refChanged_(); |
+ if (oneTime) |
+ return; |
+ |
+ this.unbind('ref'); |
+ return this.bindings.ref = value; |
+ }, |
+ |
processBindingDirectives_: function(directives) { |
if (this.iterator_) |
this.iterator_.closeDeps(); |
@@ -14514,6 +14546,12 @@ PointerGestureEvent.prototype.preventTap = function() { |
} |
this.iterator_.updateDependencies(directives, this.model_); |
+ |
+ if (templateObserver) { |
+ templateObserver.observe(this, { attributes: true, |
+ attributeFilter: ['ref'] }); |
+ } |
+ |
return this.iterator_; |
}, |
@@ -14522,7 +14560,9 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (bindingDelegate) |
delegate_ = this.newDelegate_(bindingDelegate); |
- var content = this.ref.content; |
+ if (!this.refContent_) |
+ this.refContent_ = this.ref_.content; |
+ var content = this.refContent_; |
var map = this.bindingMap_; |
if (!map || map.content !== content) { |
// TODO(rafaelw): Setup a MutationObserver on content to detect |
@@ -14574,6 +14614,27 @@ PointerGestureEvent.prototype.preventTap = function() { |
return this.delegate_ && this.delegate_.raw; |
}, |
+ refChanged_: function() { |
+ if (!this.iterator_ || this.refContent_ === this.ref_.content) |
+ return; |
+ |
+ this.refContent_ = undefined; |
+ this.iterator_.valueChanged(); |
+ this.iterator_.updateIteratedValue(); |
+ }, |
+ |
+ clear: function() { |
+ this.model_ = undefined; |
+ this.delegate_ = undefined; |
+ this.bindings_ = undefined; |
+ this.refContent_ = undefined; |
+ if (!this.iterator_) |
+ return; |
+ this.iterator_.valueChanged(); |
+ this.iterator_.close() |
+ this.iterator_ = undefined; |
+ }, |
+ |
setDelegate_: function(delegate) { |
this.delegate_ = delegate; |
this.bindingMap_ = undefined; |
@@ -14610,10 +14671,15 @@ PointerGestureEvent.prototype.preventTap = function() { |
// make sense to issue a warning or even throw if the template is already |
// "activated", since this would be a strange thing to do. |
set bindingDelegate(bindingDelegate) { |
+ if (this.delegate_) { |
+ throw Error('Template must be cleared before a new bindingDelegate ' + |
+ 'can be assigned'); |
+ } |
+ |
this.setDelegate_(this.newDelegate_(bindingDelegate)); |
}, |
- get ref() { |
+ get ref_() { |
var ref = searchRefId(this, this.getAttribute('ref')); |
if (!ref) |
ref = this.instanceRef_; |
@@ -14621,7 +14687,7 @@ PointerGestureEvent.prototype.preventTap = function() { |
if (!ref) |
return this; |
- var nextRef = ref.ref; |
+ var nextRef = ref.ref_; |
return nextRef ? nextRef : ref; |
} |
}); |
@@ -16357,6 +16423,9 @@ PointerGestureEvent.prototype.preventTap = function() { |
}, |
setValue: function(model, newValue) { |
+ if (this.path.length == 1); |
+ model = findScope(model, this.path[0]); |
+ |
return this.path.setValueFrom(model, newValue); |
} |
}; |
@@ -16750,21 +16819,58 @@ PointerGestureEvent.prototype.preventTap = function() { |
mixedCaseEventTypes[e.toLowerCase()] = e; |
}); |
- function prepareEventBinding(path, name) { |
+ var parentScopeName = '@' + Math.random().toString(36).slice(2); |
+ |
+ // Single ident paths must bind directly to the appropriate scope object. |
+ // I.e. Pushed values in two-bindings need to be assigned to the actual model |
+ // object. |
+ function findScope(model, prop) { |
+ while (model[parentScopeName] && |
+ !Object.prototype.hasOwnProperty.call(model, prop)) { |
+ model = model[parentScopeName]; |
+ } |
+ |
+ return model; |
+ } |
+ |
+ function resolveEventReceiver(model, path, node) { |
+ if (path.length == 0) |
+ return undefined; |
+ |
+ if (path.length == 1) |
+ return findScope(model, path[0]); |
+ |
+ for (var i = 0; model != null && i < path.length - 1; i++) { |
+ model = model[path[i]]; |
+ } |
+ |
+ return model; |
+ } |
+ |
+ function prepareEventBinding(path, name, polymerExpressions) { |
var eventType = name.substring(3); |
eventType = mixedCaseEventTypes[eventType] || eventType; |
return function(model, node, oneTime) { |
- var fn = path.getValueFrom(model); |
- |
- function handler(e) { |
- if (!oneTime) |
- fn = path.getValueFrom(model); |
+ var fn, receiver, handler; |
+ if (typeof polymerExpressions.resolveEventHandler == 'function') { |
+ handler = function(e) { |
+ fn = fn || polymerExpressions.resolveEventHandler(model, path, node); |
+ fn(e, e.detail, e.currentTarget); |
+ |
+ if (Platform && typeof Platform.flush == 'function') |
+ Platform.flush(); |
+ }; |
+ } else { |
+ handler = function(e) { |
+ fn = fn || path.getValueFrom(model); |
+ receiver = receiver || resolveEventReceiver(model, path, node); |
- fn.apply(model, [e, e.detail, e.currentTarget]); |
+ fn.apply(receiver, [e, e.detail, e.currentTarget]); |
- if (Platform && typeof Platform.flush == 'function') |
- Platform.flush(); |
+ if (Platform && typeof Platform.flush == 'function') |
+ Platform.flush(); |
+ }; |
} |
node.addEventListener(eventType, handler); |
@@ -16819,18 +16925,29 @@ PointerGestureEvent.prototype.preventTap = function() { |
}, |
prepareBinding: function(pathString, name, node) { |
+ var path = Path.get(pathString); |
if (isEventHandler(name)) { |
- var path = Path.get(pathString); |
if (!path.valid) { |
console.error('on-* bindings must be simple path expressions'); |
return; |
} |
- return prepareEventBinding(path, name); |
+ return prepareEventBinding(path, name, this); |
} |
- if (Path.get(pathString).valid) |
+ if (path.valid) { |
+ if (path.length == 1) { |
+ return function(model, node, oneTime) { |
+ if (oneTime) |
+ return path.getValueFrom(model); |
+ |
+ var scope = findScope(model, path[0]); |
+ return new PathObserver(scope, path); |
+ } |
+ } |
+ |
return; // bail out early if pathString is simple path. |
+ } |
return prepareBinding(pathString, name, node, this); |
}, |
@@ -16844,9 +16961,13 @@ PointerGestureEvent.prototype.preventTap = function() { |
template.templateInstance.model : |
template.model; |
+ var indexName = template.polymerExpressionIndexIdent_; |
+ |
return function(model) { |
var scope = Object.create(parentScope); |
scope[scopeName] = model; |
+ scope[indexName] = undefined; |
+ scope[parentScopeName] = parentScope; |
return scope; |
}; |
} |