Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(315)

Side by Side Diff: pkg/web_components/lib/platform.concat.js

Issue 558673004: update polymer js to 0.4.0 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: review updates Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/web_components/lib/platform.js ('k') | pkg/web_components/lib/platform.concat.js.map » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /** 1 /**
2 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 2 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
3 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 3 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
4 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 4 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
5 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 5 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
6 * Code distributed by Google as part of the polymer project is also 6 * Code distributed by Google as part of the polymer project is also
7 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 7 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
8 */ 8 */
9 9
10 window.Platform = window.Platform || {}; 10 window.Platform = window.Platform || {};
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 var entry = key[this.name]; 105 var entry = key[this.name];
106 if (!entry) return false; 106 if (!entry) return false;
107 return entry[0] === key; 107 return entry[0] === key;
108 } 108 }
109 }; 109 };
110 110
111 window.WeakMap = WeakMap; 111 window.WeakMap = WeakMap;
112 })(); 112 })();
113 } 113 }
114 114
115 // select ShadowDOM impl
116 if (Platform.flags.shadow) {
117
115 // Copyright 2012 Google Inc. 118 // Copyright 2012 Google Inc.
116 // 119 //
117 // Licensed under the Apache License, Version 2.0 (the "License"); 120 // Licensed under the Apache License, Version 2.0 (the "License");
118 // you may not use this file except in compliance with the License. 121 // you may not use this file except in compliance with the License.
119 // You may obtain a copy of the License at 122 // You may obtain a copy of the License at
120 // 123 //
121 // http://www.apache.org/licenses/LICENSE-2.0 124 // http://www.apache.org/licenses/LICENSE-2.0
122 // 125 //
123 // Unless required by applicable law or agreed to in writing, software 126 // Unless required by applicable law or agreed to in writing, software
124 // distributed under the License is distributed on an "AS IS" BASIS, 127 // distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 1708 matching lines...) Expand 10 before | Expand all | Expand 10 after
1833 }; 1836 };
1834 1837
1835 global.ArraySplice = ArraySplice; 1838 global.ArraySplice = ArraySplice;
1836 global.ObjectObserver = ObjectObserver; 1839 global.ObjectObserver = ObjectObserver;
1837 global.PathObserver = PathObserver; 1840 global.PathObserver = PathObserver;
1838 global.CompoundObserver = CompoundObserver; 1841 global.CompoundObserver = CompoundObserver;
1839 global.Path = Path; 1842 global.Path = Path;
1840 global.ObserverTransform = ObserverTransform; 1843 global.ObserverTransform = ObserverTransform;
1841 })(typeof global !== 'undefined' && global && typeof module !== 'undefined' && m odule ? global : this || window); 1844 })(typeof global !== 'undefined' && global && typeof module !== 'undefined' && m odule ? global : this || window);
1842 1845
1843 // select ShadowDOM impl
1844 if (Platform.flags.shadow) {
1845
1846 // Copyright 2012 The Polymer Authors. All rights reserved. 1846 // Copyright 2012 The Polymer Authors. All rights reserved.
1847 // Use of this source code is goverened by a BSD-style 1847 // Use of this source code is goverened by a BSD-style
1848 // license that can be found in the LICENSE file. 1848 // license that can be found in the LICENSE file.
1849 1849
1850 window.ShadowDOMPolyfill = {}; 1850 window.ShadowDOMPolyfill = {};
1851 1851
1852 (function(scope) { 1852 (function(scope) {
1853 'use strict'; 1853 'use strict';
1854 1854
1855 var constructorTable = new WeakMap(); 1855 var constructorTable = new WeakMap();
(...skipping 6649 matching lines...) Expand 10 before | Expand all | Expand 10 after
8505 Array.prototype.forEach.call(cssRules, function(rule) { 8505 Array.prototype.forEach.call(cssRules, function(rule) {
8506 if (rule.selectorText && (rule.style && rule.style.cssText !== undefined )) { 8506 if (rule.selectorText && (rule.style && rule.style.cssText !== undefined )) {
8507 cssText += this.scopeSelector(rule.selectorText, scopeSelector, 8507 cssText += this.scopeSelector(rule.selectorText, scopeSelector,
8508 this.strictStyling) + ' {\n\t'; 8508 this.strictStyling) + ' {\n\t';
8509 cssText += this.propertiesFromRule(rule) + '\n}\n\n'; 8509 cssText += this.propertiesFromRule(rule) + '\n}\n\n';
8510 } else if (rule.type === CSSRule.MEDIA_RULE) { 8510 } else if (rule.type === CSSRule.MEDIA_RULE) {
8511 cssText += '@media ' + rule.media.mediaText + ' {\n'; 8511 cssText += '@media ' + rule.media.mediaText + ' {\n';
8512 cssText += this.scopeRules(rule.cssRules, scopeSelector); 8512 cssText += this.scopeRules(rule.cssRules, scopeSelector);
8513 cssText += '\n}\n\n'; 8513 cssText += '\n}\n\n';
8514 } else { 8514 } else {
8515 // TODO(sjmiles): KEYFRAMES_RULE in IE11 throws when we query cssText 8515 // KEYFRAMES_RULE in IE throws when we query cssText
8516 // 'cssText' in rule returns true, but rule.cssText throws anyway 8516 // when it contains a -webkit- property.
8517 // We can test the rule type, e.g. 8517 // if this happens, we fallback to constructing the rule
8518 // else if (rule.type !== CSSRule.KEYFRAMES_RULE && rule.cssText) { 8518 // from the CSSRuleSet
8519 // but this will prevent cssText propagation in other browsers which 8519 // https://connect.microsoft.com/IE/feedbackdetail/view/955703/accessi ng-csstext-of-a-keyframe-rule-that-contains-a-webkit-property-via-cssom-generate s-exception
8520 // support it.
8521 // KEYFRAMES_RULE has a CSSRuleSet, so the text can probably be recons tructed
8522 // from that collection; this would be a proper fix.
8523 // For now, I'm trapping the exception so IE11 is unblocked in other a reas.
8524 try { 8520 try {
8525 if (rule.cssText) { 8521 if (rule.cssText) {
8526 cssText += rule.cssText + '\n\n'; 8522 cssText += rule.cssText + '\n\n';
8527 } 8523 }
8528 } catch(x) { 8524 } catch(x) {
8529 // squelch 8525 if (rule.type === CSSRule.KEYFRAMES_RULE && rule.cssRules) {
8526 cssText += this.ieSafeCssTextFromKeyFrameRule(rule);
8527 }
8530 } 8528 }
8531 } 8529 }
8532 }, this); 8530 }, this);
8533 } 8531 }
8534 return cssText; 8532 return cssText;
8535 }, 8533 },
8534 ieSafeCssTextFromKeyFrameRule: function(rule) {
8535 var cssText = '@keyframes ' + rule.name + ' {';
8536 Array.prototype.forEach.call(rule.cssRules, function(rule) {
8537 cssText += ' ' + rule.keyText + ' {' + rule.style.cssText + '}';
8538 });
8539 cssText += ' }';
8540 return cssText;
8541 },
8536 scopeSelector: function(selector, scopeSelector, strict) { 8542 scopeSelector: function(selector, scopeSelector, strict) {
8537 var r = [], parts = selector.split(','); 8543 var r = [], parts = selector.split(',');
8538 parts.forEach(function(p) { 8544 parts.forEach(function(p) {
8539 p = p.trim(); 8545 p = p.trim();
8540 if (this.selectorNeedsScoping(p, scopeSelector)) { 8546 if (this.selectorNeedsScoping(p, scopeSelector)) {
8541 p = (strict && !p.match(polyfillHostNoCombinator)) ? 8547 p = (strict && !p.match(polyfillHostNoCombinator)) ?
8542 this.applyStrictSelectorScope(p, scopeSelector) : 8548 this.applyStrictSelectorScope(p, scopeSelector) :
8543 this.applySelectorScope(p, scopeSelector); 8549 this.applySelectorScope(p, scopeSelector);
8544 } 8550 }
8545 r.push(p); 8551 r.push(p);
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
8748 var isChrome = navigator.userAgent.match('Chrome'); 8754 var isChrome = navigator.userAgent.match('Chrome');
8749 function withCssRules(cssText, callback) { 8755 function withCssRules(cssText, callback) {
8750 if (!callback) { 8756 if (!callback) {
8751 return; 8757 return;
8752 } 8758 }
8753 var rules; 8759 var rules;
8754 if (cssText.match('@import') && isChrome) { 8760 if (cssText.match('@import') && isChrome) {
8755 var style = cssTextToStyle(cssText); 8761 var style = cssTextToStyle(cssText);
8756 inFrame(function(doc) { 8762 inFrame(function(doc) {
8757 doc.head.appendChild(style.impl); 8763 doc.head.appendChild(style.impl);
8758 rules = style.sheet.cssRules; 8764 rules = Array.prototype.slice.call(style.sheet.cssRules, 0);
8759 callback(rules); 8765 callback(rules);
8760 }); 8766 });
8761 } else { 8767 } else {
8762 rules = cssToRules(cssText); 8768 rules = cssToRules(cssText);
8763 callback(rules); 8769 callback(rules);
8764 } 8770 }
8765 } 8771 }
8766 8772
8767 function rulesToCss(cssRules) { 8773 function rulesToCss(cssRules) {
8768 for (var i=0, css=[]; i < cssRules.length; i++) { 8774 for (var i=0, css=[]; i < cssRules.length; i++) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
8829 if (elt[SHIMMED_ATTRIBUTE]) { 8835 if (elt[SHIMMED_ATTRIBUTE]) {
8830 return; 8836 return;
8831 } 8837 }
8832 var style = elt.__importElement || elt; 8838 var style = elt.__importElement || elt;
8833 if (!style.hasAttribute(SHIM_ATTRIBUTE)) { 8839 if (!style.hasAttribute(SHIM_ATTRIBUTE)) {
8834 originalParseGeneric.call(this, elt); 8840 originalParseGeneric.call(this, elt);
8835 return; 8841 return;
8836 } 8842 }
8837 if (elt.__resource) { 8843 if (elt.__resource) {
8838 style = elt.ownerDocument.createElement('style'); 8844 style = elt.ownerDocument.createElement('style');
8839 style.textContent = urlResolver.resolveCssText( 8845 style.textContent = elt.__resource;
8840 elt.__resource, elt.href);
8841 } else {
8842 urlResolver.resolveStyle(style);
8843 } 8846 }
8847 // relay on HTMLImports for path fixup
8848 HTMLImports.path.resolveUrlsInStyle(style);
8844 style.textContent = ShadowCSS.shimStyle(style); 8849 style.textContent = ShadowCSS.shimStyle(style);
8845 style.removeAttribute(SHIM_ATTRIBUTE, ''); 8850 style.removeAttribute(SHIM_ATTRIBUTE, '');
8846 style.setAttribute(SHIMMED_ATTRIBUTE, ''); 8851 style.setAttribute(SHIMMED_ATTRIBUTE, '');
8847 style[SHIMMED_ATTRIBUTE] = true; 8852 style[SHIMMED_ATTRIBUTE] = true;
8848 // place in document 8853 // place in document
8849 if (style.parentNode !== head) { 8854 if (style.parentNode !== head) {
8850 // replace links in head 8855 // replace links in head
8851 if (elt.parentNode === head) { 8856 if (elt.parentNode === head) {
8852 head.replaceChild(style, elt); 8857 head.replaceChild(style, elt);
8853 } else { 8858 } else {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
8899 if (CustomElements.useNative === false) { 8904 if (CustomElements.useNative === false) {
8900 var originalCreateShadowRoot = Element.prototype.createShadowRoot; 8905 var originalCreateShadowRoot = Element.prototype.createShadowRoot;
8901 Element.prototype.createShadowRoot = function() { 8906 Element.prototype.createShadowRoot = function() {
8902 var root = originalCreateShadowRoot.call(this); 8907 var root = originalCreateShadowRoot.call(this);
8903 CustomElements.watchShadow(this); 8908 CustomElements.watchShadow(this);
8904 return root; 8909 return root;
8905 }; 8910 };
8906 } 8911 }
8907 }); 8912 });
8908 8913
8909 Platform.templateContent = function(inTemplate) {
8910 // if MDV exists, it may need to boostrap this template to reveal content
8911 if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {
8912 HTMLTemplateElement.bootstrap(inTemplate);
8913 }
8914 // fallback when there is no Shadow DOM polyfill, no MDV polyfill, and no
8915 // native template support
8916 if (!inTemplate.content && !inTemplate._content) {
8917 var frag = document.createDocumentFragment();
8918 while (inTemplate.firstChild) {
8919 frag.appendChild(inTemplate.firstChild);
8920 }
8921 inTemplate._content = frag;
8922 }
8923 return inTemplate.content || inTemplate._content;
8924 };
8925
8926 })(window.Platform); 8914 })(window.Platform);
8927 8915
8928 } 8916 }
8929 /* Any copyright is dedicated to the Public Domain. 8917 /* Any copyright is dedicated to the Public Domain.
8930 * http://creativecommons.org/publicdomain/zero/1.0/ */ 8918 * http://creativecommons.org/publicdomain/zero/1.0/ */
8931 8919
8932 (function(scope) { 8920 (function(scope) {
8933 'use strict'; 8921 'use strict';
8934 8922
8935 // feature detect for URL constructor 8923 // feature detect for URL constructor
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
9523 var self = this; 9511 var self = this;
9524 var args = Array.prototype.slice.call(arguments, 1); 9512 var args = Array.prototype.slice.call(arguments, 1);
9525 return function() { 9513 return function() {
9526 var args2 = args.slice(); 9514 var args2 = args.slice();
9527 args2.push.apply(args2, arguments); 9515 args2.push.apply(args2, arguments);
9528 return self.apply(scope, args2); 9516 return self.apply(scope, args2);
9529 }; 9517 };
9530 }; 9518 };
9531 } 9519 }
9532 9520
9533 // mixin
9534
9535 // copy all properties from inProps (et al) to inObj
9536 function mixin(inObj/*, inProps, inMoreProps, ...*/) {
9537 var obj = inObj || {};
9538 for (var i = 1; i < arguments.length; i++) {
9539 var p = arguments[i];
9540 try {
9541 for (var n in p) {
9542 copyProperty(n, p, obj);
9543 }
9544 } catch(x) {
9545 }
9546 }
9547 return obj;
9548 }
9549
9550 // copy property inName from inSource object to inTarget object
9551 function copyProperty(inName, inSource, inTarget) {
9552 var pd = getPropertyDescriptor(inSource, inName);
9553 Object.defineProperty(inTarget, inName, pd);
9554 }
9555
9556 // get property descriptor for inName on inObject, even if
9557 // inName exists on some link in inObject's prototype chain
9558 function getPropertyDescriptor(inObject, inName) {
9559 if (inObject) {
9560 var pd = Object.getOwnPropertyDescriptor(inObject, inName);
9561 return pd || getPropertyDescriptor(Object.getPrototypeOf(inObject), inName);
9562 }
9563 }
9564
9565 // export
9566
9567 scope.mixin = mixin;
9568
9569 })(window.Platform); 9521 })(window.Platform);
9570 9522
9571 /* 9523 /*
9572 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 9524 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
9573 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 9525 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
9574 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 9526 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
9575 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 9527 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
9576 * Code distributed by Google as part of the polymer project is also 9528 * Code distributed by Google as part of the polymer project is also
9577 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 9529 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
9578 */ 9530 */
9579 9531
9580 (function(scope) { 9532 (function(scope) {
9581 9533
9582 'use strict'; 9534 'use strict';
9583 9535
9584 // polyfill DOMTokenList
9585 // * add/remove: allow these methods to take multiple classNames
9586 // * toggle: add a 2nd argument which forces the given state rather
9587 // than toggling.
9588
9589 var add = DOMTokenList.prototype.add;
9590 var remove = DOMTokenList.prototype.remove;
9591 DOMTokenList.prototype.add = function() {
9592 for (var i = 0; i < arguments.length; i++) {
9593 add.call(this, arguments[i]);
9594 }
9595 };
9596 DOMTokenList.prototype.remove = function() {
9597 for (var i = 0; i < arguments.length; i++) {
9598 remove.call(this, arguments[i]);
9599 }
9600 };
9601 DOMTokenList.prototype.toggle = function(name, bool) {
9602 if (arguments.length == 1) {
9603 bool = !this.contains(name);
9604 }
9605 bool ? this.add(name) : this.remove(name);
9606 };
9607 DOMTokenList.prototype.switch = function(oldName, newName) {
9608 oldName && this.remove(oldName);
9609 newName && this.add(newName);
9610 };
9611
9612 // add array() to NodeList, NamedNodeMap, HTMLCollection
9613
9614 var ArraySlice = function() {
9615 return Array.prototype.slice.call(this);
9616 };
9617
9618 var namedNodeMap = (window.NamedNodeMap || window.MozNamedAttrMap || {});
9619
9620 NodeList.prototype.array = ArraySlice;
9621 namedNodeMap.prototype.array = ArraySlice;
9622 HTMLCollection.prototype.array = ArraySlice;
9623
9624 // polyfill performance.now 9536 // polyfill performance.now
9625 9537
9626 if (!window.performance) { 9538 if (!window.performance) {
9627 var start = Date.now(); 9539 var start = Date.now();
9628 // only at millisecond precision 9540 // only at millisecond precision
9629 window.performance = {now: function(){ return Date.now() - start }}; 9541 window.performance = {now: function(){ return Date.now() - start }};
9630 } 9542 }
9631 9543
9632 // polyfill for requestAnimationFrame 9544 // polyfill for requestAnimationFrame
9633 9545
(...skipping 17 matching lines...) Expand all
9651 if (!window.cancelAnimationFrame) { 9563 if (!window.cancelAnimationFrame) {
9652 window.cancelAnimationFrame = (function() { 9564 window.cancelAnimationFrame = (function() {
9653 return window.webkitCancelAnimationFrame || 9565 return window.webkitCancelAnimationFrame ||
9654 window.mozCancelAnimationFrame || 9566 window.mozCancelAnimationFrame ||
9655 function(id) { 9567 function(id) {
9656 clearTimeout(id); 9568 clearTimeout(id);
9657 }; 9569 };
9658 })(); 9570 })();
9659 } 9571 }
9660 9572
9661 // utility
9662
9663 function createDOM(inTagOrNode, inHTML, inAttrs) {
9664 var dom = typeof inTagOrNode == 'string' ?
9665 document.createElement(inTagOrNode) : inTagOrNode.cloneNode(true);
9666 dom.innerHTML = inHTML;
9667 if (inAttrs) {
9668 for (var n in inAttrs) {
9669 dom.setAttribute(n, inAttrs[n]);
9670 }
9671 }
9672 return dom;
9673 }
9674 // Make a stub for Polymer() for polyfill purposes; under the HTMLImports 9573 // Make a stub for Polymer() for polyfill purposes; under the HTMLImports
9675 // polyfill, scripts in the main document run before imports. That means 9574 // polyfill, scripts in the main document run before imports. That means
9676 // if (1) polymer is imported and (2) Polymer() is called in the main document 9575 // if (1) polymer is imported and (2) Polymer() is called in the main document
9677 // in a script after the import, 2 occurs before 1. We correct this here 9576 // in a script after the import, 2 occurs before 1. We correct this here
9678 // by specfiically patching Polymer(); this is not necessary under native 9577 // by specfiically patching Polymer(); this is not necessary under native
9679 // HTMLImports. 9578 // HTMLImports.
9680 var elementDeclarations = []; 9579 var elementDeclarations = [];
9681 9580
9682 var polymerStub = function(name, dictionary) { 9581 var polymerStub = function(name, dictionary) {
9582 Array.prototype.push.call(arguments, document._currentScript);
9683 elementDeclarations.push(arguments); 9583 elementDeclarations.push(arguments);
9684 } 9584 };
9685 window.Polymer = polymerStub; 9585 window.Polymer = polymerStub;
9686 9586
9687 // deliver queued delcarations 9587 // deliver queued delcarations
9688 scope.deliverDeclarations = function() { 9588 scope.consumeDeclarations = function(callback) {
9689 scope.deliverDeclarations = function() { 9589 scope.consumeDeclarations = function() {
9690 throw 'Possible attempt to load Polymer twice'; 9590 throw 'Possible attempt to load Polymer twice';
9691 }; 9591 };
9692 return elementDeclarations; 9592 if (callback) {
9693 } 9593 callback(elementDeclarations);
9594 }
9595 elementDeclarations = null;
9596 };
9694 9597
9695 // Once DOMContent has loaded, any main document scripts that depend on 9598 // Once DOMContent has loaded, any main document scripts that depend on
9696 // Polymer() should have run. Calling Polymer() now is an error until 9599 // Polymer() should have run. Calling Polymer() now is an error until
9697 // polymer is imported. 9600 // polymer is imported.
9698 window.addEventListener('DOMContentLoaded', function() { 9601 window.addEventListener('DOMContentLoaded', function() {
9699 if (window.Polymer === polymerStub) { 9602 if (window.Polymer === polymerStub) {
9700 window.Polymer = function() { 9603 window.Polymer = function() {
9701 console.error('You tried to use polymer without loading it first. To ' + 9604 console.error('You tried to use polymer without loading it first. To ' +
9702 'load polymer, <link rel="import" href="' + 9605 'load polymer, <link rel="import" href="' +
9703 'components/polymer/polymer.html">'); 9606 'components/polymer/polymer.html">');
9704 }; 9607 };
9705 } 9608 }
9706 }); 9609 });
9707 9610
9708 // exports
9709 scope.createDOM = createDOM;
9710
9711 })(window.Platform); 9611 })(window.Platform);
9712 9612
9713 /* 9613 /*
9714 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
9715 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
9716 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
9717 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
9718 * Code distributed by Google as part of the polymer project is also
9719 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
9720 */
9721
9722 // poor man's adapter for template.content on various platform scenarios
9723 (function(scope) {
9724 scope.templateContent = scope.templateContent || function(inTemplate) {
9725 return inTemplate.content;
9726 };
9727 })(window.Platform);
9728
9729 /*
9730 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
9731 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
9732 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
9733 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
9734 * Code distributed by Google as part of the polymer project is also
9735 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
9736 */
9737
9738 (function(scope) {
9739
9740 scope = scope || (window.Inspector = {});
9741
9742 var inspector;
9743
9744 window.sinspect = function(inNode, inProxy) {
9745 if (!inspector) {
9746 inspector = window.open('', 'ShadowDOM Inspector', null, true);
9747 inspector.document.write(inspectorHTML);
9748 //inspector.document.close();
9749 inspector.api = {
9750 shadowize: shadowize
9751 };
9752 }
9753 inspect(inNode || wrap(document.body), inProxy);
9754 };
9755
9756 var inspectorHTML = [
9757 '<!DOCTYPE html>',
9758 '<html>',
9759 ' <head>',
9760 ' <title>ShadowDOM Inspector</title>',
9761 ' <style>',
9762 ' body {',
9763 ' }',
9764 ' pre {',
9765 ' font: 9pt "Courier New", monospace;',
9766 ' line-height: 1.5em;',
9767 ' }',
9768 ' tag {',
9769 ' color: purple;',
9770 ' }',
9771 ' ul {',
9772 ' margin: 0;',
9773 ' padding: 0;',
9774 ' list-style: none;',
9775 ' }',
9776 ' li {',
9777 ' display: inline-block;',
9778 ' background-color: #f1f1f1;',
9779 ' padding: 4px 6px;',
9780 ' border-radius: 4px;',
9781 ' margin-right: 4px;',
9782 ' }',
9783 ' </style>',
9784 ' </head>',
9785 ' <body>',
9786 ' <ul id="crumbs">',
9787 ' </ul>',
9788 ' <div id="tree"></div>',
9789 ' </body>',
9790 '</html>'
9791 ].join('\n');
9792
9793 var crumbs = [];
9794
9795 var displayCrumbs = function() {
9796 // alias our document
9797 var d = inspector.document;
9798 // get crumbbar
9799 var cb = d.querySelector('#crumbs');
9800 // clear crumbs
9801 cb.textContent = '';
9802 // build new crumbs
9803 for (var i=0, c; c=crumbs[i]; i++) {
9804 var a = d.createElement('a');
9805 a.href = '#';
9806 a.textContent = c.localName;
9807 a.idx = i;
9808 a.onclick = function(event) {
9809 var c;
9810 while (crumbs.length > this.idx) {
9811 c = crumbs.pop();
9812 }
9813 inspect(c.shadow || c, c);
9814 event.preventDefault();
9815 };
9816 cb.appendChild(d.createElement('li')).appendChild(a);
9817 }
9818 };
9819
9820 var inspect = function(inNode, inProxy) {
9821 // alias our document
9822 var d = inspector.document;
9823 // reset list of drillable nodes
9824 drillable = [];
9825 // memoize our crumb proxy
9826 var proxy = inProxy || inNode;
9827 crumbs.push(proxy);
9828 // update crumbs
9829 displayCrumbs();
9830 // reflect local tree
9831 d.body.querySelector('#tree').innerHTML =
9832 '<pre>' + output(inNode, inNode.childNodes) + '</pre>';
9833 };
9834
9835 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
9836
9837 var blacklisted = {STYLE:1, SCRIPT:1, "#comment": 1, TEMPLATE: 1};
9838 var blacklist = function(inNode) {
9839 return blacklisted[inNode.nodeName];
9840 };
9841
9842 var output = function(inNode, inChildNodes, inIndent) {
9843 if (blacklist(inNode)) {
9844 return '';
9845 }
9846 var indent = inIndent || '';
9847 if (inNode.localName || inNode.nodeType == 11) {
9848 var name = inNode.localName || 'shadow-root';
9849 //inChildNodes = ShadowDOM.localNodes(inNode);
9850 var info = indent + describe(inNode);
9851 // if only textNodes
9852 // TODO(sjmiles): make correct for ShadowDOM
9853 /*if (!inNode.children.length && inNode.localName !== 'content' && inNode. localName !== 'shadow') {
9854 info += catTextContent(inChildNodes);
9855 } else*/ {
9856 // TODO(sjmiles): native <shadow> has no reference to its projection
9857 if (name == 'content' /*|| name == 'shadow'*/) {
9858 inChildNodes = inNode.getDistributedNodes();
9859 }
9860 info += '<br/>';
9861 var ind = indent + '&nbsp;&nbsp;';
9862 forEach(inChildNodes, function(n) {
9863 info += output(n, n.childNodes, ind);
9864 });
9865 info += indent;
9866 }
9867 if (!({br:1}[name])) {
9868 info += '<tag>&lt;/' + name + '&gt;</tag>';
9869 info += '<br/>';
9870 }
9871 } else {
9872 var text = inNode.textContent.trim();
9873 info = text ? indent + '"' + text + '"' + '<br/>' : '';
9874 }
9875 return info;
9876 };
9877
9878 var catTextContent = function(inChildNodes) {
9879 var info = '';
9880 forEach(inChildNodes, function(n) {
9881 info += n.textContent.trim();
9882 });
9883 return info;
9884 };
9885
9886 var drillable = [];
9887
9888 var describe = function(inNode) {
9889 var tag = '<tag>' + '&lt;';
9890 var name = inNode.localName || 'shadow-root';
9891 if (inNode.webkitShadowRoot || inNode.shadowRoot) {
9892 tag += ' <button idx="' + drillable.length +
9893 '" onclick="api.shadowize.call(this)">' + name + '</button>';
9894 drillable.push(inNode);
9895 } else {
9896 tag += name || 'shadow-root';
9897 }
9898 if (inNode.attributes) {
9899 forEach(inNode.attributes, function(a) {
9900 tag += ' ' + a.name + (a.value ? '="' + a.value + '"' : '');
9901 });
9902 }
9903 tag += '&gt;'+ '</tag>';
9904 return tag;
9905 };
9906
9907 // remote api
9908
9909 shadowize = function() {
9910 var idx = Number(this.attributes.idx.value);
9911 //alert(idx);
9912 var node = drillable[idx];
9913 if (node) {
9914 inspect(node.webkitShadowRoot || node.shadowRoot, node)
9915 } else {
9916 console.log("bad shadowize node");
9917 console.dir(this);
9918 }
9919 };
9920
9921 // export
9922
9923 scope.output = output;
9924
9925 })(window.Inspector);
9926
9927 /*
9928 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
9929 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
9930 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
9931 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
9932 * Code distributed by Google as part of the polymer project is also
9933 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
9934 */
9935
9936 (function(scope) {
9937
9938 // TODO(sorvell): It's desireable to provide a default stylesheet
9939 // that's convenient for styling unresolved elements, but
9940 // it's cumbersome to have to include this manually in every page.
9941 // It would make sense to put inside some HTMLImport but
9942 // the HTMLImports polyfill does not allow loading of stylesheets
9943 // that block rendering. Therefore this injection is tolerated here.
9944
9945 var style = document.createElement('style');
9946 style.textContent = ''
9947 + 'body {'
9948 + 'transition: opacity ease-in 0.2s;'
9949 + ' } \n'
9950 + 'body[unresolved] {'
9951 + 'opacity: 0; display: block; overflow: hidden;'
9952 + ' } \n'
9953 ;
9954 var head = document.querySelector('head');
9955 head.insertBefore(style, head.firstChild);
9956
9957 })(Platform);
9958
9959 /*
9960 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
9961 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
9962 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
9963 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
9964 * Code distributed by Google as part of the polymer project is also
9965 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
9966 */
9967
9968 (function(scope) {
9969
9970 function withDependencies(task, depends) {
9971 depends = depends || [];
9972 if (!depends.map) {
9973 depends = [depends];
9974 }
9975 return task.apply(this, depends.map(marshal));
9976 }
9977
9978 function module(name, dependsOrFactory, moduleFactory) {
9979 var module;
9980 switch (arguments.length) {
9981 case 0:
9982 return;
9983 case 1:
9984 module = null;
9985 break;
9986 case 2:
9987 // dependsOrFactory is `factory` in this case
9988 module = dependsOrFactory.apply(this);
9989 break;
9990 default:
9991 // dependsOrFactory is `depends` in this case
9992 module = withDependencies(moduleFactory, dependsOrFactory);
9993 break;
9994 }
9995 modules[name] = module;
9996 };
9997
9998 function marshal(name) {
9999 return modules[name];
10000 }
10001
10002 var modules = {};
10003
10004 function using(depends, task) {
10005 HTMLImports.whenImportsReady(function() {
10006 withDependencies(task, depends);
10007 });
10008 };
10009
10010 // exports
10011
10012 scope.marshal = marshal;
10013 // `module` confuses commonjs detectors
10014 scope.modularize = module;
10015 scope.using = using;
10016
10017 })(window);
10018
10019 /*
10020 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
10021 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
10022 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
10023 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
10024 * Code distributed by Google as part of the polymer project is also
10025 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
10026 */
10027
10028 (function(scope) {
10029
10030 var iterations = 0;
10031 var callbacks = [];
10032 var twiddle = document.createTextNode('');
10033
10034 function endOfMicrotask(callback) {
10035 twiddle.textContent = iterations++;
10036 callbacks.push(callback);
10037 }
10038
10039 function atEndOfMicrotask() {
10040 while (callbacks.length) {
10041 callbacks.shift()();
10042 }
10043 }
10044
10045 new (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask)
10046 .observe(twiddle, {characterData: true})
10047 ;
10048
10049 // exports
10050
10051 scope.endOfMicrotask = endOfMicrotask;
10052
10053 })(Platform);
10054
10055
10056 /*
10057 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
10058 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
10059 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
10060 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
10061 * Code distributed by Google as part of the polymer project is also
10062 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
10063 */
10064
10065 (function(scope) {
10066
10067 var urlResolver = {
10068 resolveDom: function(root, url) {
10069 url = url || root.ownerDocument.baseURI;
10070 this.resolveAttributes(root, url);
10071 this.resolveStyles(root, url);
10072 // handle template.content
10073 var templates = root.querySelectorAll('template');
10074 if (templates) {
10075 for (var i = 0, l = templates.length, t; (i < l) && (t = templates[i]); i+ +) {
10076 if (t.content) {
10077 this.resolveDom(t.content, url);
10078 }
10079 }
10080 }
10081 },
10082 resolveTemplate: function(template) {
10083 this.resolveDom(template.content, template.ownerDocument.baseURI);
10084 },
10085 resolveStyles: function(root, url) {
10086 var styles = root.querySelectorAll('style');
10087 if (styles) {
10088 for (var i = 0, l = styles.length, s; (i < l) && (s = styles[i]); i++) {
10089 this.resolveStyle(s, url);
10090 }
10091 }
10092 },
10093 resolveStyle: function(style, url) {
10094 url = url || style.ownerDocument.baseURI;
10095 style.textContent = this.resolveCssText(style.textContent, url);
10096 },
10097 resolveCssText: function(cssText, baseUrl, keepAbsolute) {
10098 cssText = replaceUrlsInCssText(cssText, baseUrl, keepAbsolute, CSS_URL_REGEX P);
10099 return replaceUrlsInCssText(cssText, baseUrl, keepAbsolute, CSS_IMPORT_REGEX P);
10100 },
10101 resolveAttributes: function(root, url) {
10102 if (root.hasAttributes && root.hasAttributes()) {
10103 this.resolveElementAttributes(root, url);
10104 }
10105 // search for attributes that host urls
10106 var nodes = root && root.querySelectorAll(URL_ATTRS_SELECTOR);
10107 if (nodes) {
10108 for (var i = 0, l = nodes.length, n; (i < l) && (n = nodes[i]); i++) {
10109 this.resolveElementAttributes(n, url);
10110 }
10111 }
10112 },
10113 resolveElementAttributes: function(node, url) {
10114 url = url || node.ownerDocument.baseURI;
10115 URL_ATTRS.forEach(function(v) {
10116 var attr = node.attributes[v];
10117 var value = attr && attr.value;
10118 var replacement;
10119 if (value && value.search(URL_TEMPLATE_SEARCH) < 0) {
10120 if (v === 'style') {
10121 replacement = replaceUrlsInCssText(value, url, false, CSS_URL_REGEXP);
10122 } else {
10123 replacement = resolveRelativeUrl(url, value);
10124 }
10125 attr.value = replacement;
10126 }
10127 });
10128 }
10129 };
10130
10131 var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g;
10132 var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g;
10133 var URL_ATTRS = ['href', 'src', 'action', 'style', 'url'];
10134 var URL_ATTRS_SELECTOR = '[' + URL_ATTRS.join('],[') + ']';
10135 var URL_TEMPLATE_SEARCH = '{{.*}}';
10136
10137 function replaceUrlsInCssText(cssText, baseUrl, keepAbsolute, regexp) {
10138 return cssText.replace(regexp, function(m, pre, url, post) {
10139 var urlPath = url.replace(/["']/g, '');
10140 urlPath = resolveRelativeUrl(baseUrl, urlPath, keepAbsolute);
10141 return pre + '\'' + urlPath + '\'' + post;
10142 });
10143 }
10144
10145 function resolveRelativeUrl(baseUrl, url, keepAbsolute) {
10146 // do not resolve '/' absolute urls
10147 if (url && url[0] === '/') {
10148 return url;
10149 }
10150 var u = new URL(url, baseUrl);
10151 return keepAbsolute ? u.href : makeDocumentRelPath(u.href);
10152 }
10153
10154 function makeDocumentRelPath(url) {
10155 var root = new URL(document.baseURI);
10156 var u = new URL(url, root);
10157 if (u.host === root.host && u.port === root.port &&
10158 u.protocol === root.protocol) {
10159 return makeRelPath(root, u);
10160 } else {
10161 return url;
10162 }
10163 }
10164
10165 // make a relative path from source to target
10166 function makeRelPath(sourceUrl, targetUrl) {
10167 var source = sourceUrl.pathname;
10168 var target = targetUrl.pathname;
10169 var s = source.split('/');
10170 var t = target.split('/');
10171 while (s.length && s[0] === t[0]){
10172 s.shift();
10173 t.shift();
10174 }
10175 for (var i = 0, l = s.length - 1; i < l; i++) {
10176 t.unshift('..');
10177 }
10178 return t.join('/') + targetUrl.search + targetUrl.hash;
10179 }
10180
10181 // exports
10182 scope.urlResolver = urlResolver;
10183
10184 })(Platform);
10185
10186 /*
10187 * Copyright 2012 The Polymer Authors. All rights reserved. 9614 * Copyright 2012 The Polymer Authors. All rights reserved.
10188 * Use of this source code is goverened by a BSD-style 9615 * Use of this source code is goverened by a BSD-style
10189 * license that can be found in the LICENSE file. 9616 * license that can be found in the LICENSE file.
10190 */ 9617 */
10191 9618
10192 (function(global) { 9619 (function(global) {
10193 9620
10194 var registrationsTable = new WeakMap(); 9621 var registrationsTable = new WeakMap();
10195 9622
10196 // We use setImmediate or postMessage for our future callback. 9623 // We use setImmediate or postMessage for our future callback.
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after
10735 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 10162 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
10736 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 10163 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
10737 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 10164 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
10738 * Code distributed by Google as part of the polymer project is also 10165 * Code distributed by Google as part of the polymer project is also
10739 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 10166 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
10740 */ 10167 */
10741 window.HTMLImports = window.HTMLImports || {flags:{}}; 10168 window.HTMLImports = window.HTMLImports || {flags:{}};
10742 /* 10169 /*
10743 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 10170 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
10744 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 10171 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
10172 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
10173 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
10174 * Code distributed by Google as part of the polymer project is also
10175 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
10176 */
10177
10178 (function(scope) {
10179
10180 var hasNative = ('import' in document.createElement('link'));
10181 var useNative = hasNative;
10182
10183 isIE = /Trident/.test(navigator.userAgent);
10184
10185 // TODO(sorvell): SD polyfill intrusion
10186 var hasShadowDOMPolyfill = Boolean(window.ShadowDOMPolyfill);
10187 var wrap = function(node) {
10188 return hasShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node) : node;
10189 };
10190 var mainDoc = wrap(document);
10191
10192 // NOTE: We cannot polyfill document.currentScript because it's not possible
10193 // both to override and maintain the ability to capture the native value;
10194 // therefore we choose to expose _currentScript both when native imports
10195 // and the polyfill are in use.
10196 var currentScriptDescriptor = {
10197 get: function() {
10198 var script = HTMLImports.currentScript || document.currentScript ||
10199 // NOTE: only works when called in synchronously executing code.
10200 // readyState should check if `loading` but IE10 is
10201 // interactive when scripts run so we cheat.
10202 (document.readyState !== 'complete' ?
10203 document.scripts[document.scripts.length - 1] : null);
10204 return wrap(script);
10205 },
10206 configurable: true
10207 };
10208
10209 Object.defineProperty(document, '_currentScript', currentScriptDescriptor);
10210 Object.defineProperty(mainDoc, '_currentScript', currentScriptDescriptor);
10211
10212 // call a callback when all HTMLImports in the document at call (or at least
10213 // document ready) time have loaded.
10214 // 1. ensure the document is in a ready state (has dom), then
10215 // 2. watch for loading of imports and call callback when done
10216 function whenImportsReady(callback, doc) {
10217 doc = doc || mainDoc;
10218 // if document is loading, wait and try again
10219 whenDocumentReady(function() {
10220 watchImportsLoad(callback, doc);
10221 }, doc);
10222 }
10223
10224 // call the callback when the document is in a ready state (has dom)
10225 var requiredReadyState = isIE ? 'complete' : 'interactive';
10226 var READY_EVENT = 'readystatechange';
10227 function isDocumentReady(doc) {
10228 return (doc.readyState === 'complete' ||
10229 doc.readyState === requiredReadyState);
10230 }
10231
10232 // call <callback> when we ensure the document is in a ready state
10233 function whenDocumentReady(callback, doc) {
10234 if (!isDocumentReady(doc)) {
10235 var checkReady = function() {
10236 if (doc.readyState === 'complete' ||
10237 doc.readyState === requiredReadyState) {
10238 doc.removeEventListener(READY_EVENT, checkReady);
10239 whenDocumentReady(callback, doc);
10240 }
10241 };
10242 doc.addEventListener(READY_EVENT, checkReady);
10243 } else if (callback) {
10244 callback();
10245 }
10246 }
10247
10248 function markTargetLoaded(event) {
10249 event.target.__loaded = true;
10250 }
10251
10252 // call <callback> when we ensure all imports have loaded
10253 function watchImportsLoad(callback, doc) {
10254 var imports = doc.querySelectorAll('link[rel=import]');
10255 var loaded = 0, l = imports.length;
10256 function checkDone(d) {
10257 if (loaded == l) {
10258 callback && callback();
10259 }
10260 }
10261 function loadedImport(e) {
10262 markTargetLoaded(e);
10263 loaded++;
10264 checkDone();
10265 }
10266 if (l) {
10267 for (var i=0, imp; (i<l) && (imp=imports[i]); i++) {
10268 if (isImportLoaded(imp)) {
10269 loadedImport.call(imp, {target: imp});
10270 } else {
10271 imp.addEventListener('load', loadedImport);
10272 imp.addEventListener('error', loadedImport);
10273 }
10274 }
10275 } else {
10276 checkDone();
10277 }
10278 }
10279
10280 // NOTE: test for native imports loading is based on explicitly watching
10281 // all imports (see below).
10282 function isImportLoaded(link) {
10283 return useNative ? link.__loaded : link.__importParsed;
10284 }
10285
10286 // TODO(sorvell): Workaround for
10287 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=25007, should be removed when
10288 // this bug is addressed.
10289 // (1) Install a mutation observer to see when HTMLImports have loaded
10290 // (2) if this script is run during document load it will watch any existing
10291 // imports for loading.
10292 //
10293 // NOTE: The workaround has restricted functionality: (1) it's only compatible
10294 // with imports that are added to document.head since the mutation observer
10295 // watches only head for perf reasons, (2) it requires this script
10296 // to run before any imports have completed loading.
10297 if (useNative) {
10298 new MutationObserver(function(mxns) {
10299 for (var i=0, l=mxns.length, m; (i < l) && (m=mxns[i]); i++) {
10300 if (m.addedNodes) {
10301 handleImports(m.addedNodes);
10302 }
10303 }
10304 }).observe(document.head, {childList: true});
10305
10306 function handleImports(nodes) {
10307 for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
10308 if (isImport(n)) {
10309 handleImport(n);
10310 }
10311 }
10312 }
10313
10314 function isImport(element) {
10315 return element.localName === 'link' && element.rel === 'import';
10316 }
10317
10318 function handleImport(element) {
10319 var loaded = element.import;
10320 if (loaded) {
10321 markTargetLoaded({target: element});
10322 } else {
10323 element.addEventListener('load', markTargetLoaded);
10324 element.addEventListener('error', markTargetLoaded);
10325 }
10326 }
10327
10328 // make sure to catch any imports that are in the process of loading
10329 // when this script is run.
10330 (function() {
10331 if (document.readyState === 'loading') {
10332 var imports = document.querySelectorAll('link[rel=import]');
10333 for (var i=0, l=imports.length, imp; (i<l) && (imp=imports[i]); i++) {
10334 handleImport(imp);
10335 }
10336 }
10337 })();
10338
10339 }
10340
10341 // Fire the 'HTMLImportsLoaded' event when imports in document at load time
10342 // have loaded. This event is required to simulate the script blocking
10343 // behavior of native imports. A main document script that needs to be sure
10344 // imports have loaded should wait for this event.
10345 whenImportsReady(function() {
10346 HTMLImports.ready = true;
10347 HTMLImports.readyTime = new Date().getTime();
10348 mainDoc.dispatchEvent(
10349 new CustomEvent('HTMLImportsLoaded', {bubbles: true})
10350 );
10351 });
10352
10353 // exports
10354 scope.useNative = useNative;
10355 scope.isImportLoaded = isImportLoaded;
10356 scope.whenReady = whenImportsReady;
10357 scope.isIE = isIE;
10358
10359 // deprecated
10360 scope.whenImportsReady = whenImportsReady;
10361
10362 })(window.HTMLImports);
10363 /*
10364 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
10365 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
10745 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 10366 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
10746 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 10367 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
10747 * Code distributed by Google as part of the polymer project is also 10368 * Code distributed by Google as part of the polymer project is also
10748 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 10369 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
10749 */(function(scope) {
10750
10751 var hasNative = ('import' in document.createElement('link'));
10752 var useNative = hasNative;
10753
10754 isIE = /Trident/.test(navigator.userAgent);
10755
10756 // TODO(sorvell): SD polyfill intrusion
10757 var hasShadowDOMPolyfill = Boolean(window.ShadowDOMPolyfill);
10758 var wrap = function(node) {
10759 return hasShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node) : node;
10760 };
10761 var mainDoc = wrap(document);
10762
10763 // NOTE: We cannot polyfill document.currentScript because it's not possible
10764 // both to override and maintain the ability to capture the native value;
10765 // therefore we choose to expose _currentScript both when native imports
10766 // and the polyfill are in use.
10767 var currentScriptDescriptor = {
10768 get: function() {
10769 var script = HTMLImports.currentScript || document.currentScript ||
10770 // NOTE: only works when called in synchronously executing code.
10771 // readyState should check if `loading` but IE10 is
10772 // interactive when scripts run so we cheat.
10773 (document.readyState !== 'complete' ?
10774 document.scripts[document.scripts.length - 1] : null);
10775 return wrap(script);
10776 },
10777 configurable: true
10778 };
10779
10780 Object.defineProperty(document, '_currentScript', currentScriptDescriptor);
10781 Object.defineProperty(mainDoc, '_currentScript', currentScriptDescriptor);
10782
10783 // call a callback when all HTMLImports in the document at call (or at least
10784 // document ready) time have loaded.
10785 // 1. ensure the document is in a ready state (has dom), then
10786 // 2. watch for loading of imports and call callback when done
10787 function whenImportsReady(callback, doc) {
10788 doc = doc || mainDoc;
10789 // if document is loading, wait and try again
10790 whenDocumentReady(function() {
10791 watchImportsLoad(callback, doc);
10792 }, doc);
10793 }
10794
10795 // call the callback when the document is in a ready state (has dom)
10796 var requiredReadyState = isIE ? 'complete' : 'interactive';
10797 var READY_EVENT = 'readystatechange';
10798 function isDocumentReady(doc) {
10799 return (doc.readyState === 'complete' ||
10800 doc.readyState === requiredReadyState);
10801 }
10802
10803 // call <callback> when we ensure the document is in a ready state
10804 function whenDocumentReady(callback, doc) {
10805 if (!isDocumentReady(doc)) {
10806 var checkReady = function() {
10807 if (doc.readyState === 'complete' ||
10808 doc.readyState === requiredReadyState) {
10809 doc.removeEventListener(READY_EVENT, checkReady);
10810 whenDocumentReady(callback, doc);
10811 }
10812 }
10813 doc.addEventListener(READY_EVENT, checkReady);
10814 } else if (callback) {
10815 callback();
10816 }
10817 }
10818
10819 // call <callback> when we ensure all imports have loaded
10820 function watchImportsLoad(callback, doc) {
10821 var imports = doc.querySelectorAll('link[rel=import]');
10822 var loaded = 0, l = imports.length;
10823 function checkDone(d) {
10824 if (loaded == l) {
10825 callback && callback();
10826 }
10827 }
10828 function loadedImport(e) {
10829 loaded++;
10830 checkDone();
10831 }
10832 if (l) {
10833 for (var i=0, imp; (i<l) && (imp=imports[i]); i++) {
10834 if (isImportLoaded(imp)) {
10835 loadedImport.call(imp);
10836 } else {
10837 imp.addEventListener('load', loadedImport);
10838 imp.addEventListener('error', loadedImport);
10839 }
10840 }
10841 } else {
10842 checkDone();
10843 }
10844 }
10845
10846 // NOTE: test for native imports loading is based on explicitly watching
10847 // all imports (see below).
10848 function isImportLoaded(link) {
10849 return useNative ? link.__loaded : link.__importParsed;
10850 }
10851
10852 // TODO(sorvell): install a mutation observer to see if HTMLImports have loaded
10853 // this is a workaround for https://www.w3.org/Bugs/Public/show_bug.cgi?id=25007
10854 // and should be removed when this bug is addressed.
10855 if (useNative) {
10856 new MutationObserver(function(mxns) {
10857 for (var i=0, l=mxns.length, m; (i < l) && (m=mxns[i]); i++) {
10858 if (m.addedNodes) {
10859 handleImports(m.addedNodes);
10860 }
10861 }
10862 }).observe(document.head, {childList: true});
10863
10864 function handleImports(nodes) {
10865 for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
10866 if (isImport(n)) {
10867 handleImport(n);
10868 }
10869 }
10870 }
10871
10872 function isImport(element) {
10873 return element.localName === 'link' && element.rel === 'import';
10874 }
10875
10876 function handleImport(element) {
10877 var loaded = element.import;
10878 if (loaded) {
10879 markTargetLoaded({target: element});
10880 } else {
10881 element.addEventListener('load', markTargetLoaded);
10882 element.addEventListener('error', markTargetLoaded);
10883 }
10884 }
10885
10886 function markTargetLoaded(event) {
10887 event.target.__loaded = true;
10888 }
10889
10890 }
10891
10892 // Fire the 'HTMLImportsLoaded' event when imports in document at load time
10893 // have loaded. This event is required to simulate the script blocking
10894 // behavior of native imports. A main document script that needs to be sure
10895 // imports have loaded should wait for this event.
10896 whenImportsReady(function() {
10897 HTMLImports.ready = true;
10898 HTMLImports.readyTime = new Date().getTime();
10899 mainDoc.dispatchEvent(
10900 new CustomEvent('HTMLImportsLoaded', {bubbles: true})
10901 );
10902 });
10903
10904 // exports
10905 scope.useNative = useNative;
10906 scope.isImportLoaded = isImportLoaded;
10907 scope.whenReady = whenImportsReady;
10908 scope.isIE = isIE;
10909
10910 // deprecated
10911 scope.whenImportsReady = whenImportsReady;
10912
10913 })(window.HTMLImports);
10914
10915 /*
10916 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
10917 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
10918 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
10919 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
10920 * Code distributed by Google as part of the polymer project is also
10921 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
10922 */ 10370 */
10923 (function(scope) { 10371 (function(scope) {
10924 10372
10925 // imports 10373 // imports
10926 var path = scope.path; 10374 var path = scope.path;
10927 var xhr = scope.xhr; 10375 var xhr = scope.xhr;
10928 var flags = scope.flags; 10376 var flags = scope.flags;
10929 10377
10930 // TODO(sorvell): this loader supports a dynamic list of urls 10378 // TODO(sorvell): this loader supports a dynamic list of urls
10931 // and an oncomplete callback that is called when the loader is done. 10379 // and an oncomplete callback that is called when the loader is done.
(...skipping 1791 matching lines...) Expand 10 before | Expand all | Expand 10 after
12723 /* 12171 /*
12724 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 12172 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
12725 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 12173 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
12726 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 12174 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
12727 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 12175 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
12728 * Code distributed by Google as part of the polymer project is also 12176 * Code distributed by Google as part of the polymer project is also
12729 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 12177 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
12730 */ 12178 */
12731 12179
12732 (function(scope) { 12180 (function(scope) {
12733 var endOfMicrotask = scope.endOfMicrotask;
12734 12181
12735 // Generic url loader 12182 // TODO(sorvell): It's desireable to provide a default stylesheet
12736 function Loader(regex) { 12183 // that's convenient for styling unresolved elements, but
12737 this.cache = Object.create(null); 12184 // it's cumbersome to have to include this manually in every page.
12738 this.map = Object.create(null); 12185 // It would make sense to put inside some HTMLImport but
12739 this.requests = 0; 12186 // the HTMLImports polyfill does not allow loading of stylesheets
12740 this.regex = regex; 12187 // that block rendering. Therefore this injection is tolerated here.
12741 }
12742 Loader.prototype = {
12743 12188
12744 // TODO(dfreedm): there may be a better factoring here 12189 var style = document.createElement('style');
12745 // extract absolute urls from the text (full of relative urls) 12190 style.textContent = ''
12746 extractUrls: function(text, base) { 12191 + 'body {'
12747 var matches = []; 12192 + 'transition: opacity ease-in 0.2s;'
12748 var matched, u; 12193 + ' } \n'
12749 while ((matched = this.regex.exec(text))) { 12194 + 'body[unresolved] {'
12750 u = new URL(matched[1], base); 12195 + 'opacity: 0; display: block; overflow: hidden;'
12751 matches.push({matched: matched[0], url: u.href}); 12196 + ' } \n'
12752 } 12197 ;
12753 return matches; 12198 var head = document.querySelector('head');
12754 }, 12199 head.insertBefore(style, head.firstChild);
12755 // take a text blob, a root url, and a callback and load all the urls found within the text
12756 // returns a map of absolute url to text
12757 process: function(text, root, callback) {
12758 var matches = this.extractUrls(text, root);
12759 12200
12760 // every call to process returns all the text this loader has ever receive d 12201 })(Platform);
12761 var done = callback.bind(null, this.map);
12762 this.fetch(matches, done);
12763 },
12764 // build a mapping of url -> text from matches
12765 fetch: function(matches, callback) {
12766 var inflight = matches.length;
12767
12768 // return early if there is no fetching to be done
12769 if (!inflight) {
12770 return callback();
12771 }
12772
12773 // wait for all subrequests to return
12774 var done = function() {
12775 if (--inflight === 0) {
12776 callback();
12777 }
12778 };
12779
12780 // start fetching all subrequests
12781 var m, req, url;
12782 for (var i = 0; i < inflight; i++) {
12783 m = matches[i];
12784 url = m.url;
12785 req = this.cache[url];
12786 // if this url has already been requested, skip requesting it again
12787 if (!req) {
12788 req = this.xhr(url);
12789 req.match = m;
12790 this.cache[url] = req;
12791 }
12792 // wait for the request to process its subrequests
12793 req.wait(done);
12794 }
12795 },
12796 handleXhr: function(request) {
12797 var match = request.match;
12798 var url = match.url;
12799
12800 // handle errors with an empty string
12801 var response = request.response || request.responseText || '';
12802 this.map[url] = response;
12803 this.fetch(this.extractUrls(response, url), request.resolve);
12804 },
12805 xhr: function(url) {
12806 this.requests++;
12807 var request = new XMLHttpRequest();
12808 request.open('GET', url, true);
12809 request.send();
12810 request.onerror = request.onload = this.handleXhr.bind(this, request);
12811
12812 // queue of tasks to run after XHR returns
12813 request.pending = [];
12814 request.resolve = function() {
12815 var pending = request.pending;
12816 for(var i = 0; i < pending.length; i++) {
12817 pending[i]();
12818 }
12819 request.pending = null;
12820 };
12821
12822 // if we have already resolved, pending is null, async call the callback
12823 request.wait = function(fn) {
12824 if (request.pending) {
12825 request.pending.push(fn);
12826 } else {
12827 endOfMicrotask(fn);
12828 }
12829 };
12830
12831 return request;
12832 }
12833 };
12834
12835 scope.Loader = Loader;
12836 })(window.Platform);
12837 12202
12838 /* 12203 /*
12839 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. 12204 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
12840 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt 12205 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
12841 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt 12206 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
12842 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt 12207 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
12843 * Code distributed by Google as part of the polymer project is also 12208 * Code distributed by Google as part of the polymer project is also
12844 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt 12209 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
12845 */ 12210 */
12846 12211
12847 (function(scope) { 12212 (function(scope) {
12848 12213
12849 var urlResolver = scope.urlResolver; 12214 function withDependencies(task, depends) {
12850 var Loader = scope.Loader; 12215 depends = depends || [];
12851 12216 if (!depends.map) {
12852 function StyleResolver() { 12217 depends = [depends];
12853 this.loader = new Loader(this.regex);
12854 }
12855 StyleResolver.prototype = {
12856 regex: /@import\s+(?:url)?["'\(]*([^'"\)]*)['"\)]*;/g,
12857 // Recursively replace @imports with the text at that url
12858 resolve: function(text, url, callback) {
12859 var done = function(map) {
12860 callback(this.flatten(text, url, map));
12861 }.bind(this);
12862 this.loader.process(text, url, done);
12863 },
12864 // resolve the textContent of a style node
12865 resolveNode: function(style, url, callback) {
12866 var text = style.textContent;
12867 var done = function(text) {
12868 style.textContent = text;
12869 callback(style);
12870 };
12871 this.resolve(text, url, done);
12872 },
12873 // flatten all the @imports to text
12874 flatten: function(text, base, map) {
12875 var matches = this.loader.extractUrls(text, base);
12876 var match, url, intermediate;
12877 for (var i = 0; i < matches.length; i++) {
12878 match = matches[i];
12879 url = match.url;
12880 // resolve any css text to be relative to the importer, keep absolute url
12881 intermediate = urlResolver.resolveCssText(map[url], url, true);
12882 // flatten intermediate @imports
12883 intermediate = this.flatten(intermediate, base, map);
12884 text = text.replace(match.matched, intermediate);
12885 } 12218 }
12886 return text; 12219 return task.apply(this, depends.map(marshal));
12887 },
12888 loadStyles: function(styles, base, callback) {
12889 var loaded=0, l = styles.length;
12890 // called in the context of the style
12891 function loadedStyle(style) {
12892 loaded++;
12893 if (loaded === l && callback) {
12894 callback();
12895 }
12896 }
12897 for (var i=0, s; (i<l) && (s=styles[i]); i++) {
12898 this.resolveNode(s, base, loadedStyle);
12899 }
12900 }
12901 };
12902
12903 var styleResolver = new StyleResolver();
12904
12905 // exports
12906 scope.styleResolver = styleResolver;
12907
12908 })(window.Platform);
12909
12910 // Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
12911 // This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
12912 // The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
12913 // The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
12914 // Code distributed by Google as part of the polymer project is also
12915 // subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
12916
12917 (function(global) {
12918 'use strict';
12919
12920 var filter = Array.prototype.filter.call.bind(Array.prototype.filter);
12921
12922 function getTreeScope(node) {
12923 while (node.parentNode) {
12924 node = node.parentNode;
12925 }
12926
12927 return typeof node.getElementById === 'function' ? node : null;
12928 } 12220 }
12929 12221
12930 Node.prototype.bind = function(name, observable) { 12222 function module(name, dependsOrFactory, moduleFactory) {
12931 console.error('Unhandled binding to Node: ', this, name, observable); 12223 var module;
12224 switch (arguments.length) {
12225 case 0:
12226 return;
12227 case 1:
12228 module = null;
12229 break;
12230 case 2:
12231 // dependsOrFactory is `factory` in this case
12232 module = dependsOrFactory.apply(this);
12233 break;
12234 default:
12235 // dependsOrFactory is `depends` in this case
12236 module = withDependencies(moduleFactory, dependsOrFactory);
12237 break;
12238 }
12239 modules[name] = module;
12932 }; 12240 };
12933 12241
12934 Node.prototype.bindFinished = function() {}; 12242 function marshal(name) {
12935 12243 return modules[name];
12936 function updateBindings(node, name, binding) {
12937 var bindings = node.bindings_;
12938 if (!bindings)
12939 bindings = node.bindings_ = {};
12940
12941 if (bindings[name])
12942 binding[name].close();
12943
12944 return bindings[name] = binding;
12945 } 12244 }
12946 12245
12947 function returnBinding(node, name, binding) { 12246 var modules = {};
12948 return binding;
12949 }
12950 12247
12951 function sanitizeValue(value) { 12248 function using(depends, task) {
12952 return value == null ? '' : value; 12249 HTMLImports.whenImportsReady(function() {
12953 } 12250 withDependencies(task, depends);
12954 12251 });
12955 function updateText(node, value) {
12956 node.data = sanitizeValue(value);
12957 }
12958
12959 function textBinding(node) {
12960 return function(value) {
12961 return updateText(node, value);
12962 };
12963 }
12964
12965 var maybeUpdateBindings = returnBinding;
12966
12967 Object.defineProperty(Platform, 'enableBindingsReflection', {
12968 get: function() {
12969 return maybeUpdateBindings === updateBindings;
12970 },
12971 set: function(enable) {
12972 maybeUpdateBindings = enable ? updateBindings : returnBinding;
12973 return enable;
12974 },
12975 configurable: true
12976 });
12977
12978 Text.prototype.bind = function(name, value, oneTime) {
12979 if (name !== 'textContent')
12980 return Node.prototype.bind.call(this, name, value, oneTime);
12981
12982 if (oneTime)
12983 return updateText(this, value);
12984
12985 var observable = value;
12986 updateText(this, observable.open(textBinding(this)));
12987 return maybeUpdateBindings(this, name, observable);
12988 }
12989
12990 function updateAttribute(el, name, conditional, value) {
12991 if (conditional) {
12992 if (value)
12993 el.setAttribute(name, '');
12994 else
12995 el.removeAttribute(name);
12996 return;
12997 }
12998
12999 el.setAttribute(name, sanitizeValue(value));
13000 }
13001
13002 function attributeBinding(el, name, conditional) {
13003 return function(value) {
13004 updateAttribute(el, name, conditional, value);
13005 };
13006 }
13007
13008 Element.prototype.bind = function(name, value, oneTime) {
13009 var conditional = name[name.length - 1] == '?';
13010 if (conditional) {
13011 this.removeAttribute(name);
13012 name = name.slice(0, -1);
13013 }
13014
13015 if (oneTime)
13016 return updateAttribute(this, name, conditional, value);
13017
13018
13019 var observable = value;
13020 updateAttribute(this, name, conditional,
13021 observable.open(attributeBinding(this, name, conditional)));
13022
13023 return maybeUpdateBindings(this, name, observable);
13024 }; 12252 };
13025 12253
13026 var checkboxEventType; 12254 // exports
13027 (function() {
13028 // Attempt to feature-detect which event (change or click) is fired first
13029 // for checkboxes.
13030 var div = document.createElement('div');
13031 var checkbox = div.appendChild(document.createElement('input'));
13032 checkbox.setAttribute('type', 'checkbox');
13033 var first;
13034 var count = 0;
13035 checkbox.addEventListener('click', function(e) {
13036 count++;
13037 first = first || 'click';
13038 });
13039 checkbox.addEventListener('change', function() {
13040 count++;
13041 first = first || 'change';
13042 });
13043 12255
13044 var event = document.createEvent('MouseEvent'); 12256 scope.marshal = marshal;
13045 event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, 12257 // `module` confuses commonjs detectors
13046 false, false, false, 0, null); 12258 scope.modularize = module;
13047 checkbox.dispatchEvent(event); 12259 scope.using = using;
13048 // WebKit/Blink don't fire the change event if the element is outside the
13049 // document, so assume 'change' for that case.
13050 checkboxEventType = count == 1 ? 'change' : first;
13051 })();
13052 12260
13053 function getEventForInputType(element) { 12261 })(window);
13054 switch (element.type) {
13055 case 'checkbox':
13056 return checkboxEventType;
13057 case 'radio':
13058 case 'select-multiple':
13059 case 'select-one':
13060 return 'change';
13061 case 'range':
13062 if (/Trident|MSIE/.test(navigator.userAgent))
13063 return 'change';
13064 default:
13065 return 'input';
13066 }
13067 }
13068
13069 function updateInput(input, property, value, santizeFn) {
13070 input[property] = (santizeFn || sanitizeValue)(value);
13071 }
13072
13073 function inputBinding(input, property, santizeFn) {
13074 return function(value) {
13075 return updateInput(input, property, value, santizeFn);
13076 }
13077 }
13078
13079 function noop() {}
13080
13081 function bindInputEvent(input, property, observable, postEventFn) {
13082 var eventType = getEventForInputType(input);
13083
13084 function eventHandler() {
13085 observable.setValue(input[property]);
13086 observable.discardChanges();
13087 (postEventFn || noop)(input);
13088 Platform.performMicrotaskCheckpoint();
13089 }
13090 input.addEventListener(eventType, eventHandler);
13091
13092 return {
13093 close: function() {
13094 input.removeEventListener(eventType, eventHandler);
13095 observable.close();
13096 },
13097
13098 observable_: observable
13099 }
13100 }
13101
13102 function booleanSanitize(value) {
13103 return Boolean(value);
13104 }
13105
13106 // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
13107 // Returns an array containing all radio buttons other than |element| that
13108 // have the same |name|, either in the form that |element| belongs to or,
13109 // if no form, in the document tree to which |element| belongs.
13110 //
13111 // This implementation is based upon the HTML spec definition of a
13112 // "radio button group":
13113 // http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state. html#radio-button-group
13114 //
13115 function getAssociatedRadioButtons(element) {
13116 if (element.form) {
13117 return filter(element.form.elements, function(el) {
13118 return el != element &&
13119 el.tagName == 'INPUT' &&
13120 el.type == 'radio' &&
13121 el.name == element.name;
13122 });
13123 } else {
13124 var treeScope = getTreeScope(element);
13125 if (!treeScope)
13126 return [];
13127 var radios = treeScope.querySelectorAll(
13128 'input[type="radio"][name="' + element.name + '"]');
13129 return filter(radios, function(el) {
13130 return el != element && !el.form;
13131 });
13132 }
13133 }
13134
13135 function checkedPostEvent(input) {
13136 // Only the radio button that is getting checked gets an event. We
13137 // therefore find all the associated radio buttons and update their
13138 // check binding manually.
13139 if (input.tagName === 'INPUT' &&
13140 input.type === 'radio') {
13141 getAssociatedRadioButtons(input).forEach(function(radio) {
13142 var checkedBinding = radio.bindings_.checked;
13143 if (checkedBinding) {
13144 // Set the value directly to avoid an infinite call stack.
13145 checkedBinding.observable_.setValue(false);
13146 }
13147 });
13148 }
13149 }
13150
13151 HTMLInputElement.prototype.bind = function(name, value, oneTime) {
13152 if (name !== 'value' && name !== 'checked')
13153 return HTMLElement.prototype.bind.call(this, name, value, oneTime);
13154
13155 this.removeAttribute(name);
13156 var sanitizeFn = name == 'checked' ? booleanSanitize : sanitizeValue;
13157 var postEventFn = name == 'checked' ? checkedPostEvent : noop;
13158
13159 if (oneTime)
13160 return updateInput(this, name, value, sanitizeFn);
13161
13162
13163 var observable = value;
13164 var binding = bindInputEvent(this, name, observable, postEventFn);
13165 updateInput(this, name,
13166 observable.open(inputBinding(this, name, sanitizeFn)),
13167 sanitizeFn);
13168
13169 // Checkboxes may need to update bindings of other checkboxes.
13170 return updateBindings(this, name, binding);
13171 }
13172
13173 HTMLTextAreaElement.prototype.bind = function(name, value, oneTime) {
13174 if (name !== 'value')
13175 return HTMLElement.prototype.bind.call(this, name, value, oneTime);
13176
13177 this.removeAttribute('value');
13178
13179 if (oneTime)
13180 return updateInput(this, 'value', value);
13181
13182 var observable = value;
13183 var binding = bindInputEvent(this, 'value', observable);
13184 updateInput(this, 'value',
13185 observable.open(inputBinding(this, 'value', sanitizeValue)));
13186 return maybeUpdateBindings(this, name, binding);
13187 }
13188
13189 function updateOption(option, value) {
13190 var parentNode = option.parentNode;;
13191 var select;
13192 var selectBinding;
13193 var oldValue;
13194 if (parentNode instanceof HTMLSelectElement &&
13195 parentNode.bindings_ &&
13196 parentNode.bindings_.value) {
13197 select = parentNode;
13198 selectBinding = select.bindings_.value;
13199 oldValue = select.value;
13200 }
13201
13202 option.value = sanitizeValue(value);
13203
13204 if (select && select.value != oldValue) {
13205 selectBinding.observable_.setValue(select.value);
13206 selectBinding.observable_.discardChanges();
13207 Platform.performMicrotaskCheckpoint();
13208 }
13209 }
13210
13211 function optionBinding(option) {
13212 return function(value) {
13213 updateOption(option, value);
13214 }
13215 }
13216
13217 HTMLOptionElement.prototype.bind = function(name, value, oneTime) {
13218 if (name !== 'value')
13219 return HTMLElement.prototype.bind.call(this, name, value, oneTime);
13220
13221 this.removeAttribute('value');
13222
13223 if (oneTime)
13224 return updateOption(this, value);
13225
13226 var observable = value;
13227 var binding = bindInputEvent(this, 'value', observable);
13228 updateOption(this, observable.open(optionBinding(this)));
13229 return maybeUpdateBindings(this, name, binding);
13230 }
13231
13232 HTMLSelectElement.prototype.bind = function(name, value, oneTime) {
13233 if (name === 'selectedindex')
13234 name = 'selectedIndex';
13235
13236 if (name !== 'selectedIndex' && name !== 'value')
13237 return HTMLElement.prototype.bind.call(this, name, value, oneTime);
13238
13239 this.removeAttribute(name);
13240
13241 if (oneTime)
13242 return updateInput(this, name, value);
13243
13244 var observable = value;
13245 var binding = bindInputEvent(this, name, observable);
13246 updateInput(this, name,
13247 observable.open(inputBinding(this, name)));
13248
13249 // Option update events may need to access select bindings.
13250 return updateBindings(this, name, binding);
13251 }
13252 })(this);
13253
13254 // Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
13255 // This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
13256 // The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
13257 // The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
13258 // Code distributed by Google as part of the polymer project is also
13259 // subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
13260
13261 (function(global) {
13262 'use strict';
13263
13264 function assert(v) {
13265 if (!v)
13266 throw new Error('Assertion failed');
13267 }
13268
13269 var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
13270
13271 function getFragmentRoot(node) {
13272 var p;
13273 while (p = node.parentNode) {
13274 node = p;
13275 }
13276
13277 return node;
13278 }
13279
13280 function searchRefId(node, id) {
13281 if (!id)
13282 return;
13283
13284 var ref;
13285 var selector = '#' + id;
13286 while (!ref) {
13287 node = getFragmentRoot(node);
13288
13289 if (node.protoContent_)
13290 ref = node.protoContent_.querySelector(selector);
13291 else if (node.getElementById)
13292 ref = node.getElementById(id);
13293
13294 if (ref || !node.templateCreator_)
13295 break
13296
13297 node = node.templateCreator_;
13298 }
13299
13300 return ref;
13301 }
13302
13303 function getInstanceRoot(node) {
13304 while (node.parentNode) {
13305 node = node.parentNode;
13306 }
13307 return node.templateCreator_ ? node : null;
13308 }
13309
13310 var Map;
13311 if (global.Map && typeof global.Map.prototype.forEach === 'function') {
13312 Map = global.Map;
13313 } else {
13314 Map = function() {
13315 this.keys = [];
13316 this.values = [];
13317 };
13318
13319 Map.prototype = {
13320 set: function(key, value) {
13321 var index = this.keys.indexOf(key);
13322 if (index < 0) {
13323 this.keys.push(key);
13324 this.values.push(value);
13325 } else {
13326 this.values[index] = value;
13327 }
13328 },
13329
13330 get: function(key) {
13331 var index = this.keys.indexOf(key);
13332 if (index < 0)
13333 return;
13334
13335 return this.values[index];
13336 },
13337
13338 delete: function(key, value) {
13339 var index = this.keys.indexOf(key);
13340 if (index < 0)
13341 return false;
13342
13343 this.keys.splice(index, 1);
13344 this.values.splice(index, 1);
13345 return true;
13346 },
13347
13348 forEach: function(f, opt_this) {
13349 for (var i = 0; i < this.keys.length; i++)
13350 f.call(opt_this || this, this.values[i], this.keys[i], this);
13351 }
13352 };
13353 }
13354
13355 // JScript does not have __proto__. We wrap all object literals with
13356 // createObject which uses Object.create, Object.defineProperty and
13357 // Object.getOwnPropertyDescriptor to create a new object that does the exact
13358 // same thing. The main downside to this solution is that we have to extract
13359 // all those property descriptors for IE.
13360 var createObject = ('__proto__' in {}) ?
13361 function(obj) { return obj; } :
13362 function(obj) {
13363 var proto = obj.__proto__;
13364 if (!proto)
13365 return obj;
13366 var newObject = Object.create(proto);
13367 Object.getOwnPropertyNames(obj).forEach(function(name) {
13368 Object.defineProperty(newObject, name,
13369 Object.getOwnPropertyDescriptor(obj, name));
13370 });
13371 return newObject;
13372 };
13373
13374 // IE does not support have Document.prototype.contains.
13375 if (typeof document.contains != 'function') {
13376 Document.prototype.contains = function(node) {
13377 if (node === this || node.parentNode === this)
13378 return true;
13379 return this.documentElement.contains(node);
13380 }
13381 }
13382
13383 var BIND = 'bind';
13384 var REPEAT = 'repeat';
13385 var IF = 'if';
13386
13387 var templateAttributeDirectives = {
13388 'template': true,
13389 'repeat': true,
13390 'bind': true,
13391 'ref': true
13392 };
13393
13394 var semanticTemplateElements = {
13395 'THEAD': true,
13396 'TBODY': true,
13397 'TFOOT': true,
13398 'TH': true,
13399 'TR': true,
13400 'TD': true,
13401 'COLGROUP': true,
13402 'COL': true,
13403 'CAPTION': true,
13404 'OPTION': true,
13405 'OPTGROUP': true
13406 };
13407
13408 var hasTemplateElement = typeof HTMLTemplateElement !== 'undefined';
13409 if (hasTemplateElement) {
13410 // TODO(rafaelw): Remove when fix for
13411 // https://codereview.chromium.org/164803002/
13412 // makes it to Chrome release.
13413 (function() {
13414 var t = document.createElement('template');
13415 var d = t.content.ownerDocument;
13416 var html = d.appendChild(d.createElement('html'));
13417 var head = html.appendChild(d.createElement('head'));
13418 var base = d.createElement('base');
13419 base.href = document.baseURI;
13420 head.appendChild(base);
13421 })();
13422 }
13423
13424 var allTemplatesSelectors = 'template, ' +
13425 Object.keys(semanticTemplateElements).map(function(tagName) {
13426 return tagName.toLowerCase() + '[template]';
13427 }).join(', ');
13428
13429 function isSVGTemplate(el) {
13430 return el.tagName == 'template' &&
13431 el.namespaceURI == 'http://www.w3.org/2000/svg';
13432 }
13433
13434 function isHTMLTemplate(el) {
13435 return el.tagName == 'TEMPLATE' &&
13436 el.namespaceURI == 'http://www.w3.org/1999/xhtml';
13437 }
13438
13439 function isAttributeTemplate(el) {
13440 return Boolean(semanticTemplateElements[el.tagName] &&
13441 el.hasAttribute('template'));
13442 }
13443
13444 function isTemplate(el) {
13445 if (el.isTemplate_ === undefined)
13446 el.isTemplate_ = el.tagName == 'TEMPLATE' || isAttributeTemplate(el);
13447
13448 return el.isTemplate_;
13449 }
13450
13451 // FIXME: Observe templates being added/removed from documents
13452 // FIXME: Expose imperative API to decorate and observe templates in
13453 // "disconnected tress" (e.g. ShadowRoot)
13454 document.addEventListener('DOMContentLoaded', function(e) {
13455 bootstrapTemplatesRecursivelyFrom(document);
13456 // FIXME: Is this needed? Seems like it shouldn't be.
13457 Platform.performMicrotaskCheckpoint();
13458 }, false);
13459
13460 function forAllTemplatesFrom(node, fn) {
13461 var subTemplates = node.querySelectorAll(allTemplatesSelectors);
13462
13463 if (isTemplate(node))
13464 fn(node)
13465 forEach(subTemplates, fn);
13466 }
13467
13468 function bootstrapTemplatesRecursivelyFrom(node) {
13469 function bootstrap(template) {
13470 if (!HTMLTemplateElement.decorate(template))
13471 bootstrapTemplatesRecursivelyFrom(template.content);
13472 }
13473
13474 forAllTemplatesFrom(node, bootstrap);
13475 }
13476
13477 if (!hasTemplateElement) {
13478 /**
13479 * This represents a <template> element.
13480 * @constructor
13481 * @extends {HTMLElement}
13482 */
13483 global.HTMLTemplateElement = function() {
13484 throw TypeError('Illegal constructor');
13485 };
13486 }
13487
13488 var hasProto = '__proto__' in {};
13489
13490 function mixin(to, from) {
13491 Object.getOwnPropertyNames(from).forEach(function(name) {
13492 Object.defineProperty(to, name,
13493 Object.getOwnPropertyDescriptor(from, name));
13494 });
13495 }
13496
13497 // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html# dfn-template-contents-owner
13498 function getOrCreateTemplateContentsOwner(template) {
13499 var doc = template.ownerDocument
13500 if (!doc.defaultView)
13501 return doc;
13502 var d = doc.templateContentsOwner_;
13503 if (!d) {
13504 // TODO(arv): This should either be a Document or HTMLDocument depending
13505 // on doc.
13506 d = doc.implementation.createHTMLDocument('');
13507 while (d.lastChild) {
13508 d.removeChild(d.lastChild);
13509 }
13510 doc.templateContentsOwner_ = d;
13511 }
13512 return d;
13513 }
13514
13515 function getTemplateStagingDocument(template) {
13516 if (!template.stagingDocument_) {
13517 var owner = template.ownerDocument;
13518 if (!owner.stagingDocument_) {
13519 owner.stagingDocument_ = owner.implementation.createHTMLDocument('');
13520 owner.stagingDocument_.isStagingDocument = true;
13521 // TODO(rafaelw): Remove when fix for
13522 // https://codereview.chromium.org/164803002/
13523 // makes it to Chrome release.
13524 var base = owner.stagingDocument_.createElement('base');
13525 base.href = document.baseURI;
13526 owner.stagingDocument_.head.appendChild(base);
13527
13528 owner.stagingDocument_.stagingDocument_ = owner.stagingDocument_;
13529 }
13530
13531 template.stagingDocument_ = owner.stagingDocument_;
13532 }
13533
13534 return template.stagingDocument_;
13535 }
13536
13537 // For non-template browsers, the parser will disallow <template> in certain
13538 // locations, so we allow "attribute templates" which combine the template
13539 // element with the top-level container node of the content, e.g.
13540 //
13541 // <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr>
13542 //
13543 // becomes
13544 //
13545 // <template repeat="{{ foo }}">
13546 // + #document-fragment
13547 // + <tr class="bar">
13548 // + <td>Bar</td>
13549 //
13550 function extractTemplateFromAttributeTemplate(el) {
13551 var template = el.ownerDocument.createElement('template');
13552 el.parentNode.insertBefore(template, el);
13553
13554 var attribs = el.attributes;
13555 var count = attribs.length;
13556 while (count-- > 0) {
13557 var attrib = attribs[count];
13558 if (templateAttributeDirectives[attrib.name]) {
13559 if (attrib.name !== 'template')
13560 template.setAttribute(attrib.name, attrib.value);
13561 el.removeAttribute(attrib.name);
13562 }
13563 }
13564
13565 return template;
13566 }
13567
13568 function extractTemplateFromSVGTemplate(el) {
13569 var template = el.ownerDocument.createElement('template');
13570 el.parentNode.insertBefore(template, el);
13571
13572 var attribs = el.attributes;
13573 var count = attribs.length;
13574 while (count-- > 0) {
13575 var attrib = attribs[count];
13576 template.setAttribute(attrib.name, attrib.value);
13577 el.removeAttribute(attrib.name);
13578 }
13579
13580 el.parentNode.removeChild(el);
13581 return template;
13582 }
13583
13584 function liftNonNativeTemplateChildrenIntoContent(template, el, useRoot) {
13585 var content = template.content;
13586 if (useRoot) {
13587 content.appendChild(el);
13588 return;
13589 }
13590
13591 var child;
13592 while (child = el.firstChild) {
13593 content.appendChild(child);
13594 }
13595 }
13596
13597 var templateObserver;
13598 if (typeof MutationObserver == 'function') {
13599 templateObserver = new MutationObserver(function(records) {
13600 for (var i = 0; i < records.length; i++) {
13601 records[i].target.refChanged_();
13602 }
13603 });
13604 }
13605
13606 /**
13607 * Ensures proper API and content model for template elements.
13608 * @param {HTMLTemplateElement} opt_instanceRef The template element which
13609 * |el| template element will return as the value of its ref(), and whose
13610 * content will be used as source when createInstance() is invoked.
13611 */
13612 HTMLTemplateElement.decorate = function(el, opt_instanceRef) {
13613 if (el.templateIsDecorated_)
13614 return false;
13615
13616 var templateElement = el;
13617 templateElement.templateIsDecorated_ = true;
13618
13619 var isNativeHTMLTemplate = isHTMLTemplate(templateElement) &&
13620 hasTemplateElement;
13621 var bootstrapContents = isNativeHTMLTemplate;
13622 var liftContents = !isNativeHTMLTemplate;
13623 var liftRoot = false;
13624
13625 if (!isNativeHTMLTemplate) {
13626 if (isAttributeTemplate(templateElement)) {
13627 assert(!opt_instanceRef);
13628 templateElement = extractTemplateFromAttributeTemplate(el);
13629 templateElement.templateIsDecorated_ = true;
13630 isNativeHTMLTemplate = hasTemplateElement;
13631 liftRoot = true;
13632 } else if (isSVGTemplate(templateElement)) {
13633 templateElement = extractTemplateFromSVGTemplate(el);
13634 templateElement.templateIsDecorated_ = true;
13635 isNativeHTMLTemplate = hasTemplateElement;
13636 }
13637 }
13638
13639 if (!isNativeHTMLTemplate) {
13640 fixTemplateElementPrototype(templateElement);
13641 var doc = getOrCreateTemplateContentsOwner(templateElement);
13642 templateElement.content_ = doc.createDocumentFragment();
13643 }
13644
13645 if (opt_instanceRef) {
13646 // template is contained within an instance, its direct content must be
13647 // empty
13648 templateElement.instanceRef_ = opt_instanceRef;
13649 } else if (liftContents) {
13650 liftNonNativeTemplateChildrenIntoContent(templateElement,
13651 el,
13652 liftRoot);
13653 } else if (bootstrapContents) {
13654 bootstrapTemplatesRecursivelyFrom(templateElement.content);
13655 }
13656
13657 return true;
13658 };
13659
13660 // TODO(rafaelw): This used to decorate recursively all templates from a given
13661 // node. This happens by default on 'DOMContentLoaded', but may be needed
13662 // in subtrees not descendent from document (e.g. ShadowRoot).
13663 // Review whether this is the right public API.
13664 HTMLTemplateElement.bootstrap = bootstrapTemplatesRecursivelyFrom;
13665
13666 var htmlElement = global.HTMLUnknownElement || HTMLElement;
13667
13668 var contentDescriptor = {
13669 get: function() {
13670 return this.content_;
13671 },
13672 enumerable: true,
13673 configurable: true
13674 };
13675
13676 if (!hasTemplateElement) {
13677 // Gecko is more picky with the prototype than WebKit. Make sure to use the
13678 // same prototype as created in the constructor.
13679 HTMLTemplateElement.prototype = Object.create(htmlElement.prototype);
13680
13681 Object.defineProperty(HTMLTemplateElement.prototype, 'content',
13682 contentDescriptor);
13683 }
13684
13685 function fixTemplateElementPrototype(el) {
13686 if (hasProto)
13687 el.__proto__ = HTMLTemplateElement.prototype;
13688 else
13689 mixin(el, HTMLTemplateElement.prototype);
13690 }
13691
13692 function ensureSetModelScheduled(template) {
13693 if (!template.setModelFn_) {
13694 template.setModelFn_ = function() {
13695 template.setModelFnScheduled_ = false;
13696 var map = getBindings(template,
13697 template.delegate_ && template.delegate_.prepareBinding);
13698 processBindings(template, map, template.model_);
13699 };
13700 }
13701
13702 if (!template.setModelFnScheduled_) {
13703 template.setModelFnScheduled_ = true;
13704 Observer.runEOM_(template.setModelFn_);
13705 }
13706 }
13707
13708 mixin(HTMLTemplateElement.prototype, {
13709 bind: function(name, value, oneTime) {
13710 if (name != 'ref')
13711 return Element.prototype.bind.call(this, name, value, oneTime);
13712
13713 var self = this;
13714 var ref = oneTime ? value : value.open(function(ref) {
13715 self.setAttribute('ref', ref);
13716 self.refChanged_();
13717 });
13718
13719 this.setAttribute('ref', ref);
13720 this.refChanged_();
13721 if (oneTime)
13722 return;
13723
13724 if (!this.bindings_) {
13725 this.bindings_ = { ref: value };
13726 } else {
13727 this.bindings_.ref = value;
13728 }
13729
13730 return value;
13731 },
13732
13733 processBindingDirectives_: function(directives) {
13734 if (this.iterator_)
13735 this.iterator_.closeDeps();
13736
13737 if (!directives.if && !directives.bind && !directives.repeat) {
13738 if (this.iterator_) {
13739 this.iterator_.close();
13740 this.iterator_ = undefined;
13741 }
13742
13743 return;
13744 }
13745
13746 if (!this.iterator_) {
13747 this.iterator_ = new TemplateIterator(this);
13748 }
13749
13750 this.iterator_.updateDependencies(directives, this.model_);
13751
13752 if (templateObserver) {
13753 templateObserver.observe(this, { attributes: true,
13754 attributeFilter: ['ref'] });
13755 }
13756
13757 return this.iterator_;
13758 },
13759
13760 createInstance: function(model, bindingDelegate, delegate_) {
13761 if (bindingDelegate)
13762 delegate_ = this.newDelegate_(bindingDelegate);
13763 else if (!delegate_)
13764 delegate_ = this.delegate_;
13765
13766 if (!this.refContent_)
13767 this.refContent_ = this.ref_.content;
13768 var content = this.refContent_;
13769 if (content.firstChild === null)
13770 return emptyInstance;
13771
13772 var map = getInstanceBindingMap(content, delegate_);
13773 var stagingDocument = getTemplateStagingDocument(this);
13774 var instance = stagingDocument.createDocumentFragment();
13775 instance.templateCreator_ = this;
13776 instance.protoContent_ = content;
13777 instance.bindings_ = [];
13778 instance.terminator_ = null;
13779 var instanceRecord = instance.templateInstance_ = {
13780 firstNode: null,
13781 lastNode: null,
13782 model: model
13783 };
13784
13785 var i = 0;
13786 var collectTerminator = false;
13787 for (var child = content.firstChild; child; child = child.nextSibling) {
13788 // The terminator of the instance is the clone of the last child of the
13789 // content. If the last child is an active template, it may produce
13790 // instances as a result of production, so simply collecting the last
13791 // child of the instance after it has finished producing may be wrong.
13792 if (child.nextSibling === null)
13793 collectTerminator = true;
13794
13795 var clone = cloneAndBindInstance(child, instance, stagingDocument,
13796 map.children[i++],
13797 model,
13798 delegate_,
13799 instance.bindings_);
13800 clone.templateInstance_ = instanceRecord;
13801 if (collectTerminator)
13802 instance.terminator_ = clone;
13803 }
13804
13805 instanceRecord.firstNode = instance.firstChild;
13806 instanceRecord.lastNode = instance.lastChild;
13807 instance.templateCreator_ = undefined;
13808 instance.protoContent_ = undefined;
13809 return instance;
13810 },
13811
13812 get model() {
13813 return this.model_;
13814 },
13815
13816 set model(model) {
13817 this.model_ = model;
13818 ensureSetModelScheduled(this);
13819 },
13820
13821 get bindingDelegate() {
13822 return this.delegate_ && this.delegate_.raw;
13823 },
13824
13825 refChanged_: function() {
13826 if (!this.iterator_ || this.refContent_ === this.ref_.content)
13827 return;
13828
13829 this.refContent_ = undefined;
13830 this.iterator_.valueChanged();
13831 this.iterator_.updateIteratedValue(this.iterator_.getUpdatedValue());
13832 },
13833
13834 clear: function() {
13835 this.model_ = undefined;
13836 this.delegate_ = undefined;
13837 if (this.bindings_ && this.bindings_.ref)
13838 this.bindings_.ref.close()
13839 this.refContent_ = undefined;
13840 if (!this.iterator_)
13841 return;
13842 this.iterator_.valueChanged();
13843 this.iterator_.close()
13844 this.iterator_ = undefined;
13845 },
13846
13847 setDelegate_: function(delegate) {
13848 this.delegate_ = delegate;
13849 this.bindingMap_ = undefined;
13850 if (this.iterator_) {
13851 this.iterator_.instancePositionChangedFn_ = undefined;
13852 this.iterator_.instanceModelFn_ = undefined;
13853 }
13854 },
13855
13856 newDelegate_: function(bindingDelegate) {
13857 if (!bindingDelegate)
13858 return;
13859
13860 function delegateFn(name) {
13861 var fn = bindingDelegate && bindingDelegate[name];
13862 if (typeof fn != 'function')
13863 return;
13864
13865 return function() {
13866 return fn.apply(bindingDelegate, arguments);
13867 };
13868 }
13869
13870 return {
13871 bindingMaps: {},
13872 raw: bindingDelegate,
13873 prepareBinding: delegateFn('prepareBinding'),
13874 prepareInstanceModel: delegateFn('prepareInstanceModel'),
13875 prepareInstancePositionChanged:
13876 delegateFn('prepareInstancePositionChanged')
13877 };
13878 },
13879
13880 set bindingDelegate(bindingDelegate) {
13881 if (this.delegate_) {
13882 throw Error('Template must be cleared before a new bindingDelegate ' +
13883 'can be assigned');
13884 }
13885
13886 this.setDelegate_(this.newDelegate_(bindingDelegate));
13887 },
13888
13889 get ref_() {
13890 var ref = searchRefId(this, this.getAttribute('ref'));
13891 if (!ref)
13892 ref = this.instanceRef_;
13893
13894 if (!ref)
13895 return this;
13896
13897 var nextRef = ref.ref_;
13898 return nextRef ? nextRef : ref;
13899 }
13900 });
13901
13902 // Returns
13903 // a) undefined if there are no mustaches.
13904 // b) [TEXT, (ONE_TIME?, PATH, DELEGATE_FN, TEXT)+] if there is at least one mustache.
13905 function parseMustaches(s, name, node, prepareBindingFn) {
13906 if (!s || !s.length)
13907 return;
13908
13909 var tokens;
13910 var length = s.length;
13911 var startIndex = 0, lastIndex = 0, endIndex = 0;
13912 var onlyOneTime = true;
13913 while (lastIndex < length) {
13914 var startIndex = s.indexOf('{{', lastIndex);
13915 var oneTimeStart = s.indexOf('[[', lastIndex);
13916 var oneTime = false;
13917 var terminator = '}}';
13918
13919 if (oneTimeStart >= 0 &&
13920 (startIndex < 0 || oneTimeStart < startIndex)) {
13921 startIndex = oneTimeStart;
13922 oneTime = true;
13923 terminator = ']]';
13924 }
13925
13926 endIndex = startIndex < 0 ? -1 : s.indexOf(terminator, startIndex + 2);
13927
13928 if (endIndex < 0) {
13929 if (!tokens)
13930 return;
13931
13932 tokens.push(s.slice(lastIndex)); // TEXT
13933 break;
13934 }
13935
13936 tokens = tokens || [];
13937 tokens.push(s.slice(lastIndex, startIndex)); // TEXT
13938 var pathString = s.slice(startIndex + 2, endIndex).trim();
13939 tokens.push(oneTime); // ONE_TIME?
13940 onlyOneTime = onlyOneTime && oneTime;
13941 var delegateFn = prepareBindingFn &&
13942 prepareBindingFn(pathString, name, node);
13943 // Don't try to parse the expression if there's a prepareBinding function
13944 if (delegateFn == null) {
13945 tokens.push(Path.get(pathString)); // PATH
13946 } else {
13947 tokens.push(null);
13948 }
13949 tokens.push(delegateFn); // DELEGATE_FN
13950 lastIndex = endIndex + 2;
13951 }
13952
13953 if (lastIndex === length)
13954 tokens.push(''); // TEXT
13955
13956 tokens.hasOnePath = tokens.length === 5;
13957 tokens.isSimplePath = tokens.hasOnePath &&
13958 tokens[0] == '' &&
13959 tokens[4] == '';
13960 tokens.onlyOneTime = onlyOneTime;
13961
13962 tokens.combinator = function(values) {
13963 var newValue = tokens[0];
13964
13965 for (var i = 1; i < tokens.length; i += 4) {
13966 var value = tokens.hasOnePath ? values : values[(i - 1) / 4];
13967 if (value !== undefined)
13968 newValue += value;
13969 newValue += tokens[i + 3];
13970 }
13971
13972 return newValue;
13973 }
13974
13975 return tokens;
13976 };
13977
13978 function processOneTimeBinding(name, tokens, node, model) {
13979 if (tokens.hasOnePath) {
13980 var delegateFn = tokens[3];
13981 var value = delegateFn ? delegateFn(model, node, true) :
13982 tokens[2].getValueFrom(model);
13983 return tokens.isSimplePath ? value : tokens.combinator(value);
13984 }
13985
13986 var values = [];
13987 for (var i = 1; i < tokens.length; i += 4) {
13988 var delegateFn = tokens[i + 2];
13989 values[(i - 1) / 4] = delegateFn ? delegateFn(model, node) :
13990 tokens[i + 1].getValueFrom(model);
13991 }
13992
13993 return tokens.combinator(values);
13994 }
13995
13996 function processSinglePathBinding(name, tokens, node, model) {
13997 var delegateFn = tokens[3];
13998 var observer = delegateFn ? delegateFn(model, node, false) :
13999 new PathObserver(model, tokens[2]);
14000
14001 return tokens.isSimplePath ? observer :
14002 new ObserverTransform(observer, tokens.combinator);
14003 }
14004
14005 function processBinding(name, tokens, node, model) {
14006 if (tokens.onlyOneTime)
14007 return processOneTimeBinding(name, tokens, node, model);
14008
14009 if (tokens.hasOnePath)
14010 return processSinglePathBinding(name, tokens, node, model);
14011
14012 var observer = new CompoundObserver();
14013
14014 for (var i = 1; i < tokens.length; i += 4) {
14015 var oneTime = tokens[i];
14016 var delegateFn = tokens[i + 2];
14017
14018 if (delegateFn) {
14019 var value = delegateFn(model, node, oneTime);
14020 if (oneTime)
14021 observer.addPath(value)
14022 else
14023 observer.addObserver(value);
14024 continue;
14025 }
14026
14027 var path = tokens[i + 1];
14028 if (oneTime)
14029 observer.addPath(path.getValueFrom(model))
14030 else
14031 observer.addPath(model, path);
14032 }
14033
14034 return new ObserverTransform(observer, tokens.combinator);
14035 }
14036
14037 function processBindings(node, bindings, model, instanceBindings) {
14038 for (var i = 0; i < bindings.length; i += 2) {
14039 var name = bindings[i]
14040 var tokens = bindings[i + 1];
14041 var value = processBinding(name, tokens, node, model);
14042 var binding = node.bind(name, value, tokens.onlyOneTime);
14043 if (binding && instanceBindings)
14044 instanceBindings.push(binding);
14045 }
14046
14047 node.bindFinished();
14048 if (!bindings.isTemplate)
14049 return;
14050
14051 node.model_ = model;
14052 var iter = node.processBindingDirectives_(bindings);
14053 if (instanceBindings && iter)
14054 instanceBindings.push(iter);
14055 }
14056
14057 function parseWithDefault(el, name, prepareBindingFn) {
14058 var v = el.getAttribute(name);
14059 return parseMustaches(v == '' ? '{{}}' : v, name, el, prepareBindingFn);
14060 }
14061
14062 function parseAttributeBindings(element, prepareBindingFn) {
14063 assert(element);
14064
14065 var bindings = [];
14066 var ifFound = false;
14067 var bindFound = false;
14068
14069 for (var i = 0; i < element.attributes.length; i++) {
14070 var attr = element.attributes[i];
14071 var name = attr.name;
14072 var value = attr.value;
14073
14074 // Allow bindings expressed in attributes to be prefixed with underbars.
14075 // We do this to allow correct semantics for browsers that don't implement
14076 // <template> where certain attributes might trigger side-effects -- and
14077 // for IE which sanitizes certain attributes, disallowing mustache
14078 // replacements in their text.
14079 while (name[0] === '_') {
14080 name = name.substring(1);
14081 }
14082
14083 if (isTemplate(element) &&
14084 (name === IF || name === BIND || name === REPEAT)) {
14085 continue;
14086 }
14087
14088 var tokens = parseMustaches(value, name, element,
14089 prepareBindingFn);
14090 if (!tokens)
14091 continue;
14092
14093 bindings.push(name, tokens);
14094 }
14095
14096 if (isTemplate(element)) {
14097 bindings.isTemplate = true;
14098 bindings.if = parseWithDefault(element, IF, prepareBindingFn);
14099 bindings.bind = parseWithDefault(element, BIND, prepareBindingFn);
14100 bindings.repeat = parseWithDefault(element, REPEAT, prepareBindingFn);
14101
14102 if (bindings.if && !bindings.bind && !bindings.repeat)
14103 bindings.bind = parseMustaches('{{}}', BIND, element, prepareBindingFn);
14104 }
14105
14106 return bindings;
14107 }
14108
14109 function getBindings(node, prepareBindingFn) {
14110 if (node.nodeType === Node.ELEMENT_NODE)
14111 return parseAttributeBindings(node, prepareBindingFn);
14112
14113 if (node.nodeType === Node.TEXT_NODE) {
14114 var tokens = parseMustaches(node.data, 'textContent', node,
14115 prepareBindingFn);
14116 if (tokens)
14117 return ['textContent', tokens];
14118 }
14119
14120 return [];
14121 }
14122
14123 function cloneAndBindInstance(node, parent, stagingDocument, bindings, model,
14124 delegate,
14125 instanceBindings,
14126 instanceRecord) {
14127 var clone = parent.appendChild(stagingDocument.importNode(node, false));
14128
14129 var i = 0;
14130 for (var child = node.firstChild; child; child = child.nextSibling) {
14131 cloneAndBindInstance(child, clone, stagingDocument,
14132 bindings.children[i++],
14133 model,
14134 delegate,
14135 instanceBindings);
14136 }
14137
14138 if (bindings.isTemplate) {
14139 HTMLTemplateElement.decorate(clone, node);
14140 if (delegate)
14141 clone.setDelegate_(delegate);
14142 }
14143
14144 processBindings(clone, bindings, model, instanceBindings);
14145 return clone;
14146 }
14147
14148 function createInstanceBindingMap(node, prepareBindingFn) {
14149 var map = getBindings(node, prepareBindingFn);
14150 map.children = {};
14151 var index = 0;
14152 for (var child = node.firstChild; child; child = child.nextSibling) {
14153 map.children[index++] = createInstanceBindingMap(child, prepareBindingFn);
14154 }
14155
14156 return map;
14157 }
14158
14159 var contentUidCounter = 1;
14160
14161 // TODO(rafaelw): Setup a MutationObserver on content which clears the id
14162 // so that bindingMaps regenerate when the template.content changes.
14163 function getContentUid(content) {
14164 var id = content.id_;
14165 if (!id)
14166 id = content.id_ = contentUidCounter++;
14167 return id;
14168 }
14169
14170 // Each delegate is associated with a set of bindingMaps, one for each
14171 // content which may be used by a template. The intent is that each binding
14172 // delegate gets the opportunity to prepare the instance (via the prepare*
14173 // delegate calls) once across all uses.
14174 // TODO(rafaelw): Separate out the parse map from the binding map. In the
14175 // current implementation, if two delegates need a binding map for the same
14176 // content, the second will have to reparse.
14177 function getInstanceBindingMap(content, delegate_) {
14178 var contentId = getContentUid(content);
14179 if (delegate_) {
14180 var map = delegate_.bindingMaps[contentId];
14181 if (!map) {
14182 map = delegate_.bindingMaps[contentId] =
14183 createInstanceBindingMap(content, delegate_.prepareBinding) || [];
14184 }
14185 return map;
14186 }
14187
14188 var map = content.bindingMap_;
14189 if (!map) {
14190 map = content.bindingMap_ =
14191 createInstanceBindingMap(content, undefined) || [];
14192 }
14193 return map;
14194 }
14195
14196 Object.defineProperty(Node.prototype, 'templateInstance', {
14197 get: function() {
14198 var instance = this.templateInstance_;
14199 return instance ? instance :
14200 (this.parentNode ? this.parentNode.templateInstance : undefined);
14201 }
14202 });
14203
14204 var emptyInstance = document.createDocumentFragment();
14205 emptyInstance.bindings_ = [];
14206 emptyInstance.terminator_ = null;
14207
14208 function TemplateIterator(templateElement) {
14209 this.closed = false;
14210 this.templateElement_ = templateElement;
14211 this.instances = [];
14212 this.deps = undefined;
14213 this.iteratedValue = [];
14214 this.presentValue = undefined;
14215 this.arrayObserver = undefined;
14216 }
14217
14218 TemplateIterator.prototype = {
14219 closeDeps: function() {
14220 var deps = this.deps;
14221 if (deps) {
14222 if (deps.ifOneTime === false)
14223 deps.ifValue.close();
14224 if (deps.oneTime === false)
14225 deps.value.close();
14226 }
14227 },
14228
14229 updateDependencies: function(directives, model) {
14230 this.closeDeps();
14231
14232 var deps = this.deps = {};
14233 var template = this.templateElement_;
14234
14235 var ifValue = true;
14236 if (directives.if) {
14237 deps.hasIf = true;
14238 deps.ifOneTime = directives.if.onlyOneTime;
14239 deps.ifValue = processBinding(IF, directives.if, template, model);
14240
14241 ifValue = deps.ifValue;
14242
14243 // oneTime if & predicate is false. nothing else to do.
14244 if (deps.ifOneTime && !ifValue) {
14245 this.valueChanged();
14246 return;
14247 }
14248
14249 if (!deps.ifOneTime)
14250 ifValue = ifValue.open(this.updateIfValue, this);
14251 }
14252
14253 if (directives.repeat) {
14254 deps.repeat = true;
14255 deps.oneTime = directives.repeat.onlyOneTime;
14256 deps.value = processBinding(REPEAT, directives.repeat, template, model);
14257 } else {
14258 deps.repeat = false;
14259 deps.oneTime = directives.bind.onlyOneTime;
14260 deps.value = processBinding(BIND, directives.bind, template, model);
14261 }
14262
14263 var value = deps.value;
14264 if (!deps.oneTime)
14265 value = value.open(this.updateIteratedValue, this);
14266
14267 if (!ifValue) {
14268 this.valueChanged();
14269 return;
14270 }
14271
14272 this.updateValue(value);
14273 },
14274
14275 /**
14276 * Gets the updated value of the bind/repeat. This can potentially call
14277 * user code (if a bindingDelegate is set up) so we try to avoid it if we
14278 * already have the value in hand (from Observer.open).
14279 */
14280 getUpdatedValue: function() {
14281 var value = this.deps.value;
14282 if (!this.deps.oneTime)
14283 value = value.discardChanges();
14284 return value;
14285 },
14286
14287 updateIfValue: function(ifValue) {
14288 if (!ifValue) {
14289 this.valueChanged();
14290 return;
14291 }
14292
14293 this.updateValue(this.getUpdatedValue());
14294 },
14295
14296 updateIteratedValue: function(value) {
14297 if (this.deps.hasIf) {
14298 var ifValue = this.deps.ifValue;
14299 if (!this.deps.ifOneTime)
14300 ifValue = ifValue.discardChanges();
14301 if (!ifValue) {
14302 this.valueChanged();
14303 return;
14304 }
14305 }
14306
14307 this.updateValue(value);
14308 },
14309
14310 updateValue: function(value) {
14311 if (!this.deps.repeat)
14312 value = [value];
14313 var observe = this.deps.repeat &&
14314 !this.deps.oneTime &&
14315 Array.isArray(value);
14316 this.valueChanged(value, observe);
14317 },
14318
14319 valueChanged: function(value, observeValue) {
14320 if (!Array.isArray(value))
14321 value = [];
14322
14323 if (value === this.iteratedValue)
14324 return;
14325
14326 this.unobserve();
14327 this.presentValue = value;
14328 if (observeValue) {
14329 this.arrayObserver = new ArrayObserver(this.presentValue);
14330 this.arrayObserver.open(this.handleSplices, this);
14331 }
14332
14333 this.handleSplices(ArrayObserver.calculateSplices(this.presentValue,
14334 this.iteratedValue));
14335 },
14336
14337 getLastInstanceNode: function(index) {
14338 if (index == -1)
14339 return this.templateElement_;
14340 var instance = this.instances[index];
14341 var terminator = instance.terminator_;
14342 if (!terminator)
14343 return this.getLastInstanceNode(index - 1);
14344
14345 if (terminator.nodeType !== Node.ELEMENT_NODE ||
14346 this.templateElement_ === terminator) {
14347 return terminator;
14348 }
14349
14350 var subtemplateIterator = terminator.iterator_;
14351 if (!subtemplateIterator)
14352 return terminator;
14353
14354 return subtemplateIterator.getLastTemplateNode();
14355 },
14356
14357 getLastTemplateNode: function() {
14358 return this.getLastInstanceNode(this.instances.length - 1);
14359 },
14360
14361 insertInstanceAt: function(index, fragment) {
14362 var previousInstanceLast = this.getLastInstanceNode(index - 1);
14363 var parent = this.templateElement_.parentNode;
14364 this.instances.splice(index, 0, fragment);
14365
14366 parent.insertBefore(fragment, previousInstanceLast.nextSibling);
14367 },
14368
14369 extractInstanceAt: function(index) {
14370 var previousInstanceLast = this.getLastInstanceNode(index - 1);
14371 var lastNode = this.getLastInstanceNode(index);
14372 var parent = this.templateElement_.parentNode;
14373 var instance = this.instances.splice(index, 1)[0];
14374
14375 while (lastNode !== previousInstanceLast) {
14376 var node = previousInstanceLast.nextSibling;
14377 if (node == lastNode)
14378 lastNode = previousInstanceLast;
14379
14380 instance.appendChild(parent.removeChild(node));
14381 }
14382
14383 return instance;
14384 },
14385
14386 getDelegateFn: function(fn) {
14387 fn = fn && fn(this.templateElement_);
14388 return typeof fn === 'function' ? fn : null;
14389 },
14390
14391 handleSplices: function(splices) {
14392 if (this.closed || !splices.length)
14393 return;
14394
14395 var template = this.templateElement_;
14396
14397 if (!template.parentNode) {
14398 this.close();
14399 return;
14400 }
14401
14402 ArrayObserver.applySplices(this.iteratedValue, this.presentValue,
14403 splices);
14404
14405 var delegate = template.delegate_;
14406 if (this.instanceModelFn_ === undefined) {
14407 this.instanceModelFn_ =
14408 this.getDelegateFn(delegate && delegate.prepareInstanceModel);
14409 }
14410
14411 if (this.instancePositionChangedFn_ === undefined) {
14412 this.instancePositionChangedFn_ =
14413 this.getDelegateFn(delegate &&
14414 delegate.prepareInstancePositionChanged);
14415 }
14416
14417 // Instance Removals
14418 var instanceCache = new Map;
14419 var removeDelta = 0;
14420 for (var i = 0; i < splices.length; i++) {
14421 var splice = splices[i];
14422 var removed = splice.removed;
14423 for (var j = 0; j < removed.length; j++) {
14424 var model = removed[j];
14425 var instance = this.extractInstanceAt(splice.index + removeDelta);
14426 if (instance !== emptyInstance) {
14427 instanceCache.set(model, instance);
14428 }
14429 }
14430
14431 removeDelta -= splice.addedCount;
14432 }
14433
14434 // Instance Insertions
14435 for (var i = 0; i < splices.length; i++) {
14436 var splice = splices[i];
14437 var addIndex = splice.index;
14438 for (; addIndex < splice.index + splice.addedCount; addIndex++) {
14439 var model = this.iteratedValue[addIndex];
14440 var instance = instanceCache.get(model);
14441 if (instance) {
14442 instanceCache.delete(model);
14443 } else {
14444 if (this.instanceModelFn_) {
14445 model = this.instanceModelFn_(model);
14446 }
14447
14448 if (model === undefined) {
14449 instance = emptyInstance;
14450 } else {
14451 instance = template.createInstance(model, undefined, delegate);
14452 }
14453 }
14454
14455 this.insertInstanceAt(addIndex, instance);
14456 }
14457 }
14458
14459 instanceCache.forEach(function(instance) {
14460 this.closeInstanceBindings(instance);
14461 }, this);
14462
14463 if (this.instancePositionChangedFn_)
14464 this.reportInstancesMoved(splices);
14465 },
14466
14467 reportInstanceMoved: function(index) {
14468 var instance = this.instances[index];
14469 if (instance === emptyInstance)
14470 return;
14471
14472 this.instancePositionChangedFn_(instance.templateInstance_, index);
14473 },
14474
14475 reportInstancesMoved: function(splices) {
14476 var index = 0;
14477 var offset = 0;
14478 for (var i = 0; i < splices.length; i++) {
14479 var splice = splices[i];
14480 if (offset != 0) {
14481 while (index < splice.index) {
14482 this.reportInstanceMoved(index);
14483 index++;
14484 }
14485 } else {
14486 index = splice.index;
14487 }
14488
14489 while (index < splice.index + splice.addedCount) {
14490 this.reportInstanceMoved(index);
14491 index++;
14492 }
14493
14494 offset += splice.addedCount - splice.removed.length;
14495 }
14496
14497 if (offset == 0)
14498 return;
14499
14500 var length = this.instances.length;
14501 while (index < length) {
14502 this.reportInstanceMoved(index);
14503 index++;
14504 }
14505 },
14506
14507 closeInstanceBindings: function(instance) {
14508 var bindings = instance.bindings_;
14509 for (var i = 0; i < bindings.length; i++) {
14510 bindings[i].close();
14511 }
14512 },
14513
14514 unobserve: function() {
14515 if (!this.arrayObserver)
14516 return;
14517
14518 this.arrayObserver.close();
14519 this.arrayObserver = undefined;
14520 },
14521
14522 close: function() {
14523 if (this.closed)
14524 return;
14525 this.unobserve();
14526 for (var i = 0; i < this.instances.length; i++) {
14527 this.closeInstanceBindings(this.instances[i]);
14528 }
14529
14530 this.instances.length = 0;
14531 this.closeDeps();
14532 this.templateElement_.iterator_ = undefined;
14533 this.closed = true;
14534 }
14535 };
14536
14537 // Polyfill-specific API.
14538 HTMLTemplateElement.forAllTemplatesFrom_ = forAllTemplatesFrom;
14539 })(this);
14540
14541 /*
14542 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
14543 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
14544 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
14545 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
14546 * Code distributed by Google as part of the polymer project is also
14547 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
14548 */
14549
14550 (function(scope) {
14551
14552 // inject style sheet
14553 var style = document.createElement('style');
14554 style.textContent = 'template {display: none !important;} /* injected by platfor m.js */';
14555 var head = document.querySelector('head');
14556 head.insertBefore(style, head.firstChild);
14557
14558 // flush (with logging)
14559 var flushing;
14560 function flush() {
14561 if (!flushing) {
14562 flushing = true;
14563 scope.endOfMicrotask(function() {
14564 flushing = false;
14565 logFlags.data && console.group('Platform.flush()');
14566 scope.performMicrotaskCheckpoint();
14567 logFlags.data && console.groupEnd();
14568 });
14569 }
14570 };
14571
14572 // polling dirty checker
14573 // flush periodically if platform does not have object observe.
14574 if (!Observer.hasObjectObserve) {
14575 var FLUSH_POLL_INTERVAL = 125;
14576 window.addEventListener('WebComponentsReady', function() {
14577 flush();
14578 scope.flushPoll = setInterval(flush, FLUSH_POLL_INTERVAL);
14579 });
14580 } else {
14581 // make flush a no-op when we have Object.observe
14582 flush = function() {};
14583 }
14584
14585 if (window.CustomElements && !CustomElements.useNative) {
14586 var originalImportNode = Document.prototype.importNode;
14587 Document.prototype.importNode = function(node, deep) {
14588 var imported = originalImportNode.call(this, node, deep);
14589 CustomElements.upgradeAll(imported);
14590 return imported;
14591 }
14592 }
14593
14594 // exports
14595 scope.flush = flush;
14596
14597 })(window.Platform);
14598
14599 12262
14600 //# sourceMappingURL=platform.concat.js.map 12263 //# sourceMappingURL=platform.concat.js.map
OLDNEW
« no previous file with comments | « pkg/web_components/lib/platform.js ('k') | pkg/web_components/lib/platform.concat.js.map » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698