| Index: pkg/web_components/lib/platform.concat.js
|
| diff --git a/pkg/web_components/lib/platform.concat.js b/pkg/web_components/lib/platform.concat.js
|
| index 6eea86858eae0662dae51b4d21570024a9388a2c..9b7ff43b306605248f61313126fcba359fd2e5f2 100644
|
| --- a/pkg/web_components/lib/platform.concat.js
|
| +++ b/pkg/web_components/lib/platform.concat.js
|
| @@ -112,6 +112,9 @@ if (typeof WeakMap === 'undefined') {
|
| })();
|
| }
|
|
|
| +// select ShadowDOM impl
|
| +if (Platform.flags.shadow) {
|
| +
|
| // Copyright 2012 Google Inc.
|
| //
|
| // Licensed under the Apache License, Version 2.0 (the "License");
|
| @@ -1840,9 +1843,6 @@ if (typeof WeakMap === 'undefined') {
|
| global.ObserverTransform = ObserverTransform;
|
| })(typeof global !== 'undefined' && global && typeof module !== 'undefined' && module ? global : this || window);
|
|
|
| -// select ShadowDOM impl
|
| -if (Platform.flags.shadow) {
|
| -
|
| // Copyright 2012 The Polymer Authors. All rights reserved.
|
| // Use of this source code is goverened by a BSD-style
|
| // license that can be found in the LICENSE file.
|
| @@ -8512,27 +8512,33 @@ var ShadowCSS = {
|
| cssText += this.scopeRules(rule.cssRules, scopeSelector);
|
| cssText += '\n}\n\n';
|
| } else {
|
| - // TODO(sjmiles): KEYFRAMES_RULE in IE11 throws when we query cssText
|
| - // 'cssText' in rule returns true, but rule.cssText throws anyway
|
| - // We can test the rule type, e.g.
|
| - // else if (rule.type !== CSSRule.KEYFRAMES_RULE && rule.cssText) {
|
| - // but this will prevent cssText propagation in other browsers which
|
| - // support it.
|
| - // KEYFRAMES_RULE has a CSSRuleSet, so the text can probably be reconstructed
|
| - // from that collection; this would be a proper fix.
|
| - // For now, I'm trapping the exception so IE11 is unblocked in other areas.
|
| + // KEYFRAMES_RULE in IE throws when we query cssText
|
| + // when it contains a -webkit- property.
|
| + // if this happens, we fallback to constructing the rule
|
| + // from the CSSRuleSet
|
| + // https://connect.microsoft.com/IE/feedbackdetail/view/955703/accessing-csstext-of-a-keyframe-rule-that-contains-a-webkit-property-via-cssom-generates-exception
|
| try {
|
| if (rule.cssText) {
|
| cssText += rule.cssText + '\n\n';
|
| }
|
| } catch(x) {
|
| - // squelch
|
| + if (rule.type === CSSRule.KEYFRAMES_RULE && rule.cssRules) {
|
| + cssText += this.ieSafeCssTextFromKeyFrameRule(rule);
|
| + }
|
| }
|
| }
|
| }, this);
|
| }
|
| return cssText;
|
| },
|
| + ieSafeCssTextFromKeyFrameRule: function(rule) {
|
| + var cssText = '@keyframes ' + rule.name + ' {';
|
| + Array.prototype.forEach.call(rule.cssRules, function(rule) {
|
| + cssText += ' ' + rule.keyText + ' {' + rule.style.cssText + '}';
|
| + });
|
| + cssText += ' }';
|
| + return cssText;
|
| + },
|
| scopeSelector: function(selector, scopeSelector, strict) {
|
| var r = [], parts = selector.split(',');
|
| parts.forEach(function(p) {
|
| @@ -8755,7 +8761,7 @@ function withCssRules(cssText, callback) {
|
| var style = cssTextToStyle(cssText);
|
| inFrame(function(doc) {
|
| doc.head.appendChild(style.impl);
|
| - rules = style.sheet.cssRules;
|
| + rules = Array.prototype.slice.call(style.sheet.cssRules, 0);
|
| callback(rules);
|
| });
|
| } else {
|
| @@ -8836,11 +8842,10 @@ if (window.ShadowDOMPolyfill) {
|
| }
|
| if (elt.__resource) {
|
| style = elt.ownerDocument.createElement('style');
|
| - style.textContent = urlResolver.resolveCssText(
|
| - elt.__resource, elt.href);
|
| - } else {
|
| - urlResolver.resolveStyle(style);
|
| + style.textContent = elt.__resource;
|
| }
|
| + // relay on HTMLImports for path fixup
|
| + HTMLImports.path.resolveUrlsInStyle(style);
|
| style.textContent = ShadowCSS.shimStyle(style);
|
| style.removeAttribute(SHIM_ATTRIBUTE, '');
|
| style.setAttribute(SHIMMED_ATTRIBUTE, '');
|
| @@ -8906,23 +8911,6 @@ scope.ShadowCSS = ShadowCSS;
|
| }
|
| });
|
|
|
| - Platform.templateContent = function(inTemplate) {
|
| - // if MDV exists, it may need to boostrap this template to reveal content
|
| - if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) {
|
| - HTMLTemplateElement.bootstrap(inTemplate);
|
| - }
|
| - // fallback when there is no Shadow DOM polyfill, no MDV polyfill, and no
|
| - // native template support
|
| - if (!inTemplate.content && !inTemplate._content) {
|
| - var frag = document.createDocumentFragment();
|
| - while (inTemplate.firstChild) {
|
| - frag.appendChild(inTemplate.firstChild);
|
| - }
|
| - inTemplate._content = frag;
|
| - }
|
| - return inTemplate.content || inTemplate._content;
|
| - };
|
| -
|
| })(window.Platform);
|
|
|
| }
|
| @@ -9530,42 +9518,6 @@ if (!Function.prototype.bind) {
|
| };
|
| }
|
|
|
| -// mixin
|
| -
|
| -// copy all properties from inProps (et al) to inObj
|
| -function mixin(inObj/*, inProps, inMoreProps, ...*/) {
|
| - var obj = inObj || {};
|
| - for (var i = 1; i < arguments.length; i++) {
|
| - var p = arguments[i];
|
| - try {
|
| - for (var n in p) {
|
| - copyProperty(n, p, obj);
|
| - }
|
| - } catch(x) {
|
| - }
|
| - }
|
| - return obj;
|
| -}
|
| -
|
| -// copy property inName from inSource object to inTarget object
|
| -function copyProperty(inName, inSource, inTarget) {
|
| - var pd = getPropertyDescriptor(inSource, inName);
|
| - Object.defineProperty(inTarget, inName, pd);
|
| -}
|
| -
|
| -// get property descriptor for inName on inObject, even if
|
| -// inName exists on some link in inObject's prototype chain
|
| -function getPropertyDescriptor(inObject, inName) {
|
| - if (inObject) {
|
| - var pd = Object.getOwnPropertyDescriptor(inObject, inName);
|
| - return pd || getPropertyDescriptor(Object.getPrototypeOf(inObject), inName);
|
| - }
|
| -}
|
| -
|
| -// export
|
| -
|
| -scope.mixin = mixin;
|
| -
|
| })(window.Platform);
|
|
|
| /*
|
| @@ -9581,46 +9533,6 @@ scope.mixin = mixin;
|
|
|
| 'use strict';
|
|
|
| - // polyfill DOMTokenList
|
| - // * add/remove: allow these methods to take multiple classNames
|
| - // * toggle: add a 2nd argument which forces the given state rather
|
| - // than toggling.
|
| -
|
| - var add = DOMTokenList.prototype.add;
|
| - var remove = DOMTokenList.prototype.remove;
|
| - DOMTokenList.prototype.add = function() {
|
| - for (var i = 0; i < arguments.length; i++) {
|
| - add.call(this, arguments[i]);
|
| - }
|
| - };
|
| - DOMTokenList.prototype.remove = function() {
|
| - for (var i = 0; i < arguments.length; i++) {
|
| - remove.call(this, arguments[i]);
|
| - }
|
| - };
|
| - DOMTokenList.prototype.toggle = function(name, bool) {
|
| - if (arguments.length == 1) {
|
| - bool = !this.contains(name);
|
| - }
|
| - bool ? this.add(name) : this.remove(name);
|
| - };
|
| - DOMTokenList.prototype.switch = function(oldName, newName) {
|
| - oldName && this.remove(oldName);
|
| - newName && this.add(newName);
|
| - };
|
| -
|
| - // add array() to NodeList, NamedNodeMap, HTMLCollection
|
| -
|
| - var ArraySlice = function() {
|
| - return Array.prototype.slice.call(this);
|
| - };
|
| -
|
| - var namedNodeMap = (window.NamedNodeMap || window.MozNamedAttrMap || {});
|
| -
|
| - NodeList.prototype.array = ArraySlice;
|
| - namedNodeMap.prototype.array = ArraySlice;
|
| - HTMLCollection.prototype.array = ArraySlice;
|
| -
|
| // polyfill performance.now
|
|
|
| if (!window.performance) {
|
| @@ -9658,19 +9570,6 @@ scope.mixin = mixin;
|
| })();
|
| }
|
|
|
| - // utility
|
| -
|
| - function createDOM(inTagOrNode, inHTML, inAttrs) {
|
| - var dom = typeof inTagOrNode == 'string' ?
|
| - document.createElement(inTagOrNode) : inTagOrNode.cloneNode(true);
|
| - dom.innerHTML = inHTML;
|
| - if (inAttrs) {
|
| - for (var n in inAttrs) {
|
| - dom.setAttribute(n, inAttrs[n]);
|
| - }
|
| - }
|
| - return dom;
|
| - }
|
| // Make a stub for Polymer() for polyfill purposes; under the HTMLImports
|
| // polyfill, scripts in the main document run before imports. That means
|
| // if (1) polymer is imported and (2) Polymer() is called in the main document
|
| @@ -9680,17 +9579,21 @@ scope.mixin = mixin;
|
| var elementDeclarations = [];
|
|
|
| var polymerStub = function(name, dictionary) {
|
| + Array.prototype.push.call(arguments, document._currentScript);
|
| elementDeclarations.push(arguments);
|
| - }
|
| + };
|
| window.Polymer = polymerStub;
|
|
|
| // deliver queued delcarations
|
| - scope.deliverDeclarations = function() {
|
| - scope.deliverDeclarations = function() {
|
| + scope.consumeDeclarations = function(callback) {
|
| + scope.consumeDeclarations = function() {
|
| throw 'Possible attempt to load Polymer twice';
|
| };
|
| - return elementDeclarations;
|
| - }
|
| + if (callback) {
|
| + callback(elementDeclarations);
|
| + }
|
| + elementDeclarations = null;
|
| + };
|
|
|
| // Once DOMContent has loaded, any main document scripts that depend on
|
| // Polymer() should have run. Calling Polymer() now is an error until
|
| @@ -9705,583 +9608,107 @@ scope.mixin = mixin;
|
| }
|
| });
|
|
|
| - // exports
|
| - scope.createDOM = createDOM;
|
| -
|
| -})(window.Platform);
|
| -
|
| -/*
|
| - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| - * Code distributed by Google as part of the polymer project is also
|
| - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| - */
|
| -
|
| -// poor man's adapter for template.content on various platform scenarios
|
| -(function(scope) {
|
| - scope.templateContent = scope.templateContent || function(inTemplate) {
|
| - return inTemplate.content;
|
| - };
|
| })(window.Platform);
|
|
|
| /*
|
| - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| - * Code distributed by Google as part of the polymer project is also
|
| - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| + * Copyright 2012 The Polymer Authors. All rights reserved.
|
| + * Use of this source code is goverened by a BSD-style
|
| + * license that can be found in the LICENSE file.
|
| */
|
|
|
| -(function(scope) {
|
| -
|
| - scope = scope || (window.Inspector = {});
|
| -
|
| - var inspector;
|
| -
|
| - window.sinspect = function(inNode, inProxy) {
|
| - if (!inspector) {
|
| - inspector = window.open('', 'ShadowDOM Inspector', null, true);
|
| - inspector.document.write(inspectorHTML);
|
| - //inspector.document.close();
|
| - inspector.api = {
|
| - shadowize: shadowize
|
| - };
|
| - }
|
| - inspect(inNode || wrap(document.body), inProxy);
|
| - };
|
| -
|
| - var inspectorHTML = [
|
| - '<!DOCTYPE html>',
|
| - '<html>',
|
| - ' <head>',
|
| - ' <title>ShadowDOM Inspector</title>',
|
| - ' <style>',
|
| - ' body {',
|
| - ' }',
|
| - ' pre {',
|
| - ' font: 9pt "Courier New", monospace;',
|
| - ' line-height: 1.5em;',
|
| - ' }',
|
| - ' tag {',
|
| - ' color: purple;',
|
| - ' }',
|
| - ' ul {',
|
| - ' margin: 0;',
|
| - ' padding: 0;',
|
| - ' list-style: none;',
|
| - ' }',
|
| - ' li {',
|
| - ' display: inline-block;',
|
| - ' background-color: #f1f1f1;',
|
| - ' padding: 4px 6px;',
|
| - ' border-radius: 4px;',
|
| - ' margin-right: 4px;',
|
| - ' }',
|
| - ' </style>',
|
| - ' </head>',
|
| - ' <body>',
|
| - ' <ul id="crumbs">',
|
| - ' </ul>',
|
| - ' <div id="tree"></div>',
|
| - ' </body>',
|
| - '</html>'
|
| - ].join('\n');
|
| -
|
| - var crumbs = [];
|
| -
|
| - var displayCrumbs = function() {
|
| - // alias our document
|
| - var d = inspector.document;
|
| - // get crumbbar
|
| - var cb = d.querySelector('#crumbs');
|
| - // clear crumbs
|
| - cb.textContent = '';
|
| - // build new crumbs
|
| - for (var i=0, c; c=crumbs[i]; i++) {
|
| - var a = d.createElement('a');
|
| - a.href = '#';
|
| - a.textContent = c.localName;
|
| - a.idx = i;
|
| - a.onclick = function(event) {
|
| - var c;
|
| - while (crumbs.length > this.idx) {
|
| - c = crumbs.pop();
|
| - }
|
| - inspect(c.shadow || c, c);
|
| - event.preventDefault();
|
| - };
|
| - cb.appendChild(d.createElement('li')).appendChild(a);
|
| - }
|
| - };
|
| -
|
| - var inspect = function(inNode, inProxy) {
|
| - // alias our document
|
| - var d = inspector.document;
|
| - // reset list of drillable nodes
|
| - drillable = [];
|
| - // memoize our crumb proxy
|
| - var proxy = inProxy || inNode;
|
| - crumbs.push(proxy);
|
| - // update crumbs
|
| - displayCrumbs();
|
| - // reflect local tree
|
| - d.body.querySelector('#tree').innerHTML =
|
| - '<pre>' + output(inNode, inNode.childNodes) + '</pre>';
|
| - };
|
| +(function(global) {
|
|
|
| - var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
|
| + var registrationsTable = new WeakMap();
|
|
|
| - var blacklisted = {STYLE:1, SCRIPT:1, "#comment": 1, TEMPLATE: 1};
|
| - var blacklist = function(inNode) {
|
| - return blacklisted[inNode.nodeName];
|
| - };
|
| + // We use setImmediate or postMessage for our future callback.
|
| + var setImmediate = window.msSetImmediate;
|
|
|
| - var output = function(inNode, inChildNodes, inIndent) {
|
| - if (blacklist(inNode)) {
|
| - return '';
|
| - }
|
| - var indent = inIndent || '';
|
| - if (inNode.localName || inNode.nodeType == 11) {
|
| - var name = inNode.localName || 'shadow-root';
|
| - //inChildNodes = ShadowDOM.localNodes(inNode);
|
| - var info = indent + describe(inNode);
|
| - // if only textNodes
|
| - // TODO(sjmiles): make correct for ShadowDOM
|
| - /*if (!inNode.children.length && inNode.localName !== 'content' && inNode.localName !== 'shadow') {
|
| - info += catTextContent(inChildNodes);
|
| - } else*/ {
|
| - // TODO(sjmiles): native <shadow> has no reference to its projection
|
| - if (name == 'content' /*|| name == 'shadow'*/) {
|
| - inChildNodes = inNode.getDistributedNodes();
|
| - }
|
| - info += '<br/>';
|
| - var ind = indent + ' ';
|
| - forEach(inChildNodes, function(n) {
|
| - info += output(n, n.childNodes, ind);
|
| + // Use post message to emulate setImmediate.
|
| + if (!setImmediate) {
|
| + var setImmediateQueue = [];
|
| + var sentinel = String(Math.random());
|
| + window.addEventListener('message', function(e) {
|
| + if (e.data === sentinel) {
|
| + var queue = setImmediateQueue;
|
| + setImmediateQueue = [];
|
| + queue.forEach(function(func) {
|
| + func();
|
| });
|
| - info += indent;
|
| - }
|
| - if (!({br:1}[name])) {
|
| - info += '<tag></' + name + '></tag>';
|
| - info += '<br/>';
|
| }
|
| - } else {
|
| - var text = inNode.textContent.trim();
|
| - info = text ? indent + '"' + text + '"' + '<br/>' : '';
|
| - }
|
| - return info;
|
| - };
|
| -
|
| - var catTextContent = function(inChildNodes) {
|
| - var info = '';
|
| - forEach(inChildNodes, function(n) {
|
| - info += n.textContent.trim();
|
| });
|
| - return info;
|
| - };
|
| -
|
| - var drillable = [];
|
| + setImmediate = function(func) {
|
| + setImmediateQueue.push(func);
|
| + window.postMessage(sentinel, '*');
|
| + };
|
| + }
|
|
|
| - var describe = function(inNode) {
|
| - var tag = '<tag>' + '<';
|
| - var name = inNode.localName || 'shadow-root';
|
| - if (inNode.webkitShadowRoot || inNode.shadowRoot) {
|
| - tag += ' <button idx="' + drillable.length +
|
| - '" onclick="api.shadowize.call(this)">' + name + '</button>';
|
| - drillable.push(inNode);
|
| - } else {
|
| - tag += name || 'shadow-root';
|
| - }
|
| - if (inNode.attributes) {
|
| - forEach(inNode.attributes, function(a) {
|
| - tag += ' ' + a.name + (a.value ? '="' + a.value + '"' : '');
|
| - });
|
| - }
|
| - tag += '>'+ '</tag>';
|
| - return tag;
|
| - };
|
| + // This is used to ensure that we never schedule 2 callas to setImmediate
|
| + var isScheduled = false;
|
|
|
| - // remote api
|
| + // Keep track of observers that needs to be notified next time.
|
| + var scheduledObservers = [];
|
|
|
| - shadowize = function() {
|
| - var idx = Number(this.attributes.idx.value);
|
| - //alert(idx);
|
| - var node = drillable[idx];
|
| - if (node) {
|
| - inspect(node.webkitShadowRoot || node.shadowRoot, node)
|
| - } else {
|
| - console.log("bad shadowize node");
|
| - console.dir(this);
|
| + /**
|
| + * Schedules |dispatchCallback| to be called in the future.
|
| + * @param {MutationObserver} observer
|
| + */
|
| + function scheduleCallback(observer) {
|
| + scheduledObservers.push(observer);
|
| + if (!isScheduled) {
|
| + isScheduled = true;
|
| + setImmediate(dispatchCallbacks);
|
| }
|
| - };
|
| -
|
| - // export
|
| -
|
| - scope.output = output;
|
| -
|
| -})(window.Inspector);
|
| + }
|
|
|
| -/*
|
| - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| - * Code distributed by Google as part of the polymer project is also
|
| - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| - */
|
| + function wrapIfNeeded(node) {
|
| + return window.ShadowDOMPolyfill &&
|
| + window.ShadowDOMPolyfill.wrapIfNeeded(node) ||
|
| + node;
|
| + }
|
|
|
| -(function(scope) {
|
| + function dispatchCallbacks() {
|
| + // http://dom.spec.whatwg.org/#mutation-observers
|
|
|
| - // TODO(sorvell): It's desireable to provide a default stylesheet
|
| - // that's convenient for styling unresolved elements, but
|
| - // it's cumbersome to have to include this manually in every page.
|
| - // It would make sense to put inside some HTMLImport but
|
| - // the HTMLImports polyfill does not allow loading of stylesheets
|
| - // that block rendering. Therefore this injection is tolerated here.
|
| + isScheduled = false; // Used to allow a new setImmediate call above.
|
|
|
| - var style = document.createElement('style');
|
| - style.textContent = ''
|
| - + 'body {'
|
| - + 'transition: opacity ease-in 0.2s;'
|
| - + ' } \n'
|
| - + 'body[unresolved] {'
|
| - + 'opacity: 0; display: block; overflow: hidden;'
|
| - + ' } \n'
|
| - ;
|
| - var head = document.querySelector('head');
|
| - head.insertBefore(style, head.firstChild);
|
| + var observers = scheduledObservers;
|
| + scheduledObservers = [];
|
| + // Sort observers based on their creation UID (incremental).
|
| + observers.sort(function(o1, o2) {
|
| + return o1.uid_ - o2.uid_;
|
| + });
|
|
|
| -})(Platform);
|
| + var anyNonEmpty = false;
|
| + observers.forEach(function(observer) {
|
|
|
| -/*
|
| - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| - * Code distributed by Google as part of the polymer project is also
|
| - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| - */
|
| + // 2.1, 2.2
|
| + var queue = observer.takeRecords();
|
| + // 2.3. Remove all transient registered observers whose observer is mo.
|
| + removeTransientObserversFor(observer);
|
|
|
| -(function(scope) {
|
| + // 2.4
|
| + if (queue.length) {
|
| + observer.callback_(queue, observer);
|
| + anyNonEmpty = true;
|
| + }
|
| + });
|
|
|
| - function withDependencies(task, depends) {
|
| - depends = depends || [];
|
| - if (!depends.map) {
|
| - depends = [depends];
|
| - }
|
| - return task.apply(this, depends.map(marshal));
|
| + // 3.
|
| + if (anyNonEmpty)
|
| + dispatchCallbacks();
|
| }
|
|
|
| - function module(name, dependsOrFactory, moduleFactory) {
|
| - var module;
|
| - switch (arguments.length) {
|
| - case 0:
|
| + function removeTransientObserversFor(observer) {
|
| + observer.nodes_.forEach(function(node) {
|
| + var registrations = registrationsTable.get(node);
|
| + if (!registrations)
|
| return;
|
| - case 1:
|
| - module = null;
|
| - break;
|
| - case 2:
|
| - // dependsOrFactory is `factory` in this case
|
| - module = dependsOrFactory.apply(this);
|
| - break;
|
| - default:
|
| - // dependsOrFactory is `depends` in this case
|
| - module = withDependencies(moduleFactory, dependsOrFactory);
|
| - break;
|
| - }
|
| - modules[name] = module;
|
| - };
|
| -
|
| - function marshal(name) {
|
| - return modules[name];
|
| - }
|
| -
|
| - var modules = {};
|
| -
|
| - function using(depends, task) {
|
| - HTMLImports.whenImportsReady(function() {
|
| - withDependencies(task, depends);
|
| + registrations.forEach(function(registration) {
|
| + if (registration.observer === observer)
|
| + registration.removeTransientObservers();
|
| + });
|
| });
|
| - };
|
| -
|
| - // exports
|
| -
|
| - scope.marshal = marshal;
|
| - // `module` confuses commonjs detectors
|
| - scope.modularize = module;
|
| - scope.using = using;
|
| -
|
| -})(window);
|
| -
|
| -/*
|
| - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| - * Code distributed by Google as part of the polymer project is also
|
| - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| - */
|
| -
|
| -(function(scope) {
|
| -
|
| -var iterations = 0;
|
| -var callbacks = [];
|
| -var twiddle = document.createTextNode('');
|
| -
|
| -function endOfMicrotask(callback) {
|
| - twiddle.textContent = iterations++;
|
| - callbacks.push(callback);
|
| -}
|
| -
|
| -function atEndOfMicrotask() {
|
| - while (callbacks.length) {
|
| - callbacks.shift()();
|
| - }
|
| -}
|
| -
|
| -new (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask)
|
| - .observe(twiddle, {characterData: true})
|
| - ;
|
| -
|
| -// exports
|
| -
|
| -scope.endOfMicrotask = endOfMicrotask;
|
| -
|
| -})(Platform);
|
| -
|
| -
|
| -/*
|
| - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| - * Code distributed by Google as part of the polymer project is also
|
| - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| - */
|
| -
|
| -(function(scope) {
|
| -
|
| -var urlResolver = {
|
| - resolveDom: function(root, url) {
|
| - url = url || root.ownerDocument.baseURI;
|
| - this.resolveAttributes(root, url);
|
| - this.resolveStyles(root, url);
|
| - // handle template.content
|
| - var templates = root.querySelectorAll('template');
|
| - if (templates) {
|
| - for (var i = 0, l = templates.length, t; (i < l) && (t = templates[i]); i++) {
|
| - if (t.content) {
|
| - this.resolveDom(t.content, url);
|
| - }
|
| - }
|
| - }
|
| - },
|
| - resolveTemplate: function(template) {
|
| - this.resolveDom(template.content, template.ownerDocument.baseURI);
|
| - },
|
| - resolveStyles: function(root, url) {
|
| - var styles = root.querySelectorAll('style');
|
| - if (styles) {
|
| - for (var i = 0, l = styles.length, s; (i < l) && (s = styles[i]); i++) {
|
| - this.resolveStyle(s, url);
|
| - }
|
| - }
|
| - },
|
| - resolveStyle: function(style, url) {
|
| - url = url || style.ownerDocument.baseURI;
|
| - style.textContent = this.resolveCssText(style.textContent, url);
|
| - },
|
| - resolveCssText: function(cssText, baseUrl, keepAbsolute) {
|
| - cssText = replaceUrlsInCssText(cssText, baseUrl, keepAbsolute, CSS_URL_REGEXP);
|
| - return replaceUrlsInCssText(cssText, baseUrl, keepAbsolute, CSS_IMPORT_REGEXP);
|
| - },
|
| - resolveAttributes: function(root, url) {
|
| - if (root.hasAttributes && root.hasAttributes()) {
|
| - this.resolveElementAttributes(root, url);
|
| - }
|
| - // search for attributes that host urls
|
| - var nodes = root && root.querySelectorAll(URL_ATTRS_SELECTOR);
|
| - if (nodes) {
|
| - for (var i = 0, l = nodes.length, n; (i < l) && (n = nodes[i]); i++) {
|
| - this.resolveElementAttributes(n, url);
|
| - }
|
| - }
|
| - },
|
| - resolveElementAttributes: function(node, url) {
|
| - url = url || node.ownerDocument.baseURI;
|
| - URL_ATTRS.forEach(function(v) {
|
| - var attr = node.attributes[v];
|
| - var value = attr && attr.value;
|
| - var replacement;
|
| - if (value && value.search(URL_TEMPLATE_SEARCH) < 0) {
|
| - if (v === 'style') {
|
| - replacement = replaceUrlsInCssText(value, url, false, CSS_URL_REGEXP);
|
| - } else {
|
| - replacement = resolveRelativeUrl(url, value);
|
| - }
|
| - attr.value = replacement;
|
| - }
|
| - });
|
| - }
|
| -};
|
| -
|
| -var CSS_URL_REGEXP = /(url\()([^)]*)(\))/g;
|
| -var CSS_IMPORT_REGEXP = /(@import[\s]+(?!url\())([^;]*)(;)/g;
|
| -var URL_ATTRS = ['href', 'src', 'action', 'style', 'url'];
|
| -var URL_ATTRS_SELECTOR = '[' + URL_ATTRS.join('],[') + ']';
|
| -var URL_TEMPLATE_SEARCH = '{{.*}}';
|
| -
|
| -function replaceUrlsInCssText(cssText, baseUrl, keepAbsolute, regexp) {
|
| - return cssText.replace(regexp, function(m, pre, url, post) {
|
| - var urlPath = url.replace(/["']/g, '');
|
| - urlPath = resolveRelativeUrl(baseUrl, urlPath, keepAbsolute);
|
| - return pre + '\'' + urlPath + '\'' + post;
|
| - });
|
| -}
|
| -
|
| -function resolveRelativeUrl(baseUrl, url, keepAbsolute) {
|
| - // do not resolve '/' absolute urls
|
| - if (url && url[0] === '/') {
|
| - return url;
|
| - }
|
| - var u = new URL(url, baseUrl);
|
| - return keepAbsolute ? u.href : makeDocumentRelPath(u.href);
|
| -}
|
| -
|
| -function makeDocumentRelPath(url) {
|
| - var root = new URL(document.baseURI);
|
| - var u = new URL(url, root);
|
| - if (u.host === root.host && u.port === root.port &&
|
| - u.protocol === root.protocol) {
|
| - return makeRelPath(root, u);
|
| - } else {
|
| - return url;
|
| - }
|
| -}
|
| -
|
| -// make a relative path from source to target
|
| -function makeRelPath(sourceUrl, targetUrl) {
|
| - var source = sourceUrl.pathname;
|
| - var target = targetUrl.pathname;
|
| - var s = source.split('/');
|
| - var t = target.split('/');
|
| - while (s.length && s[0] === t[0]){
|
| - s.shift();
|
| - t.shift();
|
| - }
|
| - for (var i = 0, l = s.length - 1; i < l; i++) {
|
| - t.unshift('..');
|
| - }
|
| - return t.join('/') + targetUrl.search + targetUrl.hash;
|
| -}
|
| -
|
| -// exports
|
| -scope.urlResolver = urlResolver;
|
| -
|
| -})(Platform);
|
| -
|
| -/*
|
| - * Copyright 2012 The Polymer Authors. All rights reserved.
|
| - * Use of this source code is goverened by a BSD-style
|
| - * license that can be found in the LICENSE file.
|
| - */
|
| -
|
| -(function(global) {
|
| -
|
| - var registrationsTable = new WeakMap();
|
| -
|
| - // We use setImmediate or postMessage for our future callback.
|
| - var setImmediate = window.msSetImmediate;
|
| -
|
| - // Use post message to emulate setImmediate.
|
| - if (!setImmediate) {
|
| - var setImmediateQueue = [];
|
| - var sentinel = String(Math.random());
|
| - window.addEventListener('message', function(e) {
|
| - if (e.data === sentinel) {
|
| - var queue = setImmediateQueue;
|
| - setImmediateQueue = [];
|
| - queue.forEach(function(func) {
|
| - func();
|
| - });
|
| - }
|
| - });
|
| - setImmediate = function(func) {
|
| - setImmediateQueue.push(func);
|
| - window.postMessage(sentinel, '*');
|
| - };
|
| - }
|
| -
|
| - // This is used to ensure that we never schedule 2 callas to setImmediate
|
| - var isScheduled = false;
|
| -
|
| - // Keep track of observers that needs to be notified next time.
|
| - var scheduledObservers = [];
|
| -
|
| - /**
|
| - * Schedules |dispatchCallback| to be called in the future.
|
| - * @param {MutationObserver} observer
|
| - */
|
| - function scheduleCallback(observer) {
|
| - scheduledObservers.push(observer);
|
| - if (!isScheduled) {
|
| - isScheduled = true;
|
| - setImmediate(dispatchCallbacks);
|
| - }
|
| - }
|
| -
|
| - function wrapIfNeeded(node) {
|
| - return window.ShadowDOMPolyfill &&
|
| - window.ShadowDOMPolyfill.wrapIfNeeded(node) ||
|
| - node;
|
| - }
|
| -
|
| - function dispatchCallbacks() {
|
| - // http://dom.spec.whatwg.org/#mutation-observers
|
| -
|
| - isScheduled = false; // Used to allow a new setImmediate call above.
|
| -
|
| - var observers = scheduledObservers;
|
| - scheduledObservers = [];
|
| - // Sort observers based on their creation UID (incremental).
|
| - observers.sort(function(o1, o2) {
|
| - return o1.uid_ - o2.uid_;
|
| - });
|
| -
|
| - var anyNonEmpty = false;
|
| - observers.forEach(function(observer) {
|
| -
|
| - // 2.1, 2.2
|
| - var queue = observer.takeRecords();
|
| - // 2.3. Remove all transient registered observers whose observer is mo.
|
| - removeTransientObserversFor(observer);
|
| -
|
| - // 2.4
|
| - if (queue.length) {
|
| - observer.callback_(queue, observer);
|
| - anyNonEmpty = true;
|
| - }
|
| - });
|
| -
|
| - // 3.
|
| - if (anyNonEmpty)
|
| - dispatchCallbacks();
|
| - }
|
| -
|
| - function removeTransientObserversFor(observer) {
|
| - observer.nodes_.forEach(function(node) {
|
| - var registrations = registrationsTable.get(node);
|
| - if (!registrations)
|
| - return;
|
| - registrations.forEach(function(registration) {
|
| - if (registration.observer === observer)
|
| - registration.removeTransientObservers();
|
| - });
|
| - });
|
| - }
|
| + }
|
|
|
| /**
|
| * This function is used for the "For each registered observer observer (with
|
| @@ -10739,6 +10166,200 @@ scope.urlResolver = urlResolver;
|
| * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| */
|
| window.HTMLImports = window.HTMLImports || {flags:{}};
|
| +/*
|
| + * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| + * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| + * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| + * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| + * Code distributed by Google as part of the polymer project is also
|
| + * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| + */
|
| +
|
| +(function(scope) {
|
| +
|
| +var hasNative = ('import' in document.createElement('link'));
|
| +var useNative = hasNative;
|
| +
|
| +isIE = /Trident/.test(navigator.userAgent);
|
| +
|
| +// TODO(sorvell): SD polyfill intrusion
|
| +var hasShadowDOMPolyfill = Boolean(window.ShadowDOMPolyfill);
|
| +var wrap = function(node) {
|
| + return hasShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node) : node;
|
| +};
|
| +var mainDoc = wrap(document);
|
| +
|
| +// NOTE: We cannot polyfill document.currentScript because it's not possible
|
| +// both to override and maintain the ability to capture the native value;
|
| +// therefore we choose to expose _currentScript both when native imports
|
| +// and the polyfill are in use.
|
| +var currentScriptDescriptor = {
|
| + get: function() {
|
| + var script = HTMLImports.currentScript || document.currentScript ||
|
| + // NOTE: only works when called in synchronously executing code.
|
| + // readyState should check if `loading` but IE10 is
|
| + // interactive when scripts run so we cheat.
|
| + (document.readyState !== 'complete' ?
|
| + document.scripts[document.scripts.length - 1] : null);
|
| + return wrap(script);
|
| + },
|
| + configurable: true
|
| +};
|
| +
|
| +Object.defineProperty(document, '_currentScript', currentScriptDescriptor);
|
| +Object.defineProperty(mainDoc, '_currentScript', currentScriptDescriptor);
|
| +
|
| +// call a callback when all HTMLImports in the document at call (or at least
|
| +// document ready) time have loaded.
|
| +// 1. ensure the document is in a ready state (has dom), then
|
| +// 2. watch for loading of imports and call callback when done
|
| +function whenImportsReady(callback, doc) {
|
| + doc = doc || mainDoc;
|
| + // if document is loading, wait and try again
|
| + whenDocumentReady(function() {
|
| + watchImportsLoad(callback, doc);
|
| + }, doc);
|
| +}
|
| +
|
| +// call the callback when the document is in a ready state (has dom)
|
| +var requiredReadyState = isIE ? 'complete' : 'interactive';
|
| +var READY_EVENT = 'readystatechange';
|
| +function isDocumentReady(doc) {
|
| + return (doc.readyState === 'complete' ||
|
| + doc.readyState === requiredReadyState);
|
| +}
|
| +
|
| +// call <callback> when we ensure the document is in a ready state
|
| +function whenDocumentReady(callback, doc) {
|
| + if (!isDocumentReady(doc)) {
|
| + var checkReady = function() {
|
| + if (doc.readyState === 'complete' ||
|
| + doc.readyState === requiredReadyState) {
|
| + doc.removeEventListener(READY_EVENT, checkReady);
|
| + whenDocumentReady(callback, doc);
|
| + }
|
| + };
|
| + doc.addEventListener(READY_EVENT, checkReady);
|
| + } else if (callback) {
|
| + callback();
|
| + }
|
| +}
|
| +
|
| +function markTargetLoaded(event) {
|
| + event.target.__loaded = true;
|
| +}
|
| +
|
| +// call <callback> when we ensure all imports have loaded
|
| +function watchImportsLoad(callback, doc) {
|
| + var imports = doc.querySelectorAll('link[rel=import]');
|
| + var loaded = 0, l = imports.length;
|
| + function checkDone(d) {
|
| + if (loaded == l) {
|
| + callback && callback();
|
| + }
|
| + }
|
| + function loadedImport(e) {
|
| + markTargetLoaded(e);
|
| + loaded++;
|
| + checkDone();
|
| + }
|
| + if (l) {
|
| + for (var i=0, imp; (i<l) && (imp=imports[i]); i++) {
|
| + if (isImportLoaded(imp)) {
|
| + loadedImport.call(imp, {target: imp});
|
| + } else {
|
| + imp.addEventListener('load', loadedImport);
|
| + imp.addEventListener('error', loadedImport);
|
| + }
|
| + }
|
| + } else {
|
| + checkDone();
|
| + }
|
| +}
|
| +
|
| +// NOTE: test for native imports loading is based on explicitly watching
|
| +// all imports (see below).
|
| +function isImportLoaded(link) {
|
| + return useNative ? link.__loaded : link.__importParsed;
|
| +}
|
| +
|
| +// TODO(sorvell): Workaround for
|
| +// https://www.w3.org/Bugs/Public/show_bug.cgi?id=25007, should be removed when
|
| +// this bug is addressed.
|
| +// (1) Install a mutation observer to see when HTMLImports have loaded
|
| +// (2) if this script is run during document load it will watch any existing
|
| +// imports for loading.
|
| +//
|
| +// NOTE: The workaround has restricted functionality: (1) it's only compatible
|
| +// with imports that are added to document.head since the mutation observer
|
| +// watches only head for perf reasons, (2) it requires this script
|
| +// to run before any imports have completed loading.
|
| +if (useNative) {
|
| + new MutationObserver(function(mxns) {
|
| + for (var i=0, l=mxns.length, m; (i < l) && (m=mxns[i]); i++) {
|
| + if (m.addedNodes) {
|
| + handleImports(m.addedNodes);
|
| + }
|
| + }
|
| + }).observe(document.head, {childList: true});
|
| +
|
| + function handleImports(nodes) {
|
| + for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
|
| + if (isImport(n)) {
|
| + handleImport(n);
|
| + }
|
| + }
|
| + }
|
| +
|
| + function isImport(element) {
|
| + return element.localName === 'link' && element.rel === 'import';
|
| + }
|
| +
|
| + function handleImport(element) {
|
| + var loaded = element.import;
|
| + if (loaded) {
|
| + markTargetLoaded({target: element});
|
| + } else {
|
| + element.addEventListener('load', markTargetLoaded);
|
| + element.addEventListener('error', markTargetLoaded);
|
| + }
|
| + }
|
| +
|
| + // make sure to catch any imports that are in the process of loading
|
| + // when this script is run.
|
| + (function() {
|
| + if (document.readyState === 'loading') {
|
| + var imports = document.querySelectorAll('link[rel=import]');
|
| + for (var i=0, l=imports.length, imp; (i<l) && (imp=imports[i]); i++) {
|
| + handleImport(imp);
|
| + }
|
| + }
|
| + })();
|
| +
|
| +}
|
| +
|
| +// Fire the 'HTMLImportsLoaded' event when imports in document at load time
|
| +// have loaded. This event is required to simulate the script blocking
|
| +// behavior of native imports. A main document script that needs to be sure
|
| +// imports have loaded should wait for this event.
|
| +whenImportsReady(function() {
|
| + HTMLImports.ready = true;
|
| + HTMLImports.readyTime = new Date().getTime();
|
| + mainDoc.dispatchEvent(
|
| + new CustomEvent('HTMLImportsLoaded', {bubbles: true})
|
| + );
|
| +});
|
| +
|
| +// exports
|
| +scope.useNative = useNative;
|
| +scope.isImportLoaded = isImportLoaded;
|
| +scope.whenReady = whenImportsReady;
|
| +scope.isIE = isIE;
|
| +
|
| +// deprecated
|
| +scope.whenImportsReady = whenImportsReady;
|
| +
|
| +})(window.HTMLImports);
|
| /*
|
| * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| @@ -10746,186 +10367,13 @@ window.HTMLImports = window.HTMLImports || {flags:{}};
|
| * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| * Code distributed by Google as part of the polymer project is also
|
| * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| - */(function(scope) {
|
| -
|
| -var hasNative = ('import' in document.createElement('link'));
|
| -var useNative = hasNative;
|
| + */
|
| +(function(scope) {
|
|
|
| -isIE = /Trident/.test(navigator.userAgent);
|
| -
|
| -// TODO(sorvell): SD polyfill intrusion
|
| -var hasShadowDOMPolyfill = Boolean(window.ShadowDOMPolyfill);
|
| -var wrap = function(node) {
|
| - return hasShadowDOMPolyfill ? ShadowDOMPolyfill.wrapIfNeeded(node) : node;
|
| -};
|
| -var mainDoc = wrap(document);
|
| -
|
| -// NOTE: We cannot polyfill document.currentScript because it's not possible
|
| -// both to override and maintain the ability to capture the native value;
|
| -// therefore we choose to expose _currentScript both when native imports
|
| -// and the polyfill are in use.
|
| -var currentScriptDescriptor = {
|
| - get: function() {
|
| - var script = HTMLImports.currentScript || document.currentScript ||
|
| - // NOTE: only works when called in synchronously executing code.
|
| - // readyState should check if `loading` but IE10 is
|
| - // interactive when scripts run so we cheat.
|
| - (document.readyState !== 'complete' ?
|
| - document.scripts[document.scripts.length - 1] : null);
|
| - return wrap(script);
|
| - },
|
| - configurable: true
|
| -};
|
| -
|
| -Object.defineProperty(document, '_currentScript', currentScriptDescriptor);
|
| -Object.defineProperty(mainDoc, '_currentScript', currentScriptDescriptor);
|
| -
|
| -// call a callback when all HTMLImports in the document at call (or at least
|
| -// document ready) time have loaded.
|
| -// 1. ensure the document is in a ready state (has dom), then
|
| -// 2. watch for loading of imports and call callback when done
|
| -function whenImportsReady(callback, doc) {
|
| - doc = doc || mainDoc;
|
| - // if document is loading, wait and try again
|
| - whenDocumentReady(function() {
|
| - watchImportsLoad(callback, doc);
|
| - }, doc);
|
| -}
|
| -
|
| -// call the callback when the document is in a ready state (has dom)
|
| -var requiredReadyState = isIE ? 'complete' : 'interactive';
|
| -var READY_EVENT = 'readystatechange';
|
| -function isDocumentReady(doc) {
|
| - return (doc.readyState === 'complete' ||
|
| - doc.readyState === requiredReadyState);
|
| -}
|
| -
|
| -// call <callback> when we ensure the document is in a ready state
|
| -function whenDocumentReady(callback, doc) {
|
| - if (!isDocumentReady(doc)) {
|
| - var checkReady = function() {
|
| - if (doc.readyState === 'complete' ||
|
| - doc.readyState === requiredReadyState) {
|
| - doc.removeEventListener(READY_EVENT, checkReady);
|
| - whenDocumentReady(callback, doc);
|
| - }
|
| - }
|
| - doc.addEventListener(READY_EVENT, checkReady);
|
| - } else if (callback) {
|
| - callback();
|
| - }
|
| -}
|
| -
|
| -// call <callback> when we ensure all imports have loaded
|
| -function watchImportsLoad(callback, doc) {
|
| - var imports = doc.querySelectorAll('link[rel=import]');
|
| - var loaded = 0, l = imports.length;
|
| - function checkDone(d) {
|
| - if (loaded == l) {
|
| - callback && callback();
|
| - }
|
| - }
|
| - function loadedImport(e) {
|
| - loaded++;
|
| - checkDone();
|
| - }
|
| - if (l) {
|
| - for (var i=0, imp; (i<l) && (imp=imports[i]); i++) {
|
| - if (isImportLoaded(imp)) {
|
| - loadedImport.call(imp);
|
| - } else {
|
| - imp.addEventListener('load', loadedImport);
|
| - imp.addEventListener('error', loadedImport);
|
| - }
|
| - }
|
| - } else {
|
| - checkDone();
|
| - }
|
| -}
|
| -
|
| -// NOTE: test for native imports loading is based on explicitly watching
|
| -// all imports (see below).
|
| -function isImportLoaded(link) {
|
| - return useNative ? link.__loaded : link.__importParsed;
|
| -}
|
| -
|
| -// TODO(sorvell): install a mutation observer to see if HTMLImports have loaded
|
| -// this is a workaround for https://www.w3.org/Bugs/Public/show_bug.cgi?id=25007
|
| -// and should be removed when this bug is addressed.
|
| -if (useNative) {
|
| - new MutationObserver(function(mxns) {
|
| - for (var i=0, l=mxns.length, m; (i < l) && (m=mxns[i]); i++) {
|
| - if (m.addedNodes) {
|
| - handleImports(m.addedNodes);
|
| - }
|
| - }
|
| - }).observe(document.head, {childList: true});
|
| -
|
| - function handleImports(nodes) {
|
| - for (var i=0, l=nodes.length, n; (i<l) && (n=nodes[i]); i++) {
|
| - if (isImport(n)) {
|
| - handleImport(n);
|
| - }
|
| - }
|
| - }
|
| -
|
| - function isImport(element) {
|
| - return element.localName === 'link' && element.rel === 'import';
|
| - }
|
| -
|
| - function handleImport(element) {
|
| - var loaded = element.import;
|
| - if (loaded) {
|
| - markTargetLoaded({target: element});
|
| - } else {
|
| - element.addEventListener('load', markTargetLoaded);
|
| - element.addEventListener('error', markTargetLoaded);
|
| - }
|
| - }
|
| -
|
| - function markTargetLoaded(event) {
|
| - event.target.__loaded = true;
|
| - }
|
| -
|
| -}
|
| -
|
| -// Fire the 'HTMLImportsLoaded' event when imports in document at load time
|
| -// have loaded. This event is required to simulate the script blocking
|
| -// behavior of native imports. A main document script that needs to be sure
|
| -// imports have loaded should wait for this event.
|
| -whenImportsReady(function() {
|
| - HTMLImports.ready = true;
|
| - HTMLImports.readyTime = new Date().getTime();
|
| - mainDoc.dispatchEvent(
|
| - new CustomEvent('HTMLImportsLoaded', {bubbles: true})
|
| - );
|
| -});
|
| -
|
| -// exports
|
| -scope.useNative = useNative;
|
| -scope.isImportLoaded = isImportLoaded;
|
| -scope.whenReady = whenImportsReady;
|
| -scope.isIE = isIE;
|
| -
|
| -// deprecated
|
| -scope.whenImportsReady = whenImportsReady;
|
| -
|
| -})(window.HTMLImports);
|
| -
|
| -/*
|
| - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| - * Code distributed by Google as part of the polymer project is also
|
| - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| - */
|
| -(function(scope) {
|
| -
|
| - // imports
|
| - var path = scope.path;
|
| - var xhr = scope.xhr;
|
| - var flags = scope.flags;
|
| + // imports
|
| + var path = scope.path;
|
| + var xhr = scope.xhr;
|
| + var flags = scope.flags;
|
|
|
| // TODO(sorvell): this loader supports a dynamic list of urls
|
| // and an oncomplete callback that is called when the loader is done.
|
| @@ -12730,110 +12178,27 @@ if (window.ShadowDOMPolyfill) {
|
| */
|
|
|
| (function(scope) {
|
| - var endOfMicrotask = scope.endOfMicrotask;
|
| -
|
| - // Generic url loader
|
| - function Loader(regex) {
|
| - this.cache = Object.create(null);
|
| - this.map = Object.create(null);
|
| - this.requests = 0;
|
| - this.regex = regex;
|
| - }
|
| - Loader.prototype = {
|
| -
|
| - // TODO(dfreedm): there may be a better factoring here
|
| - // extract absolute urls from the text (full of relative urls)
|
| - extractUrls: function(text, base) {
|
| - var matches = [];
|
| - var matched, u;
|
| - while ((matched = this.regex.exec(text))) {
|
| - u = new URL(matched[1], base);
|
| - matches.push({matched: matched[0], url: u.href});
|
| - }
|
| - return matches;
|
| - },
|
| - // take a text blob, a root url, and a callback and load all the urls found within the text
|
| - // returns a map of absolute url to text
|
| - process: function(text, root, callback) {
|
| - var matches = this.extractUrls(text, root);
|
| -
|
| - // every call to process returns all the text this loader has ever received
|
| - var done = callback.bind(null, this.map);
|
| - this.fetch(matches, done);
|
| - },
|
| - // build a mapping of url -> text from matches
|
| - fetch: function(matches, callback) {
|
| - var inflight = matches.length;
|
| -
|
| - // return early if there is no fetching to be done
|
| - if (!inflight) {
|
| - return callback();
|
| - }
|
| -
|
| - // wait for all subrequests to return
|
| - var done = function() {
|
| - if (--inflight === 0) {
|
| - callback();
|
| - }
|
| - };
|
| -
|
| - // start fetching all subrequests
|
| - var m, req, url;
|
| - for (var i = 0; i < inflight; i++) {
|
| - m = matches[i];
|
| - url = m.url;
|
| - req = this.cache[url];
|
| - // if this url has already been requested, skip requesting it again
|
| - if (!req) {
|
| - req = this.xhr(url);
|
| - req.match = m;
|
| - this.cache[url] = req;
|
| - }
|
| - // wait for the request to process its subrequests
|
| - req.wait(done);
|
| - }
|
| - },
|
| - handleXhr: function(request) {
|
| - var match = request.match;
|
| - var url = match.url;
|
| -
|
| - // handle errors with an empty string
|
| - var response = request.response || request.responseText || '';
|
| - this.map[url] = response;
|
| - this.fetch(this.extractUrls(response, url), request.resolve);
|
| - },
|
| - xhr: function(url) {
|
| - this.requests++;
|
| - var request = new XMLHttpRequest();
|
| - request.open('GET', url, true);
|
| - request.send();
|
| - request.onerror = request.onload = this.handleXhr.bind(this, request);
|
| -
|
| - // queue of tasks to run after XHR returns
|
| - request.pending = [];
|
| - request.resolve = function() {
|
| - var pending = request.pending;
|
| - for(var i = 0; i < pending.length; i++) {
|
| - pending[i]();
|
| - }
|
| - request.pending = null;
|
| - };
|
|
|
| - // if we have already resolved, pending is null, async call the callback
|
| - request.wait = function(fn) {
|
| - if (request.pending) {
|
| - request.pending.push(fn);
|
| - } else {
|
| - endOfMicrotask(fn);
|
| - }
|
| - };
|
| + // TODO(sorvell): It's desireable to provide a default stylesheet
|
| + // that's convenient for styling unresolved elements, but
|
| + // it's cumbersome to have to include this manually in every page.
|
| + // It would make sense to put inside some HTMLImport but
|
| + // the HTMLImports polyfill does not allow loading of stylesheets
|
| + // that block rendering. Therefore this injection is tolerated here.
|
|
|
| - return request;
|
| - }
|
| - };
|
| + var style = document.createElement('style');
|
| + style.textContent = ''
|
| + + 'body {'
|
| + + 'transition: opacity ease-in 0.2s;'
|
| + + ' } \n'
|
| + + 'body[unresolved] {'
|
| + + 'opacity: 0; display: block; overflow: hidden;'
|
| + + ' } \n'
|
| + ;
|
| + var head = document.querySelector('head');
|
| + head.insertBefore(style, head.firstChild);
|
|
|
| - scope.Loader = Loader;
|
| -})(window.Platform);
|
| +})(Platform);
|
|
|
| /*
|
| * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| @@ -12846,1755 +12211,53 @@ if (window.ShadowDOMPolyfill) {
|
|
|
| (function(scope) {
|
|
|
| -var urlResolver = scope.urlResolver;
|
| -var Loader = scope.Loader;
|
| -
|
| -function StyleResolver() {
|
| - this.loader = new Loader(this.regex);
|
| -}
|
| -StyleResolver.prototype = {
|
| - regex: /@import\s+(?:url)?["'\(]*([^'"\)]*)['"\)]*;/g,
|
| - // Recursively replace @imports with the text at that url
|
| - resolve: function(text, url, callback) {
|
| - var done = function(map) {
|
| - callback(this.flatten(text, url, map));
|
| - }.bind(this);
|
| - this.loader.process(text, url, done);
|
| - },
|
| - // resolve the textContent of a style node
|
| - resolveNode: function(style, url, callback) {
|
| - var text = style.textContent;
|
| - var done = function(text) {
|
| - style.textContent = text;
|
| - callback(style);
|
| - };
|
| - this.resolve(text, url, done);
|
| - },
|
| - // flatten all the @imports to text
|
| - flatten: function(text, base, map) {
|
| - var matches = this.loader.extractUrls(text, base);
|
| - var match, url, intermediate;
|
| - for (var i = 0; i < matches.length; i++) {
|
| - match = matches[i];
|
| - url = match.url;
|
| - // resolve any css text to be relative to the importer, keep absolute url
|
| - intermediate = urlResolver.resolveCssText(map[url], url, true);
|
| - // flatten intermediate @imports
|
| - intermediate = this.flatten(intermediate, base, map);
|
| - text = text.replace(match.matched, intermediate);
|
| - }
|
| - return text;
|
| - },
|
| - loadStyles: function(styles, base, callback) {
|
| - var loaded=0, l = styles.length;
|
| - // called in the context of the style
|
| - function loadedStyle(style) {
|
| - loaded++;
|
| - if (loaded === l && callback) {
|
| - callback();
|
| - }
|
| - }
|
| - for (var i=0, s; (i<l) && (s=styles[i]); i++) {
|
| - this.resolveNode(s, base, loadedStyle);
|
| + function withDependencies(task, depends) {
|
| + depends = depends || [];
|
| + if (!depends.map) {
|
| + depends = [depends];
|
| }
|
| + return task.apply(this, depends.map(marshal));
|
| }
|
| -};
|
| -
|
| -var styleResolver = new StyleResolver();
|
| -
|
| -// exports
|
| -scope.styleResolver = styleResolver;
|
|
|
| -})(window.Platform);
|
| -
|
| -// Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| -// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| -// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| -// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| -// Code distributed by Google as part of the polymer project is also
|
| -// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| -
|
| -(function(global) {
|
| - 'use strict';
|
| -
|
| - var filter = Array.prototype.filter.call.bind(Array.prototype.filter);
|
| -
|
| - function getTreeScope(node) {
|
| - while (node.parentNode) {
|
| - node = node.parentNode;
|
| + function module(name, dependsOrFactory, moduleFactory) {
|
| + var module;
|
| + switch (arguments.length) {
|
| + case 0:
|
| + return;
|
| + case 1:
|
| + module = null;
|
| + break;
|
| + case 2:
|
| + // dependsOrFactory is `factory` in this case
|
| + module = dependsOrFactory.apply(this);
|
| + break;
|
| + default:
|
| + // dependsOrFactory is `depends` in this case
|
| + module = withDependencies(moduleFactory, dependsOrFactory);
|
| + break;
|
| }
|
| -
|
| - return typeof node.getElementById === 'function' ? node : null;
|
| - }
|
| -
|
| - Node.prototype.bind = function(name, observable) {
|
| - console.error('Unhandled binding to Node: ', this, name, observable);
|
| + modules[name] = module;
|
| };
|
|
|
| - Node.prototype.bindFinished = function() {};
|
| -
|
| - function updateBindings(node, name, binding) {
|
| - var bindings = node.bindings_;
|
| - if (!bindings)
|
| - bindings = node.bindings_ = {};
|
| -
|
| - if (bindings[name])
|
| - binding[name].close();
|
| -
|
| - return bindings[name] = binding;
|
| - }
|
| -
|
| - function returnBinding(node, name, binding) {
|
| - return binding;
|
| - }
|
| -
|
| - function sanitizeValue(value) {
|
| - return value == null ? '' : value;
|
| - }
|
| -
|
| - function updateText(node, value) {
|
| - node.data = sanitizeValue(value);
|
| - }
|
| -
|
| - function textBinding(node) {
|
| - return function(value) {
|
| - return updateText(node, value);
|
| - };
|
| - }
|
| -
|
| - var maybeUpdateBindings = returnBinding;
|
| -
|
| - Object.defineProperty(Platform, 'enableBindingsReflection', {
|
| - get: function() {
|
| - return maybeUpdateBindings === updateBindings;
|
| - },
|
| - set: function(enable) {
|
| - maybeUpdateBindings = enable ? updateBindings : returnBinding;
|
| - return enable;
|
| - },
|
| - configurable: true
|
| - });
|
| -
|
| - Text.prototype.bind = function(name, value, oneTime) {
|
| - if (name !== 'textContent')
|
| - return Node.prototype.bind.call(this, name, value, oneTime);
|
| -
|
| - if (oneTime)
|
| - return updateText(this, value);
|
| -
|
| - var observable = value;
|
| - updateText(this, observable.open(textBinding(this)));
|
| - return maybeUpdateBindings(this, name, observable);
|
| - }
|
| -
|
| - function updateAttribute(el, name, conditional, value) {
|
| - if (conditional) {
|
| - if (value)
|
| - el.setAttribute(name, '');
|
| - else
|
| - el.removeAttribute(name);
|
| - return;
|
| - }
|
| -
|
| - el.setAttribute(name, sanitizeValue(value));
|
| - }
|
| -
|
| - function attributeBinding(el, name, conditional) {
|
| - return function(value) {
|
| - updateAttribute(el, name, conditional, value);
|
| - };
|
| + function marshal(name) {
|
| + return modules[name];
|
| }
|
|
|
| - Element.prototype.bind = function(name, value, oneTime) {
|
| - var conditional = name[name.length - 1] == '?';
|
| - if (conditional) {
|
| - this.removeAttribute(name);
|
| - name = name.slice(0, -1);
|
| - }
|
| -
|
| - if (oneTime)
|
| - return updateAttribute(this, name, conditional, value);
|
| -
|
| -
|
| - var observable = value;
|
| - updateAttribute(this, name, conditional,
|
| - observable.open(attributeBinding(this, name, conditional)));
|
| -
|
| - return maybeUpdateBindings(this, name, observable);
|
| - };
|
| + var modules = {};
|
|
|
| - var checkboxEventType;
|
| - (function() {
|
| - // Attempt to feature-detect which event (change or click) is fired first
|
| - // for checkboxes.
|
| - var div = document.createElement('div');
|
| - var checkbox = div.appendChild(document.createElement('input'));
|
| - checkbox.setAttribute('type', 'checkbox');
|
| - var first;
|
| - var count = 0;
|
| - checkbox.addEventListener('click', function(e) {
|
| - count++;
|
| - first = first || 'click';
|
| - });
|
| - checkbox.addEventListener('change', function() {
|
| - count++;
|
| - first = first || 'change';
|
| + function using(depends, task) {
|
| + HTMLImports.whenImportsReady(function() {
|
| + withDependencies(task, depends);
|
| });
|
| + };
|
|
|
| - var event = document.createEvent('MouseEvent');
|
| - event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false,
|
| - false, false, false, 0, null);
|
| - checkbox.dispatchEvent(event);
|
| - // WebKit/Blink don't fire the change event if the element is outside the
|
| - // document, so assume 'change' for that case.
|
| - checkboxEventType = count == 1 ? 'change' : first;
|
| - })();
|
| -
|
| - function getEventForInputType(element) {
|
| - switch (element.type) {
|
| - case 'checkbox':
|
| - return checkboxEventType;
|
| - case 'radio':
|
| - case 'select-multiple':
|
| - case 'select-one':
|
| - return 'change';
|
| - case 'range':
|
| - if (/Trident|MSIE/.test(navigator.userAgent))
|
| - return 'change';
|
| - default:
|
| - return 'input';
|
| - }
|
| - }
|
| -
|
| - function updateInput(input, property, value, santizeFn) {
|
| - input[property] = (santizeFn || sanitizeValue)(value);
|
| - }
|
| -
|
| - function inputBinding(input, property, santizeFn) {
|
| - return function(value) {
|
| - return updateInput(input, property, value, santizeFn);
|
| - }
|
| - }
|
| -
|
| - function noop() {}
|
| -
|
| - function bindInputEvent(input, property, observable, postEventFn) {
|
| - var eventType = getEventForInputType(input);
|
| -
|
| - function eventHandler() {
|
| - observable.setValue(input[property]);
|
| - observable.discardChanges();
|
| - (postEventFn || noop)(input);
|
| - Platform.performMicrotaskCheckpoint();
|
| - }
|
| - input.addEventListener(eventType, eventHandler);
|
| -
|
| - return {
|
| - close: function() {
|
| - input.removeEventListener(eventType, eventHandler);
|
| - observable.close();
|
| - },
|
| -
|
| - observable_: observable
|
| - }
|
| - }
|
| -
|
| - function booleanSanitize(value) {
|
| - return Boolean(value);
|
| - }
|
| -
|
| - // |element| is assumed to be an HTMLInputElement with |type| == 'radio'.
|
| - // Returns an array containing all radio buttons other than |element| that
|
| - // have the same |name|, either in the form that |element| belongs to or,
|
| - // if no form, in the document tree to which |element| belongs.
|
| - //
|
| - // This implementation is based upon the HTML spec definition of a
|
| - // "radio button group":
|
| - // http://www.whatwg.org/specs/web-apps/current-work/multipage/number-state.html#radio-button-group
|
| - //
|
| - function getAssociatedRadioButtons(element) {
|
| - if (element.form) {
|
| - return filter(element.form.elements, function(el) {
|
| - return el != element &&
|
| - el.tagName == 'INPUT' &&
|
| - el.type == 'radio' &&
|
| - el.name == element.name;
|
| - });
|
| - } else {
|
| - var treeScope = getTreeScope(element);
|
| - if (!treeScope)
|
| - return [];
|
| - var radios = treeScope.querySelectorAll(
|
| - 'input[type="radio"][name="' + element.name + '"]');
|
| - return filter(radios, function(el) {
|
| - return el != element && !el.form;
|
| - });
|
| - }
|
| - }
|
| -
|
| - function checkedPostEvent(input) {
|
| - // Only the radio button that is getting checked gets an event. We
|
| - // therefore find all the associated radio buttons and update their
|
| - // check binding manually.
|
| - if (input.tagName === 'INPUT' &&
|
| - input.type === 'radio') {
|
| - getAssociatedRadioButtons(input).forEach(function(radio) {
|
| - var checkedBinding = radio.bindings_.checked;
|
| - if (checkedBinding) {
|
| - // Set the value directly to avoid an infinite call stack.
|
| - checkedBinding.observable_.setValue(false);
|
| - }
|
| - });
|
| - }
|
| - }
|
| -
|
| - HTMLInputElement.prototype.bind = function(name, value, oneTime) {
|
| - if (name !== 'value' && name !== 'checked')
|
| - return HTMLElement.prototype.bind.call(this, name, value, oneTime);
|
| -
|
| - this.removeAttribute(name);
|
| - var sanitizeFn = name == 'checked' ? booleanSanitize : sanitizeValue;
|
| - var postEventFn = name == 'checked' ? checkedPostEvent : noop;
|
| -
|
| - if (oneTime)
|
| - return updateInput(this, name, value, sanitizeFn);
|
| -
|
| -
|
| - var observable = value;
|
| - var binding = bindInputEvent(this, name, observable, postEventFn);
|
| - updateInput(this, name,
|
| - observable.open(inputBinding(this, name, sanitizeFn)),
|
| - sanitizeFn);
|
| -
|
| - // Checkboxes may need to update bindings of other checkboxes.
|
| - return updateBindings(this, name, binding);
|
| - }
|
| -
|
| - HTMLTextAreaElement.prototype.bind = function(name, value, oneTime) {
|
| - if (name !== 'value')
|
| - return HTMLElement.prototype.bind.call(this, name, value, oneTime);
|
| -
|
| - this.removeAttribute('value');
|
| + // exports
|
|
|
| - if (oneTime)
|
| - return updateInput(this, 'value', value);
|
| -
|
| - var observable = value;
|
| - var binding = bindInputEvent(this, 'value', observable);
|
| - updateInput(this, 'value',
|
| - observable.open(inputBinding(this, 'value', sanitizeValue)));
|
| - return maybeUpdateBindings(this, name, binding);
|
| - }
|
| -
|
| - function updateOption(option, value) {
|
| - var parentNode = option.parentNode;;
|
| - var select;
|
| - var selectBinding;
|
| - var oldValue;
|
| - if (parentNode instanceof HTMLSelectElement &&
|
| - parentNode.bindings_ &&
|
| - parentNode.bindings_.value) {
|
| - select = parentNode;
|
| - selectBinding = select.bindings_.value;
|
| - oldValue = select.value;
|
| - }
|
| -
|
| - option.value = sanitizeValue(value);
|
| -
|
| - if (select && select.value != oldValue) {
|
| - selectBinding.observable_.setValue(select.value);
|
| - selectBinding.observable_.discardChanges();
|
| - Platform.performMicrotaskCheckpoint();
|
| - }
|
| - }
|
| -
|
| - function optionBinding(option) {
|
| - return function(value) {
|
| - updateOption(option, value);
|
| - }
|
| - }
|
| -
|
| - HTMLOptionElement.prototype.bind = function(name, value, oneTime) {
|
| - if (name !== 'value')
|
| - return HTMLElement.prototype.bind.call(this, name, value, oneTime);
|
| -
|
| - this.removeAttribute('value');
|
| -
|
| - if (oneTime)
|
| - return updateOption(this, value);
|
| -
|
| - var observable = value;
|
| - var binding = bindInputEvent(this, 'value', observable);
|
| - updateOption(this, observable.open(optionBinding(this)));
|
| - return maybeUpdateBindings(this, name, binding);
|
| - }
|
| -
|
| - HTMLSelectElement.prototype.bind = function(name, value, oneTime) {
|
| - if (name === 'selectedindex')
|
| - name = 'selectedIndex';
|
| -
|
| - if (name !== 'selectedIndex' && name !== 'value')
|
| - return HTMLElement.prototype.bind.call(this, name, value, oneTime);
|
| -
|
| - this.removeAttribute(name);
|
| -
|
| - if (oneTime)
|
| - return updateInput(this, name, value);
|
| -
|
| - var observable = value;
|
| - var binding = bindInputEvent(this, name, observable);
|
| - updateInput(this, name,
|
| - observable.open(inputBinding(this, name)));
|
| -
|
| - // Option update events may need to access select bindings.
|
| - return updateBindings(this, name, binding);
|
| - }
|
| -})(this);
|
| -
|
| -// Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| -// This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| -// The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| -// The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| -// Code distributed by Google as part of the polymer project is also
|
| -// subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| -
|
| -(function(global) {
|
| - 'use strict';
|
| -
|
| - function assert(v) {
|
| - if (!v)
|
| - throw new Error('Assertion failed');
|
| - }
|
| -
|
| - var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
|
| -
|
| - function getFragmentRoot(node) {
|
| - var p;
|
| - while (p = node.parentNode) {
|
| - node = p;
|
| - }
|
| -
|
| - return node;
|
| - }
|
| -
|
| - function searchRefId(node, id) {
|
| - if (!id)
|
| - return;
|
| -
|
| - var ref;
|
| - var selector = '#' + id;
|
| - while (!ref) {
|
| - node = getFragmentRoot(node);
|
| -
|
| - if (node.protoContent_)
|
| - ref = node.protoContent_.querySelector(selector);
|
| - else if (node.getElementById)
|
| - ref = node.getElementById(id);
|
| -
|
| - if (ref || !node.templateCreator_)
|
| - break
|
| -
|
| - node = node.templateCreator_;
|
| - }
|
| -
|
| - return ref;
|
| - }
|
| -
|
| - function getInstanceRoot(node) {
|
| - while (node.parentNode) {
|
| - node = node.parentNode;
|
| - }
|
| - return node.templateCreator_ ? node : null;
|
| - }
|
| -
|
| - var Map;
|
| - if (global.Map && typeof global.Map.prototype.forEach === 'function') {
|
| - Map = global.Map;
|
| - } else {
|
| - Map = function() {
|
| - this.keys = [];
|
| - this.values = [];
|
| - };
|
| -
|
| - Map.prototype = {
|
| - set: function(key, value) {
|
| - var index = this.keys.indexOf(key);
|
| - if (index < 0) {
|
| - this.keys.push(key);
|
| - this.values.push(value);
|
| - } else {
|
| - this.values[index] = value;
|
| - }
|
| - },
|
| -
|
| - get: function(key) {
|
| - var index = this.keys.indexOf(key);
|
| - if (index < 0)
|
| - return;
|
| -
|
| - return this.values[index];
|
| - },
|
| -
|
| - delete: function(key, value) {
|
| - var index = this.keys.indexOf(key);
|
| - if (index < 0)
|
| - return false;
|
| -
|
| - this.keys.splice(index, 1);
|
| - this.values.splice(index, 1);
|
| - return true;
|
| - },
|
| -
|
| - forEach: function(f, opt_this) {
|
| - for (var i = 0; i < this.keys.length; i++)
|
| - f.call(opt_this || this, this.values[i], this.keys[i], this);
|
| - }
|
| - };
|
| - }
|
| -
|
| - // JScript does not have __proto__. We wrap all object literals with
|
| - // createObject which uses Object.create, Object.defineProperty and
|
| - // Object.getOwnPropertyDescriptor to create a new object that does the exact
|
| - // same thing. The main downside to this solution is that we have to extract
|
| - // all those property descriptors for IE.
|
| - var createObject = ('__proto__' in {}) ?
|
| - function(obj) { return obj; } :
|
| - function(obj) {
|
| - var proto = obj.__proto__;
|
| - if (!proto)
|
| - return obj;
|
| - var newObject = Object.create(proto);
|
| - Object.getOwnPropertyNames(obj).forEach(function(name) {
|
| - Object.defineProperty(newObject, name,
|
| - Object.getOwnPropertyDescriptor(obj, name));
|
| - });
|
| - return newObject;
|
| - };
|
| -
|
| - // IE does not support have Document.prototype.contains.
|
| - if (typeof document.contains != 'function') {
|
| - Document.prototype.contains = function(node) {
|
| - if (node === this || node.parentNode === this)
|
| - return true;
|
| - return this.documentElement.contains(node);
|
| - }
|
| - }
|
| -
|
| - var BIND = 'bind';
|
| - var REPEAT = 'repeat';
|
| - var IF = 'if';
|
| -
|
| - var templateAttributeDirectives = {
|
| - 'template': true,
|
| - 'repeat': true,
|
| - 'bind': true,
|
| - 'ref': true
|
| - };
|
| -
|
| - var semanticTemplateElements = {
|
| - 'THEAD': true,
|
| - 'TBODY': true,
|
| - 'TFOOT': true,
|
| - 'TH': true,
|
| - 'TR': true,
|
| - 'TD': true,
|
| - 'COLGROUP': true,
|
| - 'COL': true,
|
| - 'CAPTION': true,
|
| - 'OPTION': true,
|
| - 'OPTGROUP': true
|
| - };
|
| -
|
| - var hasTemplateElement = typeof HTMLTemplateElement !== 'undefined';
|
| - if (hasTemplateElement) {
|
| - // TODO(rafaelw): Remove when fix for
|
| - // https://codereview.chromium.org/164803002/
|
| - // makes it to Chrome release.
|
| - (function() {
|
| - var t = document.createElement('template');
|
| - var d = t.content.ownerDocument;
|
| - var html = d.appendChild(d.createElement('html'));
|
| - var head = html.appendChild(d.createElement('head'));
|
| - var base = d.createElement('base');
|
| - base.href = document.baseURI;
|
| - head.appendChild(base);
|
| - })();
|
| - }
|
| -
|
| - var allTemplatesSelectors = 'template, ' +
|
| - Object.keys(semanticTemplateElements).map(function(tagName) {
|
| - return tagName.toLowerCase() + '[template]';
|
| - }).join(', ');
|
| -
|
| - function isSVGTemplate(el) {
|
| - return el.tagName == 'template' &&
|
| - el.namespaceURI == 'http://www.w3.org/2000/svg';
|
| - }
|
| -
|
| - function isHTMLTemplate(el) {
|
| - return el.tagName == 'TEMPLATE' &&
|
| - el.namespaceURI == 'http://www.w3.org/1999/xhtml';
|
| - }
|
| -
|
| - function isAttributeTemplate(el) {
|
| - return Boolean(semanticTemplateElements[el.tagName] &&
|
| - el.hasAttribute('template'));
|
| - }
|
| -
|
| - function isTemplate(el) {
|
| - if (el.isTemplate_ === undefined)
|
| - el.isTemplate_ = el.tagName == 'TEMPLATE' || isAttributeTemplate(el);
|
| -
|
| - return el.isTemplate_;
|
| - }
|
| -
|
| - // FIXME: Observe templates being added/removed from documents
|
| - // FIXME: Expose imperative API to decorate and observe templates in
|
| - // "disconnected tress" (e.g. ShadowRoot)
|
| - document.addEventListener('DOMContentLoaded', function(e) {
|
| - bootstrapTemplatesRecursivelyFrom(document);
|
| - // FIXME: Is this needed? Seems like it shouldn't be.
|
| - Platform.performMicrotaskCheckpoint();
|
| - }, false);
|
| -
|
| - function forAllTemplatesFrom(node, fn) {
|
| - var subTemplates = node.querySelectorAll(allTemplatesSelectors);
|
| -
|
| - if (isTemplate(node))
|
| - fn(node)
|
| - forEach(subTemplates, fn);
|
| - }
|
| -
|
| - function bootstrapTemplatesRecursivelyFrom(node) {
|
| - function bootstrap(template) {
|
| - if (!HTMLTemplateElement.decorate(template))
|
| - bootstrapTemplatesRecursivelyFrom(template.content);
|
| - }
|
| -
|
| - forAllTemplatesFrom(node, bootstrap);
|
| - }
|
| -
|
| - if (!hasTemplateElement) {
|
| - /**
|
| - * This represents a <template> element.
|
| - * @constructor
|
| - * @extends {HTMLElement}
|
| - */
|
| - global.HTMLTemplateElement = function() {
|
| - throw TypeError('Illegal constructor');
|
| - };
|
| - }
|
| -
|
| - var hasProto = '__proto__' in {};
|
| -
|
| - function mixin(to, from) {
|
| - Object.getOwnPropertyNames(from).forEach(function(name) {
|
| - Object.defineProperty(to, name,
|
| - Object.getOwnPropertyDescriptor(from, name));
|
| - });
|
| - }
|
| -
|
| - // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/templates/index.html#dfn-template-contents-owner
|
| - function getOrCreateTemplateContentsOwner(template) {
|
| - var doc = template.ownerDocument
|
| - if (!doc.defaultView)
|
| - return doc;
|
| - var d = doc.templateContentsOwner_;
|
| - if (!d) {
|
| - // TODO(arv): This should either be a Document or HTMLDocument depending
|
| - // on doc.
|
| - d = doc.implementation.createHTMLDocument('');
|
| - while (d.lastChild) {
|
| - d.removeChild(d.lastChild);
|
| - }
|
| - doc.templateContentsOwner_ = d;
|
| - }
|
| - return d;
|
| - }
|
| -
|
| - function getTemplateStagingDocument(template) {
|
| - if (!template.stagingDocument_) {
|
| - var owner = template.ownerDocument;
|
| - if (!owner.stagingDocument_) {
|
| - owner.stagingDocument_ = owner.implementation.createHTMLDocument('');
|
| - owner.stagingDocument_.isStagingDocument = true;
|
| - // TODO(rafaelw): Remove when fix for
|
| - // https://codereview.chromium.org/164803002/
|
| - // makes it to Chrome release.
|
| - var base = owner.stagingDocument_.createElement('base');
|
| - base.href = document.baseURI;
|
| - owner.stagingDocument_.head.appendChild(base);
|
| -
|
| - owner.stagingDocument_.stagingDocument_ = owner.stagingDocument_;
|
| - }
|
| -
|
| - template.stagingDocument_ = owner.stagingDocument_;
|
| - }
|
| -
|
| - return template.stagingDocument_;
|
| - }
|
| -
|
| - // For non-template browsers, the parser will disallow <template> in certain
|
| - // locations, so we allow "attribute templates" which combine the template
|
| - // element with the top-level container node of the content, e.g.
|
| - //
|
| - // <tr template repeat="{{ foo }}"" class="bar"><td>Bar</td></tr>
|
| - //
|
| - // becomes
|
| - //
|
| - // <template repeat="{{ foo }}">
|
| - // + #document-fragment
|
| - // + <tr class="bar">
|
| - // + <td>Bar</td>
|
| - //
|
| - function extractTemplateFromAttributeTemplate(el) {
|
| - var template = el.ownerDocument.createElement('template');
|
| - el.parentNode.insertBefore(template, el);
|
| -
|
| - var attribs = el.attributes;
|
| - var count = attribs.length;
|
| - while (count-- > 0) {
|
| - var attrib = attribs[count];
|
| - if (templateAttributeDirectives[attrib.name]) {
|
| - if (attrib.name !== 'template')
|
| - template.setAttribute(attrib.name, attrib.value);
|
| - el.removeAttribute(attrib.name);
|
| - }
|
| - }
|
| -
|
| - return template;
|
| - }
|
| -
|
| - function extractTemplateFromSVGTemplate(el) {
|
| - var template = el.ownerDocument.createElement('template');
|
| - el.parentNode.insertBefore(template, el);
|
| -
|
| - var attribs = el.attributes;
|
| - var count = attribs.length;
|
| - while (count-- > 0) {
|
| - var attrib = attribs[count];
|
| - template.setAttribute(attrib.name, attrib.value);
|
| - el.removeAttribute(attrib.name);
|
| - }
|
| -
|
| - el.parentNode.removeChild(el);
|
| - return template;
|
| - }
|
| -
|
| - function liftNonNativeTemplateChildrenIntoContent(template, el, useRoot) {
|
| - var content = template.content;
|
| - if (useRoot) {
|
| - content.appendChild(el);
|
| - return;
|
| - }
|
| -
|
| - var child;
|
| - while (child = el.firstChild) {
|
| - content.appendChild(child);
|
| - }
|
| - }
|
| -
|
| - var templateObserver;
|
| - if (typeof MutationObserver == 'function') {
|
| - templateObserver = new MutationObserver(function(records) {
|
| - for (var i = 0; i < records.length; i++) {
|
| - records[i].target.refChanged_();
|
| - }
|
| - });
|
| - }
|
| -
|
| - /**
|
| - * Ensures proper API and content model for template elements.
|
| - * @param {HTMLTemplateElement} opt_instanceRef The template element which
|
| - * |el| template element will return as the value of its ref(), and whose
|
| - * content will be used as source when createInstance() is invoked.
|
| - */
|
| - HTMLTemplateElement.decorate = function(el, opt_instanceRef) {
|
| - if (el.templateIsDecorated_)
|
| - return false;
|
| -
|
| - var templateElement = el;
|
| - templateElement.templateIsDecorated_ = true;
|
| -
|
| - var isNativeHTMLTemplate = isHTMLTemplate(templateElement) &&
|
| - hasTemplateElement;
|
| - var bootstrapContents = isNativeHTMLTemplate;
|
| - var liftContents = !isNativeHTMLTemplate;
|
| - var liftRoot = false;
|
| -
|
| - if (!isNativeHTMLTemplate) {
|
| - if (isAttributeTemplate(templateElement)) {
|
| - assert(!opt_instanceRef);
|
| - templateElement = extractTemplateFromAttributeTemplate(el);
|
| - templateElement.templateIsDecorated_ = true;
|
| - isNativeHTMLTemplate = hasTemplateElement;
|
| - liftRoot = true;
|
| - } else if (isSVGTemplate(templateElement)) {
|
| - templateElement = extractTemplateFromSVGTemplate(el);
|
| - templateElement.templateIsDecorated_ = true;
|
| - isNativeHTMLTemplate = hasTemplateElement;
|
| - }
|
| - }
|
| -
|
| - if (!isNativeHTMLTemplate) {
|
| - fixTemplateElementPrototype(templateElement);
|
| - var doc = getOrCreateTemplateContentsOwner(templateElement);
|
| - templateElement.content_ = doc.createDocumentFragment();
|
| - }
|
| -
|
| - if (opt_instanceRef) {
|
| - // template is contained within an instance, its direct content must be
|
| - // empty
|
| - templateElement.instanceRef_ = opt_instanceRef;
|
| - } else if (liftContents) {
|
| - liftNonNativeTemplateChildrenIntoContent(templateElement,
|
| - el,
|
| - liftRoot);
|
| - } else if (bootstrapContents) {
|
| - bootstrapTemplatesRecursivelyFrom(templateElement.content);
|
| - }
|
| -
|
| - return true;
|
| - };
|
| -
|
| - // TODO(rafaelw): This used to decorate recursively all templates from a given
|
| - // node. This happens by default on 'DOMContentLoaded', but may be needed
|
| - // in subtrees not descendent from document (e.g. ShadowRoot).
|
| - // Review whether this is the right public API.
|
| - HTMLTemplateElement.bootstrap = bootstrapTemplatesRecursivelyFrom;
|
| -
|
| - var htmlElement = global.HTMLUnknownElement || HTMLElement;
|
| -
|
| - var contentDescriptor = {
|
| - get: function() {
|
| - return this.content_;
|
| - },
|
| - enumerable: true,
|
| - configurable: true
|
| - };
|
| -
|
| - if (!hasTemplateElement) {
|
| - // Gecko is more picky with the prototype than WebKit. Make sure to use the
|
| - // same prototype as created in the constructor.
|
| - HTMLTemplateElement.prototype = Object.create(htmlElement.prototype);
|
| -
|
| - Object.defineProperty(HTMLTemplateElement.prototype, 'content',
|
| - contentDescriptor);
|
| - }
|
| -
|
| - function fixTemplateElementPrototype(el) {
|
| - if (hasProto)
|
| - el.__proto__ = HTMLTemplateElement.prototype;
|
| - else
|
| - mixin(el, HTMLTemplateElement.prototype);
|
| - }
|
| -
|
| - function ensureSetModelScheduled(template) {
|
| - if (!template.setModelFn_) {
|
| - template.setModelFn_ = function() {
|
| - template.setModelFnScheduled_ = false;
|
| - var map = getBindings(template,
|
| - template.delegate_ && template.delegate_.prepareBinding);
|
| - processBindings(template, map, template.model_);
|
| - };
|
| - }
|
| -
|
| - if (!template.setModelFnScheduled_) {
|
| - template.setModelFnScheduled_ = true;
|
| - Observer.runEOM_(template.setModelFn_);
|
| - }
|
| - }
|
| -
|
| - mixin(HTMLTemplateElement.prototype, {
|
| - bind: function(name, value, oneTime) {
|
| - if (name != 'ref')
|
| - return Element.prototype.bind.call(this, name, value, oneTime);
|
| -
|
| - var self = this;
|
| - var ref = oneTime ? value : value.open(function(ref) {
|
| - self.setAttribute('ref', ref);
|
| - self.refChanged_();
|
| - });
|
| -
|
| - this.setAttribute('ref', ref);
|
| - this.refChanged_();
|
| - if (oneTime)
|
| - return;
|
| -
|
| - if (!this.bindings_) {
|
| - this.bindings_ = { ref: value };
|
| - } else {
|
| - this.bindings_.ref = value;
|
| - }
|
| -
|
| - return value;
|
| - },
|
| -
|
| - processBindingDirectives_: function(directives) {
|
| - if (this.iterator_)
|
| - this.iterator_.closeDeps();
|
| -
|
| - if (!directives.if && !directives.bind && !directives.repeat) {
|
| - if (this.iterator_) {
|
| - this.iterator_.close();
|
| - this.iterator_ = undefined;
|
| - }
|
| -
|
| - return;
|
| - }
|
| -
|
| - if (!this.iterator_) {
|
| - this.iterator_ = new TemplateIterator(this);
|
| - }
|
| -
|
| - this.iterator_.updateDependencies(directives, this.model_);
|
| -
|
| - if (templateObserver) {
|
| - templateObserver.observe(this, { attributes: true,
|
| - attributeFilter: ['ref'] });
|
| - }
|
| -
|
| - return this.iterator_;
|
| - },
|
| -
|
| - createInstance: function(model, bindingDelegate, delegate_) {
|
| - if (bindingDelegate)
|
| - delegate_ = this.newDelegate_(bindingDelegate);
|
| - else if (!delegate_)
|
| - delegate_ = this.delegate_;
|
| -
|
| - if (!this.refContent_)
|
| - this.refContent_ = this.ref_.content;
|
| - var content = this.refContent_;
|
| - if (content.firstChild === null)
|
| - return emptyInstance;
|
| -
|
| - var map = getInstanceBindingMap(content, delegate_);
|
| - var stagingDocument = getTemplateStagingDocument(this);
|
| - var instance = stagingDocument.createDocumentFragment();
|
| - instance.templateCreator_ = this;
|
| - instance.protoContent_ = content;
|
| - instance.bindings_ = [];
|
| - instance.terminator_ = null;
|
| - var instanceRecord = instance.templateInstance_ = {
|
| - firstNode: null,
|
| - lastNode: null,
|
| - model: model
|
| - };
|
| -
|
| - var i = 0;
|
| - var collectTerminator = false;
|
| - for (var child = content.firstChild; child; child = child.nextSibling) {
|
| - // The terminator of the instance is the clone of the last child of the
|
| - // content. If the last child is an active template, it may produce
|
| - // instances as a result of production, so simply collecting the last
|
| - // child of the instance after it has finished producing may be wrong.
|
| - if (child.nextSibling === null)
|
| - collectTerminator = true;
|
| -
|
| - var clone = cloneAndBindInstance(child, instance, stagingDocument,
|
| - map.children[i++],
|
| - model,
|
| - delegate_,
|
| - instance.bindings_);
|
| - clone.templateInstance_ = instanceRecord;
|
| - if (collectTerminator)
|
| - instance.terminator_ = clone;
|
| - }
|
| -
|
| - instanceRecord.firstNode = instance.firstChild;
|
| - instanceRecord.lastNode = instance.lastChild;
|
| - instance.templateCreator_ = undefined;
|
| - instance.protoContent_ = undefined;
|
| - return instance;
|
| - },
|
| -
|
| - get model() {
|
| - return this.model_;
|
| - },
|
| -
|
| - set model(model) {
|
| - this.model_ = model;
|
| - ensureSetModelScheduled(this);
|
| - },
|
| -
|
| - get bindingDelegate() {
|
| - return this.delegate_ && this.delegate_.raw;
|
| - },
|
| -
|
| - refChanged_: function() {
|
| - if (!this.iterator_ || this.refContent_ === this.ref_.content)
|
| - return;
|
| -
|
| - this.refContent_ = undefined;
|
| - this.iterator_.valueChanged();
|
| - this.iterator_.updateIteratedValue(this.iterator_.getUpdatedValue());
|
| - },
|
| -
|
| - clear: function() {
|
| - this.model_ = undefined;
|
| - this.delegate_ = undefined;
|
| - if (this.bindings_ && this.bindings_.ref)
|
| - this.bindings_.ref.close()
|
| - this.refContent_ = undefined;
|
| - if (!this.iterator_)
|
| - return;
|
| - this.iterator_.valueChanged();
|
| - this.iterator_.close()
|
| - this.iterator_ = undefined;
|
| - },
|
| -
|
| - setDelegate_: function(delegate) {
|
| - this.delegate_ = delegate;
|
| - this.bindingMap_ = undefined;
|
| - if (this.iterator_) {
|
| - this.iterator_.instancePositionChangedFn_ = undefined;
|
| - this.iterator_.instanceModelFn_ = undefined;
|
| - }
|
| - },
|
| -
|
| - newDelegate_: function(bindingDelegate) {
|
| - if (!bindingDelegate)
|
| - return;
|
| -
|
| - function delegateFn(name) {
|
| - var fn = bindingDelegate && bindingDelegate[name];
|
| - if (typeof fn != 'function')
|
| - return;
|
| -
|
| - return function() {
|
| - return fn.apply(bindingDelegate, arguments);
|
| - };
|
| - }
|
| -
|
| - return {
|
| - bindingMaps: {},
|
| - raw: bindingDelegate,
|
| - prepareBinding: delegateFn('prepareBinding'),
|
| - prepareInstanceModel: delegateFn('prepareInstanceModel'),
|
| - prepareInstancePositionChanged:
|
| - delegateFn('prepareInstancePositionChanged')
|
| - };
|
| - },
|
| -
|
| - set bindingDelegate(bindingDelegate) {
|
| - if (this.delegate_) {
|
| - throw Error('Template must be cleared before a new bindingDelegate ' +
|
| - 'can be assigned');
|
| - }
|
| -
|
| - this.setDelegate_(this.newDelegate_(bindingDelegate));
|
| - },
|
| -
|
| - get ref_() {
|
| - var ref = searchRefId(this, this.getAttribute('ref'));
|
| - if (!ref)
|
| - ref = this.instanceRef_;
|
| -
|
| - if (!ref)
|
| - return this;
|
| -
|
| - var nextRef = ref.ref_;
|
| - return nextRef ? nextRef : ref;
|
| - }
|
| - });
|
| -
|
| - // Returns
|
| - // a) undefined if there are no mustaches.
|
| - // b) [TEXT, (ONE_TIME?, PATH, DELEGATE_FN, TEXT)+] if there is at least one mustache.
|
| - function parseMustaches(s, name, node, prepareBindingFn) {
|
| - if (!s || !s.length)
|
| - return;
|
| -
|
| - var tokens;
|
| - var length = s.length;
|
| - var startIndex = 0, lastIndex = 0, endIndex = 0;
|
| - var onlyOneTime = true;
|
| - while (lastIndex < length) {
|
| - var startIndex = s.indexOf('{{', lastIndex);
|
| - var oneTimeStart = s.indexOf('[[', lastIndex);
|
| - var oneTime = false;
|
| - var terminator = '}}';
|
| -
|
| - if (oneTimeStart >= 0 &&
|
| - (startIndex < 0 || oneTimeStart < startIndex)) {
|
| - startIndex = oneTimeStart;
|
| - oneTime = true;
|
| - terminator = ']]';
|
| - }
|
| -
|
| - endIndex = startIndex < 0 ? -1 : s.indexOf(terminator, startIndex + 2);
|
| -
|
| - if (endIndex < 0) {
|
| - if (!tokens)
|
| - return;
|
| -
|
| - tokens.push(s.slice(lastIndex)); // TEXT
|
| - break;
|
| - }
|
| -
|
| - tokens = tokens || [];
|
| - tokens.push(s.slice(lastIndex, startIndex)); // TEXT
|
| - var pathString = s.slice(startIndex + 2, endIndex).trim();
|
| - tokens.push(oneTime); // ONE_TIME?
|
| - onlyOneTime = onlyOneTime && oneTime;
|
| - var delegateFn = prepareBindingFn &&
|
| - prepareBindingFn(pathString, name, node);
|
| - // Don't try to parse the expression if there's a prepareBinding function
|
| - if (delegateFn == null) {
|
| - tokens.push(Path.get(pathString)); // PATH
|
| - } else {
|
| - tokens.push(null);
|
| - }
|
| - tokens.push(delegateFn); // DELEGATE_FN
|
| - lastIndex = endIndex + 2;
|
| - }
|
| -
|
| - if (lastIndex === length)
|
| - tokens.push(''); // TEXT
|
| -
|
| - tokens.hasOnePath = tokens.length === 5;
|
| - tokens.isSimplePath = tokens.hasOnePath &&
|
| - tokens[0] == '' &&
|
| - tokens[4] == '';
|
| - tokens.onlyOneTime = onlyOneTime;
|
| -
|
| - tokens.combinator = function(values) {
|
| - var newValue = tokens[0];
|
| -
|
| - for (var i = 1; i < tokens.length; i += 4) {
|
| - var value = tokens.hasOnePath ? values : values[(i - 1) / 4];
|
| - if (value !== undefined)
|
| - newValue += value;
|
| - newValue += tokens[i + 3];
|
| - }
|
| -
|
| - return newValue;
|
| - }
|
| -
|
| - return tokens;
|
| - };
|
| -
|
| - function processOneTimeBinding(name, tokens, node, model) {
|
| - if (tokens.hasOnePath) {
|
| - var delegateFn = tokens[3];
|
| - var value = delegateFn ? delegateFn(model, node, true) :
|
| - tokens[2].getValueFrom(model);
|
| - return tokens.isSimplePath ? value : tokens.combinator(value);
|
| - }
|
| -
|
| - var values = [];
|
| - for (var i = 1; i < tokens.length; i += 4) {
|
| - var delegateFn = tokens[i + 2];
|
| - values[(i - 1) / 4] = delegateFn ? delegateFn(model, node) :
|
| - tokens[i + 1].getValueFrom(model);
|
| - }
|
| -
|
| - return tokens.combinator(values);
|
| - }
|
| -
|
| - function processSinglePathBinding(name, tokens, node, model) {
|
| - var delegateFn = tokens[3];
|
| - var observer = delegateFn ? delegateFn(model, node, false) :
|
| - new PathObserver(model, tokens[2]);
|
| -
|
| - return tokens.isSimplePath ? observer :
|
| - new ObserverTransform(observer, tokens.combinator);
|
| - }
|
| -
|
| - function processBinding(name, tokens, node, model) {
|
| - if (tokens.onlyOneTime)
|
| - return processOneTimeBinding(name, tokens, node, model);
|
| -
|
| - if (tokens.hasOnePath)
|
| - return processSinglePathBinding(name, tokens, node, model);
|
| -
|
| - var observer = new CompoundObserver();
|
| -
|
| - for (var i = 1; i < tokens.length; i += 4) {
|
| - var oneTime = tokens[i];
|
| - var delegateFn = tokens[i + 2];
|
| -
|
| - if (delegateFn) {
|
| - var value = delegateFn(model, node, oneTime);
|
| - if (oneTime)
|
| - observer.addPath(value)
|
| - else
|
| - observer.addObserver(value);
|
| - continue;
|
| - }
|
| -
|
| - var path = tokens[i + 1];
|
| - if (oneTime)
|
| - observer.addPath(path.getValueFrom(model))
|
| - else
|
| - observer.addPath(model, path);
|
| - }
|
| -
|
| - return new ObserverTransform(observer, tokens.combinator);
|
| - }
|
| -
|
| - function processBindings(node, bindings, model, instanceBindings) {
|
| - for (var i = 0; i < bindings.length; i += 2) {
|
| - var name = bindings[i]
|
| - var tokens = bindings[i + 1];
|
| - var value = processBinding(name, tokens, node, model);
|
| - var binding = node.bind(name, value, tokens.onlyOneTime);
|
| - if (binding && instanceBindings)
|
| - instanceBindings.push(binding);
|
| - }
|
| -
|
| - node.bindFinished();
|
| - if (!bindings.isTemplate)
|
| - return;
|
| -
|
| - node.model_ = model;
|
| - var iter = node.processBindingDirectives_(bindings);
|
| - if (instanceBindings && iter)
|
| - instanceBindings.push(iter);
|
| - }
|
| -
|
| - function parseWithDefault(el, name, prepareBindingFn) {
|
| - var v = el.getAttribute(name);
|
| - return parseMustaches(v == '' ? '{{}}' : v, name, el, prepareBindingFn);
|
| - }
|
| -
|
| - function parseAttributeBindings(element, prepareBindingFn) {
|
| - assert(element);
|
| -
|
| - var bindings = [];
|
| - var ifFound = false;
|
| - var bindFound = false;
|
| -
|
| - for (var i = 0; i < element.attributes.length; i++) {
|
| - var attr = element.attributes[i];
|
| - var name = attr.name;
|
| - var value = attr.value;
|
| -
|
| - // Allow bindings expressed in attributes to be prefixed with underbars.
|
| - // We do this to allow correct semantics for browsers that don't implement
|
| - // <template> where certain attributes might trigger side-effects -- and
|
| - // for IE which sanitizes certain attributes, disallowing mustache
|
| - // replacements in their text.
|
| - while (name[0] === '_') {
|
| - name = name.substring(1);
|
| - }
|
| -
|
| - if (isTemplate(element) &&
|
| - (name === IF || name === BIND || name === REPEAT)) {
|
| - continue;
|
| - }
|
| -
|
| - var tokens = parseMustaches(value, name, element,
|
| - prepareBindingFn);
|
| - if (!tokens)
|
| - continue;
|
| -
|
| - bindings.push(name, tokens);
|
| - }
|
| -
|
| - if (isTemplate(element)) {
|
| - bindings.isTemplate = true;
|
| - bindings.if = parseWithDefault(element, IF, prepareBindingFn);
|
| - bindings.bind = parseWithDefault(element, BIND, prepareBindingFn);
|
| - bindings.repeat = parseWithDefault(element, REPEAT, prepareBindingFn);
|
| -
|
| - if (bindings.if && !bindings.bind && !bindings.repeat)
|
| - bindings.bind = parseMustaches('{{}}', BIND, element, prepareBindingFn);
|
| - }
|
| -
|
| - return bindings;
|
| - }
|
| -
|
| - function getBindings(node, prepareBindingFn) {
|
| - if (node.nodeType === Node.ELEMENT_NODE)
|
| - return parseAttributeBindings(node, prepareBindingFn);
|
| -
|
| - if (node.nodeType === Node.TEXT_NODE) {
|
| - var tokens = parseMustaches(node.data, 'textContent', node,
|
| - prepareBindingFn);
|
| - if (tokens)
|
| - return ['textContent', tokens];
|
| - }
|
| -
|
| - return [];
|
| - }
|
| -
|
| - function cloneAndBindInstance(node, parent, stagingDocument, bindings, model,
|
| - delegate,
|
| - instanceBindings,
|
| - instanceRecord) {
|
| - var clone = parent.appendChild(stagingDocument.importNode(node, false));
|
| -
|
| - var i = 0;
|
| - for (var child = node.firstChild; child; child = child.nextSibling) {
|
| - cloneAndBindInstance(child, clone, stagingDocument,
|
| - bindings.children[i++],
|
| - model,
|
| - delegate,
|
| - instanceBindings);
|
| - }
|
| -
|
| - if (bindings.isTemplate) {
|
| - HTMLTemplateElement.decorate(clone, node);
|
| - if (delegate)
|
| - clone.setDelegate_(delegate);
|
| - }
|
| -
|
| - processBindings(clone, bindings, model, instanceBindings);
|
| - return clone;
|
| - }
|
| -
|
| - function createInstanceBindingMap(node, prepareBindingFn) {
|
| - var map = getBindings(node, prepareBindingFn);
|
| - map.children = {};
|
| - var index = 0;
|
| - for (var child = node.firstChild; child; child = child.nextSibling) {
|
| - map.children[index++] = createInstanceBindingMap(child, prepareBindingFn);
|
| - }
|
| -
|
| - return map;
|
| - }
|
| -
|
| - var contentUidCounter = 1;
|
| -
|
| - // TODO(rafaelw): Setup a MutationObserver on content which clears the id
|
| - // so that bindingMaps regenerate when the template.content changes.
|
| - function getContentUid(content) {
|
| - var id = content.id_;
|
| - if (!id)
|
| - id = content.id_ = contentUidCounter++;
|
| - return id;
|
| - }
|
| -
|
| - // Each delegate is associated with a set of bindingMaps, one for each
|
| - // content which may be used by a template. The intent is that each binding
|
| - // delegate gets the opportunity to prepare the instance (via the prepare*
|
| - // delegate calls) once across all uses.
|
| - // TODO(rafaelw): Separate out the parse map from the binding map. In the
|
| - // current implementation, if two delegates need a binding map for the same
|
| - // content, the second will have to reparse.
|
| - function getInstanceBindingMap(content, delegate_) {
|
| - var contentId = getContentUid(content);
|
| - if (delegate_) {
|
| - var map = delegate_.bindingMaps[contentId];
|
| - if (!map) {
|
| - map = delegate_.bindingMaps[contentId] =
|
| - createInstanceBindingMap(content, delegate_.prepareBinding) || [];
|
| - }
|
| - return map;
|
| - }
|
| -
|
| - var map = content.bindingMap_;
|
| - if (!map) {
|
| - map = content.bindingMap_ =
|
| - createInstanceBindingMap(content, undefined) || [];
|
| - }
|
| - return map;
|
| - }
|
| -
|
| - Object.defineProperty(Node.prototype, 'templateInstance', {
|
| - get: function() {
|
| - var instance = this.templateInstance_;
|
| - return instance ? instance :
|
| - (this.parentNode ? this.parentNode.templateInstance : undefined);
|
| - }
|
| - });
|
| -
|
| - var emptyInstance = document.createDocumentFragment();
|
| - emptyInstance.bindings_ = [];
|
| - emptyInstance.terminator_ = null;
|
| -
|
| - function TemplateIterator(templateElement) {
|
| - this.closed = false;
|
| - this.templateElement_ = templateElement;
|
| - this.instances = [];
|
| - this.deps = undefined;
|
| - this.iteratedValue = [];
|
| - this.presentValue = undefined;
|
| - this.arrayObserver = undefined;
|
| - }
|
| -
|
| - TemplateIterator.prototype = {
|
| - closeDeps: function() {
|
| - var deps = this.deps;
|
| - if (deps) {
|
| - if (deps.ifOneTime === false)
|
| - deps.ifValue.close();
|
| - if (deps.oneTime === false)
|
| - deps.value.close();
|
| - }
|
| - },
|
| -
|
| - updateDependencies: function(directives, model) {
|
| - this.closeDeps();
|
| -
|
| - var deps = this.deps = {};
|
| - var template = this.templateElement_;
|
| -
|
| - var ifValue = true;
|
| - if (directives.if) {
|
| - deps.hasIf = true;
|
| - deps.ifOneTime = directives.if.onlyOneTime;
|
| - deps.ifValue = processBinding(IF, directives.if, template, model);
|
| -
|
| - ifValue = deps.ifValue;
|
| -
|
| - // oneTime if & predicate is false. nothing else to do.
|
| - if (deps.ifOneTime && !ifValue) {
|
| - this.valueChanged();
|
| - return;
|
| - }
|
| -
|
| - if (!deps.ifOneTime)
|
| - ifValue = ifValue.open(this.updateIfValue, this);
|
| - }
|
| -
|
| - if (directives.repeat) {
|
| - deps.repeat = true;
|
| - deps.oneTime = directives.repeat.onlyOneTime;
|
| - deps.value = processBinding(REPEAT, directives.repeat, template, model);
|
| - } else {
|
| - deps.repeat = false;
|
| - deps.oneTime = directives.bind.onlyOneTime;
|
| - deps.value = processBinding(BIND, directives.bind, template, model);
|
| - }
|
| -
|
| - var value = deps.value;
|
| - if (!deps.oneTime)
|
| - value = value.open(this.updateIteratedValue, this);
|
| -
|
| - if (!ifValue) {
|
| - this.valueChanged();
|
| - return;
|
| - }
|
| -
|
| - this.updateValue(value);
|
| - },
|
| -
|
| - /**
|
| - * Gets the updated value of the bind/repeat. This can potentially call
|
| - * user code (if a bindingDelegate is set up) so we try to avoid it if we
|
| - * already have the value in hand (from Observer.open).
|
| - */
|
| - getUpdatedValue: function() {
|
| - var value = this.deps.value;
|
| - if (!this.deps.oneTime)
|
| - value = value.discardChanges();
|
| - return value;
|
| - },
|
| -
|
| - updateIfValue: function(ifValue) {
|
| - if (!ifValue) {
|
| - this.valueChanged();
|
| - return;
|
| - }
|
| -
|
| - this.updateValue(this.getUpdatedValue());
|
| - },
|
| -
|
| - updateIteratedValue: function(value) {
|
| - if (this.deps.hasIf) {
|
| - var ifValue = this.deps.ifValue;
|
| - if (!this.deps.ifOneTime)
|
| - ifValue = ifValue.discardChanges();
|
| - if (!ifValue) {
|
| - this.valueChanged();
|
| - return;
|
| - }
|
| - }
|
| -
|
| - this.updateValue(value);
|
| - },
|
| -
|
| - updateValue: function(value) {
|
| - if (!this.deps.repeat)
|
| - value = [value];
|
| - var observe = this.deps.repeat &&
|
| - !this.deps.oneTime &&
|
| - Array.isArray(value);
|
| - this.valueChanged(value, observe);
|
| - },
|
| -
|
| - valueChanged: function(value, observeValue) {
|
| - if (!Array.isArray(value))
|
| - value = [];
|
| -
|
| - if (value === this.iteratedValue)
|
| - return;
|
| -
|
| - this.unobserve();
|
| - this.presentValue = value;
|
| - if (observeValue) {
|
| - this.arrayObserver = new ArrayObserver(this.presentValue);
|
| - this.arrayObserver.open(this.handleSplices, this);
|
| - }
|
| -
|
| - this.handleSplices(ArrayObserver.calculateSplices(this.presentValue,
|
| - this.iteratedValue));
|
| - },
|
| -
|
| - getLastInstanceNode: function(index) {
|
| - if (index == -1)
|
| - return this.templateElement_;
|
| - var instance = this.instances[index];
|
| - var terminator = instance.terminator_;
|
| - if (!terminator)
|
| - return this.getLastInstanceNode(index - 1);
|
| -
|
| - if (terminator.nodeType !== Node.ELEMENT_NODE ||
|
| - this.templateElement_ === terminator) {
|
| - return terminator;
|
| - }
|
| -
|
| - var subtemplateIterator = terminator.iterator_;
|
| - if (!subtemplateIterator)
|
| - return terminator;
|
| -
|
| - return subtemplateIterator.getLastTemplateNode();
|
| - },
|
| -
|
| - getLastTemplateNode: function() {
|
| - return this.getLastInstanceNode(this.instances.length - 1);
|
| - },
|
| -
|
| - insertInstanceAt: function(index, fragment) {
|
| - var previousInstanceLast = this.getLastInstanceNode(index - 1);
|
| - var parent = this.templateElement_.parentNode;
|
| - this.instances.splice(index, 0, fragment);
|
| -
|
| - parent.insertBefore(fragment, previousInstanceLast.nextSibling);
|
| - },
|
| -
|
| - extractInstanceAt: function(index) {
|
| - var previousInstanceLast = this.getLastInstanceNode(index - 1);
|
| - var lastNode = this.getLastInstanceNode(index);
|
| - var parent = this.templateElement_.parentNode;
|
| - var instance = this.instances.splice(index, 1)[0];
|
| -
|
| - while (lastNode !== previousInstanceLast) {
|
| - var node = previousInstanceLast.nextSibling;
|
| - if (node == lastNode)
|
| - lastNode = previousInstanceLast;
|
| -
|
| - instance.appendChild(parent.removeChild(node));
|
| - }
|
| -
|
| - return instance;
|
| - },
|
| -
|
| - getDelegateFn: function(fn) {
|
| - fn = fn && fn(this.templateElement_);
|
| - return typeof fn === 'function' ? fn : null;
|
| - },
|
| -
|
| - handleSplices: function(splices) {
|
| - if (this.closed || !splices.length)
|
| - return;
|
| -
|
| - var template = this.templateElement_;
|
| -
|
| - if (!template.parentNode) {
|
| - this.close();
|
| - return;
|
| - }
|
| -
|
| - ArrayObserver.applySplices(this.iteratedValue, this.presentValue,
|
| - splices);
|
| -
|
| - var delegate = template.delegate_;
|
| - if (this.instanceModelFn_ === undefined) {
|
| - this.instanceModelFn_ =
|
| - this.getDelegateFn(delegate && delegate.prepareInstanceModel);
|
| - }
|
| -
|
| - if (this.instancePositionChangedFn_ === undefined) {
|
| - this.instancePositionChangedFn_ =
|
| - this.getDelegateFn(delegate &&
|
| - delegate.prepareInstancePositionChanged);
|
| - }
|
| -
|
| - // Instance Removals
|
| - var instanceCache = new Map;
|
| - var removeDelta = 0;
|
| - for (var i = 0; i < splices.length; i++) {
|
| - var splice = splices[i];
|
| - var removed = splice.removed;
|
| - for (var j = 0; j < removed.length; j++) {
|
| - var model = removed[j];
|
| - var instance = this.extractInstanceAt(splice.index + removeDelta);
|
| - if (instance !== emptyInstance) {
|
| - instanceCache.set(model, instance);
|
| - }
|
| - }
|
| -
|
| - removeDelta -= splice.addedCount;
|
| - }
|
| -
|
| - // Instance Insertions
|
| - for (var i = 0; i < splices.length; i++) {
|
| - var splice = splices[i];
|
| - var addIndex = splice.index;
|
| - for (; addIndex < splice.index + splice.addedCount; addIndex++) {
|
| - var model = this.iteratedValue[addIndex];
|
| - var instance = instanceCache.get(model);
|
| - if (instance) {
|
| - instanceCache.delete(model);
|
| - } else {
|
| - if (this.instanceModelFn_) {
|
| - model = this.instanceModelFn_(model);
|
| - }
|
| -
|
| - if (model === undefined) {
|
| - instance = emptyInstance;
|
| - } else {
|
| - instance = template.createInstance(model, undefined, delegate);
|
| - }
|
| - }
|
| -
|
| - this.insertInstanceAt(addIndex, instance);
|
| - }
|
| - }
|
| -
|
| - instanceCache.forEach(function(instance) {
|
| - this.closeInstanceBindings(instance);
|
| - }, this);
|
| -
|
| - if (this.instancePositionChangedFn_)
|
| - this.reportInstancesMoved(splices);
|
| - },
|
| -
|
| - reportInstanceMoved: function(index) {
|
| - var instance = this.instances[index];
|
| - if (instance === emptyInstance)
|
| - return;
|
| -
|
| - this.instancePositionChangedFn_(instance.templateInstance_, index);
|
| - },
|
| -
|
| - reportInstancesMoved: function(splices) {
|
| - var index = 0;
|
| - var offset = 0;
|
| - for (var i = 0; i < splices.length; i++) {
|
| - var splice = splices[i];
|
| - if (offset != 0) {
|
| - while (index < splice.index) {
|
| - this.reportInstanceMoved(index);
|
| - index++;
|
| - }
|
| - } else {
|
| - index = splice.index;
|
| - }
|
| -
|
| - while (index < splice.index + splice.addedCount) {
|
| - this.reportInstanceMoved(index);
|
| - index++;
|
| - }
|
| -
|
| - offset += splice.addedCount - splice.removed.length;
|
| - }
|
| -
|
| - if (offset == 0)
|
| - return;
|
| -
|
| - var length = this.instances.length;
|
| - while (index < length) {
|
| - this.reportInstanceMoved(index);
|
| - index++;
|
| - }
|
| - },
|
| -
|
| - closeInstanceBindings: function(instance) {
|
| - var bindings = instance.bindings_;
|
| - for (var i = 0; i < bindings.length; i++) {
|
| - bindings[i].close();
|
| - }
|
| - },
|
| -
|
| - unobserve: function() {
|
| - if (!this.arrayObserver)
|
| - return;
|
| -
|
| - this.arrayObserver.close();
|
| - this.arrayObserver = undefined;
|
| - },
|
| -
|
| - close: function() {
|
| - if (this.closed)
|
| - return;
|
| - this.unobserve();
|
| - for (var i = 0; i < this.instances.length; i++) {
|
| - this.closeInstanceBindings(this.instances[i]);
|
| - }
|
| -
|
| - this.instances.length = 0;
|
| - this.closeDeps();
|
| - this.templateElement_.iterator_ = undefined;
|
| - this.closed = true;
|
| - }
|
| - };
|
| -
|
| - // Polyfill-specific API.
|
| - HTMLTemplateElement.forAllTemplatesFrom_ = forAllTemplatesFrom;
|
| -})(this);
|
| -
|
| -/*
|
| - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
| - * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| - * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| - * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| - * Code distributed by Google as part of the polymer project is also
|
| - * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| - */
|
| -
|
| -(function(scope) {
|
| -
|
| -// inject style sheet
|
| -var style = document.createElement('style');
|
| -style.textContent = 'template {display: none !important;} /* injected by platform.js */';
|
| -var head = document.querySelector('head');
|
| -head.insertBefore(style, head.firstChild);
|
| -
|
| -// flush (with logging)
|
| -var flushing;
|
| -function flush() {
|
| - if (!flushing) {
|
| - flushing = true;
|
| - scope.endOfMicrotask(function() {
|
| - flushing = false;
|
| - logFlags.data && console.group('Platform.flush()');
|
| - scope.performMicrotaskCheckpoint();
|
| - logFlags.data && console.groupEnd();
|
| - });
|
| - }
|
| -};
|
| -
|
| -// polling dirty checker
|
| -// flush periodically if platform does not have object observe.
|
| -if (!Observer.hasObjectObserve) {
|
| - var FLUSH_POLL_INTERVAL = 125;
|
| - window.addEventListener('WebComponentsReady', function() {
|
| - flush();
|
| - scope.flushPoll = setInterval(flush, FLUSH_POLL_INTERVAL);
|
| - });
|
| -} else {
|
| - // make flush a no-op when we have Object.observe
|
| - flush = function() {};
|
| -}
|
| -
|
| -if (window.CustomElements && !CustomElements.useNative) {
|
| - var originalImportNode = Document.prototype.importNode;
|
| - Document.prototype.importNode = function(node, deep) {
|
| - var imported = originalImportNode.call(this, node, deep);
|
| - CustomElements.upgradeAll(imported);
|
| - return imported;
|
| - }
|
| -}
|
| -
|
| -// exports
|
| -scope.flush = flush;
|
| -
|
| -})(window.Platform);
|
| + scope.marshal = marshal;
|
| + // `module` confuses commonjs detectors
|
| + scope.modularize = module;
|
| + scope.using = using;
|
|
|
| +})(window);
|
|
|
| //# sourceMappingURL=platform.concat.js.map
|
|
|