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

Side by Side Diff: appengine/swarming/elements/build/index-build.html

Issue 2174903002: Add stub pages and oauth-blessed request to /newui (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@master
Patch Set: more docs Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <!DOCTYPE html><html><head><!--
2 @license
3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
9 --><!--
10 @license
11 Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
12 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
13 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
14 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
15 Code distributed by Google as part of the polymer project is also
16 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
17 -->
18 <title>Many World, wow such hello</title>
19 <meta charset="utf-8">
20 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
21 <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial- scale=1, user-scalable=yes">
22
23 <script>/**
24 * @license
25 * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
26 * This code may only be used under the BSD style license found at http://polyme r.github.io/LICENSE.txt
27 * The complete set of authors may be found at http://polymer.github.io/AUTHORS. txt
28 * The complete set of contributors may be found at http://polymer.github.io/CON TRIBUTORS.txt
29 * Code distributed by Google as part of the polymer project is also
30 * subject to an additional IP rights grant found at http://polymer.github.io/PA TENTS.txt
31 */
32 // @version 0.7.22
33 !function(){window.WebComponents=window.WebComponents||{flags:{}};var e="webcomp onents-lite.js",t=document.querySelector('script[src*="'+e+'"]'),n={};if(!n.noOp ts){if(location.search.slice(1).split("&").forEach(function(e){var t,o=e.split(" =");o[0]&&(t=o[0].match(/wc-(.+)/))&&(n[t[1]]=o[1]||!0)}),t)for(var o,r=0;o=t.at tributes[r];r++)"src"!==o.name&&(n[o.name]=o.value||!0);if(n.log&&n.log.split){v ar i=n.log.split(",");n.log={},i.forEach(function(e){n.log[e]=!0})}else n.log={} }n.register&&(window.CustomElements=window.CustomElements||{flags:{}},window.Cus tomElements.flags.register=n.register),WebComponents.flags=n}(),function(e){"use strict";function t(e){return void 0!==h[e]}function n(){s.call(this),this._isIn valid=!0}function o(e){return""==e&&n.call(this),e.toLowerCase()}function r(e){v ar t=e.charCodeAt(0);return t>32&&127>t&&-1==[34,35,60,62,63,96].indexOf(t)?e:en codeURIComponent(e)}function i(e){var t=e.charCodeAt(0);return t>32&&127>t&&-1== [34,35,60,62,96].indexOf(t)?e:encodeURIComponent(e)}function a(e,a,s){function c (e){g.push(e)}var d=a||"scheme start",l=0,u="",w=!1,_=!1,g=[];e:for(;(e[l-1]!=p| |0==l)&&!this._isInvalid;){var b=e[l];switch(d){case"scheme start":if(!b||!m.tes t(b)){if(a){c("Invalid scheme.");break e}u="",d="no scheme";continue}u+=b.toLowe rCase(),d="scheme";break;case"scheme":if(b&&v.test(b))u+=b.toLowerCase();else{if (":"!=b){if(a){if(p==b)break e;c("Code point not allowed in scheme: "+b);break e }u="",l=0,d="no scheme";continue}if(this._scheme=u,u="",a)break e;t(this._scheme )&&(this._isRelative=!0),d="file"==this._scheme?"relative":this._isRelative&&s&& s._scheme==this._scheme?"relative or authority":this._isRelative?"authority firs t slash":"scheme data"}break;case"scheme data":"?"==b?(this._query="?",d="query" ):"#"==b?(this._fragment="#",d="fragment"):p!=b&&" "!=b&&"\n"!=b&&"\r"!=b&& (this._schemeData+=r(b));break;case"no scheme":if(s&&t(s._scheme)){d="relative"; continue}c("Missing scheme."),n.call(this);break;case"relative or authority":if( "/"!=b||"/"!=e[l+1]){c("Expected /, got: "+b),d="relative";continue}d="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._schem e&&(this._scheme=s._scheme),p==b){this._host=s._host,this._port=s._port,this._pa th=s._path.slice(),this._query=s._query,this._username=s._username,this._passwor d=s._password;break e}if("/"==b||"\\"==b)"\\"==b&&c("\\ is an invalid code point ."),d="relative slash";else if("?"==b)this._host=s._host,this._port=s._port,this ._path=s._path.slice(),this._query="?",this._username=s._username,this._password =s._password,d="query";else{if("#"!=b){var y=e[l+1],E=e[l+2];("file"!=this._sche me||!m.test(b)||":"!=y&&"|"!=y||p!=E&&"/"!=E&&"\\"!=E&&"?"!=E&&"#"!=E)&&(this._h ost=s._host,this._port=s._port,this._username=s._username,this._password=s._pass word,this._path=s._path.slice(),this._path.pop()),d="relative path";continue}thi s._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._que ry,this._fragment="#",this._username=s._username,this._password=s._password,d="f ragment"}break;case"relative slash":if("/"!=b&&"\\"!=b){"file"!=this._scheme&&(t his._host=s._host,this._port=s._port,this._username=s._username,this._password=s ._password),d="relative path";continue}"\\"==b&&c("\\ is an invalid code point." ),d="file"==this._scheme?"file host":"authority ignore slashes";break;case"autho rity first slash":if("/"!=b){c("Expected '/', got: "+b),d="authority ignore slas hes";continue}d="authority second slash";break;case"authority second slash":if(d ="authority ignore slashes","/"!=b){c("Expected '/', got: "+b);continue}break;ca se"authority ignore slashes":if("/"!=b&&"\\"!=b){d="authority";continue}c("Expec ted authority, got: "+b);break;case"authority":if("@"==b){w&&(c("@ already seen. "),u+="%40"),w=!0;for(var L=0;L<u.length;L++){var N=u[L];if(" "!=N&&"\n"!=N&&" \r"!=N)if(":"!=N||null!==this._password){var M=r(N);null!==this._password?this._ password+=M:this._username+=M}else this._password="";else c("Invalid whitespace in authority.")}u=""}else{if(p==b||"/"==b||"\\"==b||"?"==b||"#"==b){l-=u.length, u="",d="host";continue}u+=b}break;case"file host":if(p==b||"/"==b||"\\"==b||"?"= =b||"#"==b){2!=u.length||!m.test(u[0])||":"!=u[1]&&"|"!=u[1]?0==u.length?d="rela tive path start":(this._host=o.call(this,u),u="",d="relative path start"):d="rel ative path";continue}" "==b||"\n"==b||"\r"==b?c("Invalid whitespace in file hos t."):u+=b;break;case"host":case"hostname":if(":"!=b||_){if(p==b||"/"==b||"\\"==b ||"?"==b||"#"==b){if(this._host=o.call(this,u),u="",d="relative path start",a)br eak e;continue}" "!=b&&"\n"!=b&&"\r"!=b?("["==b?_=!0:"]"==b&&(_=!1),u+=b) :c("Invalid code point in host/hostname: "+b)}else if(this._host=o.call(this,u), u="",d="port","hostname"==a)break e;break;case"port":if(/[0-9]/.test(b))u+=b;els e{if(p==b||"/"==b||"\\"==b||"?"==b||"#"==b||a){if(""!=u){var T=parseInt(u,10);T! =h[this._scheme]&&(this._port=T+""),u=""}if(a)break e;d="relative path start";co ntinue}" "==b||"\n"==b||"\r"==b?c("Invalid code point in port: "+b):n.cal l(this)}break;case"relative path start":if("\\"==b&&c("'\\' not allowed in path. "),d="relative path","/"!=b&&"\\"!=b)continue;break;case"relative path":if(p!=b& &"/"!=b&&"\\"!=b&&(a||"?"!=b&&"#"!=b))" "!=b&&"\n"!=b&&"\r"!=b&&(u+=r(b));else{" \\"==b&&c("\\ not allowed in relative path.");var O;(O=f[u.toLowerCase()])&&(u=O ),".."==u?(this._path.pop(),"/"!=b&&"\\"!=b&&this._path.push("")):"."==u&&"/"!=b &&"\\"!=b?this._path.push(""):"."!=u&&("file"==this._scheme&&0==this._path.lengt h&&2==u.length&&m.test(u[0])&&"|"==u[1]&&(u=u[0]+":"),this._path.push(u)),u=""," ?"==b?(this._query="?",d="query"):"#"==b&&(this._fragment="#",d="fragment")}brea k;case"query":a||"#"!=b?p!=b&&" "!=b&&"\n"!=b&&"\r"!=b&&(this._query+=i(b)):(thi s._fragment="#",d="fragment");break;case"fragment":p!=b&&" "!=b&&"\n"!=b&&" \r"!=b&&(this._fragment+=b)}l++}}function s(){this._scheme="",this._schemeData=" ",this._username="",this._password=null,this._host="",this._port="",this._path=[ ],this._query="",this._fragment="",this._isInvalid=!1,this._isRelative=!1}functi on c(e,t){void 0===t||t instanceof c||(t=new c(String(t))),this._url=e,s.call(th is);var n=e.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g,"");a.call(this,n,null,t)}var d=!1;if(!e.forceJURL)try{var l=new URL("b","http://a");l.pathname="c%20d",d="ht tp://a/c%20d"===l.href}catch(u){}if(!d){var h=Object.create(null);h.ftp=21,h.fil e=0,h.gopher=70,h.http=80,h.https=443,h.ws=80,h.wss=443;var f=Object.create(null );f["%2e"]=".",f[".%2e"]="..",f["%2e."]="..",f["%2e%2e"]="..";var p=void 0,m=/[a -zA-Z]/,v=/[a-zA-Z0-9\+\-\.]/;c.prototype={toString:function(){return this.href} ,get href(){if(this._isInvalid)return this._url;var e="";return""==this._usernam e&&null==this._password||(e=this._username+(null!=this._password?":"+this._passw ord:"")+"@"),this.protocol+(this._isRelative?"//"+e+this.host:"")+this.pathname+ this._query+this._fragment},set href(e){s.call(this),a.call(this,e)},get protoco l(){return this._scheme+":"},set protocol(e){this._isInvalid||a.call(this,e+":", "scheme start")},get host(){return this._isInvalid?"":this._port?this._host+":"+ this._port:this._host},set host(e){!this._isInvalid&&this._isRelative&&a.call(th is,e,"host")},get hostname(){return this._host},set hostname(e){!this._isInvalid &&this._isRelative&&a.call(this,e,"hostname")},get port(){return this._port},set port(e){!this._isInvalid&&this._isRelative&&a.call(this,e,"port")},get pathname (){return this._isInvalid?"":this._isRelative?"/"+this._path.join("/"):this._sch emeData},set pathname(e){!this._isInvalid&&this._isRelative&&(this._path=[],a.ca ll(this,e,"relative path start"))},get search(){return this._isInvalid||!this._q uery||"?"==this._query?"":this._query},set search(e){!this._isInvalid&&this._isR elative&&(this._query="?","?"==e[0]&&(e=e.slice(1)),a.call(this,e,"query"))},get hash(){return this._isInvalid||!this._fragment||"#"==this._fragment?"":this._fr agment},set hash(e){this._isInvalid||(this._fragment="#","#"==e[0]&&(e=e.slice(1 )),a.call(this,e,"fragment"))},get origin(){var e;if(this._isInvalid||!this._sch eme)return"";switch(this._scheme){case"data":case"file":case"javascript":case"ma ilto":return"null"}return e=this.host,e?this._scheme+"://"+e:""}};var w=e.URL;w& &(c.createObjectURL=function(e){return w.createObjectURL.apply(w,arguments)},c.r evokeObjectURL=function(e){w.revokeObjectURL(e)}),e.URL=c}}(self),"undefined"==t ypeof WeakMap&&!function(){var e=Object.defineProperty,t=Date.now()%1e9,n=functi on(){this.name="__st"+(1e9*Math.random()>>>0)+(t++ +"__")};n.prototype={set:func tion(t,n){var o=t[this.name];return o&&o[0]===t?o[1]=n:e(t,this.name,{value:[t,n ],writable:!0}),this},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1 ]:void 0},"delete":function(e){var t=e[this.name];return t&&t[0]===e?(t[0]=t[1]= void 0,!0):!1},has:function(e){var t=e[this.name];return t?t[0]===e:!1}},window. WeakMap=n}(),function(e){function t(e){b.push(e),g||(g=!0,m(o))}function n(e){re turn window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(e)||e}funct ion o(){g=!1;var e=b;b=[],e.sort(function(e,t){return e.uid_-t.uid_});var t=!1;e .forEach(function(e){var n=e.takeRecords();r(e),n.length&&(e.callback_(n,e),t=!0 )}),t&&o()}function r(e){e.nodes_.forEach(function(t){var n=v.get(t);n&&n.forEac h(function(t){t.observer===e&&t.removeTransientObservers()})})}function i(e,t){f or(var n=e;n;n=n.parentNode){var o=v.get(n);if(o)for(var r=0;r<o.length;r++){var i=o[r],a=i.options;if(n===e||a.subtree){var s=t(a);s&&i.enqueue(s)}}}}function a(e){this.callback_=e,this.nodes_=[],this.records_=[],this.uid_=++y}function s(e ,t){this.type=e,this.target=t,this.addedNodes=[],this.removedNodes=[],this.previ ousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeName space=null,this.oldValue=null}function c(e){var t=new s(e.type,e.target);return t.addedNodes=e.addedNodes.slice(),t.removedNodes=e.removedNodes.slice(),t.previo usSibling=e.previousSibling,t.nextSibling=e.nextSibling,t.attributeName=e.attrib uteName,t.attributeNamespace=e.attributeNamespace,t.oldValue=e.oldValue,t}functi on d(e,t){return E=new s(e,t)}function l(e){return L?L:(L=c(E),L.oldValue=e,L)}f unction u(){E=L=void 0}function h(e){return e===L||e===E}function f(e,t){return e===t?e:L&&h(e)?L:null}function p(e,t,n){this.observer=e,this.target=t,this.opti ons=n,this.transientObservedNodes=[]}if(!e.JsMutationObserver){var m,v=new WeakM ap;if(/Trident|Edge/.test(navigator.userAgent))m=setTimeout;else if(window.setIm mediate)m=window.setImmediate;else{var w=[],_=String(Math.random());window.addEv entListener("message",function(e){if(e.data===_){var t=w;w=[],t.forEach(function (e){e()})}}),m=function(e){w.push(e),window.postMessage(_,"*")}}var g=!1,b=[],y= 0;a.prototype={observe:function(e,t){if(e=n(e),!t.childList&&!t.attributes&&!t.c haracterData||t.attributeOldValue&&!t.attributes||t.attributeFilter&&t.attribute Filter.length&&!t.attributes||t.characterDataOldValue&&!t.characterData)throw ne w SyntaxError;var o=v.get(e);o||v.set(e,o=[]);for(var r,i=0;i<o.length;i++)if(o[ i].observer===this){r=o[i],r.removeListeners(),r.options=t;break}r||(r=new p(thi s,e,t),o.push(r),this.nodes_.push(e)),r.addListeners()},disconnect:function(){th is.nodes_.forEach(function(e){for(var t=v.get(e),n=0;n<t.length;n++){var o=t[n]; if(o.observer===this){o.removeListeners(),t.splice(n,1);break}}},this),this.reco rds_=[]},takeRecords:function(){var e=this.records_;return this.records_=[],e}}; var E,L;p.prototype={enqueue:function(e){var n=this.observer.records_,o=n.length ;if(n.length>0){var r=n[o-1],i=f(r,e);if(i)return void(n[o-1]=i)}else t(this.obs erver);n[o]=e},addListeners:function(){this.addListeners_(this.target)},addListe ners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrMo dified",this,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified", this,!0),t.childList&&e.addEventListener("DOMNodeInserted",this,!0),(t.childList ||t.subtree)&&e.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:func tion(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=th is.options;t.attributes&&e.removeEventListener("DOMAttrModified",this,!0),t.char acterData&&e.removeEventListener("DOMCharacterDataModified",this,!0),t.childList &&e.removeEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.r emoveEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(e){i f(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=v.get(e);t||v.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){ var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(funct ion(e){this.removeListeners_(e);for(var t=v.get(e),n=0;n<t.length;n++)if(t[n]=== this){t.splice(n,1);break}},this)},handleEvent:function(e){switch(e.stopImmediat ePropagation(),e.type){case"DOMAttrModified":var t=e.attrName,n=e.relatedNode.na mespaceURI,o=e.target,r=new d("attributes",o);r.attributeName=t,r.attributeNames pace=n;var a=e.attrChange===MutationEvent.ADDITION?null:e.prevValue;i(o,function (e){return!e.attributes||e.attributeFilter&&e.attributeFilter.length&&-1===e.att ributeFilter.indexOf(t)&&-1===e.attributeFilter.indexOf(n)?void 0:e.attributeOld Value?l(a):r});break;case"DOMCharacterDataModified":var o=e.target,r=d("characte rData",o),a=e.prevValue;i(o,function(e){return e.characterData?e.characterDataOl dValue?l(a):r:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(e.ta rget);case"DOMNodeInserted":var s,c,h=e.target;"DOMNodeInserted"===e.type?(s=[h] ,c=[]):(s=[],c=[h]);var f=h.previousSibling,p=h.nextSibling,r=d("childList",e.ta rget.parentNode);r.addedNodes=s,r.removedNodes=c,r.previousSibling=f,r.nextSibli ng=p,i(e.relatedNode,function(e){return e.childList?r:void 0})}u()}},e.JsMutatio nObserver=a,e.MutationObserver||(e.MutationObserver=a,a._isPolyfilled=!0)}}(self ),function(){function e(e){switch(e){case"&":return"&amp;";case"<":return"&lt;"; case">":return"&gt;";case" ":return"&nbsp;"}}function t(t){return t.replace(u,e) }var n="undefined"==typeof HTMLTemplateElement;/Trident/.test(navigator.userAgen t)&&!function(){var e=document.importNode;document.importNode=function(){var t=e .apply(document,arguments);if(t.nodeType===Node.DOCUMENT_FRAGMENT_NODE){var n=do cument.createDocumentFragment();return n.appendChild(t),n}return t}}();var o=fun ction(){if(!n){var e=document.createElement("template"),t=document.createElement ("template");t.content.appendChild(document.createElement("div")),e.content.appe ndChild(t);var o=e.cloneNode(!0);return 0===o.content.childNodes.length||0===o.c ontent.firstChild.content.childNodes.length}}(),r="template",i=function(){};if(n ){var a=document.implementation.createHTMLDocument("template"),s=!0,c=document.c reateElement("style");c.textContent=r+"{display:none;}";var d=document.head;d.in sertBefore(c,d.firstElementChild),i.prototype=Object.create(HTMLElement.prototyp e),i.decorate=function(e){if(!e.content){e.content=a.createDocumentFragment();fo r(var n;n=e.firstChild;)e.content.appendChild(n);if(e.cloneNode=function(e){retu rn i.cloneNode(this,e)},s)try{Object.defineProperty(e,"innerHTML",{get:function( ){for(var e="",n=this.content.firstChild;n;n=n.nextSibling)e+=n.outerHTML||t(n.d ata);return e},set:function(e){for(a.body.innerHTML=e,i.bootstrap(a);this.conten t.firstChild;)this.content.removeChild(this.content.firstChild);for(;a.body.firs tChild;)this.content.appendChild(a.body.firstChild)},configurable:!0})}catch(o){ s=!1}i.bootstrap(e.content)}},i.bootstrap=function(e){for(var t,n=e.querySelecto rAll(r),o=0,a=n.length;a>o&&(t=n[o]);o++)i.decorate(t)},document.addEventListene r("DOMContentLoaded",function(){i.bootstrap(document)});var l=document.createEle ment;document.createElement=function(){"use strict";var e=l.apply(document,argum ents);return"template"===e.localName&&i.decorate(e),e};var u=/[&\u00A0<>]/g}if(n ||o){var h=Node.prototype.cloneNode;i.cloneNode=function(e,t){var n=h.call(e,!1) ;return this.decorate&&this.decorate(n),t&&(n.content.appendChild(h.call(e.conte nt,!0)),this.fixClonedDom(n.content,e.content)),n},i.fixClonedDom=function(e,t){ if(t.querySelectorAll)for(var n,o,i=t.querySelectorAll(r),a=e.querySelectorAll(r ),s=0,c=a.length;c>s;s++)o=i[s],n=a[s],this.decorate&&this.decorate(o),n.parentN ode.replaceChild(o.cloneNode(!0),n)};var f=document.importNode;Node.prototype.cl oneNode=function(e){var t=h.call(this,e);return e&&i.fixClonedDom(t,this),t},doc ument.importNode=function(e,t){if(e.localName===r)return i.cloneNode(e,t);var n= f.call(document,e,t);return t&&i.fixClonedDom(n,e),n},o&&(HTMLTemplateElement.pr ototype.cloneNode=function(e){return i.cloneNode(this,e)})}n&&(window.HTMLTempla teElement=i)}(),function(e){"use strict";if(!window.performance){var t=Date.now( );window.performance={now:function(){return Date.now()-t}}}window.requestAnimati onFrame||(window.requestAnimationFrame=function(){var e=window.webkitRequestAnim ationFrame||window.mozRequestAnimationFrame;return e?function(t){return e(functi on(){t(performance.now())})}:function(e){return window.setTimeout(e,1e3/60)}}()) ,window.cancelAnimationFrame||(window.cancelAnimationFrame=function(){return win dow.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||function(e){clea rTimeout(e)}}());var n=function(){var e=document.createEvent("Event");return e.i nitEvent("foo",!0,!0),e.preventDefault(),e.defaultPrevented}();if(!n){var o=Even t.prototype.preventDefault;Event.prototype.preventDefault=function(){this.cancel able&&(o.call(this),Object.defineProperty(this,"defaultPrevented",{get:function( ){return!0},configurable:!0}))}}var r=/Trident/.test(navigator.userAgent);if((!w indow.CustomEvent||r&&"function"!=typeof window.CustomEvent)&&(window.CustomEven t=function(e,t){t=t||{};var n=document.createEvent("CustomEvent");return n.initC ustomEvent(e,Boolean(t.bubbles),Boolean(t.cancelable),t.detail),n},window.Custom Event.prototype=window.Event.prototype),!window.Event||r&&"function"!=typeof win dow.Event){var i=window.Event;window.Event=function(e,t){t=t||{};var n=document. createEvent("Event");return n.initEvent(e,Boolean(t.bubbles),Boolean(t.cancelabl e)),n},window.Event.prototype=i.prototype}}(window.WebComponents),window.HTMLImp orts=window.HTMLImports||{flags:{}},function(e){function t(e,t){t=t||p,o(functio n(){i(e,t)},t)}function n(e){return"complete"===e.readyState||e.readyState===w}f unction o(e,t){if(n(t))e&&e();else{var r=function(){"complete"!==t.readyState&&t .readyState!==w||(t.removeEventListener(_,r),o(e,t))};t.addEventListener(_,r)}}f unction r(e){e.target.__loaded=!0}function i(e,t){function n(){c==d&&e&&e({allIm ports:s,loadedImports:l,errorImports:u})}function o(e){r(e),l.push(this),c++,n() }function i(e){u.push(this),c++,n()}var s=t.querySelectorAll("link[rel=import]") ,c=0,d=s.length,l=[],u=[];if(d)for(var h,f=0;d>f&&(h=s[f]);f++)a(h)?(l.push(this ),c++,n()):(h.addEventListener("load",o),h.addEventListener("error",i));else n() }function a(e){return u?e.__loaded||e["import"]&&"loading"!==e["import"].readySt ate:e.__importParsed}function s(e){for(var t,n=0,o=e.length;o>n&&(t=e[n]);n++)c( t)&&d(t)}function c(e){return"link"===e.localName&&"import"===e.rel}function d(e ){var t=e["import"];t?r({target:e}):(e.addEventListener("load",r),e.addEventList ener("error",r))}var l="import",u=Boolean(l in document.createElement("link")),h =Boolean(window.ShadowDOMPolyfill),f=function(e){return h?window.ShadowDOMPolyfi ll.wrapIfNeeded(e):e},p=f(document),m={get:function(){var e=window.HTMLImports.c urrentScript||document.currentScript||("complete"!==document.readyState?document .scripts[document.scripts.length-1]:null);return f(e)},configurable:!0};Object.d efineProperty(document,"_currentScript",m),Object.defineProperty(p,"_currentScri pt",m);var v=/Trident/.test(navigator.userAgent),w=v?"complete":"interactive",_= "readystatechange";u&&(new MutationObserver(function(e){for(var t,n=0,o=e.length ;o>n&&(t=e[n]);n++)t.addedNodes&&s(t.addedNodes)}).observe(document.head,{childL ist:!0}),function(){if("loading"===document.readyState)for(var e,t=document.quer ySelectorAll("link[rel=import]"),n=0,o=t.length;o>n&&(e=t[n]);n++)d(e)}()),t(fun ction(e){window.HTMLImports.ready=!0,window.HTMLImports.readyTime=(new Date).get Time();var t=p.createEvent("CustomEvent");t.initCustomEvent("HTMLImportsLoaded", !0,!0,e),p.dispatchEvent(t)}),e.IMPORT_LINK_TYPE=l,e.useNative=u,e.rootDocument= p,e.whenReady=t,e.isIE=v}(window.HTMLImports),function(e){var t=[],n=function(e) {t.push(e)},o=function(){t.forEach(function(t){t(e)})};e.addModule=n,e.initializ eModules=o}(window.HTMLImports),window.HTMLImports.addModule(function(e){var t=/ (url\()([^)]*)(\))/g,n=/(@import[\s]+(?!url\())([^;]*)(;)/g,o={resolveUrlsInStyl e:function(e,t){var n=e.ownerDocument,o=n.createElement("a");return e.textConten t=this.resolveUrlsInCssText(e.textContent,t,o),e},resolveUrlsInCssText:function( e,o,r){var i=this.replaceUrls(e,r,o,t);return i=this.replaceUrls(i,r,o,n)},repla ceUrls:function(e,t,n,o){return e.replace(o,function(e,o,r,i){var a=r.replace(/[ "']/g,"");return n&&(a=new URL(a,n).href),t.href=a,a=t.href,o+"'"+a+"'"+i})}};e. path=o}),window.HTMLImports.addModule(function(e){var t={async:!0,ok:function(e) {return e.status>=200&&e.status<300||304===e.status||0===e.status},load:function (n,o,r){var i=new XMLHttpRequest;return(e.flags.debug||e.flags.bust)&&(n+="?"+Ma th.random()),i.open("GET",n,t.async),i.addEventListener("readystatechange",funct ion(e){if(4===i.readyState){var n=null;try{var a=i.getResponseHeader("Location") ;a&&(n="/"===a.substr(0,1)?location.origin+a:a)}catch(e){console.error(e.message )}o.call(r,!t.ok(i)&&i,i.response||i.responseText,n)}}),i.send(),i},loadDocument :function(e,t,n){this.load(e,t,n).responseType="document"}};e.xhr=t}),window.HTM LImports.addModule(function(e){var t=e.xhr,n=e.flags,o=function(e,t){this.cache= {},this.onload=e,this.oncomplete=t,this.inflight=0,this.pending={}};o.prototype= {addNodes:function(e){this.inflight+=e.length;for(var t,n=0,o=e.length;o>n&&(t=e [n]);n++)this.require(t);this.checkDone()},addNode:function(e){this.inflight++,t his.require(e),this.checkDone()},require:function(e){var t=e.src||e.href;e.__nod eUrl=t,this.dedupe(t,e)||this.fetch(t,e)},dedupe:function(e,t){if(this.pending[e ])return this.pending[e].push(t),!0;return this.cache[e]?(this.onload(e,t,this.c ache[e]),this.tail(),!0):(this.pending[e]=[t],!1)},fetch:function(e,o){if(n.load &&console.log("fetch",e,o),e)if(e.match(/^data:/)){var r=e.split(","),i=r[0],a=r [1];a=i.indexOf(";base64")>-1?atob(a):decodeURIComponent(a),setTimeout(function( ){this.receive(e,o,null,a)}.bind(this),0)}else{var s=function(t,n,r){this.receiv e(e,o,t,n,r)}.bind(this);t.load(e,s)}else setTimeout(function(){this.receive(e,o ,{error:"href must be specified"},null)}.bind(this),0)},receive:function(e,t,n,o ,r){this.cache[e]=o;for(var i,a=this.pending[e],s=0,c=a.length;c>s&&(i=a[s]);s++ )this.onload(e,i,o,n,r),this.tail();this.pending[e]=null},tail:function(){--this .inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete( )}},e.Loader=o}),window.HTMLImports.addModule(function(e){var t=function(e){this .addCallback=e,this.mo=new MutationObserver(this.handler.bind(this))};t.prototyp e={handler:function(e){for(var t,n=0,o=e.length;o>n&&(t=e[n]);n++)"childList"=== t.type&&t.addedNodes.length&&this.addedNodes(t.addedNodes)},addedNodes:function( e){this.addCallback&&this.addCallback(e);for(var t,n=0,o=e.length;o>n&&(t=e[n]); n++)t.children&&t.children.length&&this.addedNodes(t.children)},observe:function (e){this.mo.observe(e,{childList:!0,subtree:!0})}},e.Observer=t}),window.HTMLImp orts.addModule(function(e){function t(e){return"link"===e.localName&&e.rel===l}f unction n(e){var t=o(e);return"data:text/javascript;charset=utf-8,"+encodeURICom ponent(t)}function o(e){return e.textContent+r(e)}function r(e){var t=e.ownerDoc ument;t.__importedScripts=t.__importedScripts||0;var n=e.ownerDocument.baseURI,o =t.__importedScripts?"-"+t.__importedScripts:"";return t.__importedScripts++,"\n //# sourceURL="+n+o+".js\n"}function i(e){var t=e.ownerDocument.createElement("s tyle");return t.textContent=e.textContent,a.resolveUrlsInStyle(t),t}var a=e.path ,s=e.rootDocument,c=e.flags,d=e.isIE,l=e.IMPORT_LINK_TYPE,u="link[rel="+l+"]",h= {documentSelectors:u,importsSelectors:[u,"link[rel=stylesheet]:not([type])","sty le:not([type])","script:not([type])",'script[type="application/javascript"]','sc ript[type="text/javascript"]'].join(","),map:{link:"parseLink",script:"parseScri pt",style:"parseStyle"},dynamicElements:[],parseNext:function(){var e=this.nextT oParse();e&&this.parse(e)},parse:function(e){if(this.isParsed(e))return void(c.p arse&&console.log("[%s] is already parsed",e.localName));var t=this[this.map[e.l ocalName]];t&&(this.markParsing(e),t.call(this,e))},parseDynamic:function(e,t){t his.dynamicElements.push(e),t||this.parseNext()},markParsing:function(e){c.parse &&console.log("parsing",e),this.parsingElement=e},markParsingComplete:function(e ){e.__importParsed=!0,this.markDynamicParsingComplete(e),e.__importElement&&(e._ _importElement.__importParsed=!0,this.markDynamicParsingComplete(e.__importEleme nt)),this.parsingElement=null,c.parse&&console.log("completed",e)},markDynamicPa rsingComplete:function(e){var t=this.dynamicElements.indexOf(e);t>=0&&this.dynam icElements.splice(t,1)},parseImport:function(e){if(e["import"]=e.__doc,window.HT MLImports.__importsParsingHook&&window.HTMLImports.__importsParsingHook(e),e["im port"]&&(e["import"].__importParsed=!0),this.markParsingComplete(e),e.__resource &&!e.__error?e.dispatchEvent(new CustomEvent("load",{bubbles:!1})):e.dispatchEve nt(new CustomEvent("error",{bubbles:!1})),e.__pending)for(var t;e.__pending.leng th;)t=e.__pending.shift(),t&&t({target:e});this.parseNext()},parseLink:function( e){t(e)?this.parseImport(e):(e.href=e.href,this.parseGeneric(e))},parseStyle:fun ction(e){var t=e;e=i(e),t.__appliedElement=e,e.__importElement=t,this.parseGener ic(e)},parseGeneric:function(e){this.trackElement(e),this.addElementToDocument(e )},rootImportForElement:function(e){for(var t=e;t.ownerDocument.__importLink;)t= t.ownerDocument.__importLink;return t},addElementToDocument:function(e){var t=th is.rootImportForElement(e.__importElement||e);t.parentNode.insertBefore(e,t)},tr ackElement:function(e,t){var n=this,o=function(r){e.removeEventListener("load",o ),e.removeEventListener("error",o),t&&t(r),n.markParsingComplete(e),n.parseNext( )};if(e.addEventListener("load",o),e.addEventListener("error",o),d&&"style"===e. localName){var r=!1;if(-1==e.textContent.indexOf("@import"))r=!0;else if(e.sheet ){r=!0;for(var i,a=e.sheet.cssRules,s=a?a.length:0,c=0;s>c&&(i=a[c]);c++)i.type= ==CSSRule.IMPORT_RULE&&(r=r&&Boolean(i.styleSheet))}r&&setTimeout(function(){e.d ispatchEvent(new CustomEvent("load",{bubbles:!1}))})}},parseScript:function(t){v ar o=document.createElement("script");o.__importElement=t,o.src=t.src?t.src:n(t) ,e.currentScript=t,this.trackElement(o,function(t){o.parentNode&&o.parentNode.re moveChild(o),e.currentScript=null}),this.addElementToDocument(o)},nextToParse:fu nction(){return this._mayParse=[],!this.parsingElement&&(this.nextToParseInDoc(s )||this.nextToParseDynamic())},nextToParseInDoc:function(e,n){if(e&&this._mayPar se.indexOf(e)<0){this._mayParse.push(e);for(var o,r=e.querySelectorAll(this.pars eSelectorsForNode(e)),i=0,a=r.length;a>i&&(o=r[i]);i++)if(!this.isParsed(o))retu rn this.hasResource(o)?t(o)?this.nextToParseInDoc(o.__doc,o):o:void 0}return n}, nextToParseDynamic:function(){return this.dynamicElements[0]},parseSelectorsForN ode:function(e){var t=e.ownerDocument||e;return t===s?this.documentSelectors:thi s.importsSelectors},isParsed:function(e){return e.__importParsed},needsDynamicPa rsing:function(e){return this.dynamicElements.indexOf(e)>=0},hasResource:functio n(e){return!t(e)||void 0!==e.__doc}};e.parser=h,e.IMPORT_SELECTOR=u}),window.HTM LImports.addModule(function(e){function t(e){return n(e,a)}function n(e,t){retur n"link"===e.localName&&e.getAttribute("rel")===t}function o(e){return!!Object.ge tOwnPropertyDescriptor(e,"baseURI")}function r(e,t){var n=document.implementatio n.createHTMLDocument(a);n._URL=t;var r=n.createElement("base");r.setAttribute("h ref",t),n.baseURI||o(n)||Object.defineProperty(n,"baseURI",{value:t});var i=n.cr eateElement("meta");return i.setAttribute("charset","utf-8"),n.head.appendChild( i),n.head.appendChild(r),n.body.innerHTML=e,window.HTMLTemplateElement&&HTMLTemp lateElement.bootstrap&&HTMLTemplateElement.bootstrap(n),n}var i=e.flags,a=e.IMPO RT_LINK_TYPE,s=e.IMPORT_SELECTOR,c=e.rootDocument,d=e.Loader,l=e.Observer,u=e.pa rser,h={documents:{},documentPreloadSelectors:s,importsPreloadSelectors:[s].join (","),loadNode:function(e){f.addNode(e)},loadSubtree:function(e){var t=this.mars halNodes(e);f.addNodes(t)},marshalNodes:function(e){return e.querySelectorAll(th is.loadSelectorsForNode(e))},loadSelectorsForNode:function(e){var t=e.ownerDocum ent||e;return t===c?this.documentPreloadSelectors:this.importsPreloadSelectors}, loaded:function(e,n,o,a,s){if(i.load&&console.log("loaded",e,n),n.__resource=o,n .__error=a,t(n)){var c=this.documents[e];void 0===c&&(c=a?null:r(o,s||e),c&&(c._ _importLink=n,this.bootDocument(c)),this.documents[e]=c),n.__doc=c}u.parseNext() },bootDocument:function(e){this.loadSubtree(e),this.observer.observe(e),u.parseN ext()},loadedAll:function(){u.parseNext()}},f=new d(h.loaded.bind(h),h.loadedAll .bind(h));if(h.observer=new l,!document.baseURI){var p={get:function(){var e=doc ument.querySelector("base");return e?e.href:window.location.href},configurable:! 0};Object.defineProperty(document,"baseURI",p),Object.defineProperty(c,"baseURI" ,p)}e.importer=h,e.importLoader=f}),window.HTMLImports.addModule(function(e){var t=e.parser,n=e.importer,o={added:function(e){for(var o,r,i,a,s=0,c=e.length;c>s &&(a=e[s]);s++)o||(o=a.ownerDocument,r=t.isParsed(o)),i=this.shouldLoadNode(a),i &&n.loadNode(a),this.shouldParseNode(a)&&r&&t.parseDynamic(a,i)},shouldLoadNode: function(e){return 1===e.nodeType&&r.call(e,n.loadSelectorsForNode(e))},shouldPa rseNode:function(e){return 1===e.nodeType&&r.call(e,t.parseSelectorsForNode(e))} };n.observer.addCallback=o.added.bind(o);var r=HTMLElement.prototype.matches||HT MLElement.prototype.matchesSelector||HTMLElement.prototype.webkitMatchesSelector ||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelec tor}),function(e){function t(){window.HTMLImports.importer.bootDocument(o)}var n =e.initializeModules;e.isIE;if(!e.useNative){n();var o=e.rootDocument;"complete" ===document.readyState||"interactive"===document.readyState&&!window.attachEvent ?t():document.addEventListener("DOMContentLoaded",t)}}(window.HTMLImports),windo w.CustomElements=window.CustomElements||{flags:{}},function(e){var t=e.flags,n=[ ],o=function(e){n.push(e)},r=function(){n.forEach(function(t){t(e)})};e.addModul e=o,e.initializeModules=r,e.hasNative=Boolean(document.registerElement),e.isIE=/ Trident/.test(navigator.userAgent),e.useNative=!t.register&&e.hasNative&&!window .ShadowDOMPolyfill&&(!window.HTMLImports||window.HTMLImports.useNative)}(window. CustomElements),window.CustomElements.addModule(function(e){function t(e,t){n(e, function(e){return t(e)?!0:void o(e,t)}),o(e,t)}function n(e,t,o){var r=e.firstE lementChild;if(!r)for(r=e.firstChild;r&&r.nodeType!==Node.ELEMENT_NODE;)r=r.next Sibling;for(;r;)t(r,o)!==!0&&n(r,t,o),r=r.nextElementSibling;return null}functio n o(e,n){for(var o=e.shadowRoot;o;)t(o,n),o=o.olderShadowRoot}function r(e,t){i( e,t,[])}function i(e,t,n){if(e=window.wrap(e),!(n.indexOf(e)>=0)){n.push(e);for( var o,r=e.querySelectorAll("link[rel="+a+"]"),s=0,c=r.length;c>s&&(o=r[s]);s++)o ["import"]&&i(o["import"],t,n);t(e)}}var a=window.HTMLImports?window.HTMLImports .IMPORT_LINK_TYPE:"none";e.forDocumentTree=r,e.forSubtree=t}),window.CustomEleme nts.addModule(function(e){function t(e,t){return n(e,t)||o(e,t)}function n(t,n){ return e.upgrade(t,n)?!0:void(n&&a(t))}function o(e,t){g(e,function(e){return n( e,t)?!0:void 0})}function r(e){L.push(e),E||(E=!0,setTimeout(i))}function i(){E= !1;for(var e,t=L,n=0,o=t.length;o>n&&(e=t[n]);n++)e();L=[]}function a(e){y?r(fun ction(){s(e)}):s(e)}function s(e){
34 e.__upgraded__&&!e.__attached&&(e.__attached=!0,e.attachedCallback&&e.attachedCa llback())}function c(e){d(e),g(e,function(e){d(e)})}function d(e){y?r(function() {l(e)}):l(e)}function l(e){e.__upgraded__&&e.__attached&&(e.__attached=!1,e.deta chedCallback&&e.detachedCallback())}function u(e){for(var t=e,n=window.wrap(docu ment);t;){if(t==n)return!0;t=t.parentNode||t.nodeType===Node.DOCUMENT_FRAGMENT_N ODE&&t.host}}function h(e){if(e.shadowRoot&&!e.shadowRoot.__watched){_.dom&&cons ole.log("watching shadow-root for: ",e.localName);for(var t=e.shadowRoot;t;)m(t) ,t=t.olderShadowRoot}}function f(e,n){if(_.dom){var o=n[0];if(o&&"childList"===o .type&&o.addedNodes&&o.addedNodes){for(var r=o.addedNodes[0];r&&r!==document&&!r .host;)r=r.parentNode;var i=r&&(r.URL||r._URL||r.host&&r.host.localName)||"";i=i .split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",n.leng th,i||"")}var a=u(e);n.forEach(function(e){"childList"===e.type&&(N(e.addedNodes ,function(e){e.localName&&t(e,a)}),N(e.removedNodes,function(e){e.localName&&c(e )}))}),_.dom&&console.groupEnd()}function p(e){for(e=window.wrap(e),e||(e=window .wrap(document));e.parentNode;)e=e.parentNode;var t=e.__observer;t&&(f(e,t.takeR ecords()),i())}function m(e){if(!e.__observer){var t=new MutationObserver(f.bind (this,e));t.observe(e,{childList:!0,subtree:!0}),e.__observer=t}}function v(e){e =window.wrap(e),_.dom&&console.group("upgradeDocument: ",e.baseURI.split("/").po p());var n=e===window.wrap(document);t(e,n),m(e),_.dom&&console.groupEnd()}funct ion w(e){b(e,v)}var _=e.flags,g=e.forSubtree,b=e.forDocumentTree,y=window.Mutati onObserver._isPolyfilled&&_["throttle-attached"];e.hasPolyfillMutations=y,e.hasT hrottledAttached=y;var E=!1,L=[],N=Array.prototype.forEach.call.bind(Array.proto type.forEach),M=Element.prototype.createShadowRoot;M&&(Element.prototype.createS hadowRoot=function(){var e=M.call(this);return window.CustomElements.watchShadow (this),e}),e.watchShadow=h,e.upgradeDocumentTree=w,e.upgradeDocument=v,e.upgrade Subtree=o,e.upgradeAll=t,e.attached=a,e.takeRecords=p}),window.CustomElements.ad dModule(function(e){function t(t,o){if("template"===t.localName&&window.HTMLTemp lateElement&&HTMLTemplateElement.decorate&&HTMLTemplateElement.decorate(t),!t.__ upgraded__&&t.nodeType===Node.ELEMENT_NODE){var r=t.getAttribute("is"),i=e.getRe gisteredDefinition(t.localName)||e.getRegisteredDefinition(r);if(i&&(r&&i.tag==t .localName||!r&&!i["extends"]))return n(t,i,o)}}function n(t,n,r){return a.upgra de&&console.group("upgrade:",t.localName),n.is&&t.setAttribute("is",n.is),o(t,n) ,t.__upgraded__=!0,i(t),r&&e.attached(t),e.upgradeSubtree(t,r),a.upgrade&&consol e.groupEnd(),t}function o(e,t){Object.__proto__?e.__proto__=t.prototype:(r(e,t.p rototype,t["native"]),e.__proto__=t.prototype)}function r(e,t,n){for(var o={},r= t;r!==n&&r!==HTMLElement.prototype;){for(var i,a=Object.getOwnPropertyNames(r),s =0;i=a[s];s++)o[i]||(Object.defineProperty(e,i,Object.getOwnPropertyDescriptor(r ,i)),o[i]=1);r=Object.getPrototypeOf(r)}}function i(e){e.createdCallback&&e.crea tedCallback()}var a=e.flags;e.upgrade=t,e.upgradeWithDefinition=n,e.implementPro totype=o}),window.CustomElements.addModule(function(e){function t(t,o){var c=o|| {};if(!t)throw new Error("document.registerElement: first argument `name` must n ot be empty");if(t.indexOf("-")<0)throw new Error("document.registerElement: fir st argument ('name') must contain a dash ('-'). Argument provided was '"+String( t)+"'.");if(r(t))throw new Error("Failed to execute 'registerElement' on 'Docume nt': Registration failed for type '"+String(t)+"'. The type name is invalid.");i f(d(t))throw new Error("DuplicateDefinitionError: a type with name '"+String(t)+ "' is already registered");return c.prototype||(c.prototype=Object.create(HTMLEl ement.prototype)),c.__name=t.toLowerCase(),c["extends"]&&(c["extends"]=c["extend s"].toLowerCase()),c.lifecycle=c.lifecycle||{},c.ancestry=i(c["extends"]),a(c),s (c),n(c.prototype),l(c.__name,c),c.ctor=u(c),c.ctor.prototype=c.prototype,c.prot otype.constructor=c.ctor,e.ready&&v(document),c.ctor}function n(e){if(!e.setAttr ibute._polyfilled){var t=e.setAttribute;e.setAttribute=function(e,n){o.call(this ,e,n,t)};var n=e.removeAttribute;e.removeAttribute=function(e){o.call(this,e,nul l,n)},e.setAttribute._polyfilled=!0}}function o(e,t,n){e=e.toLowerCase();var o=t his.getAttribute(e);n.apply(this,arguments);var r=this.getAttribute(e);this.attr ibuteChangedCallback&&r!==o&&this.attributeChangedCallback(e,o,r)}function r(e){ for(var t=0;t<y.length;t++)if(e===y[t])return!0}function i(e){var t=d(e);return t?i(t["extends"]).concat([t]):[]}function a(e){for(var t,n=e["extends"],o=0;t=e. ancestry[o];o++)n=t.is&&t.tag;e.tag=n||e.__name,n&&(e.is=e.__name)}function s(e) {if(!Object.__proto__){var t=HTMLElement.prototype;if(e.is){var n=document.creat eElement(e.tag);t=Object.getPrototypeOf(n)}for(var o,r=e.prototype,i=!1;r;)r==t& &(i=!0),o=Object.getPrototypeOf(r),o&&(r.__proto__=o),r=o;i||console.warn(e.tag+ " prototype not found in prototype chain for "+e.is),e["native"]=t}}function c(e ){return _(N(e.tag),e)}function d(e){return e?E[e.toLowerCase()]:void 0}function l(e,t){E[e]=t}function u(e){return function(){return c(e)}}function h(e,t,n){re turn e===L?f(t,n):M(e,t)}function f(e,t){e&&(e=e.toLowerCase()),t&&(t=t.toLowerC ase());var n=d(t||e);if(n){if(e==n.tag&&t==n.is)return new n.ctor;if(!t&&!n.is)r eturn new n.ctor}var o;return t?(o=f(e),o.setAttribute("is",t),o):(o=N(e),e.inde xOf("-")>=0&&g(o,HTMLElement),o)}function p(e,t){var n=e[t];e[t]=function(){var e=n.apply(this,arguments);return w(e),e}}var m,v=(e.isIE,e.upgradeDocumentTree), w=e.upgradeAll,_=e.upgradeWithDefinition,g=e.implementPrototype,b=e.useNative,y= ["annotation-xml","color-profile","font-face","font-face-src","font-face-uri","f ont-face-format","font-face-name","missing-glyph"],E={},L="http://www.w3.org/199 9/xhtml",N=document.createElement.bind(document),M=document.createElementNS.bind (document);m=Object.__proto__||b?function(e,t){return e instanceof t}:function(e ,t){if(e instanceof t)return!0;for(var n=e;n;){if(n===t.prototype)return!0;n=n._ _proto__}return!1},p(Node.prototype,"cloneNode"),p(document,"importNode"),docume nt.registerElement=t,document.createElement=f,document.createElementNS=h,e.regis try=E,e["instanceof"]=m,e.reservedTagList=y,e.getRegisteredDefinition=d,document .register=document.registerElement}),function(e){function t(){i(window.wrap(docu ment)),window.CustomElements.ready=!0;var e=window.requestAnimationFrame||functi on(e){setTimeout(e,16)};e(function(){setTimeout(function(){window.CustomElements .readyTime=Date.now(),window.HTMLImports&&(window.CustomElements.elapsed=window. CustomElements.readyTime-window.HTMLImports.readyTime),document.dispatchEvent(ne w CustomEvent("WebComponentsReady",{bubbles:!0}))})})}var n=e.useNative,o=e.init ializeModules;e.isIE;if(n){var r=function(){};e.watchShadow=r,e.upgrade=r,e.upgr adeAll=r,e.upgradeDocumentTree=r,e.upgradeSubtree=r,e.takeRecords=r,e["instanceo f"]=function(e,t){return e instanceof t}}else o();var i=e.upgradeDocumentTree,a= e.upgradeDocument;if(window.wrap||(window.ShadowDOMPolyfill?(window.wrap=window. ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=window.ShadowDOMPolyfill.unwrapIfNe eded):window.wrap=window.unwrap=function(e){return e}),window.HTMLImports&&(wind ow.HTMLImports.__importsParsingHook=function(e){e["import"]&&a(wrap(e["import"]) )}),"complete"===document.readyState||e.flags.eager)t();else if("interactive"!== document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports .ready){var s=window.HTMLImports&&!window.HTMLImports.ready?"HTMLImportsLoaded": "DOMContentLoaded";window.addEventListener(s,t)}else t()}(window.CustomElements) ,function(e){var t=document.createElement("style");t.textContent="body {transiti on: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; over flow: hidden; position: relative; } \n";var n=document.querySelector("head");n.i nsertBefore(t,n.firstChild)}(window.WebComponents);</script>
35 </head>
36
37 <body><div hidden="" by-vulcanize=""><script>(function () {
38 function resolve() {
39 document.body.removeAttribute('unresolved');
40 }
41 if (window.WebComponents) {
42 addEventListener('WebComponentsReady', resolve);
43 } else {
44 if (document.readyState === 'interactive' || document.readyState === 'complete') {
45 resolve();
46 } else {
47 addEventListener('DOMContentLoaded', resolve);
48 }
49 }
50 }());
51 window.Polymer = {
52 Settings: function () {
53 var settings = window.Polymer || {};
54 var parts = location.search.slice(1).split('&');
55 for (var i = 0, o; i < parts.length && (o = parts[i]); i++) {
56 o = o.split('=');
57 o[0] && (settings[o[0]] = o[1] || true);
58 }
59 settings.wantShadow = settings.dom === 'shadow';
60 settings.hasShadow = Boolean(Element.prototype.createShadowRoot);
61 settings.nativeShadow = settings.hasShadow && !window.ShadowDOMPolyfill;
62 settings.useShadow = settings.wantShadow && settings.hasShadow;
63 settings.hasNativeImports = Boolean('import' in document.createElement('link'));
64 settings.useNativeImports = settings.hasNativeImports;
65 settings.useNativeCustomElements = !window.CustomElements || window.CustomElemen ts.useNative;
66 settings.useNativeShadow = settings.useShadow && settings.nativeShadow;
67 settings.usePolyfillProto = !settings.useNativeCustomElements && !Object.__proto __;
68 return settings;
69 }()
70 };
71 (function () {
72 var userPolymer = window.Polymer;
73 window.Polymer = function (prototype) {
74 if (typeof prototype === 'function') {
75 prototype = prototype.prototype;
76 }
77 if (!prototype) {
78 prototype = {};
79 }
80 var factory = desugar(prototype);
81 prototype = factory.prototype;
82 var options = { prototype: prototype };
83 if (prototype.extends) {
84 options.extends = prototype.extends;
85 }
86 Polymer.telemetry._registrate(prototype);
87 document.registerElement(prototype.is, options);
88 return factory;
89 };
90 var desugar = function (prototype) {
91 var base = Polymer.Base;
92 if (prototype.extends) {
93 base = Polymer.Base._getExtendedPrototype(prototype.extends);
94 }
95 prototype = Polymer.Base.chainObject(prototype, base);
96 prototype.registerCallback();
97 return prototype.constructor;
98 };
99 if (userPolymer) {
100 for (var i in userPolymer) {
101 Polymer[i] = userPolymer[i];
102 }
103 }
104 Polymer.Class = desugar;
105 }());
106 Polymer.telemetry = {
107 registrations: [],
108 _regLog: function (prototype) {
109 console.log('[' + prototype.is + ']: registered');
110 },
111 _registrate: function (prototype) {
112 this.registrations.push(prototype);
113 Polymer.log && this._regLog(prototype);
114 },
115 dumpRegistrations: function () {
116 this.registrations.forEach(this._regLog);
117 }
118 };
119 Object.defineProperty(window, 'currentImport', {
120 enumerable: true,
121 configurable: true,
122 get: function () {
123 return (document._currentScript || document.currentScript).ownerDocument;
124 }
125 });
126 Polymer.RenderStatus = {
127 _ready: false,
128 _callbacks: [],
129 whenReady: function (cb) {
130 if (this._ready) {
131 cb();
132 } else {
133 this._callbacks.push(cb);
134 }
135 },
136 _makeReady: function () {
137 this._ready = true;
138 for (var i = 0; i < this._callbacks.length; i++) {
139 this._callbacks[i]();
140 }
141 this._callbacks = [];
142 },
143 _catchFirstRender: function () {
144 requestAnimationFrame(function () {
145 Polymer.RenderStatus._makeReady();
146 });
147 },
148 _afterNextRenderQueue: [],
149 _waitingNextRender: false,
150 afterNextRender: function (element, fn, args) {
151 this._watchNextRender();
152 this._afterNextRenderQueue.push([
153 element,
154 fn,
155 args
156 ]);
157 },
158 _watchNextRender: function () {
159 if (!this._waitingNextRender) {
160 this._waitingNextRender = true;
161 var fn = function () {
162 Polymer.RenderStatus._flushNextRender();
163 };
164 if (!this._ready) {
165 this.whenReady(fn);
166 } else {
167 requestAnimationFrame(fn);
168 }
169 }
170 },
171 _flushNextRender: function () {
172 var self = this;
173 setTimeout(function () {
174 self._flushRenderCallbacks(self._afterNextRenderQueue);
175 self._afterNextRenderQueue = [];
176 self._waitingNextRender = false;
177 });
178 },
179 _flushRenderCallbacks: function (callbacks) {
180 for (var i = 0, h; i < callbacks.length; i++) {
181 h = callbacks[i];
182 h[1].apply(h[0], h[2] || Polymer.nar);
183 }
184 }
185 };
186 if (window.HTMLImports) {
187 HTMLImports.whenReady(function () {
188 Polymer.RenderStatus._catchFirstRender();
189 });
190 } else {
191 Polymer.RenderStatus._catchFirstRender();
192 }
193 Polymer.ImportStatus = Polymer.RenderStatus;
194 Polymer.ImportStatus.whenLoaded = Polymer.ImportStatus.whenReady;
195 (function () {
196 'use strict';
197 var settings = Polymer.Settings;
198 Polymer.Base = {
199 __isPolymerInstance__: true,
200 _addFeature: function (feature) {
201 this.extend(this, feature);
202 },
203 registerCallback: function () {
204 this._desugarBehaviors();
205 this._doBehavior('beforeRegister');
206 this._registerFeatures();
207 if (!settings.lazyRegister) {
208 this.ensureRegisterFinished();
209 }
210 },
211 createdCallback: function () {
212 if (!this.__hasRegisterFinished) {
213 this._ensureRegisterFinished(this.__proto__);
214 }
215 Polymer.telemetry.instanceCount++;
216 this.root = this;
217 this._doBehavior('created');
218 this._initFeatures();
219 },
220 ensureRegisterFinished: function () {
221 this._ensureRegisterFinished(this);
222 },
223 _ensureRegisterFinished: function (proto) {
224 if (proto.__hasRegisterFinished !== proto.is) {
225 proto.__hasRegisterFinished = proto.is;
226 if (proto._finishRegisterFeatures) {
227 proto._finishRegisterFeatures();
228 }
229 proto._doBehavior('registered');
230 }
231 },
232 attachedCallback: function () {
233 var self = this;
234 Polymer.RenderStatus.whenReady(function () {
235 self.isAttached = true;
236 self._doBehavior('attached');
237 });
238 },
239 detachedCallback: function () {
240 this.isAttached = false;
241 this._doBehavior('detached');
242 },
243 attributeChangedCallback: function (name, oldValue, newValue) {
244 this._attributeChangedImpl(name);
245 this._doBehavior('attributeChanged', [
246 name,
247 oldValue,
248 newValue
249 ]);
250 },
251 _attributeChangedImpl: function (name) {
252 this._setAttributeToProperty(this, name);
253 },
254 extend: function (prototype, api) {
255 if (prototype && api) {
256 var n$ = Object.getOwnPropertyNames(api);
257 for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
258 this.copyOwnProperty(n, api, prototype);
259 }
260 }
261 return prototype || api;
262 },
263 mixin: function (target, source) {
264 for (var i in source) {
265 target[i] = source[i];
266 }
267 return target;
268 },
269 copyOwnProperty: function (name, source, target) {
270 var pd = Object.getOwnPropertyDescriptor(source, name);
271 if (pd) {
272 Object.defineProperty(target, name, pd);
273 }
274 },
275 _log: console.log.apply.bind(console.log, console),
276 _warn: console.warn.apply.bind(console.warn, console),
277 _error: console.error.apply.bind(console.error, console),
278 _logf: function () {
279 return this._logPrefix.concat([this.is]).concat(Array.prototype.slice.call(argum ents, 0));
280 }
281 };
282 Polymer.Base._logPrefix = function () {
283 var color = window.chrome || /firefox/i.test(navigator.userAgent);
284 return color ? [
285 '%c[%s::%s]:',
286 'font-weight: bold; background-color:#EEEE00;'
287 ] : ['[%s::%s]:'];
288 }();
289 Polymer.Base.chainObject = function (object, inherited) {
290 if (object && inherited && object !== inherited) {
291 if (!Object.__proto__) {
292 object = Polymer.Base.extend(Object.create(inherited), object);
293 }
294 object.__proto__ = inherited;
295 }
296 return object;
297 };
298 Polymer.Base = Polymer.Base.chainObject(Polymer.Base, HTMLElement.prototype);
299 if (window.CustomElements) {
300 Polymer.instanceof = CustomElements.instanceof;
301 } else {
302 Polymer.instanceof = function (obj, ctor) {
303 return obj instanceof ctor;
304 };
305 }
306 Polymer.isInstance = function (obj) {
307 return Boolean(obj && obj.__isPolymerInstance__);
308 };
309 Polymer.telemetry.instanceCount = 0;
310 }());
311 (function () {
312 var modules = {};
313 var lcModules = {};
314 var findModule = function (id) {
315 return modules[id] || lcModules[id.toLowerCase()];
316 };
317 var DomModule = function () {
318 return document.createElement('dom-module');
319 };
320 DomModule.prototype = Object.create(HTMLElement.prototype);
321 Polymer.Base.extend(DomModule.prototype, {
322 constructor: DomModule,
323 createdCallback: function () {
324 this.register();
325 },
326 register: function (id) {
327 id = id || this.id || this.getAttribute('name') || this.getAttribute('is');
328 if (id) {
329 this.id = id;
330 modules[id] = this;
331 lcModules[id.toLowerCase()] = this;
332 }
333 },
334 import: function (id, selector) {
335 if (id) {
336 var m = findModule(id);
337 if (!m) {
338 forceDomModulesUpgrade();
339 m = findModule(id);
340 }
341 if (m && selector) {
342 m = m.querySelector(selector);
343 }
344 return m;
345 }
346 }
347 });
348 var cePolyfill = window.CustomElements && !CustomElements.useNative;
349 document.registerElement('dom-module', DomModule);
350 function forceDomModulesUpgrade() {
351 if (cePolyfill) {
352 var script = document._currentScript || document.currentScript;
353 var doc = script && script.ownerDocument || document;
354 var modules = doc.querySelectorAll('dom-module');
355 for (var i = modules.length - 1, m; i >= 0 && (m = modules[i]); i--) {
356 if (m.__upgraded__) {
357 return;
358 } else {
359 CustomElements.upgrade(m);
360 }
361 }
362 }
363 }
364 }());
365 Polymer.Base._addFeature({
366 _prepIs: function () {
367 if (!this.is) {
368 var module = (document._currentScript || document.currentScript).parentNode;
369 if (module.localName === 'dom-module') {
370 var id = module.id || module.getAttribute('name') || module.getAttribute('is');
371 this.is = id;
372 }
373 }
374 if (this.is) {
375 this.is = this.is.toLowerCase();
376 }
377 }
378 });
379 Polymer.Base._addFeature({
380 behaviors: [],
381 _desugarBehaviors: function () {
382 if (this.behaviors.length) {
383 this.behaviors = this._desugarSomeBehaviors(this.behaviors);
384 }
385 },
386 _desugarSomeBehaviors: function (behaviors) {
387 var behaviorSet = [];
388 behaviors = this._flattenBehaviorsList(behaviors);
389 for (var i = behaviors.length - 1; i >= 0; i--) {
390 var b = behaviors[i];
391 if (behaviorSet.indexOf(b) === -1) {
392 this._mixinBehavior(b);
393 behaviorSet.unshift(b);
394 }
395 }
396 return behaviorSet;
397 },
398 _flattenBehaviorsList: function (behaviors) {
399 var flat = [];
400 for (var i = 0; i < behaviors.length; i++) {
401 var b = behaviors[i];
402 if (b instanceof Array) {
403 flat = flat.concat(this._flattenBehaviorsList(b));
404 } else if (b) {
405 flat.push(b);
406 } else {
407 this._warn(this._logf('_flattenBehaviorsList', 'behavior is null, check for miss ing or 404 import'));
408 }
409 }
410 return flat;
411 },
412 _mixinBehavior: function (b) {
413 var n$ = Object.getOwnPropertyNames(b);
414 for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
415 if (!Polymer.Base._behaviorProperties[n] && !this.hasOwnProperty(n)) {
416 this.copyOwnProperty(n, b, this);
417 }
418 }
419 },
420 _prepBehaviors: function () {
421 this._prepFlattenedBehaviors(this.behaviors);
422 },
423 _prepFlattenedBehaviors: function (behaviors) {
424 for (var i = 0, l = behaviors.length; i < l; i++) {
425 this._prepBehavior(behaviors[i]);
426 }
427 this._prepBehavior(this);
428 },
429 _doBehavior: function (name, args) {
430 for (var i = 0; i < this.behaviors.length; i++) {
431 this._invokeBehavior(this.behaviors[i], name, args);
432 }
433 this._invokeBehavior(this, name, args);
434 },
435 _invokeBehavior: function (b, name, args) {
436 var fn = b[name];
437 if (fn) {
438 fn.apply(this, args || Polymer.nar);
439 }
440 },
441 _marshalBehaviors: function () {
442 for (var i = 0; i < this.behaviors.length; i++) {
443 this._marshalBehavior(this.behaviors[i]);
444 }
445 this._marshalBehavior(this);
446 }
447 });
448 Polymer.Base._behaviorProperties = {
449 hostAttributes: true,
450 beforeRegister: true,
451 registered: true,
452 properties: true,
453 observers: true,
454 listeners: true,
455 created: true,
456 attached: true,
457 detached: true,
458 attributeChanged: true,
459 ready: true
460 };
461 Polymer.Base._addFeature({
462 _getExtendedPrototype: function (tag) {
463 return this._getExtendedNativePrototype(tag);
464 },
465 _nativePrototypes: {},
466 _getExtendedNativePrototype: function (tag) {
467 var p = this._nativePrototypes[tag];
468 if (!p) {
469 var np = this.getNativePrototype(tag);
470 p = this.extend(Object.create(np), Polymer.Base);
471 this._nativePrototypes[tag] = p;
472 }
473 return p;
474 },
475 getNativePrototype: function (tag) {
476 return Object.getPrototypeOf(document.createElement(tag));
477 }
478 });
479 Polymer.Base._addFeature({
480 _prepConstructor: function () {
481 this._factoryArgs = this.extends ? [
482 this.extends,
483 this.is
484 ] : [this.is];
485 var ctor = function () {
486 return this._factory(arguments);
487 };
488 if (this.hasOwnProperty('extends')) {
489 ctor.extends = this.extends;
490 }
491 Object.defineProperty(this, 'constructor', {
492 value: ctor,
493 writable: true,
494 configurable: true
495 });
496 ctor.prototype = this;
497 },
498 _factory: function (args) {
499 var elt = document.createElement.apply(document, this._factoryArgs);
500 if (this.factoryImpl) {
501 this.factoryImpl.apply(elt, args);
502 }
503 return elt;
504 }
505 });
506 Polymer.nob = Object.create(null);
507 Polymer.Base._addFeature({
508 properties: {},
509 getPropertyInfo: function (property) {
510 var info = this._getPropertyInfo(property, this.properties);
511 if (!info) {
512 for (var i = 0; i < this.behaviors.length; i++) {
513 info = this._getPropertyInfo(property, this.behaviors[i].properties);
514 if (info) {
515 return info;
516 }
517 }
518 }
519 return info || Polymer.nob;
520 },
521 _getPropertyInfo: function (property, properties) {
522 var p = properties && properties[property];
523 if (typeof p === 'function') {
524 p = properties[property] = { type: p };
525 }
526 if (p) {
527 p.defined = true;
528 }
529 return p;
530 },
531 _prepPropertyInfo: function () {
532 this._propertyInfo = {};
533 for (var i = 0; i < this.behaviors.length; i++) {
534 this._addPropertyInfo(this._propertyInfo, this.behaviors[i].properties);
535 }
536 this._addPropertyInfo(this._propertyInfo, this.properties);
537 this._addPropertyInfo(this._propertyInfo, this._propertyEffects);
538 },
539 _addPropertyInfo: function (target, source) {
540 if (source) {
541 var t, s;
542 for (var i in source) {
543 t = target[i];
544 s = source[i];
545 if (i[0] === '_' && !s.readOnly) {
546 continue;
547 }
548 if (!target[i]) {
549 target[i] = {
550 type: typeof s === 'function' ? s : s.type,
551 readOnly: s.readOnly,
552 attribute: Polymer.CaseMap.camelToDashCase(i)
553 };
554 } else {
555 if (!t.type) {
556 t.type = s.type;
557 }
558 if (!t.readOnly) {
559 t.readOnly = s.readOnly;
560 }
561 }
562 }
563 }
564 }
565 });
566 Polymer.CaseMap = {
567 _caseMap: {},
568 _rx: {
569 dashToCamel: /-[a-z]/g,
570 camelToDash: /([A-Z])/g
571 },
572 dashToCamelCase: function (dash) {
573 return this._caseMap[dash] || (this._caseMap[dash] = dash.indexOf('-') < 0 ? das h : dash.replace(this._rx.dashToCamel, function (m) {
574 return m[1].toUpperCase();
575 }));
576 },
577 camelToDashCase: function (camel) {
578 return this._caseMap[camel] || (this._caseMap[camel] = camel.replace(this._rx.ca melToDash, '-$1').toLowerCase());
579 }
580 };
581 Polymer.Base._addFeature({
582 _addHostAttributes: function (attributes) {
583 if (!this._aggregatedAttributes) {
584 this._aggregatedAttributes = {};
585 }
586 if (attributes) {
587 this.mixin(this._aggregatedAttributes, attributes);
588 }
589 },
590 _marshalHostAttributes: function () {
591 if (this._aggregatedAttributes) {
592 this._applyAttributes(this, this._aggregatedAttributes);
593 }
594 },
595 _applyAttributes: function (node, attr$) {
596 for (var n in attr$) {
597 if (!this.hasAttribute(n) && n !== 'class') {
598 var v = attr$[n];
599 this.serializeValueToAttribute(v, n, this);
600 }
601 }
602 },
603 _marshalAttributes: function () {
604 this._takeAttributesToModel(this);
605 },
606 _takeAttributesToModel: function (model) {
607 if (this.hasAttributes()) {
608 for (var i in this._propertyInfo) {
609 var info = this._propertyInfo[i];
610 if (this.hasAttribute(info.attribute)) {
611 this._setAttributeToProperty(model, info.attribute, i, info);
612 }
613 }
614 }
615 },
616 _setAttributeToProperty: function (model, attribute, property, info) {
617 if (!this._serializing) {
618 property = property || Polymer.CaseMap.dashToCamelCase(attribute);
619 info = info || this._propertyInfo && this._propertyInfo[property];
620 if (info && !info.readOnly) {
621 var v = this.getAttribute(attribute);
622 model[property] = this.deserialize(v, info.type);
623 }
624 }
625 },
626 _serializing: false,
627 reflectPropertyToAttribute: function (property, attribute, value) {
628 this._serializing = true;
629 value = value === undefined ? this[property] : value;
630 this.serializeValueToAttribute(value, attribute || Polymer.CaseMap.camelToDashCa se(property));
631 this._serializing = false;
632 },
633 serializeValueToAttribute: function (value, attribute, node) {
634 var str = this.serialize(value);
635 node = node || this;
636 if (str === undefined) {
637 node.removeAttribute(attribute);
638 } else {
639 node.setAttribute(attribute, str);
640 }
641 },
642 deserialize: function (value, type) {
643 switch (type) {
644 case Number:
645 value = Number(value);
646 break;
647 case Boolean:
648 value = value != null;
649 break;
650 case Object:
651 try {
652 value = JSON.parse(value);
653 } catch (x) {
654 }
655 break;
656 case Array:
657 try {
658 value = JSON.parse(value);
659 } catch (x) {
660 value = null;
661 console.warn('Polymer::Attributes: couldn`t decode Array as JSON');
662 }
663 break;
664 case Date:
665 value = new Date(value);
666 break;
667 case String:
668 default:
669 break;
670 }
671 return value;
672 },
673 serialize: function (value) {
674 switch (typeof value) {
675 case 'boolean':
676 return value ? '' : undefined;
677 case 'object':
678 if (value instanceof Date) {
679 return value.toString();
680 } else if (value) {
681 try {
682 return JSON.stringify(value);
683 } catch (x) {
684 return '';
685 }
686 }
687 default:
688 return value != null ? value : undefined;
689 }
690 }
691 });
692 Polymer.version = '1.4.0';
693 Polymer.Base._addFeature({
694 _registerFeatures: function () {
695 this._prepIs();
696 this._prepBehaviors();
697 this._prepConstructor();
698 this._prepPropertyInfo();
699 },
700 _prepBehavior: function (b) {
701 this._addHostAttributes(b.hostAttributes);
702 },
703 _marshalBehavior: function (b) {
704 },
705 _initFeatures: function () {
706 this._marshalHostAttributes();
707 this._marshalBehaviors();
708 }
709 });</script><script>Polymer.Base._addFeature({
710 _prepTemplate: function () {
711 if (this._template === undefined) {
712 this._template = Polymer.DomModule.import(this.is, 'template');
713 }
714 if (this._template && this._template.hasAttribute('is')) {
715 this._warn(this._logf('_prepTemplate', 'top-level Polymer template ' + 'must not be a type-extension, found', this._template, 'Move inside simple <template>.')) ;
716 }
717 if (this._template && !this._template.content && window.HTMLTemplateElement && H TMLTemplateElement.decorate) {
718 HTMLTemplateElement.decorate(this._template);
719 }
720 },
721 _stampTemplate: function () {
722 if (this._template) {
723 this.root = this.instanceTemplate(this._template);
724 }
725 },
726 instanceTemplate: function (template) {
727 var dom = document.importNode(template._content || template.content, true);
728 return dom;
729 }
730 });
731 (function () {
732 var baseAttachedCallback = Polymer.Base.attachedCallback;
733 Polymer.Base._addFeature({
734 _hostStack: [],
735 ready: function () {
736 },
737 _registerHost: function (host) {
738 this.dataHost = host = host || Polymer.Base._hostStack[Polymer.Base._hostStack.l ength - 1];
739 if (host && host._clients) {
740 host._clients.push(this);
741 }
742 this._clients = null;
743 this._clientsReadied = false;
744 },
745 _beginHosting: function () {
746 Polymer.Base._hostStack.push(this);
747 if (!this._clients) {
748 this._clients = [];
749 }
750 },
751 _endHosting: function () {
752 Polymer.Base._hostStack.pop();
753 },
754 _tryReady: function () {
755 this._readied = false;
756 if (this._canReady()) {
757 this._ready();
758 }
759 },
760 _canReady: function () {
761 return !this.dataHost || this.dataHost._clientsReadied;
762 },
763 _ready: function () {
764 this._beforeClientsReady();
765 if (this._template) {
766 this._setupRoot();
767 this._readyClients();
768 }
769 this._clientsReadied = true;
770 this._clients = null;
771 this._afterClientsReady();
772 this._readySelf();
773 },
774 _readyClients: function () {
775 this._beginDistribute();
776 var c$ = this._clients;
777 if (c$) {
778 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
779 c._ready();
780 }
781 }
782 this._finishDistribute();
783 },
784 _readySelf: function () {
785 this._doBehavior('ready');
786 this._readied = true;
787 if (this._attachedPending) {
788 this._attachedPending = false;
789 this.attachedCallback();
790 }
791 },
792 _beforeClientsReady: function () {
793 },
794 _afterClientsReady: function () {
795 },
796 _beforeAttached: function () {
797 },
798 attachedCallback: function () {
799 if (this._readied) {
800 this._beforeAttached();
801 baseAttachedCallback.call(this);
802 } else {
803 this._attachedPending = true;
804 }
805 }
806 });
807 }());
808 Polymer.ArraySplice = function () {
809 function newSplice(index, removed, addedCount) {
810 return {
811 index: index,
812 removed: removed,
813 addedCount: addedCount
814 };
815 }
816 var EDIT_LEAVE = 0;
817 var EDIT_UPDATE = 1;
818 var EDIT_ADD = 2;
819 var EDIT_DELETE = 3;
820 function ArraySplice() {
821 }
822 ArraySplice.prototype = {
823 calcEditDistances: function (current, currentStart, currentEnd, old, oldStart, o ldEnd) {
824 var rowCount = oldEnd - oldStart + 1;
825 var columnCount = currentEnd - currentStart + 1;
826 var distances = new Array(rowCount);
827 for (var i = 0; i < rowCount; i++) {
828 distances[i] = new Array(columnCount);
829 distances[i][0] = i;
830 }
831 for (var j = 0; j < columnCount; j++)
832 distances[0][j] = j;
833 for (i = 1; i < rowCount; i++) {
834 for (j = 1; j < columnCount; j++) {
835 if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1]))
836 distances[i][j] = distances[i - 1][j - 1];
837 else {
838 var north = distances[i - 1][j] + 1;
839 var west = distances[i][j - 1] + 1;
840 distances[i][j] = north < west ? north : west;
841 }
842 }
843 }
844 return distances;
845 },
846 spliceOperationsFromEditDistances: function (distances) {
847 var i = distances.length - 1;
848 var j = distances[0].length - 1;
849 var current = distances[i][j];
850 var edits = [];
851 while (i > 0 || j > 0) {
852 if (i == 0) {
853 edits.push(EDIT_ADD);
854 j--;
855 continue;
856 }
857 if (j == 0) {
858 edits.push(EDIT_DELETE);
859 i--;
860 continue;
861 }
862 var northWest = distances[i - 1][j - 1];
863 var west = distances[i - 1][j];
864 var north = distances[i][j - 1];
865 var min;
866 if (west < north)
867 min = west < northWest ? west : northWest;
868 else
869 min = north < northWest ? north : northWest;
870 if (min == northWest) {
871 if (northWest == current) {
872 edits.push(EDIT_LEAVE);
873 } else {
874 edits.push(EDIT_UPDATE);
875 current = northWest;
876 }
877 i--;
878 j--;
879 } else if (min == west) {
880 edits.push(EDIT_DELETE);
881 i--;
882 current = west;
883 } else {
884 edits.push(EDIT_ADD);
885 j--;
886 current = north;
887 }
888 }
889 edits.reverse();
890 return edits;
891 },
892 calcSplices: function (current, currentStart, currentEnd, old, oldStart, oldEnd) {
893 var prefixCount = 0;
894 var suffixCount = 0;
895 var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart);
896 if (currentStart == 0 && oldStart == 0)
897 prefixCount = this.sharedPrefix(current, old, minLength);
898 if (currentEnd == current.length && oldEnd == old.length)
899 suffixCount = this.sharedSuffix(current, old, minLength - prefixCount);
900 currentStart += prefixCount;
901 oldStart += prefixCount;
902 currentEnd -= suffixCount;
903 oldEnd -= suffixCount;
904 if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0)
905 return [];
906 if (currentStart == currentEnd) {
907 var splice = newSplice(currentStart, [], 0);
908 while (oldStart < oldEnd)
909 splice.removed.push(old[oldStart++]);
910 return [splice];
911 } else if (oldStart == oldEnd)
912 return [newSplice(currentStart, [], currentEnd - currentStart)];
913 var ops = this.spliceOperationsFromEditDistances(this.calcEditDistances(current, currentStart, currentEnd, old, oldStart, oldEnd));
914 splice = undefined;
915 var splices = [];
916 var index = currentStart;
917 var oldIndex = oldStart;
918 for (var i = 0; i < ops.length; i++) {
919 switch (ops[i]) {
920 case EDIT_LEAVE:
921 if (splice) {
922 splices.push(splice);
923 splice = undefined;
924 }
925 index++;
926 oldIndex++;
927 break;
928 case EDIT_UPDATE:
929 if (!splice)
930 splice = newSplice(index, [], 0);
931 splice.addedCount++;
932 index++;
933 splice.removed.push(old[oldIndex]);
934 oldIndex++;
935 break;
936 case EDIT_ADD:
937 if (!splice)
938 splice = newSplice(index, [], 0);
939 splice.addedCount++;
940 index++;
941 break;
942 case EDIT_DELETE:
943 if (!splice)
944 splice = newSplice(index, [], 0);
945 splice.removed.push(old[oldIndex]);
946 oldIndex++;
947 break;
948 }
949 }
950 if (splice) {
951 splices.push(splice);
952 }
953 return splices;
954 },
955 sharedPrefix: function (current, old, searchLength) {
956 for (var i = 0; i < searchLength; i++)
957 if (!this.equals(current[i], old[i]))
958 return i;
959 return searchLength;
960 },
961 sharedSuffix: function (current, old, searchLength) {
962 var index1 = current.length;
963 var index2 = old.length;
964 var count = 0;
965 while (count < searchLength && this.equals(current[--index1], old[--index2]))
966 count++;
967 return count;
968 },
969 calculateSplices: function (current, previous) {
970 return this.calcSplices(current, 0, current.length, previous, 0, previous.length );
971 },
972 equals: function (currentValue, previousValue) {
973 return currentValue === previousValue;
974 }
975 };
976 return new ArraySplice();
977 }();
978 Polymer.domInnerHTML = function () {
979 var escapeAttrRegExp = /[&\u00A0"]/g;
980 var escapeDataRegExp = /[&\u00A0<>]/g;
981 function escapeReplace(c) {
982 switch (c) {
983 case '&':
984 return '&amp;';
985 case '<':
986 return '&lt;';
987 case '>':
988 return '&gt;';
989 case '"':
990 return '&quot;';
991 case '\xA0':
992 return '&nbsp;';
993 }
994 }
995 function escapeAttr(s) {
996 return s.replace(escapeAttrRegExp, escapeReplace);
997 }
998 function escapeData(s) {
999 return s.replace(escapeDataRegExp, escapeReplace);
1000 }
1001 function makeSet(arr) {
1002 var set = {};
1003 for (var i = 0; i < arr.length; i++) {
1004 set[arr[i]] = true;
1005 }
1006 return set;
1007 }
1008 var voidElements = makeSet([
1009 'area',
1010 'base',
1011 'br',
1012 'col',
1013 'command',
1014 'embed',
1015 'hr',
1016 'img',
1017 'input',
1018 'keygen',
1019 'link',
1020 'meta',
1021 'param',
1022 'source',
1023 'track',
1024 'wbr'
1025 ]);
1026 var plaintextParents = makeSet([
1027 'style',
1028 'script',
1029 'xmp',
1030 'iframe',
1031 'noembed',
1032 'noframes',
1033 'plaintext',
1034 'noscript'
1035 ]);
1036 function getOuterHTML(node, parentNode, composed) {
1037 switch (node.nodeType) {
1038 case Node.ELEMENT_NODE:
1039 var tagName = node.localName;
1040 var s = '<' + tagName;
1041 var attrs = node.attributes;
1042 for (var i = 0, attr; attr = attrs[i]; i++) {
1043 s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"';
1044 }
1045 s += '>';
1046 if (voidElements[tagName]) {
1047 return s;
1048 }
1049 return s + getInnerHTML(node, composed) + '</' + tagName + '>';
1050 case Node.TEXT_NODE:
1051 var data = node.data;
1052 if (parentNode && plaintextParents[parentNode.localName]) {
1053 return data;
1054 }
1055 return escapeData(data);
1056 case Node.COMMENT_NODE:
1057 return '<!--' + node.data + '-->';
1058 default:
1059 console.error(node);
1060 throw new Error('not implemented');
1061 }
1062 }
1063 function getInnerHTML(node, composed) {
1064 if (node instanceof HTMLTemplateElement)
1065 node = node.content;
1066 var s = '';
1067 var c$ = Polymer.dom(node).childNodes;
1068 for (var i = 0, l = c$.length, child; i < l && (child = c$[i]); i++) {
1069 s += getOuterHTML(child, node, composed);
1070 }
1071 return s;
1072 }
1073 return { getInnerHTML: getInnerHTML };
1074 }();
1075 (function () {
1076 'use strict';
1077 var nativeInsertBefore = Element.prototype.insertBefore;
1078 var nativeAppendChild = Element.prototype.appendChild;
1079 var nativeRemoveChild = Element.prototype.removeChild;
1080 Polymer.TreeApi = {
1081 arrayCopyChildNodes: function (parent) {
1082 var copy = [], i = 0;
1083 for (var n = parent.firstChild; n; n = n.nextSibling) {
1084 copy[i++] = n;
1085 }
1086 return copy;
1087 },
1088 arrayCopyChildren: function (parent) {
1089 var copy = [], i = 0;
1090 for (var n = parent.firstElementChild; n; n = n.nextElementSibling) {
1091 copy[i++] = n;
1092 }
1093 return copy;
1094 },
1095 arrayCopy: function (a$) {
1096 var l = a$.length;
1097 var copy = new Array(l);
1098 for (var i = 0; i < l; i++) {
1099 copy[i] = a$[i];
1100 }
1101 return copy;
1102 }
1103 };
1104 Polymer.TreeApi.Logical = {
1105 hasParentNode: function (node) {
1106 return Boolean(node.__dom && node.__dom.parentNode);
1107 },
1108 hasChildNodes: function (node) {
1109 return Boolean(node.__dom && node.__dom.childNodes !== undefined);
1110 },
1111 getChildNodes: function (node) {
1112 return this.hasChildNodes(node) ? this._getChildNodes(node) : node.childNodes;
1113 },
1114 _getChildNodes: function (node) {
1115 if (!node.__dom.childNodes) {
1116 node.__dom.childNodes = [];
1117 for (var n = node.__dom.firstChild; n; n = n.__dom.nextSibling) {
1118 node.__dom.childNodes.push(n);
1119 }
1120 }
1121 return node.__dom.childNodes;
1122 },
1123 getParentNode: function (node) {
1124 return node.__dom && node.__dom.parentNode !== undefined ? node.__dom.parentNode : node.parentNode;
1125 },
1126 getFirstChild: function (node) {
1127 return node.__dom && node.__dom.firstChild !== undefined ? node.__dom.firstChild : node.firstChild;
1128 },
1129 getLastChild: function (node) {
1130 return node.__dom && node.__dom.lastChild !== undefined ? node.__dom.lastChild : node.lastChild;
1131 },
1132 getNextSibling: function (node) {
1133 return node.__dom && node.__dom.nextSibling !== undefined ? node.__dom.nextSibli ng : node.nextSibling;
1134 },
1135 getPreviousSibling: function (node) {
1136 return node.__dom && node.__dom.previousSibling !== undefined ? node.__dom.previ ousSibling : node.previousSibling;
1137 },
1138 getFirstElementChild: function (node) {
1139 return node.__dom && node.__dom.firstChild !== undefined ? this._getFirstElement Child(node) : node.firstElementChild;
1140 },
1141 _getFirstElementChild: function (node) {
1142 var n = node.__dom.firstChild;
1143 while (n && n.nodeType !== Node.ELEMENT_NODE) {
1144 n = n.__dom.nextSibling;
1145 }
1146 return n;
1147 },
1148 getLastElementChild: function (node) {
1149 return node.__dom && node.__dom.lastChild !== undefined ? this._getLastElementCh ild(node) : node.lastElementChild;
1150 },
1151 _getLastElementChild: function (node) {
1152 var n = node.__dom.lastChild;
1153 while (n && n.nodeType !== Node.ELEMENT_NODE) {
1154 n = n.__dom.previousSibling;
1155 }
1156 return n;
1157 },
1158 getNextElementSibling: function (node) {
1159 return node.__dom && node.__dom.nextSibling !== undefined ? this._getNextElement Sibling(node) : node.nextElementSibling;
1160 },
1161 _getNextElementSibling: function (node) {
1162 var n = node.__dom.nextSibling;
1163 while (n && n.nodeType !== Node.ELEMENT_NODE) {
1164 n = n.__dom.nextSibling;
1165 }
1166 return n;
1167 },
1168 getPreviousElementSibling: function (node) {
1169 return node.__dom && node.__dom.previousSibling !== undefined ? this._getPreviou sElementSibling(node) : node.previousElementSibling;
1170 },
1171 _getPreviousElementSibling: function (node) {
1172 var n = node.__dom.previousSibling;
1173 while (n && n.nodeType !== Node.ELEMENT_NODE) {
1174 n = n.__dom.previousSibling;
1175 }
1176 return n;
1177 },
1178 saveChildNodes: function (node) {
1179 if (!this.hasChildNodes(node)) {
1180 node.__dom = node.__dom || {};
1181 node.__dom.firstChild = node.firstChild;
1182 node.__dom.lastChild = node.lastChild;
1183 node.__dom.childNodes = [];
1184 for (var n = node.firstChild; n; n = n.nextSibling) {
1185 n.__dom = n.__dom || {};
1186 n.__dom.parentNode = node;
1187 node.__dom.childNodes.push(n);
1188 n.__dom.nextSibling = n.nextSibling;
1189 n.__dom.previousSibling = n.previousSibling;
1190 }
1191 }
1192 },
1193 recordInsertBefore: function (node, container, ref_node) {
1194 container.__dom.childNodes = null;
1195 if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
1196 for (var n = node.firstChild; n; n = n.nextSibling) {
1197 this._linkNode(n, container, ref_node);
1198 }
1199 } else {
1200 this._linkNode(node, container, ref_node);
1201 }
1202 },
1203 _linkNode: function (node, container, ref_node) {
1204 node.__dom = node.__dom || {};
1205 container.__dom = container.__dom || {};
1206 if (ref_node) {
1207 ref_node.__dom = ref_node.__dom || {};
1208 }
1209 node.__dom.previousSibling = ref_node ? ref_node.__dom.previousSibling : contain er.__dom.lastChild;
1210 if (node.__dom.previousSibling) {
1211 node.__dom.previousSibling.__dom.nextSibling = node;
1212 }
1213 node.__dom.nextSibling = ref_node;
1214 if (node.__dom.nextSibling) {
1215 node.__dom.nextSibling.__dom.previousSibling = node;
1216 }
1217 node.__dom.parentNode = container;
1218 if (ref_node) {
1219 if (ref_node === container.__dom.firstChild) {
1220 container.__dom.firstChild = node;
1221 }
1222 } else {
1223 container.__dom.lastChild = node;
1224 if (!container.__dom.firstChild) {
1225 container.__dom.firstChild = node;
1226 }
1227 }
1228 container.__dom.childNodes = null;
1229 },
1230 recordRemoveChild: function (node, container) {
1231 node.__dom = node.__dom || {};
1232 container.__dom = container.__dom || {};
1233 if (node === container.__dom.firstChild) {
1234 container.__dom.firstChild = node.__dom.nextSibling;
1235 }
1236 if (node === container.__dom.lastChild) {
1237 container.__dom.lastChild = node.__dom.previousSibling;
1238 }
1239 var p = node.__dom.previousSibling;
1240 var n = node.__dom.nextSibling;
1241 if (p) {
1242 p.__dom.nextSibling = n;
1243 }
1244 if (n) {
1245 n.__dom.previousSibling = p;
1246 }
1247 node.__dom.parentNode = node.__dom.previousSibling = node.__dom.nextSibling = un defined;
1248 container.__dom.childNodes = null;
1249 }
1250 };
1251 Polymer.TreeApi.Composed = {
1252 getChildNodes: function (node) {
1253 return Polymer.TreeApi.arrayCopyChildNodes(node);
1254 },
1255 getParentNode: function (node) {
1256 return node.parentNode;
1257 },
1258 clearChildNodes: function (node) {
1259 node.textContent = '';
1260 },
1261 insertBefore: function (parentNode, newChild, refChild) {
1262 return nativeInsertBefore.call(parentNode, newChild, refChild || null);
1263 },
1264 appendChild: function (parentNode, newChild) {
1265 return nativeAppendChild.call(parentNode, newChild);
1266 },
1267 removeChild: function (parentNode, node) {
1268 return nativeRemoveChild.call(parentNode, node);
1269 }
1270 };
1271 }());
1272 Polymer.DomApi = function () {
1273 'use strict';
1274 var Settings = Polymer.Settings;
1275 var TreeApi = Polymer.TreeApi;
1276 var DomApi = function (node) {
1277 this.node = needsToWrap ? DomApi.wrap(node) : node;
1278 };
1279 var needsToWrap = Settings.hasShadow && !Settings.nativeShadow;
1280 DomApi.wrap = window.wrap ? window.wrap : function (node) {
1281 return node;
1282 };
1283 DomApi.prototype = {
1284 flush: function () {
1285 Polymer.dom.flush();
1286 },
1287 deepContains: function (node) {
1288 if (this.node.contains(node)) {
1289 return true;
1290 }
1291 var n = node;
1292 var doc = node.ownerDocument;
1293 while (n && n !== doc && n !== this.node) {
1294 n = Polymer.dom(n).parentNode || n.host;
1295 }
1296 return n === this.node;
1297 },
1298 queryDistributedElements: function (selector) {
1299 var c$ = this.getEffectiveChildNodes();
1300 var list = [];
1301 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
1302 if (c.nodeType === Node.ELEMENT_NODE && DomApi.matchesSelector.call(c, selector) ) {
1303 list.push(c);
1304 }
1305 }
1306 return list;
1307 },
1308 getEffectiveChildNodes: function () {
1309 var list = [];
1310 var c$ = this.childNodes;
1311 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
1312 if (c.localName === CONTENT) {
1313 var d$ = dom(c).getDistributedNodes();
1314 for (var j = 0; j < d$.length; j++) {
1315 list.push(d$[j]);
1316 }
1317 } else {
1318 list.push(c);
1319 }
1320 }
1321 return list;
1322 },
1323 observeNodes: function (callback) {
1324 if (callback) {
1325 if (!this.observer) {
1326 this.observer = this.node.localName === CONTENT ? new DomApi.DistributedNodesObs erver(this) : new DomApi.EffectiveNodesObserver(this);
1327 }
1328 return this.observer.addListener(callback);
1329 }
1330 },
1331 unobserveNodes: function (handle) {
1332 if (this.observer) {
1333 this.observer.removeListener(handle);
1334 }
1335 },
1336 notifyObserver: function () {
1337 if (this.observer) {
1338 this.observer.notify();
1339 }
1340 },
1341 _query: function (matcher, node, halter) {
1342 node = node || this.node;
1343 var list = [];
1344 this._queryElements(TreeApi.Logical.getChildNodes(node), matcher, halter, list);
1345 return list;
1346 },
1347 _queryElements: function (elements, matcher, halter, list) {
1348 for (var i = 0, l = elements.length, c; i < l && (c = elements[i]); i++) {
1349 if (c.nodeType === Node.ELEMENT_NODE) {
1350 if (this._queryElement(c, matcher, halter, list)) {
1351 return true;
1352 }
1353 }
1354 }
1355 },
1356 _queryElement: function (node, matcher, halter, list) {
1357 var result = matcher(node);
1358 if (result) {
1359 list.push(node);
1360 }
1361 if (halter && halter(result)) {
1362 return result;
1363 }
1364 this._queryElements(TreeApi.Logical.getChildNodes(node), matcher, halter, list);
1365 }
1366 };
1367 var CONTENT = DomApi.CONTENT = 'content';
1368 var dom = DomApi.factory = function (node) {
1369 node = node || document;
1370 if (!node.__domApi) {
1371 node.__domApi = new DomApi.ctor(node);
1372 }
1373 return node.__domApi;
1374 };
1375 DomApi.hasApi = function (node) {
1376 return Boolean(node.__domApi);
1377 };
1378 DomApi.ctor = DomApi;
1379 Polymer.dom = function (obj, patch) {
1380 if (obj instanceof Event) {
1381 return Polymer.EventApi.factory(obj);
1382 } else {
1383 return DomApi.factory(obj, patch);
1384 }
1385 };
1386 var p = Element.prototype;
1387 DomApi.matchesSelector = p.matches || p.matchesSelector || p.mozMatchesSelector || p.msMatchesSelector || p.oMatchesSelector || p.webkitMatchesSelector;
1388 return DomApi;
1389 }();
1390 (function () {
1391 'use strict';
1392 var Settings = Polymer.Settings;
1393 var DomApi = Polymer.DomApi;
1394 var dom = DomApi.factory;
1395 var TreeApi = Polymer.TreeApi;
1396 var getInnerHTML = Polymer.domInnerHTML.getInnerHTML;
1397 var CONTENT = DomApi.CONTENT;
1398 if (Settings.useShadow) {
1399 return;
1400 }
1401 var nativeCloneNode = Element.prototype.cloneNode;
1402 var nativeImportNode = Document.prototype.importNode;
1403 Polymer.Base.extend(DomApi.prototype, {
1404 _lazyDistribute: function (host) {
1405 if (host.shadyRoot && host.shadyRoot._distributionClean) {
1406 host.shadyRoot._distributionClean = false;
1407 Polymer.dom.addDebouncer(host.debounce('_distribute', host._distributeContent));
1408 }
1409 },
1410 appendChild: function (node) {
1411 return this.insertBefore(node);
1412 },
1413 insertBefore: function (node, ref_node) {
1414 if (ref_node && TreeApi.Logical.getParentNode(ref_node) !== this.node) {
1415 throw Error('The ref_node to be inserted before is not a child ' + 'of this node ');
1416 }
1417 if (node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
1418 var parent = TreeApi.Logical.getParentNode(node);
1419 if (parent) {
1420 if (DomApi.hasApi(parent)) {
1421 dom(parent).notifyObserver();
1422 }
1423 this._removeNode(node);
1424 } else {
1425 this._removeOwnerShadyRoot(node);
1426 }
1427 }
1428 if (!this._addNode(node, ref_node)) {
1429 if (ref_node) {
1430 ref_node = ref_node.localName === CONTENT ? this._firstComposedNode(ref_node) : ref_node;
1431 }
1432 var container = this.node._isShadyRoot ? this.node.host : this.node;
1433 if (ref_node) {
1434 TreeApi.Composed.insertBefore(container, node, ref_node);
1435 } else {
1436 TreeApi.Composed.appendChild(container, node);
1437 }
1438 }
1439 this.notifyObserver();
1440 return node;
1441 },
1442 _addNode: function (node, ref_node) {
1443 var root = this.getOwnerRoot();
1444 if (root) {
1445 var ipAdded = this._maybeAddInsertionPoint(node, this.node);
1446 if (!root._invalidInsertionPoints) {
1447 root._invalidInsertionPoints = ipAdded;
1448 }
1449 this._addNodeToHost(root.host, node);
1450 }
1451 if (TreeApi.Logical.hasChildNodes(this.node)) {
1452 TreeApi.Logical.recordInsertBefore(node, this.node, ref_node);
1453 }
1454 var handled = this._maybeDistribute(node) || this.node.shadyRoot;
1455 if (handled) {
1456 if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
1457 while (node.firstChild) {
1458 TreeApi.Composed.removeChild(node, node.firstChild);
1459 }
1460 } else {
1461 var parent = TreeApi.Composed.getParentNode(node);
1462 if (parent) {
1463 TreeApi.Composed.removeChild(parent, node);
1464 }
1465 }
1466 }
1467 return handled;
1468 },
1469 removeChild: function (node) {
1470 if (TreeApi.Logical.getParentNode(node) !== this.node) {
1471 throw Error('The node to be removed is not a child of this node: ' + node);
1472 }
1473 if (!this._removeNode(node)) {
1474 var container = this.node._isShadyRoot ? this.node.host : this.node;
1475 var parent = TreeApi.Composed.getParentNode(node);
1476 if (container === parent) {
1477 TreeApi.Composed.removeChild(container, node);
1478 }
1479 }
1480 this.notifyObserver();
1481 return node;
1482 },
1483 _removeNode: function (node) {
1484 var logicalParent = TreeApi.Logical.hasParentNode(node) && TreeApi.Logical.getPa rentNode(node);
1485 var distributed;
1486 var root = this._ownerShadyRootForNode(node);
1487 if (logicalParent) {
1488 distributed = dom(node)._maybeDistributeParent();
1489 TreeApi.Logical.recordRemoveChild(node, logicalParent);
1490 if (root && this._removeDistributedChildren(root, node)) {
1491 root._invalidInsertionPoints = true;
1492 this._lazyDistribute(root.host);
1493 }
1494 }
1495 this._removeOwnerShadyRoot(node);
1496 if (root) {
1497 this._removeNodeFromHost(root.host, node);
1498 }
1499 return distributed;
1500 },
1501 replaceChild: function (node, ref_node) {
1502 this.insertBefore(node, ref_node);
1503 this.removeChild(ref_node);
1504 return node;
1505 },
1506 _hasCachedOwnerRoot: function (node) {
1507 return Boolean(node._ownerShadyRoot !== undefined);
1508 },
1509 getOwnerRoot: function () {
1510 return this._ownerShadyRootForNode(this.node);
1511 },
1512 _ownerShadyRootForNode: function (node) {
1513 if (!node) {
1514 return;
1515 }
1516 var root = node._ownerShadyRoot;
1517 if (root === undefined) {
1518 if (node._isShadyRoot) {
1519 root = node;
1520 } else {
1521 var parent = TreeApi.Logical.getParentNode(node);
1522 if (parent) {
1523 root = parent._isShadyRoot ? parent : this._ownerShadyRootForNode(parent);
1524 } else {
1525 root = null;
1526 }
1527 }
1528 if (root || document.documentElement.contains(node)) {
1529 node._ownerShadyRoot = root;
1530 }
1531 }
1532 return root;
1533 },
1534 _maybeDistribute: function (node) {
1535 var fragContent = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !node.__noCon tent && dom(node).querySelector(CONTENT);
1536 var wrappedContent = fragContent && TreeApi.Logical.getParentNode(fragContent).n odeType !== Node.DOCUMENT_FRAGMENT_NODE;
1537 var hasContent = fragContent || node.localName === CONTENT;
1538 if (hasContent) {
1539 var root = this.getOwnerRoot();
1540 if (root) {
1541 this._lazyDistribute(root.host);
1542 }
1543 }
1544 var needsDist = this._nodeNeedsDistribution(this.node);
1545 if (needsDist) {
1546 this._lazyDistribute(this.node);
1547 }
1548 return needsDist || hasContent && !wrappedContent;
1549 },
1550 _maybeAddInsertionPoint: function (node, parent) {
1551 var added;
1552 if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE && !node.__noContent) {
1553 var c$ = dom(node).querySelectorAll(CONTENT);
1554 for (var i = 0, n, np, na; i < c$.length && (n = c$[i]); i++) {
1555 np = TreeApi.Logical.getParentNode(n);
1556 if (np === node) {
1557 np = parent;
1558 }
1559 na = this._maybeAddInsertionPoint(n, np);
1560 added = added || na;
1561 }
1562 } else if (node.localName === CONTENT) {
1563 TreeApi.Logical.saveChildNodes(parent);
1564 TreeApi.Logical.saveChildNodes(node);
1565 added = true;
1566 }
1567 return added;
1568 },
1569 _updateInsertionPoints: function (host) {
1570 var i$ = host.shadyRoot._insertionPoints = dom(host.shadyRoot).querySelectorAll( CONTENT);
1571 for (var i = 0, c; i < i$.length; i++) {
1572 c = i$[i];
1573 TreeApi.Logical.saveChildNodes(c);
1574 TreeApi.Logical.saveChildNodes(TreeApi.Logical.getParentNode(c));
1575 }
1576 },
1577 _nodeNeedsDistribution: function (node) {
1578 return node && node.shadyRoot && DomApi.hasInsertionPoint(node.shadyRoot);
1579 },
1580 _addNodeToHost: function (host, node) {
1581 if (host._elementAdd) {
1582 host._elementAdd(node);
1583 }
1584 },
1585 _removeNodeFromHost: function (host, node) {
1586 if (host._elementRemove) {
1587 host._elementRemove(node);
1588 }
1589 },
1590 _removeDistributedChildren: function (root, container) {
1591 var hostNeedsDist;
1592 var ip$ = root._insertionPoints;
1593 for (var i = 0; i < ip$.length; i++) {
1594 var content = ip$[i];
1595 if (this._contains(container, content)) {
1596 var dc$ = dom(content).getDistributedNodes();
1597 for (var j = 0; j < dc$.length; j++) {
1598 hostNeedsDist = true;
1599 var node = dc$[j];
1600 var parent = TreeApi.Composed.getParentNode(node);
1601 if (parent) {
1602 TreeApi.Composed.removeChild(parent, node);
1603 }
1604 }
1605 }
1606 }
1607 return hostNeedsDist;
1608 },
1609 _contains: function (container, node) {
1610 while (node) {
1611 if (node == container) {
1612 return true;
1613 }
1614 node = TreeApi.Logical.getParentNode(node);
1615 }
1616 },
1617 _removeOwnerShadyRoot: function (node) {
1618 if (this._hasCachedOwnerRoot(node)) {
1619 var c$ = TreeApi.Logical.getChildNodes(node);
1620 for (var i = 0, l = c$.length, n; i < l && (n = c$[i]); i++) {
1621 this._removeOwnerShadyRoot(n);
1622 }
1623 }
1624 node._ownerShadyRoot = undefined;
1625 },
1626 _firstComposedNode: function (content) {
1627 var n$ = dom(content).getDistributedNodes();
1628 for (var i = 0, l = n$.length, n, p$; i < l && (n = n$[i]); i++) {
1629 p$ = dom(n).getDestinationInsertionPoints();
1630 if (p$[p$.length - 1] === content) {
1631 return n;
1632 }
1633 }
1634 },
1635 querySelector: function (selector) {
1636 var result = this._query(function (n) {
1637 return DomApi.matchesSelector.call(n, selector);
1638 }, this.node, function (n) {
1639 return Boolean(n);
1640 })[0];
1641 return result || null;
1642 },
1643 querySelectorAll: function (selector) {
1644 return this._query(function (n) {
1645 return DomApi.matchesSelector.call(n, selector);
1646 }, this.node);
1647 },
1648 getDestinationInsertionPoints: function () {
1649 return this.node._destinationInsertionPoints || [];
1650 },
1651 getDistributedNodes: function () {
1652 return this.node._distributedNodes || [];
1653 },
1654 _clear: function () {
1655 while (this.childNodes.length) {
1656 this.removeChild(this.childNodes[0]);
1657 }
1658 },
1659 setAttribute: function (name, value) {
1660 this.node.setAttribute(name, value);
1661 this._maybeDistributeParent();
1662 },
1663 removeAttribute: function (name) {
1664 this.node.removeAttribute(name);
1665 this._maybeDistributeParent();
1666 },
1667 _maybeDistributeParent: function () {
1668 if (this._nodeNeedsDistribution(this.parentNode)) {
1669 this._lazyDistribute(this.parentNode);
1670 return true;
1671 }
1672 },
1673 cloneNode: function (deep) {
1674 var n = nativeCloneNode.call(this.node, false);
1675 if (deep) {
1676 var c$ = this.childNodes;
1677 var d = dom(n);
1678 for (var i = 0, nc; i < c$.length; i++) {
1679 nc = dom(c$[i]).cloneNode(true);
1680 d.appendChild(nc);
1681 }
1682 }
1683 return n;
1684 },
1685 importNode: function (externalNode, deep) {
1686 var doc = this.node instanceof Document ? this.node : this.node.ownerDocument;
1687 var n = nativeImportNode.call(doc, externalNode, false);
1688 if (deep) {
1689 var c$ = TreeApi.Logical.getChildNodes(externalNode);
1690 var d = dom(n);
1691 for (var i = 0, nc; i < c$.length; i++) {
1692 nc = dom(doc).importNode(c$[i], true);
1693 d.appendChild(nc);
1694 }
1695 }
1696 return n;
1697 },
1698 _getComposedInnerHTML: function () {
1699 return getInnerHTML(this.node, true);
1700 }
1701 });
1702 Object.defineProperties(DomApi.prototype, {
1703 activeElement: {
1704 get: function () {
1705 var active = document.activeElement;
1706 if (!active) {
1707 return null;
1708 }
1709 var isShadyRoot = !!this.node._isShadyRoot;
1710 if (this.node !== document) {
1711 if (!isShadyRoot) {
1712 return null;
1713 }
1714 if (this.node.host === active || !this.node.host.contains(active)) {
1715 return null;
1716 }
1717 }
1718 var activeRoot = dom(active).getOwnerRoot();
1719 while (activeRoot && activeRoot !== this.node) {
1720 active = activeRoot.host;
1721 activeRoot = dom(active).getOwnerRoot();
1722 }
1723 if (this.node === document) {
1724 return activeRoot ? null : active;
1725 } else {
1726 return activeRoot === this.node ? active : null;
1727 }
1728 },
1729 configurable: true
1730 },
1731 childNodes: {
1732 get: function () {
1733 var c$ = TreeApi.Logical.getChildNodes(this.node);
1734 return Array.isArray(c$) ? c$ : TreeApi.arrayCopyChildNodes(this.node);
1735 },
1736 configurable: true
1737 },
1738 children: {
1739 get: function () {
1740 if (TreeApi.Logical.hasChildNodes(this.node)) {
1741 return Array.prototype.filter.call(this.childNodes, function (n) {
1742 return n.nodeType === Node.ELEMENT_NODE;
1743 });
1744 } else {
1745 return TreeApi.arrayCopyChildren(this.node);
1746 }
1747 },
1748 configurable: true
1749 },
1750 parentNode: {
1751 get: function () {
1752 return TreeApi.Logical.getParentNode(this.node);
1753 },
1754 configurable: true
1755 },
1756 firstChild: {
1757 get: function () {
1758 return TreeApi.Logical.getFirstChild(this.node);
1759 },
1760 configurable: true
1761 },
1762 lastChild: {
1763 get: function () {
1764 return TreeApi.Logical.getLastChild(this.node);
1765 },
1766 configurable: true
1767 },
1768 nextSibling: {
1769 get: function () {
1770 return TreeApi.Logical.getNextSibling(this.node);
1771 },
1772 configurable: true
1773 },
1774 previousSibling: {
1775 get: function () {
1776 return TreeApi.Logical.getPreviousSibling(this.node);
1777 },
1778 configurable: true
1779 },
1780 firstElementChild: {
1781 get: function () {
1782 return TreeApi.Logical.getFirstElementChild(this.node);
1783 },
1784 configurable: true
1785 },
1786 lastElementChild: {
1787 get: function () {
1788 return TreeApi.Logical.getLastElementChild(this.node);
1789 },
1790 configurable: true
1791 },
1792 nextElementSibling: {
1793 get: function () {
1794 return TreeApi.Logical.getNextElementSibling(this.node);
1795 },
1796 configurable: true
1797 },
1798 previousElementSibling: {
1799 get: function () {
1800 return TreeApi.Logical.getPreviousElementSibling(this.node);
1801 },
1802 configurable: true
1803 },
1804 textContent: {
1805 get: function () {
1806 var nt = this.node.nodeType;
1807 if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) {
1808 return this.node.textContent;
1809 } else {
1810 var tc = [];
1811 for (var i = 0, cn = this.childNodes, c; c = cn[i]; i++) {
1812 if (c.nodeType !== Node.COMMENT_NODE) {
1813 tc.push(c.textContent);
1814 }
1815 }
1816 return tc.join('');
1817 }
1818 },
1819 set: function (text) {
1820 var nt = this.node.nodeType;
1821 if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) {
1822 this.node.textContent = text;
1823 } else {
1824 this._clear();
1825 if (text) {
1826 this.appendChild(document.createTextNode(text));
1827 }
1828 }
1829 },
1830 configurable: true
1831 },
1832 innerHTML: {
1833 get: function () {
1834 var nt = this.node.nodeType;
1835 if (nt === Node.TEXT_NODE || nt === Node.COMMENT_NODE) {
1836 return null;
1837 } else {
1838 return getInnerHTML(this.node);
1839 }
1840 },
1841 set: function (text) {
1842 var nt = this.node.nodeType;
1843 if (nt !== Node.TEXT_NODE || nt !== Node.COMMENT_NODE) {
1844 this._clear();
1845 var d = document.createElement('div');
1846 d.innerHTML = text;
1847 var c$ = TreeApi.arrayCopyChildNodes(d);
1848 for (var i = 0; i < c$.length; i++) {
1849 this.appendChild(c$[i]);
1850 }
1851 }
1852 },
1853 configurable: true
1854 }
1855 });
1856 DomApi.hasInsertionPoint = function (root) {
1857 return Boolean(root && root._insertionPoints.length);
1858 };
1859 }());
1860 (function () {
1861 'use strict';
1862 var Settings = Polymer.Settings;
1863 var TreeApi = Polymer.TreeApi;
1864 var DomApi = Polymer.DomApi;
1865 if (!Settings.useShadow) {
1866 return;
1867 }
1868 Polymer.Base.extend(DomApi.prototype, {
1869 querySelectorAll: function (selector) {
1870 return TreeApi.arrayCopy(this.node.querySelectorAll(selector));
1871 },
1872 getOwnerRoot: function () {
1873 var n = this.node;
1874 while (n) {
1875 if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host) {
1876 return n;
1877 }
1878 n = n.parentNode;
1879 }
1880 },
1881 importNode: function (externalNode, deep) {
1882 var doc = this.node instanceof Document ? this.node : this.node.ownerDocument;
1883 return doc.importNode(externalNode, deep);
1884 },
1885 getDestinationInsertionPoints: function () {
1886 var n$ = this.node.getDestinationInsertionPoints && this.node.getDestinationInse rtionPoints();
1887 return n$ ? TreeApi.arrayCopy(n$) : [];
1888 },
1889 getDistributedNodes: function () {
1890 var n$ = this.node.getDistributedNodes && this.node.getDistributedNodes();
1891 return n$ ? TreeApi.arrayCopy(n$) : [];
1892 }
1893 });
1894 Object.defineProperties(DomApi.prototype, {
1895 activeElement: {
1896 get: function () {
1897 var node = DomApi.wrap(this.node);
1898 var activeElement = node.activeElement;
1899 return node.contains(activeElement) ? activeElement : null;
1900 },
1901 configurable: true
1902 },
1903 childNodes: {
1904 get: function () {
1905 return TreeApi.arrayCopyChildNodes(this.node);
1906 },
1907 configurable: true
1908 },
1909 children: {
1910 get: function () {
1911 return TreeApi.arrayCopyChildren(this.node);
1912 },
1913 configurable: true
1914 },
1915 textContent: {
1916 get: function () {
1917 return this.node.textContent;
1918 },
1919 set: function (value) {
1920 return this.node.textContent = value;
1921 },
1922 configurable: true
1923 },
1924 innerHTML: {
1925 get: function () {
1926 return this.node.innerHTML;
1927 },
1928 set: function (value) {
1929 return this.node.innerHTML = value;
1930 },
1931 configurable: true
1932 }
1933 });
1934 var forwardMethods = function (m$) {
1935 for (var i = 0; i < m$.length; i++) {
1936 forwardMethod(m$[i]);
1937 }
1938 };
1939 var forwardMethod = function (method) {
1940 DomApi.prototype[method] = function () {
1941 return this.node[method].apply(this.node, arguments);
1942 };
1943 };
1944 forwardMethods([
1945 'cloneNode',
1946 'appendChild',
1947 'insertBefore',
1948 'removeChild',
1949 'replaceChild',
1950 'setAttribute',
1951 'removeAttribute',
1952 'querySelector'
1953 ]);
1954 var forwardProperties = function (f$) {
1955 for (var i = 0; i < f$.length; i++) {
1956 forwardProperty(f$[i]);
1957 }
1958 };
1959 var forwardProperty = function (name) {
1960 Object.defineProperty(DomApi.prototype, name, {
1961 get: function () {
1962 return this.node[name];
1963 },
1964 configurable: true
1965 });
1966 };
1967 forwardProperties([
1968 'parentNode',
1969 'firstChild',
1970 'lastChild',
1971 'nextSibling',
1972 'previousSibling',
1973 'firstElementChild',
1974 'lastElementChild',
1975 'nextElementSibling',
1976 'previousElementSibling'
1977 ]);
1978 }());
1979 Polymer.Base.extend(Polymer.dom, {
1980 _flushGuard: 0,
1981 _FLUSH_MAX: 100,
1982 _needsTakeRecords: !Polymer.Settings.useNativeCustomElements,
1983 _debouncers: [],
1984 _staticFlushList: [],
1985 _finishDebouncer: null,
1986 flush: function () {
1987 this._flushGuard = 0;
1988 this._prepareFlush();
1989 while (this._debouncers.length && this._flushGuard < this._FLUSH_MAX) {
1990 while (this._debouncers.length) {
1991 this._debouncers.shift().complete();
1992 }
1993 if (this._finishDebouncer) {
1994 this._finishDebouncer.complete();
1995 }
1996 this._prepareFlush();
1997 this._flushGuard++;
1998 }
1999 if (this._flushGuard >= this._FLUSH_MAX) {
2000 console.warn('Polymer.dom.flush aborted. Flush may not be complete.');
2001 }
2002 },
2003 _prepareFlush: function () {
2004 if (this._needsTakeRecords) {
2005 CustomElements.takeRecords();
2006 }
2007 for (var i = 0; i < this._staticFlushList.length; i++) {
2008 this._staticFlushList[i]();
2009 }
2010 },
2011 addStaticFlush: function (fn) {
2012 this._staticFlushList.push(fn);
2013 },
2014 removeStaticFlush: function (fn) {
2015 var i = this._staticFlushList.indexOf(fn);
2016 if (i >= 0) {
2017 this._staticFlushList.splice(i, 1);
2018 }
2019 },
2020 addDebouncer: function (debouncer) {
2021 this._debouncers.push(debouncer);
2022 this._finishDebouncer = Polymer.Debounce(this._finishDebouncer, this._finishFlus h);
2023 },
2024 _finishFlush: function () {
2025 Polymer.dom._debouncers = [];
2026 }
2027 });
2028 Polymer.EventApi = function () {
2029 'use strict';
2030 var DomApi = Polymer.DomApi.ctor;
2031 var Settings = Polymer.Settings;
2032 DomApi.Event = function (event) {
2033 this.event = event;
2034 };
2035 if (Settings.useShadow) {
2036 DomApi.Event.prototype = {
2037 get rootTarget() {
2038 return this.event.path[0];
2039 },
2040 get localTarget() {
2041 return this.event.target;
2042 },
2043 get path() {
2044 var path = this.event.path;
2045 if (!Array.isArray(path)) {
2046 path = Array.prototype.slice.call(path);
2047 }
2048 return path;
2049 }
2050 };
2051 } else {
2052 DomApi.Event.prototype = {
2053 get rootTarget() {
2054 return this.event.target;
2055 },
2056 get localTarget() {
2057 var current = this.event.currentTarget;
2058 var currentRoot = current && Polymer.dom(current).getOwnerRoot();
2059 var p$ = this.path;
2060 for (var i = 0; i < p$.length; i++) {
2061 if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) {
2062 return p$[i];
2063 }
2064 }
2065 },
2066 get path() {
2067 if (!this.event._path) {
2068 var path = [];
2069 var current = this.rootTarget;
2070 while (current) {
2071 path.push(current);
2072 var insertionPoints = Polymer.dom(current).getDestinationInsertionPoints();
2073 if (insertionPoints.length) {
2074 for (var i = 0; i < insertionPoints.length - 1; i++) {
2075 path.push(insertionPoints[i]);
2076 }
2077 current = insertionPoints[insertionPoints.length - 1];
2078 } else {
2079 current = Polymer.dom(current).parentNode || current.host;
2080 }
2081 }
2082 path.push(window);
2083 this.event._path = path;
2084 }
2085 return this.event._path;
2086 }
2087 };
2088 }
2089 var factory = function (event) {
2090 if (!event.__eventApi) {
2091 event.__eventApi = new DomApi.Event(event);
2092 }
2093 return event.__eventApi;
2094 };
2095 return { factory: factory };
2096 }();
2097 (function () {
2098 'use strict';
2099 var DomApi = Polymer.DomApi.ctor;
2100 var useShadow = Polymer.Settings.useShadow;
2101 Object.defineProperty(DomApi.prototype, 'classList', {
2102 get: function () {
2103 if (!this._classList) {
2104 this._classList = new DomApi.ClassList(this);
2105 }
2106 return this._classList;
2107 },
2108 configurable: true
2109 });
2110 DomApi.ClassList = function (host) {
2111 this.domApi = host;
2112 this.node = host.node;
2113 };
2114 DomApi.ClassList.prototype = {
2115 add: function () {
2116 this.node.classList.add.apply(this.node.classList, arguments);
2117 this._distributeParent();
2118 },
2119 remove: function () {
2120 this.node.classList.remove.apply(this.node.classList, arguments);
2121 this._distributeParent();
2122 },
2123 toggle: function () {
2124 this.node.classList.toggle.apply(this.node.classList, arguments);
2125 this._distributeParent();
2126 },
2127 _distributeParent: function () {
2128 if (!useShadow) {
2129 this.domApi._maybeDistributeParent();
2130 }
2131 },
2132 contains: function () {
2133 return this.node.classList.contains.apply(this.node.classList, arguments);
2134 }
2135 };
2136 }());
2137 (function () {
2138 'use strict';
2139 var DomApi = Polymer.DomApi.ctor;
2140 var Settings = Polymer.Settings;
2141 DomApi.EffectiveNodesObserver = function (domApi) {
2142 this.domApi = domApi;
2143 this.node = this.domApi.node;
2144 this._listeners = [];
2145 };
2146 DomApi.EffectiveNodesObserver.prototype = {
2147 addListener: function (callback) {
2148 if (!this._isSetup) {
2149 this._setup();
2150 this._isSetup = true;
2151 }
2152 var listener = {
2153 fn: callback,
2154 _nodes: []
2155 };
2156 this._listeners.push(listener);
2157 this._scheduleNotify();
2158 return listener;
2159 },
2160 removeListener: function (handle) {
2161 var i = this._listeners.indexOf(handle);
2162 if (i >= 0) {
2163 this._listeners.splice(i, 1);
2164 handle._nodes = [];
2165 }
2166 if (!this._hasListeners()) {
2167 this._cleanup();
2168 this._isSetup = false;
2169 }
2170 },
2171 _setup: function () {
2172 this._observeContentElements(this.domApi.childNodes);
2173 },
2174 _cleanup: function () {
2175 this._unobserveContentElements(this.domApi.childNodes);
2176 },
2177 _hasListeners: function () {
2178 return Boolean(this._listeners.length);
2179 },
2180 _scheduleNotify: function () {
2181 if (this._debouncer) {
2182 this._debouncer.stop();
2183 }
2184 this._debouncer = Polymer.Debounce(this._debouncer, this._notify);
2185 this._debouncer.context = this;
2186 Polymer.dom.addDebouncer(this._debouncer);
2187 },
2188 notify: function () {
2189 if (this._hasListeners()) {
2190 this._scheduleNotify();
2191 }
2192 },
2193 _notify: function () {
2194 this._beforeCallListeners();
2195 this._callListeners();
2196 },
2197 _beforeCallListeners: function () {
2198 this._updateContentElements();
2199 },
2200 _updateContentElements: function () {
2201 this._observeContentElements(this.domApi.childNodes);
2202 },
2203 _observeContentElements: function (elements) {
2204 for (var i = 0, n; i < elements.length && (n = elements[i]); i++) {
2205 if (this._isContent(n)) {
2206 n.__observeNodesMap = n.__observeNodesMap || new WeakMap();
2207 if (!n.__observeNodesMap.has(this)) {
2208 n.__observeNodesMap.set(this, this._observeContent(n));
2209 }
2210 }
2211 }
2212 },
2213 _observeContent: function (content) {
2214 var self = this;
2215 var h = Polymer.dom(content).observeNodes(function () {
2216 self._scheduleNotify();
2217 });
2218 h._avoidChangeCalculation = true;
2219 return h;
2220 },
2221 _unobserveContentElements: function (elements) {
2222 for (var i = 0, n, h; i < elements.length && (n = elements[i]); i++) {
2223 if (this._isContent(n)) {
2224 h = n.__observeNodesMap.get(this);
2225 if (h) {
2226 Polymer.dom(n).unobserveNodes(h);
2227 n.__observeNodesMap.delete(this);
2228 }
2229 }
2230 }
2231 },
2232 _isContent: function (node) {
2233 return node.localName === 'content';
2234 },
2235 _callListeners: function () {
2236 var o$ = this._listeners;
2237 var nodes = this._getEffectiveNodes();
2238 for (var i = 0, o; i < o$.length && (o = o$[i]); i++) {
2239 var info = this._generateListenerInfo(o, nodes);
2240 if (info || o._alwaysNotify) {
2241 this._callListener(o, info);
2242 }
2243 }
2244 },
2245 _getEffectiveNodes: function () {
2246 return this.domApi.getEffectiveChildNodes();
2247 },
2248 _generateListenerInfo: function (listener, newNodes) {
2249 if (listener._avoidChangeCalculation) {
2250 return true;
2251 }
2252 var oldNodes = listener._nodes;
2253 var info = {
2254 target: this.node,
2255 addedNodes: [],
2256 removedNodes: []
2257 };
2258 var splices = Polymer.ArraySplice.calculateSplices(newNodes, oldNodes);
2259 for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
2260 for (var j = 0, n; j < s.removed.length && (n = s.removed[j]); j++) {
2261 info.removedNodes.push(n);
2262 }
2263 }
2264 for (i = 0, s; i < splices.length && (s = splices[i]); i++) {
2265 for (j = s.index; j < s.index + s.addedCount; j++) {
2266 info.addedNodes.push(newNodes[j]);
2267 }
2268 }
2269 listener._nodes = newNodes;
2270 if (info.addedNodes.length || info.removedNodes.length) {
2271 return info;
2272 }
2273 },
2274 _callListener: function (listener, info) {
2275 return listener.fn.call(this.node, info);
2276 },
2277 enableShadowAttributeTracking: function () {
2278 }
2279 };
2280 if (Settings.useShadow) {
2281 var baseSetup = DomApi.EffectiveNodesObserver.prototype._setup;
2282 var baseCleanup = DomApi.EffectiveNodesObserver.prototype._cleanup;
2283 Polymer.Base.extend(DomApi.EffectiveNodesObserver.prototype, {
2284 _setup: function () {
2285 if (!this._observer) {
2286 var self = this;
2287 this._mutationHandler = function (mxns) {
2288 if (mxns && mxns.length) {
2289 self._scheduleNotify();
2290 }
2291 };
2292 this._observer = new MutationObserver(this._mutationHandler);
2293 this._boundFlush = function () {
2294 self._flush();
2295 };
2296 Polymer.dom.addStaticFlush(this._boundFlush);
2297 this._observer.observe(this.node, { childList: true });
2298 }
2299 baseSetup.call(this);
2300 },
2301 _cleanup: function () {
2302 this._observer.disconnect();
2303 this._observer = null;
2304 this._mutationHandler = null;
2305 Polymer.dom.removeStaticFlush(this._boundFlush);
2306 baseCleanup.call(this);
2307 },
2308 _flush: function () {
2309 if (this._observer) {
2310 this._mutationHandler(this._observer.takeRecords());
2311 }
2312 },
2313 enableShadowAttributeTracking: function () {
2314 if (this._observer) {
2315 this._makeContentListenersAlwaysNotify();
2316 this._observer.disconnect();
2317 this._observer.observe(this.node, {
2318 childList: true,
2319 attributes: true,
2320 subtree: true
2321 });
2322 var root = this.domApi.getOwnerRoot();
2323 var host = root && root.host;
2324 if (host && Polymer.dom(host).observer) {
2325 Polymer.dom(host).observer.enableShadowAttributeTracking();
2326 }
2327 }
2328 },
2329 _makeContentListenersAlwaysNotify: function () {
2330 for (var i = 0, h; i < this._listeners.length; i++) {
2331 h = this._listeners[i];
2332 h._alwaysNotify = h._isContentListener;
2333 }
2334 }
2335 });
2336 }
2337 }());
2338 (function () {
2339 'use strict';
2340 var DomApi = Polymer.DomApi.ctor;
2341 var Settings = Polymer.Settings;
2342 DomApi.DistributedNodesObserver = function (domApi) {
2343 DomApi.EffectiveNodesObserver.call(this, domApi);
2344 };
2345 DomApi.DistributedNodesObserver.prototype = Object.create(DomApi.EffectiveNodesO bserver.prototype);
2346 Polymer.Base.extend(DomApi.DistributedNodesObserver.prototype, {
2347 _setup: function () {
2348 },
2349 _cleanup: function () {
2350 },
2351 _beforeCallListeners: function () {
2352 },
2353 _getEffectiveNodes: function () {
2354 return this.domApi.getDistributedNodes();
2355 }
2356 });
2357 if (Settings.useShadow) {
2358 Polymer.Base.extend(DomApi.DistributedNodesObserver.prototype, {
2359 _setup: function () {
2360 if (!this._observer) {
2361 var root = this.domApi.getOwnerRoot();
2362 var host = root && root.host;
2363 if (host) {
2364 var self = this;
2365 this._observer = Polymer.dom(host).observeNodes(function () {
2366 self._scheduleNotify();
2367 });
2368 this._observer._isContentListener = true;
2369 if (this._hasAttrSelect()) {
2370 Polymer.dom(host).observer.enableShadowAttributeTracking();
2371 }
2372 }
2373 }
2374 },
2375 _hasAttrSelect: function () {
2376 var select = this.node.getAttribute('select');
2377 return select && select.match(/[[.]+/);
2378 },
2379 _cleanup: function () {
2380 var root = this.domApi.getOwnerRoot();
2381 var host = root && root.host;
2382 if (host) {
2383 Polymer.dom(host).unobserveNodes(this._observer);
2384 }
2385 this._observer = null;
2386 }
2387 });
2388 }
2389 }());
2390 (function () {
2391 var DomApi = Polymer.DomApi;
2392 var TreeApi = Polymer.TreeApi;
2393 Polymer.Base._addFeature({
2394 _prepShady: function () {
2395 this._useContent = this._useContent || Boolean(this._template);
2396 },
2397 _setupShady: function () {
2398 this.shadyRoot = null;
2399 if (!this.__domApi) {
2400 this.__domApi = null;
2401 }
2402 if (!this.__dom) {
2403 this.__dom = null;
2404 }
2405 if (!this._ownerShadyRoot) {
2406 this._ownerShadyRoot = undefined;
2407 }
2408 },
2409 _poolContent: function () {
2410 if (this._useContent) {
2411 TreeApi.Logical.saveChildNodes(this);
2412 }
2413 },
2414 _setupRoot: function () {
2415 if (this._useContent) {
2416 this._createLocalRoot();
2417 if (!this.dataHost) {
2418 upgradeLogicalChildren(TreeApi.Logical.getChildNodes(this));
2419 }
2420 }
2421 },
2422 _createLocalRoot: function () {
2423 this.shadyRoot = this.root;
2424 this.shadyRoot._distributionClean = false;
2425 this.shadyRoot._hasDistributed = false;
2426 this.shadyRoot._isShadyRoot = true;
2427 this.shadyRoot._dirtyRoots = [];
2428 var i$ = this.shadyRoot._insertionPoints = !this._notes || this._notes._hasConte nt ? this.shadyRoot.querySelectorAll('content') : [];
2429 TreeApi.Logical.saveChildNodes(this.shadyRoot);
2430 for (var i = 0, c; i < i$.length; i++) {
2431 c = i$[i];
2432 TreeApi.Logical.saveChildNodes(c);
2433 TreeApi.Logical.saveChildNodes(c.parentNode);
2434 }
2435 this.shadyRoot.host = this;
2436 },
2437 get domHost() {
2438 var root = Polymer.dom(this).getOwnerRoot();
2439 return root && root.host;
2440 },
2441 distributeContent: function (updateInsertionPoints) {
2442 if (this.shadyRoot) {
2443 this.shadyRoot._invalidInsertionPoints = this.shadyRoot._invalidInsertionPoints || updateInsertionPoints;
2444 var host = getTopDistributingHost(this);
2445 Polymer.dom(this)._lazyDistribute(host);
2446 }
2447 },
2448 _distributeContent: function () {
2449 if (this._useContent && !this.shadyRoot._distributionClean) {
2450 if (this.shadyRoot._invalidInsertionPoints) {
2451 Polymer.dom(this)._updateInsertionPoints(this);
2452 this.shadyRoot._invalidInsertionPoints = false;
2453 }
2454 this._beginDistribute();
2455 this._distributeDirtyRoots();
2456 this._finishDistribute();
2457 }
2458 },
2459 _beginDistribute: function () {
2460 if (this._useContent && DomApi.hasInsertionPoint(this.shadyRoot)) {
2461 this._resetDistribution();
2462 this._distributePool(this.shadyRoot, this._collectPool());
2463 }
2464 },
2465 _distributeDirtyRoots: function () {
2466 var c$ = this.shadyRoot._dirtyRoots;
2467 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
2468 c._distributeContent();
2469 }
2470 this.shadyRoot._dirtyRoots = [];
2471 },
2472 _finishDistribute: function () {
2473 if (this._useContent) {
2474 this.shadyRoot._distributionClean = true;
2475 if (DomApi.hasInsertionPoint(this.shadyRoot)) {
2476 this._composeTree();
2477 notifyContentObservers(this.shadyRoot);
2478 } else {
2479 if (!this.shadyRoot._hasDistributed) {
2480 TreeApi.Composed.clearChildNodes(this);
2481 this.appendChild(this.shadyRoot);
2482 } else {
2483 var children = this._composeNode(this);
2484 this._updateChildNodes(this, children);
2485 }
2486 }
2487 if (!this.shadyRoot._hasDistributed) {
2488 notifyInitialDistribution(this);
2489 }
2490 this.shadyRoot._hasDistributed = true;
2491 }
2492 },
2493 elementMatches: function (selector, node) {
2494 node = node || this;
2495 return DomApi.matchesSelector.call(node, selector);
2496 },
2497 _resetDistribution: function () {
2498 var children = TreeApi.Logical.getChildNodes(this);
2499 for (var i = 0; i < children.length; i++) {
2500 var child = children[i];
2501 if (child._destinationInsertionPoints) {
2502 child._destinationInsertionPoints = undefined;
2503 }
2504 if (isInsertionPoint(child)) {
2505 clearDistributedDestinationInsertionPoints(child);
2506 }
2507 }
2508 var root = this.shadyRoot;
2509 var p$ = root._insertionPoints;
2510 for (var j = 0; j < p$.length; j++) {
2511 p$[j]._distributedNodes = [];
2512 }
2513 },
2514 _collectPool: function () {
2515 var pool = [];
2516 var children = TreeApi.Logical.getChildNodes(this);
2517 for (var i = 0; i < children.length; i++) {
2518 var child = children[i];
2519 if (isInsertionPoint(child)) {
2520 pool.push.apply(pool, child._distributedNodes);
2521 } else {
2522 pool.push(child);
2523 }
2524 }
2525 return pool;
2526 },
2527 _distributePool: function (node, pool) {
2528 var p$ = node._insertionPoints;
2529 for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) {
2530 this._distributeInsertionPoint(p, pool);
2531 maybeRedistributeParent(p, this);
2532 }
2533 },
2534 _distributeInsertionPoint: function (content, pool) {
2535 var anyDistributed = false;
2536 for (var i = 0, l = pool.length, node; i < l; i++) {
2537 node = pool[i];
2538 if (!node) {
2539 continue;
2540 }
2541 if (this._matchesContentSelect(node, content)) {
2542 distributeNodeInto(node, content);
2543 pool[i] = undefined;
2544 anyDistributed = true;
2545 }
2546 }
2547 if (!anyDistributed) {
2548 var children = TreeApi.Logical.getChildNodes(content);
2549 for (var j = 0; j < children.length; j++) {
2550 distributeNodeInto(children[j], content);
2551 }
2552 }
2553 },
2554 _composeTree: function () {
2555 this._updateChildNodes(this, this._composeNode(this));
2556 var p$ = this.shadyRoot._insertionPoints;
2557 for (var i = 0, l = p$.length, p, parent; i < l && (p = p$[i]); i++) {
2558 parent = TreeApi.Logical.getParentNode(p);
2559 if (!parent._useContent && parent !== this && parent !== this.shadyRoot) {
2560 this._updateChildNodes(parent, this._composeNode(parent));
2561 }
2562 }
2563 },
2564 _composeNode: function (node) {
2565 var children = [];
2566 var c$ = TreeApi.Logical.getChildNodes(node.shadyRoot || node);
2567 for (var i = 0; i < c$.length; i++) {
2568 var child = c$[i];
2569 if (isInsertionPoint(child)) {
2570 var distributedNodes = child._distributedNodes;
2571 for (var j = 0; j < distributedNodes.length; j++) {
2572 var distributedNode = distributedNodes[j];
2573 if (isFinalDestination(child, distributedNode)) {
2574 children.push(distributedNode);
2575 }
2576 }
2577 } else {
2578 children.push(child);
2579 }
2580 }
2581 return children;
2582 },
2583 _updateChildNodes: function (container, children) {
2584 var composed = TreeApi.Composed.getChildNodes(container);
2585 var splices = Polymer.ArraySplice.calculateSplices(children, composed);
2586 for (var i = 0, d = 0, s; i < splices.length && (s = splices[i]); i++) {
2587 for (var j = 0, n; j < s.removed.length && (n = s.removed[j]); j++) {
2588 if (TreeApi.Composed.getParentNode(n) === container) {
2589 TreeApi.Composed.removeChild(container, n);
2590 }
2591 composed.splice(s.index + d, 1);
2592 }
2593 d -= s.addedCount;
2594 }
2595 for (var i = 0, s, next; i < splices.length && (s = splices[i]); i++) {
2596 next = composed[s.index];
2597 for (j = s.index, n; j < s.index + s.addedCount; j++) {
2598 n = children[j];
2599 TreeApi.Composed.insertBefore(container, n, next);
2600 composed.splice(j, 0, n);
2601 }
2602 }
2603 },
2604 _matchesContentSelect: function (node, contentElement) {
2605 var select = contentElement.getAttribute('select');
2606 if (!select) {
2607 return true;
2608 }
2609 select = select.trim();
2610 if (!select) {
2611 return true;
2612 }
2613 if (!(node instanceof Element)) {
2614 return false;
2615 }
2616 var validSelectors = /^(:not\()?[*.#[a-zA-Z_|]/;
2617 if (!validSelectors.test(select)) {
2618 return false;
2619 }
2620 return this.elementMatches(select, node);
2621 },
2622 _elementAdd: function () {
2623 },
2624 _elementRemove: function () {
2625 }
2626 });
2627 function distributeNodeInto(child, insertionPoint) {
2628 insertionPoint._distributedNodes.push(child);
2629 var points = child._destinationInsertionPoints;
2630 if (!points) {
2631 child._destinationInsertionPoints = [insertionPoint];
2632 } else {
2633 points.push(insertionPoint);
2634 }
2635 }
2636 function clearDistributedDestinationInsertionPoints(content) {
2637 var e$ = content._distributedNodes;
2638 if (e$) {
2639 for (var i = 0; i < e$.length; i++) {
2640 var d = e$[i]._destinationInsertionPoints;
2641 if (d) {
2642 d.splice(d.indexOf(content) + 1, d.length);
2643 }
2644 }
2645 }
2646 }
2647 function maybeRedistributeParent(content, host) {
2648 var parent = TreeApi.Logical.getParentNode(content);
2649 if (parent && parent.shadyRoot && DomApi.hasInsertionPoint(parent.shadyRoot) && parent.shadyRoot._distributionClean) {
2650 parent.shadyRoot._distributionClean = false;
2651 host.shadyRoot._dirtyRoots.push(parent);
2652 }
2653 }
2654 function isFinalDestination(insertionPoint, node) {
2655 var points = node._destinationInsertionPoints;
2656 return points && points[points.length - 1] === insertionPoint;
2657 }
2658 function isInsertionPoint(node) {
2659 return node.localName == 'content';
2660 }
2661 function getTopDistributingHost(host) {
2662 while (host && hostNeedsRedistribution(host)) {
2663 host = host.domHost;
2664 }
2665 return host;
2666 }
2667 function hostNeedsRedistribution(host) {
2668 var c$ = TreeApi.Logical.getChildNodes(host);
2669 for (var i = 0, c; i < c$.length; i++) {
2670 c = c$[i];
2671 if (c.localName && c.localName === 'content') {
2672 return host.domHost;
2673 }
2674 }
2675 }
2676 function notifyContentObservers(root) {
2677 for (var i = 0, c; i < root._insertionPoints.length; i++) {
2678 c = root._insertionPoints[i];
2679 if (DomApi.hasApi(c)) {
2680 Polymer.dom(c).notifyObserver();
2681 }
2682 }
2683 }
2684 function notifyInitialDistribution(host) {
2685 if (DomApi.hasApi(host)) {
2686 Polymer.dom(host).notifyObserver();
2687 }
2688 }
2689 var needsUpgrade = window.CustomElements && !CustomElements.useNative;
2690 function upgradeLogicalChildren(children) {
2691 if (needsUpgrade && children) {
2692 for (var i = 0; i < children.length; i++) {
2693 CustomElements.upgrade(children[i]);
2694 }
2695 }
2696 }
2697 }());
2698 if (Polymer.Settings.useShadow) {
2699 Polymer.Base._addFeature({
2700 _poolContent: function () {
2701 },
2702 _beginDistribute: function () {
2703 },
2704 distributeContent: function () {
2705 },
2706 _distributeContent: function () {
2707 },
2708 _finishDistribute: function () {
2709 },
2710 _createLocalRoot: function () {
2711 this.createShadowRoot();
2712 this.shadowRoot.appendChild(this.root);
2713 this.root = this.shadowRoot;
2714 }
2715 });
2716 }
2717 Polymer.Async = {
2718 _currVal: 0,
2719 _lastVal: 0,
2720 _callbacks: [],
2721 _twiddleContent: 0,
2722 _twiddle: document.createTextNode(''),
2723 run: function (callback, waitTime) {
2724 if (waitTime > 0) {
2725 return ~setTimeout(callback, waitTime);
2726 } else {
2727 this._twiddle.textContent = this._twiddleContent++;
2728 this._callbacks.push(callback);
2729 return this._currVal++;
2730 }
2731 },
2732 cancel: function (handle) {
2733 if (handle < 0) {
2734 clearTimeout(~handle);
2735 } else {
2736 var idx = handle - this._lastVal;
2737 if (idx >= 0) {
2738 if (!this._callbacks[idx]) {
2739 throw 'invalid async handle: ' + handle;
2740 }
2741 this._callbacks[idx] = null;
2742 }
2743 }
2744 },
2745 _atEndOfMicrotask: function () {
2746 var len = this._callbacks.length;
2747 for (var i = 0; i < len; i++) {
2748 var cb = this._callbacks[i];
2749 if (cb) {
2750 try {
2751 cb();
2752 } catch (e) {
2753 i++;
2754 this._callbacks.splice(0, i);
2755 this._lastVal += i;
2756 this._twiddle.textContent = this._twiddleContent++;
2757 throw e;
2758 }
2759 }
2760 }
2761 this._callbacks.splice(0, len);
2762 this._lastVal += len;
2763 }
2764 };
2765 new window.MutationObserver(function () {
2766 Polymer.Async._atEndOfMicrotask();
2767 }).observe(Polymer.Async._twiddle, { characterData: true });
2768 Polymer.Debounce = function () {
2769 var Async = Polymer.Async;
2770 var Debouncer = function (context) {
2771 this.context = context;
2772 var self = this;
2773 this.boundComplete = function () {
2774 self.complete();
2775 };
2776 };
2777 Debouncer.prototype = {
2778 go: function (callback, wait) {
2779 var h;
2780 this.finish = function () {
2781 Async.cancel(h);
2782 };
2783 h = Async.run(this.boundComplete, wait);
2784 this.callback = callback;
2785 },
2786 stop: function () {
2787 if (this.finish) {
2788 this.finish();
2789 this.finish = null;
2790 }
2791 },
2792 complete: function () {
2793 if (this.finish) {
2794 this.stop();
2795 this.callback.call(this.context);
2796 }
2797 }
2798 };
2799 function debounce(debouncer, callback, wait) {
2800 if (debouncer) {
2801 debouncer.stop();
2802 } else {
2803 debouncer = new Debouncer(this);
2804 }
2805 debouncer.go(callback, wait);
2806 return debouncer;
2807 }
2808 return debounce;
2809 }();
2810 Polymer.Base._addFeature({
2811 _setupDebouncers: function () {
2812 this._debouncers = {};
2813 },
2814 debounce: function (jobName, callback, wait) {
2815 return this._debouncers[jobName] = Polymer.Debounce.call(this, this._debouncers[ jobName], callback, wait);
2816 },
2817 isDebouncerActive: function (jobName) {
2818 var debouncer = this._debouncers[jobName];
2819 return !!(debouncer && debouncer.finish);
2820 },
2821 flushDebouncer: function (jobName) {
2822 var debouncer = this._debouncers[jobName];
2823 if (debouncer) {
2824 debouncer.complete();
2825 }
2826 },
2827 cancelDebouncer: function (jobName) {
2828 var debouncer = this._debouncers[jobName];
2829 if (debouncer) {
2830 debouncer.stop();
2831 }
2832 }
2833 });
2834 Polymer.DomModule = document.createElement('dom-module');
2835 Polymer.Base._addFeature({
2836 _registerFeatures: function () {
2837 this._prepIs();
2838 this._prepBehaviors();
2839 this._prepConstructor();
2840 this._prepTemplate();
2841 this._prepShady();
2842 this._prepPropertyInfo();
2843 },
2844 _prepBehavior: function (b) {
2845 this._addHostAttributes(b.hostAttributes);
2846 },
2847 _initFeatures: function () {
2848 this._registerHost();
2849 if (this._template) {
2850 this._poolContent();
2851 this._beginHosting();
2852 this._stampTemplate();
2853 this._endHosting();
2854 }
2855 this._marshalHostAttributes();
2856 this._setupDebouncers();
2857 this._marshalBehaviors();
2858 this._tryReady();
2859 },
2860 _marshalBehavior: function (b) {
2861 }
2862 });</script><script>Polymer.nar = [];
2863 Polymer.Annotations = {
2864 parseAnnotations: function (template) {
2865 var list = [];
2866 var content = template._content || template.content;
2867 this._parseNodeAnnotations(content, list, template.hasAttribute('strip-whitespac e'));
2868 return list;
2869 },
2870 _parseNodeAnnotations: function (node, list, stripWhiteSpace) {
2871 return node.nodeType === Node.TEXT_NODE ? this._parseTextNodeAnnotation(node, li st) : this._parseElementAnnotations(node, list, stripWhiteSpace);
2872 },
2873 _bindingRegex: function () {
2874 var IDENT = '(?:' + '[a-zA-Z_$][\\w.:$\\-*]*' + ')';
2875 var NUMBER = '(?:' + '[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?' + ')';
2876 var SQUOTE_STRING = '(?:' + '\'(?:[^\'\\\\]|\\\\.)*\'' + ')';
2877 var DQUOTE_STRING = '(?:' + '"(?:[^"\\\\]|\\\\.)*"' + ')';
2878 var STRING = '(?:' + SQUOTE_STRING + '|' + DQUOTE_STRING + ')';
2879 var ARGUMENT = '(?:' + IDENT + '|' + NUMBER + '|' + STRING + '\\s*' + ')';
2880 var ARGUMENTS = '(?:' + ARGUMENT + '(?:,\\s*' + ARGUMENT + ')*' + ')';
2881 var ARGUMENT_LIST = '(?:' + '\\(\\s*' + '(?:' + ARGUMENTS + '?' + ')' + '\\)\\s* ' + ')';
2882 var BINDING = '(' + IDENT + '\\s*' + ARGUMENT_LIST + '?' + ')';
2883 var OPEN_BRACKET = '(\\[\\[|{{)' + '\\s*';
2884 var CLOSE_BRACKET = '(?:]]|}})';
2885 var NEGATE = '(?:(!)\\s*)?';
2886 var EXPRESSION = OPEN_BRACKET + NEGATE + BINDING + CLOSE_BRACKET;
2887 return new RegExp(EXPRESSION, 'g');
2888 }(),
2889 _parseBindings: function (text) {
2890 var re = this._bindingRegex;
2891 var parts = [];
2892 var lastIndex = 0;
2893 var m;
2894 while ((m = re.exec(text)) !== null) {
2895 if (m.index > lastIndex) {
2896 parts.push({ literal: text.slice(lastIndex, m.index) });
2897 }
2898 var mode = m[1][0];
2899 var negate = Boolean(m[2]);
2900 var value = m[3].trim();
2901 var customEvent, notifyEvent, colon;
2902 if (mode == '{' && (colon = value.indexOf('::')) > 0) {
2903 notifyEvent = value.substring(colon + 2);
2904 value = value.substring(0, colon);
2905 customEvent = true;
2906 }
2907 parts.push({
2908 compoundIndex: parts.length,
2909 value: value,
2910 mode: mode,
2911 negate: negate,
2912 event: notifyEvent,
2913 customEvent: customEvent
2914 });
2915 lastIndex = re.lastIndex;
2916 }
2917 if (lastIndex && lastIndex < text.length) {
2918 var literal = text.substring(lastIndex);
2919 if (literal) {
2920 parts.push({ literal: literal });
2921 }
2922 }
2923 if (parts.length) {
2924 return parts;
2925 }
2926 },
2927 _literalFromParts: function (parts) {
2928 var s = '';
2929 for (var i = 0; i < parts.length; i++) {
2930 var literal = parts[i].literal;
2931 s += literal || '';
2932 }
2933 return s;
2934 },
2935 _parseTextNodeAnnotation: function (node, list) {
2936 var parts = this._parseBindings(node.textContent);
2937 if (parts) {
2938 node.textContent = this._literalFromParts(parts) || ' ';
2939 var annote = {
2940 bindings: [{
2941 kind: 'text',
2942 name: 'textContent',
2943 parts: parts,
2944 isCompound: parts.length !== 1
2945 }]
2946 };
2947 list.push(annote);
2948 return annote;
2949 }
2950 },
2951 _parseElementAnnotations: function (element, list, stripWhiteSpace) {
2952 var annote = {
2953 bindings: [],
2954 events: []
2955 };
2956 if (element.localName === 'content') {
2957 list._hasContent = true;
2958 }
2959 this._parseChildNodesAnnotations(element, annote, list, stripWhiteSpace);
2960 if (element.attributes) {
2961 this._parseNodeAttributeAnnotations(element, annote, list);
2962 if (this.prepElement) {
2963 this.prepElement(element);
2964 }
2965 }
2966 if (annote.bindings.length || annote.events.length || annote.id) {
2967 list.push(annote);
2968 }
2969 return annote;
2970 },
2971 _parseChildNodesAnnotations: function (root, annote, list, stripWhiteSpace) {
2972 if (root.firstChild) {
2973 var node = root.firstChild;
2974 var i = 0;
2975 while (node) {
2976 var next = node.nextSibling;
2977 if (node.localName === 'template' && !node.hasAttribute('preserve-content')) {
2978 this._parseTemplate(node, i, list, annote);
2979 }
2980 if (node.nodeType === Node.TEXT_NODE) {
2981 var n = next;
2982 while (n && n.nodeType === Node.TEXT_NODE) {
2983 node.textContent += n.textContent;
2984 next = n.nextSibling;
2985 root.removeChild(n);
2986 n = next;
2987 }
2988 if (stripWhiteSpace && !node.textContent.trim()) {
2989 root.removeChild(node);
2990 i--;
2991 }
2992 }
2993 if (node.parentNode) {
2994 var childAnnotation = this._parseNodeAnnotations(node, list, stripWhiteSpace);
2995 if (childAnnotation) {
2996 childAnnotation.parent = annote;
2997 childAnnotation.index = i;
2998 }
2999 }
3000 node = next;
3001 i++;
3002 }
3003 }
3004 },
3005 _parseTemplate: function (node, index, list, parent) {
3006 var content = document.createDocumentFragment();
3007 content._notes = this.parseAnnotations(node);
3008 content.appendChild(node.content);
3009 list.push({
3010 bindings: Polymer.nar,
3011 events: Polymer.nar,
3012 templateContent: content,
3013 parent: parent,
3014 index: index
3015 });
3016 },
3017 _parseNodeAttributeAnnotations: function (node, annotation) {
3018 var attrs = Array.prototype.slice.call(node.attributes);
3019 for (var i = attrs.length - 1, a; a = attrs[i]; i--) {
3020 var n = a.name;
3021 var v = a.value;
3022 var b;
3023 if (n.slice(0, 3) === 'on-') {
3024 node.removeAttribute(n);
3025 annotation.events.push({
3026 name: n.slice(3),
3027 value: v
3028 });
3029 } else if (b = this._parseNodeAttributeAnnotation(node, n, v)) {
3030 annotation.bindings.push(b);
3031 } else if (n === 'id') {
3032 annotation.id = v;
3033 }
3034 }
3035 },
3036 _parseNodeAttributeAnnotation: function (node, name, value) {
3037 var parts = this._parseBindings(value);
3038 if (parts) {
3039 var origName = name;
3040 var kind = 'property';
3041 if (name[name.length - 1] == '$') {
3042 name = name.slice(0, -1);
3043 kind = 'attribute';
3044 }
3045 var literal = this._literalFromParts(parts);
3046 if (literal && kind == 'attribute') {
3047 node.setAttribute(name, literal);
3048 }
3049 if (node.localName === 'input' && origName === 'value') {
3050 node.setAttribute(origName, '');
3051 }
3052 node.removeAttribute(origName);
3053 var propertyName = Polymer.CaseMap.dashToCamelCase(name);
3054 if (kind === 'property') {
3055 name = propertyName;
3056 }
3057 return {
3058 kind: kind,
3059 name: name,
3060 propertyName: propertyName,
3061 parts: parts,
3062 literal: literal,
3063 isCompound: parts.length !== 1
3064 };
3065 }
3066 },
3067 findAnnotatedNode: function (root, annote) {
3068 var parent = annote.parent && Polymer.Annotations.findAnnotatedNode(root, annote .parent);
3069 if (parent) {
3070 for (var n = parent.firstChild, i = 0; n; n = n.nextSibling) {
3071 if (annote.index === i++) {
3072 return n;
3073 }
3074 }
3075 } else {
3076 return root;
3077 }
3078 }
3079 };
3080 (function () {
3081 function resolveCss(cssText, ownerDocument) {
3082 return cssText.replace(CSS_URL_RX, function (m, pre, url, post) {
3083 return pre + '\'' + resolve(url.replace(/["']/g, ''), ownerDocument) + '\'' + po st;
3084 });
3085 }
3086 function resolveAttrs(element, ownerDocument) {
3087 for (var name in URL_ATTRS) {
3088 var a$ = URL_ATTRS[name];
3089 for (var i = 0, l = a$.length, a, at, v; i < l && (a = a$[i]); i++) {
3090 if (name === '*' || element.localName === name) {
3091 at = element.attributes[a];
3092 v = at && at.value;
3093 if (v && v.search(BINDING_RX) < 0) {
3094 at.value = a === 'style' ? resolveCss(v, ownerDocument) : resolve(v, ownerDocume nt);
3095 }
3096 }
3097 }
3098 }
3099 }
3100 function resolve(url, ownerDocument) {
3101 if (url && url[0] === '#') {
3102 return url;
3103 }
3104 var resolver = getUrlResolver(ownerDocument);
3105 resolver.href = url;
3106 return resolver.href || url;
3107 }
3108 var tempDoc;
3109 var tempDocBase;
3110 function resolveUrl(url, baseUri) {
3111 if (!tempDoc) {
3112 tempDoc = document.implementation.createHTMLDocument('temp');
3113 tempDocBase = tempDoc.createElement('base');
3114 tempDoc.head.appendChild(tempDocBase);
3115 }
3116 tempDocBase.href = baseUri;
3117 return resolve(url, tempDoc);
3118 }
3119 function getUrlResolver(ownerDocument) {
3120 return ownerDocument.__urlResolver || (ownerDocument.__urlResolver = ownerDocume nt.createElement('a'));
3121 }
3122 var CSS_URL_RX = /(url\()([^)]*)(\))/g;
3123 var URL_ATTRS = {
3124 '*': [
3125 'href',
3126 'src',
3127 'style',
3128 'url'
3129 ],
3130 form: ['action']
3131 };
3132 var BINDING_RX = /\{\{|\[\[/;
3133 Polymer.ResolveUrl = {
3134 resolveCss: resolveCss,
3135 resolveAttrs: resolveAttrs,
3136 resolveUrl: resolveUrl
3137 };
3138 }());
3139 Polymer.Base._addFeature({
3140 _prepAnnotations: function () {
3141 if (!this._template) {
3142 this._notes = [];
3143 } else {
3144 var self = this;
3145 Polymer.Annotations.prepElement = function (element) {
3146 self._prepElement(element);
3147 };
3148 if (this._template._content && this._template._content._notes) {
3149 this._notes = this._template._content._notes;
3150 } else {
3151 this._notes = Polymer.Annotations.parseAnnotations(this._template);
3152 this._processAnnotations(this._notes);
3153 }
3154 Polymer.Annotations.prepElement = null;
3155 }
3156 },
3157 _processAnnotations: function (notes) {
3158 for (var i = 0; i < notes.length; i++) {
3159 var note = notes[i];
3160 for (var j = 0; j < note.bindings.length; j++) {
3161 var b = note.bindings[j];
3162 for (var k = 0; k < b.parts.length; k++) {
3163 var p = b.parts[k];
3164 if (!p.literal) {
3165 var signature = this._parseMethod(p.value);
3166 if (signature) {
3167 p.signature = signature;
3168 } else {
3169 p.model = this._modelForPath(p.value);
3170 }
3171 }
3172 }
3173 }
3174 if (note.templateContent) {
3175 this._processAnnotations(note.templateContent._notes);
3176 var pp = note.templateContent._parentProps = this._discoverTemplateParentProps(n ote.templateContent._notes);
3177 var bindings = [];
3178 for (var prop in pp) {
3179 bindings.push({
3180 index: note.index,
3181 kind: 'property',
3182 name: '_parent_' + prop,
3183 parts: [{
3184 mode: '{',
3185 model: prop,
3186 value: prop
3187 }]
3188 });
3189 }
3190 note.bindings = note.bindings.concat(bindings);
3191 }
3192 }
3193 },
3194 _discoverTemplateParentProps: function (notes) {
3195 var pp = {};
3196 for (var i = 0, n; i < notes.length && (n = notes[i]); i++) {
3197 for (var j = 0, b$ = n.bindings, b; j < b$.length && (b = b$[j]); j++) {
3198 for (var k = 0, p$ = b.parts, p; k < p$.length && (p = p$[k]); k++) {
3199 if (p.signature) {
3200 var args = p.signature.args;
3201 for (var kk = 0; kk < args.length; kk++) {
3202 var model = args[kk].model;
3203 if (model) {
3204 pp[model] = true;
3205 }
3206 }
3207 } else {
3208 if (p.model) {
3209 pp[p.model] = true;
3210 }
3211 }
3212 }
3213 }
3214 if (n.templateContent) {
3215 var tpp = n.templateContent._parentProps;
3216 Polymer.Base.mixin(pp, tpp);
3217 }
3218 }
3219 return pp;
3220 },
3221 _prepElement: function (element) {
3222 Polymer.ResolveUrl.resolveAttrs(element, this._template.ownerDocument);
3223 },
3224 _findAnnotatedNode: Polymer.Annotations.findAnnotatedNode,
3225 _marshalAnnotationReferences: function () {
3226 if (this._template) {
3227 this._marshalIdNodes();
3228 this._marshalAnnotatedNodes();
3229 this._marshalAnnotatedListeners();
3230 }
3231 },
3232 _configureAnnotationReferences: function () {
3233 var notes = this._notes;
3234 var nodes = this._nodes;
3235 for (var i = 0; i < notes.length; i++) {
3236 var note = notes[i];
3237 var node = nodes[i];
3238 this._configureTemplateContent(note, node);
3239 this._configureCompoundBindings(note, node);
3240 }
3241 },
3242 _configureTemplateContent: function (note, node) {
3243 if (note.templateContent) {
3244 node._content = note.templateContent;
3245 }
3246 },
3247 _configureCompoundBindings: function (note, node) {
3248 var bindings = note.bindings;
3249 for (var i = 0; i < bindings.length; i++) {
3250 var binding = bindings[i];
3251 if (binding.isCompound) {
3252 var storage = node.__compoundStorage__ || (node.__compoundStorage__ = {});
3253 var parts = binding.parts;
3254 var literals = new Array(parts.length);
3255 for (var j = 0; j < parts.length; j++) {
3256 literals[j] = parts[j].literal;
3257 }
3258 var name = binding.name;
3259 storage[name] = literals;
3260 if (binding.literal && binding.kind == 'property') {
3261 if (node._configValue) {
3262 node._configValue(name, binding.literal);
3263 } else {
3264 node[name] = binding.literal;
3265 }
3266 }
3267 }
3268 }
3269 },
3270 _marshalIdNodes: function () {
3271 this.$ = {};
3272 for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) {
3273 if (a.id) {
3274 this.$[a.id] = this._findAnnotatedNode(this.root, a);
3275 }
3276 }
3277 },
3278 _marshalAnnotatedNodes: function () {
3279 if (this._notes && this._notes.length) {
3280 var r = new Array(this._notes.length);
3281 for (var i = 0; i < this._notes.length; i++) {
3282 r[i] = this._findAnnotatedNode(this.root, this._notes[i]);
3283 }
3284 this._nodes = r;
3285 }
3286 },
3287 _marshalAnnotatedListeners: function () {
3288 for (var i = 0, l = this._notes.length, a; i < l && (a = this._notes[i]); i++) {
3289 if (a.events && a.events.length) {
3290 var node = this._findAnnotatedNode(this.root, a);
3291 for (var j = 0, e$ = a.events, e; j < e$.length && (e = e$[j]); j++) {
3292 this.listen(node, e.name, e.value);
3293 }
3294 }
3295 }
3296 }
3297 });
3298 Polymer.Base._addFeature({
3299 listeners: {},
3300 _listenListeners: function (listeners) {
3301 var node, name, eventName;
3302 for (eventName in listeners) {
3303 if (eventName.indexOf('.') < 0) {
3304 node = this;
3305 name = eventName;
3306 } else {
3307 name = eventName.split('.');
3308 node = this.$[name[0]];
3309 name = name[1];
3310 }
3311 this.listen(node, name, listeners[eventName]);
3312 }
3313 },
3314 listen: function (node, eventName, methodName) {
3315 var handler = this._recallEventHandler(this, eventName, node, methodName);
3316 if (!handler) {
3317 handler = this._createEventHandler(node, eventName, methodName);
3318 }
3319 if (handler._listening) {
3320 return;
3321 }
3322 this._listen(node, eventName, handler);
3323 handler._listening = true;
3324 },
3325 _boundListenerKey: function (eventName, methodName) {
3326 return eventName + ':' + methodName;
3327 },
3328 _recordEventHandler: function (host, eventName, target, methodName, handler) {
3329 var hbl = host.__boundListeners;
3330 if (!hbl) {
3331 hbl = host.__boundListeners = new WeakMap();
3332 }
3333 var bl = hbl.get(target);
3334 if (!bl) {
3335 bl = {};
3336 hbl.set(target, bl);
3337 }
3338 var key = this._boundListenerKey(eventName, methodName);
3339 bl[key] = handler;
3340 },
3341 _recallEventHandler: function (host, eventName, target, methodName) {
3342 var hbl = host.__boundListeners;
3343 if (!hbl) {
3344 return;
3345 }
3346 var bl = hbl.get(target);
3347 if (!bl) {
3348 return;
3349 }
3350 var key = this._boundListenerKey(eventName, methodName);
3351 return bl[key];
3352 },
3353 _createEventHandler: function (node, eventName, methodName) {
3354 var host = this;
3355 var handler = function (e) {
3356 if (host[methodName]) {
3357 host[methodName](e, e.detail);
3358 } else {
3359 host._warn(host._logf('_createEventHandler', 'listener method `' + methodName + '` not defined'));
3360 }
3361 };
3362 handler._listening = false;
3363 this._recordEventHandler(host, eventName, node, methodName, handler);
3364 return handler;
3365 },
3366 unlisten: function (node, eventName, methodName) {
3367 var handler = this._recallEventHandler(this, eventName, node, methodName);
3368 if (handler) {
3369 this._unlisten(node, eventName, handler);
3370 handler._listening = false;
3371 }
3372 },
3373 _listen: function (node, eventName, handler) {
3374 node.addEventListener(eventName, handler);
3375 },
3376 _unlisten: function (node, eventName, handler) {
3377 node.removeEventListener(eventName, handler);
3378 }
3379 });
3380 (function () {
3381 'use strict';
3382 var wrap = Polymer.DomApi.wrap;
3383 var HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string';
3384 var GESTURE_KEY = '__polymerGestures';
3385 var HANDLED_OBJ = '__polymerGesturesHandled';
3386 var TOUCH_ACTION = '__polymerGesturesTouchAction';
3387 var TAP_DISTANCE = 25;
3388 var TRACK_DISTANCE = 5;
3389 var TRACK_LENGTH = 2;
3390 var MOUSE_TIMEOUT = 2500;
3391 var MOUSE_EVENTS = [
3392 'mousedown',
3393 'mousemove',
3394 'mouseup',
3395 'click'
3396 ];
3397 var MOUSE_WHICH_TO_BUTTONS = [
3398 0,
3399 1,
3400 4,
3401 2
3402 ];
3403 var MOUSE_HAS_BUTTONS = function () {
3404 try {
3405 return new MouseEvent('test', { buttons: 1 }).buttons === 1;
3406 } catch (e) {
3407 return false;
3408 }
3409 }();
3410 var IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);
3411 var mouseCanceller = function (mouseEvent) {
3412 mouseEvent[HANDLED_OBJ] = { skip: true };
3413 if (mouseEvent.type === 'click') {
3414 var path = Polymer.dom(mouseEvent).path;
3415 for (var i = 0; i < path.length; i++) {
3416 if (path[i] === POINTERSTATE.mouse.target) {
3417 return;
3418 }
3419 }
3420 mouseEvent.preventDefault();
3421 mouseEvent.stopPropagation();
3422 }
3423 };
3424 function setupTeardownMouseCanceller(setup) {
3425 for (var i = 0, en; i < MOUSE_EVENTS.length; i++) {
3426 en = MOUSE_EVENTS[i];
3427 if (setup) {
3428 document.addEventListener(en, mouseCanceller, true);
3429 } else {
3430 document.removeEventListener(en, mouseCanceller, true);
3431 }
3432 }
3433 }
3434 function ignoreMouse() {
3435 if (IS_TOUCH_ONLY) {
3436 return;
3437 }
3438 if (!POINTERSTATE.mouse.mouseIgnoreJob) {
3439 setupTeardownMouseCanceller(true);
3440 }
3441 var unset = function () {
3442 setupTeardownMouseCanceller();
3443 POINTERSTATE.mouse.target = null;
3444 POINTERSTATE.mouse.mouseIgnoreJob = null;
3445 };
3446 POINTERSTATE.mouse.mouseIgnoreJob = Polymer.Debounce(POINTERSTATE.mouse.mouseIgn oreJob, unset, MOUSE_TIMEOUT);
3447 }
3448 function hasLeftMouseButton(ev) {
3449 var type = ev.type;
3450 if (MOUSE_EVENTS.indexOf(type) === -1) {
3451 return false;
3452 }
3453 if (type === 'mousemove') {
3454 var buttons = ev.buttons === undefined ? 1 : ev.buttons;
3455 if (ev instanceof window.MouseEvent && !MOUSE_HAS_BUTTONS) {
3456 buttons = MOUSE_WHICH_TO_BUTTONS[ev.which] || 0;
3457 }
3458 return Boolean(buttons & 1);
3459 } else {
3460 var button = ev.button === undefined ? 0 : ev.button;
3461 return button === 0;
3462 }
3463 }
3464 function isSyntheticClick(ev) {
3465 if (ev.type === 'click') {
3466 if (ev.detail === 0) {
3467 return true;
3468 }
3469 var t = Gestures.findOriginalTarget(ev);
3470 var bcr = t.getBoundingClientRect();
3471 var x = ev.pageX, y = ev.pageY;
3472 return !(x >= bcr.left && x <= bcr.right && (y >= bcr.top && y <= bcr.bottom));
3473 }
3474 return false;
3475 }
3476 var POINTERSTATE = {
3477 mouse: {
3478 target: null,
3479 mouseIgnoreJob: null
3480 },
3481 touch: {
3482 x: 0,
3483 y: 0,
3484 id: -1,
3485 scrollDecided: false
3486 }
3487 };
3488 function firstTouchAction(ev) {
3489 var path = Polymer.dom(ev).path;
3490 var ta = 'auto';
3491 for (var i = 0, n; i < path.length; i++) {
3492 n = path[i];
3493 if (n[TOUCH_ACTION]) {
3494 ta = n[TOUCH_ACTION];
3495 break;
3496 }
3497 }
3498 return ta;
3499 }
3500 function trackDocument(stateObj, movefn, upfn) {
3501 stateObj.movefn = movefn;
3502 stateObj.upfn = upfn;
3503 document.addEventListener('mousemove', movefn);
3504 document.addEventListener('mouseup', upfn);
3505 }
3506 function untrackDocument(stateObj) {
3507 document.removeEventListener('mousemove', stateObj.movefn);
3508 document.removeEventListener('mouseup', stateObj.upfn);
3509 stateObj.movefn = null;
3510 stateObj.upfn = null;
3511 }
3512 var Gestures = {
3513 gestures: {},
3514 recognizers: [],
3515 deepTargetFind: function (x, y) {
3516 var node = document.elementFromPoint(x, y);
3517 var next = node;
3518 while (next && next.shadowRoot) {
3519 next = next.shadowRoot.elementFromPoint(x, y);
3520 if (next) {
3521 node = next;
3522 }
3523 }
3524 return node;
3525 },
3526 findOriginalTarget: function (ev) {
3527 if (ev.path) {
3528 return ev.path[0];
3529 }
3530 return ev.target;
3531 },
3532 handleNative: function (ev) {
3533 var handled;
3534 var type = ev.type;
3535 var node = wrap(ev.currentTarget);
3536 var gobj = node[GESTURE_KEY];
3537 if (!gobj) {
3538 return;
3539 }
3540 var gs = gobj[type];
3541 if (!gs) {
3542 return;
3543 }
3544 if (!ev[HANDLED_OBJ]) {
3545 ev[HANDLED_OBJ] = {};
3546 if (type.slice(0, 5) === 'touch') {
3547 var t = ev.changedTouches[0];
3548 if (type === 'touchstart') {
3549 if (ev.touches.length === 1) {
3550 POINTERSTATE.touch.id = t.identifier;
3551 }
3552 }
3553 if (POINTERSTATE.touch.id !== t.identifier) {
3554 return;
3555 }
3556 if (!HAS_NATIVE_TA) {
3557 if (type === 'touchstart' || type === 'touchmove') {
3558 Gestures.handleTouchAction(ev);
3559 }
3560 }
3561 if (type === 'touchend' && !ev.__polymerSimulatedTouch) {
3562 POINTERSTATE.mouse.target = Polymer.dom(ev).rootTarget;
3563 ignoreMouse(true);
3564 }
3565 }
3566 }
3567 handled = ev[HANDLED_OBJ];
3568 if (handled.skip) {
3569 return;
3570 }
3571 var recognizers = Gestures.recognizers;
3572 for (var i = 0, r; i < recognizers.length; i++) {
3573 r = recognizers[i];
3574 if (gs[r.name] && !handled[r.name]) {
3575 if (r.flow && r.flow.start.indexOf(ev.type) > -1 && r.reset) {
3576 r.reset();
3577 }
3578 }
3579 }
3580 for (i = 0, r; i < recognizers.length; i++) {
3581 r = recognizers[i];
3582 if (gs[r.name] && !handled[r.name]) {
3583 handled[r.name] = true;
3584 r[type](ev);
3585 }
3586 }
3587 },
3588 handleTouchAction: function (ev) {
3589 var t = ev.changedTouches[0];
3590 var type = ev.type;
3591 if (type === 'touchstart') {
3592 POINTERSTATE.touch.x = t.clientX;
3593 POINTERSTATE.touch.y = t.clientY;
3594 POINTERSTATE.touch.scrollDecided = false;
3595 } else if (type === 'touchmove') {
3596 if (POINTERSTATE.touch.scrollDecided) {
3597 return;
3598 }
3599 POINTERSTATE.touch.scrollDecided = true;
3600 var ta = firstTouchAction(ev);
3601 var prevent = false;
3602 var dx = Math.abs(POINTERSTATE.touch.x - t.clientX);
3603 var dy = Math.abs(POINTERSTATE.touch.y - t.clientY);
3604 if (!ev.cancelable) {
3605 } else if (ta === 'none') {
3606 prevent = true;
3607 } else if (ta === 'pan-x') {
3608 prevent = dy > dx;
3609 } else if (ta === 'pan-y') {
3610 prevent = dx > dy;
3611 }
3612 if (prevent) {
3613 ev.preventDefault();
3614 } else {
3615 Gestures.prevent('track');
3616 }
3617 }
3618 },
3619 add: function (node, evType, handler) {
3620 node = wrap(node);
3621 var recognizer = this.gestures[evType];
3622 var deps = recognizer.deps;
3623 var name = recognizer.name;
3624 var gobj = node[GESTURE_KEY];
3625 if (!gobj) {
3626 node[GESTURE_KEY] = gobj = {};
3627 }
3628 for (var i = 0, dep, gd; i < deps.length; i++) {
3629 dep = deps[i];
3630 if (IS_TOUCH_ONLY && MOUSE_EVENTS.indexOf(dep) > -1) {
3631 continue;
3632 }
3633 gd = gobj[dep];
3634 if (!gd) {
3635 gobj[dep] = gd = { _count: 0 };
3636 }
3637 if (gd._count === 0) {
3638 node.addEventListener(dep, this.handleNative);
3639 }
3640 gd[name] = (gd[name] || 0) + 1;
3641 gd._count = (gd._count || 0) + 1;
3642 }
3643 node.addEventListener(evType, handler);
3644 if (recognizer.touchAction) {
3645 this.setTouchAction(node, recognizer.touchAction);
3646 }
3647 },
3648 remove: function (node, evType, handler) {
3649 node = wrap(node);
3650 var recognizer = this.gestures[evType];
3651 var deps = recognizer.deps;
3652 var name = recognizer.name;
3653 var gobj = node[GESTURE_KEY];
3654 if (gobj) {
3655 for (var i = 0, dep, gd; i < deps.length; i++) {
3656 dep = deps[i];
3657 gd = gobj[dep];
3658 if (gd && gd[name]) {
3659 gd[name] = (gd[name] || 1) - 1;
3660 gd._count = (gd._count || 1) - 1;
3661 if (gd._count === 0) {
3662 node.removeEventListener(dep, this.handleNative);
3663 }
3664 }
3665 }
3666 }
3667 node.removeEventListener(evType, handler);
3668 },
3669 register: function (recog) {
3670 this.recognizers.push(recog);
3671 for (var i = 0; i < recog.emits.length; i++) {
3672 this.gestures[recog.emits[i]] = recog;
3673 }
3674 },
3675 findRecognizerByEvent: function (evName) {
3676 for (var i = 0, r; i < this.recognizers.length; i++) {
3677 r = this.recognizers[i];
3678 for (var j = 0, n; j < r.emits.length; j++) {
3679 n = r.emits[j];
3680 if (n === evName) {
3681 return r;
3682 }
3683 }
3684 }
3685 return null;
3686 },
3687 setTouchAction: function (node, value) {
3688 if (HAS_NATIVE_TA) {
3689 node.style.touchAction = value;
3690 }
3691 node[TOUCH_ACTION] = value;
3692 },
3693 fire: function (target, type, detail) {
3694 var ev = Polymer.Base.fire(type, detail, {
3695 node: target,
3696 bubbles: true,
3697 cancelable: true
3698 });
3699 if (ev.defaultPrevented) {
3700 var se = detail.sourceEvent;
3701 if (se && se.preventDefault) {
3702 se.preventDefault();
3703 }
3704 }
3705 },
3706 prevent: function (evName) {
3707 var recognizer = this.findRecognizerByEvent(evName);
3708 if (recognizer.info) {
3709 recognizer.info.prevent = true;
3710 }
3711 }
3712 };
3713 Gestures.register({
3714 name: 'downup',
3715 deps: [
3716 'mousedown',
3717 'touchstart',
3718 'touchend'
3719 ],
3720 flow: {
3721 start: [
3722 'mousedown',
3723 'touchstart'
3724 ],
3725 end: [
3726 'mouseup',
3727 'touchend'
3728 ]
3729 },
3730 emits: [
3731 'down',
3732 'up'
3733 ],
3734 info: {
3735 movefn: null,
3736 upfn: null
3737 },
3738 reset: function () {
3739 untrackDocument(this.info);
3740 },
3741 mousedown: function (e) {
3742 if (!hasLeftMouseButton(e)) {
3743 return;
3744 }
3745 var t = Gestures.findOriginalTarget(e);
3746 var self = this;
3747 var movefn = function movefn(e) {
3748 if (!hasLeftMouseButton(e)) {
3749 self.fire('up', t, e);
3750 untrackDocument(self.info);
3751 }
3752 };
3753 var upfn = function upfn(e) {
3754 if (hasLeftMouseButton(e)) {
3755 self.fire('up', t, e);
3756 }
3757 untrackDocument(self.info);
3758 };
3759 trackDocument(this.info, movefn, upfn);
3760 this.fire('down', t, e);
3761 },
3762 touchstart: function (e) {
3763 this.fire('down', Gestures.findOriginalTarget(e), e.changedTouches[0]);
3764 },
3765 touchend: function (e) {
3766 this.fire('up', Gestures.findOriginalTarget(e), e.changedTouches[0]);
3767 },
3768 fire: function (type, target, event) {
3769 Gestures.fire(target, type, {
3770 x: event.clientX,
3771 y: event.clientY,
3772 sourceEvent: event,
3773 prevent: function (e) {
3774 return Gestures.prevent(e);
3775 }
3776 });
3777 }
3778 });
3779 Gestures.register({
3780 name: 'track',
3781 touchAction: 'none',
3782 deps: [
3783 'mousedown',
3784 'touchstart',
3785 'touchmove',
3786 'touchend'
3787 ],
3788 flow: {
3789 start: [
3790 'mousedown',
3791 'touchstart'
3792 ],
3793 end: [
3794 'mouseup',
3795 'touchend'
3796 ]
3797 },
3798 emits: ['track'],
3799 info: {
3800 x: 0,
3801 y: 0,
3802 state: 'start',
3803 started: false,
3804 moves: [],
3805 addMove: function (move) {
3806 if (this.moves.length > TRACK_LENGTH) {
3807 this.moves.shift();
3808 }
3809 this.moves.push(move);
3810 },
3811 movefn: null,
3812 upfn: null,
3813 prevent: false
3814 },
3815 reset: function () {
3816 this.info.state = 'start';
3817 this.info.started = false;
3818 this.info.moves = [];
3819 this.info.x = 0;
3820 this.info.y = 0;
3821 this.info.prevent = false;
3822 untrackDocument(this.info);
3823 },
3824 hasMovedEnough: function (x, y) {
3825 if (this.info.prevent) {
3826 return false;
3827 }
3828 if (this.info.started) {
3829 return true;
3830 }
3831 var dx = Math.abs(this.info.x - x);
3832 var dy = Math.abs(this.info.y - y);
3833 return dx >= TRACK_DISTANCE || dy >= TRACK_DISTANCE;
3834 },
3835 mousedown: function (e) {
3836 if (!hasLeftMouseButton(e)) {
3837 return;
3838 }
3839 var t = Gestures.findOriginalTarget(e);
3840 var self = this;
3841 var movefn = function movefn(e) {
3842 var x = e.clientX, y = e.clientY;
3843 if (self.hasMovedEnough(x, y)) {
3844 self.info.state = self.info.started ? e.type === 'mouseup' ? 'end' : 'track' : ' start';
3845 if (self.info.state === 'start') {
3846 Gestures.prevent('tap');
3847 }
3848 self.info.addMove({
3849 x: x,
3850 y: y
3851 });
3852 if (!hasLeftMouseButton(e)) {
3853 self.info.state = 'end';
3854 untrackDocument(self.info);
3855 }
3856 self.fire(t, e);
3857 self.info.started = true;
3858 }
3859 };
3860 var upfn = function upfn(e) {
3861 if (self.info.started) {
3862 movefn(e);
3863 }
3864 untrackDocument(self.info);
3865 };
3866 trackDocument(this.info, movefn, upfn);
3867 this.info.x = e.clientX;
3868 this.info.y = e.clientY;
3869 },
3870 touchstart: function (e) {
3871 var ct = e.changedTouches[0];
3872 this.info.x = ct.clientX;
3873 this.info.y = ct.clientY;
3874 },
3875 touchmove: function (e) {
3876 var t = Gestures.findOriginalTarget(e);
3877 var ct = e.changedTouches[0];
3878 var x = ct.clientX, y = ct.clientY;
3879 if (this.hasMovedEnough(x, y)) {
3880 if (this.info.state === 'start') {
3881 Gestures.prevent('tap');
3882 }
3883 this.info.addMove({
3884 x: x,
3885 y: y
3886 });
3887 this.fire(t, ct);
3888 this.info.state = 'track';
3889 this.info.started = true;
3890 }
3891 },
3892 touchend: function (e) {
3893 var t = Gestures.findOriginalTarget(e);
3894 var ct = e.changedTouches[0];
3895 if (this.info.started) {
3896 this.info.state = 'end';
3897 this.info.addMove({
3898 x: ct.clientX,
3899 y: ct.clientY
3900 });
3901 this.fire(t, ct);
3902 }
3903 },
3904 fire: function (target, touch) {
3905 var secondlast = this.info.moves[this.info.moves.length - 2];
3906 var lastmove = this.info.moves[this.info.moves.length - 1];
3907 var dx = lastmove.x - this.info.x;
3908 var dy = lastmove.y - this.info.y;
3909 var ddx, ddy = 0;
3910 if (secondlast) {
3911 ddx = lastmove.x - secondlast.x;
3912 ddy = lastmove.y - secondlast.y;
3913 }
3914 return Gestures.fire(target, 'track', {
3915 state: this.info.state,
3916 x: touch.clientX,
3917 y: touch.clientY,
3918 dx: dx,
3919 dy: dy,
3920 ddx: ddx,
3921 ddy: ddy,
3922 sourceEvent: touch,
3923 hover: function () {
3924 return Gestures.deepTargetFind(touch.clientX, touch.clientY);
3925 }
3926 });
3927 }
3928 });
3929 Gestures.register({
3930 name: 'tap',
3931 deps: [
3932 'mousedown',
3933 'click',
3934 'touchstart',
3935 'touchend'
3936 ],
3937 flow: {
3938 start: [
3939 'mousedown',
3940 'touchstart'
3941 ],
3942 end: [
3943 'click',
3944 'touchend'
3945 ]
3946 },
3947 emits: ['tap'],
3948 info: {
3949 x: NaN,
3950 y: NaN,
3951 prevent: false
3952 },
3953 reset: function () {
3954 this.info.x = NaN;
3955 this.info.y = NaN;
3956 this.info.prevent = false;
3957 },
3958 save: function (e) {
3959 this.info.x = e.clientX;
3960 this.info.y = e.clientY;
3961 },
3962 mousedown: function (e) {
3963 if (hasLeftMouseButton(e)) {
3964 this.save(e);
3965 }
3966 },
3967 click: function (e) {
3968 if (hasLeftMouseButton(e)) {
3969 this.forward(e);
3970 }
3971 },
3972 touchstart: function (e) {
3973 this.save(e.changedTouches[0]);
3974 },
3975 touchend: function (e) {
3976 this.forward(e.changedTouches[0]);
3977 },
3978 forward: function (e) {
3979 var dx = Math.abs(e.clientX - this.info.x);
3980 var dy = Math.abs(e.clientY - this.info.y);
3981 var t = Gestures.findOriginalTarget(e);
3982 if (isNaN(dx) || isNaN(dy) || dx <= TAP_DISTANCE && dy <= TAP_DISTANCE || isSynt heticClick(e)) {
3983 if (!this.info.prevent) {
3984 Gestures.fire(t, 'tap', {
3985 x: e.clientX,
3986 y: e.clientY,
3987 sourceEvent: e
3988 });
3989 }
3990 }
3991 }
3992 });
3993 var DIRECTION_MAP = {
3994 x: 'pan-x',
3995 y: 'pan-y',
3996 none: 'none',
3997 all: 'auto'
3998 };
3999 Polymer.Base._addFeature({
4000 _setupGestures: function () {
4001 this.__polymerGestures = null;
4002 },
4003 _listen: function (node, eventName, handler) {
4004 if (Gestures.gestures[eventName]) {
4005 Gestures.add(node, eventName, handler);
4006 } else {
4007 node.addEventListener(eventName, handler);
4008 }
4009 },
4010 _unlisten: function (node, eventName, handler) {
4011 if (Gestures.gestures[eventName]) {
4012 Gestures.remove(node, eventName, handler);
4013 } else {
4014 node.removeEventListener(eventName, handler);
4015 }
4016 },
4017 setScrollDirection: function (direction, node) {
4018 node = node || this;
4019 Gestures.setTouchAction(node, DIRECTION_MAP[direction] || 'auto');
4020 }
4021 });
4022 Polymer.Gestures = Gestures;
4023 }());
4024 Polymer.Base._addFeature({
4025 $$: function (slctr) {
4026 return Polymer.dom(this.root).querySelector(slctr);
4027 },
4028 toggleClass: function (name, bool, node) {
4029 node = node || this;
4030 if (arguments.length == 1) {
4031 bool = !node.classList.contains(name);
4032 }
4033 if (bool) {
4034 Polymer.dom(node).classList.add(name);
4035 } else {
4036 Polymer.dom(node).classList.remove(name);
4037 }
4038 },
4039 toggleAttribute: function (name, bool, node) {
4040 node = node || this;
4041 if (arguments.length == 1) {
4042 bool = !node.hasAttribute(name);
4043 }
4044 if (bool) {
4045 Polymer.dom(node).setAttribute(name, '');
4046 } else {
4047 Polymer.dom(node).removeAttribute(name);
4048 }
4049 },
4050 classFollows: function (name, toElement, fromElement) {
4051 if (fromElement) {
4052 Polymer.dom(fromElement).classList.remove(name);
4053 }
4054 if (toElement) {
4055 Polymer.dom(toElement).classList.add(name);
4056 }
4057 },
4058 attributeFollows: function (name, toElement, fromElement) {
4059 if (fromElement) {
4060 Polymer.dom(fromElement).removeAttribute(name);
4061 }
4062 if (toElement) {
4063 Polymer.dom(toElement).setAttribute(name, '');
4064 }
4065 },
4066 getEffectiveChildNodes: function () {
4067 return Polymer.dom(this).getEffectiveChildNodes();
4068 },
4069 getEffectiveChildren: function () {
4070 var list = Polymer.dom(this).getEffectiveChildNodes();
4071 return list.filter(function (n) {
4072 return n.nodeType === Node.ELEMENT_NODE;
4073 });
4074 },
4075 getEffectiveTextContent: function () {
4076 var cn = this.getEffectiveChildNodes();
4077 var tc = [];
4078 for (var i = 0, c; c = cn[i]; i++) {
4079 if (c.nodeType !== Node.COMMENT_NODE) {
4080 tc.push(Polymer.dom(c).textContent);
4081 }
4082 }
4083 return tc.join('');
4084 },
4085 queryEffectiveChildren: function (slctr) {
4086 var e$ = Polymer.dom(this).queryDistributedElements(slctr);
4087 return e$ && e$[0];
4088 },
4089 queryAllEffectiveChildren: function (slctr) {
4090 return Polymer.dom(this).queryDistributedElements(slctr);
4091 },
4092 getContentChildNodes: function (slctr) {
4093 var content = Polymer.dom(this.root).querySelector(slctr || 'content');
4094 return content ? Polymer.dom(content).getDistributedNodes() : [];
4095 },
4096 getContentChildren: function (slctr) {
4097 return this.getContentChildNodes(slctr).filter(function (n) {
4098 return n.nodeType === Node.ELEMENT_NODE;
4099 });
4100 },
4101 fire: function (type, detail, options) {
4102 options = options || Polymer.nob;
4103 var node = options.node || this;
4104 detail = detail === null || detail === undefined ? {} : detail;
4105 var bubbles = options.bubbles === undefined ? true : options.bubbles;
4106 var cancelable = Boolean(options.cancelable);
4107 var useCache = options._useCache;
4108 var event = this._getEvent(type, bubbles, cancelable, useCache);
4109 event.detail = detail;
4110 if (useCache) {
4111 this.__eventCache[type] = null;
4112 }
4113 node.dispatchEvent(event);
4114 if (useCache) {
4115 this.__eventCache[type] = event;
4116 }
4117 return event;
4118 },
4119 __eventCache: {},
4120 _getEvent: function (type, bubbles, cancelable, useCache) {
4121 var event = useCache && this.__eventCache[type];
4122 if (!event || (event.bubbles != bubbles || event.cancelable != cancelable)) {
4123 event = new Event(type, {
4124 bubbles: Boolean(bubbles),
4125 cancelable: cancelable
4126 });
4127 }
4128 return event;
4129 },
4130 async: function (callback, waitTime) {
4131 var self = this;
4132 return Polymer.Async.run(function () {
4133 callback.call(self);
4134 }, waitTime);
4135 },
4136 cancelAsync: function (handle) {
4137 Polymer.Async.cancel(handle);
4138 },
4139 arrayDelete: function (path, item) {
4140 var index;
4141 if (Array.isArray(path)) {
4142 index = path.indexOf(item);
4143 if (index >= 0) {
4144 return path.splice(index, 1);
4145 }
4146 } else {
4147 var arr = this._get(path);
4148 index = arr.indexOf(item);
4149 if (index >= 0) {
4150 return this.splice(path, index, 1);
4151 }
4152 }
4153 },
4154 transform: function (transform, node) {
4155 node = node || this;
4156 node.style.webkitTransform = transform;
4157 node.style.transform = transform;
4158 },
4159 translate3d: function (x, y, z, node) {
4160 node = node || this;
4161 this.transform('translate3d(' + x + ',' + y + ',' + z + ')', node);
4162 },
4163 importHref: function (href, onload, onerror, optAsync) {
4164 var l = document.createElement('link');
4165 l.rel = 'import';
4166 l.href = href;
4167 optAsync = Boolean(optAsync);
4168 if (optAsync) {
4169 l.setAttribute('async', '');
4170 }
4171 var self = this;
4172 if (onload) {
4173 l.onload = function (e) {
4174 return onload.call(self, e);
4175 };
4176 }
4177 if (onerror) {
4178 l.onerror = function (e) {
4179 return onerror.call(self, e);
4180 };
4181 }
4182 document.head.appendChild(l);
4183 return l;
4184 },
4185 create: function (tag, props) {
4186 var elt = document.createElement(tag);
4187 if (props) {
4188 for (var n in props) {
4189 elt[n] = props[n];
4190 }
4191 }
4192 return elt;
4193 },
4194 isLightDescendant: function (node) {
4195 return this !== node && this.contains(node) && Polymer.dom(this).getOwnerRoot() === Polymer.dom(node).getOwnerRoot();
4196 },
4197 isLocalDescendant: function (node) {
4198 return this.root === Polymer.dom(node).getOwnerRoot();
4199 }
4200 });
4201 Polymer.Bind = {
4202 _dataEventCache: {},
4203 prepareModel: function (model) {
4204 Polymer.Base.mixin(model, this._modelApi);
4205 },
4206 _modelApi: {
4207 _notifyChange: function (source, event, value) {
4208 value = value === undefined ? this[source] : value;
4209 event = event || Polymer.CaseMap.camelToDashCase(source) + '-changed';
4210 this.fire(event, { value: value }, {
4211 bubbles: false,
4212 cancelable: false,
4213 _useCache: true
4214 });
4215 },
4216 _propertySetter: function (property, value, effects, fromAbove) {
4217 var old = this.__data__[property];
4218 if (old !== value && (old === old || value === value)) {
4219 this.__data__[property] = value;
4220 if (typeof value == 'object') {
4221 this._clearPath(property);
4222 }
4223 if (this._propertyChanged) {
4224 this._propertyChanged(property, value, old);
4225 }
4226 if (effects) {
4227 this._effectEffects(property, value, effects, old, fromAbove);
4228 }
4229 }
4230 return old;
4231 },
4232 __setProperty: function (property, value, quiet, node) {
4233 node = node || this;
4234 var effects = node._propertyEffects && node._propertyEffects[property];
4235 if (effects) {
4236 node._propertySetter(property, value, effects, quiet);
4237 } else {
4238 node[property] = value;
4239 }
4240 },
4241 _effectEffects: function (property, value, effects, old, fromAbove) {
4242 for (var i = 0, l = effects.length, fx; i < l && (fx = effects[i]); i++) {
4243 fx.fn.call(this, property, value, fx.effect, old, fromAbove);
4244 }
4245 },
4246 _clearPath: function (path) {
4247 for (var prop in this.__data__) {
4248 if (prop.indexOf(path + '.') === 0) {
4249 this.__data__[prop] = undefined;
4250 }
4251 }
4252 }
4253 },
4254 ensurePropertyEffects: function (model, property) {
4255 if (!model._propertyEffects) {
4256 model._propertyEffects = {};
4257 }
4258 var fx = model._propertyEffects[property];
4259 if (!fx) {
4260 fx = model._propertyEffects[property] = [];
4261 }
4262 return fx;
4263 },
4264 addPropertyEffect: function (model, property, kind, effect) {
4265 var fx = this.ensurePropertyEffects(model, property);
4266 var propEffect = {
4267 kind: kind,
4268 effect: effect,
4269 fn: Polymer.Bind['_' + kind + 'Effect']
4270 };
4271 fx.push(propEffect);
4272 return propEffect;
4273 },
4274 createBindings: function (model) {
4275 var fx$ = model._propertyEffects;
4276 if (fx$) {
4277 for (var n in fx$) {
4278 var fx = fx$[n];
4279 fx.sort(this._sortPropertyEffects);
4280 this._createAccessors(model, n, fx);
4281 }
4282 }
4283 },
4284 _sortPropertyEffects: function () {
4285 var EFFECT_ORDER = {
4286 'compute': 0,
4287 'annotation': 1,
4288 'annotatedComputation': 2,
4289 'reflect': 3,
4290 'notify': 4,
4291 'observer': 5,
4292 'complexObserver': 6,
4293 'function': 7
4294 };
4295 return function (a, b) {
4296 return EFFECT_ORDER[a.kind] - EFFECT_ORDER[b.kind];
4297 };
4298 }(),
4299 _createAccessors: function (model, property, effects) {
4300 var defun = {
4301 get: function () {
4302 return this.__data__[property];
4303 }
4304 };
4305 var setter = function (value) {
4306 this._propertySetter(property, value, effects);
4307 };
4308 var info = model.getPropertyInfo && model.getPropertyInfo(property);
4309 if (info && info.readOnly) {
4310 if (!info.computed) {
4311 model['_set' + this.upper(property)] = setter;
4312 }
4313 } else {
4314 defun.set = setter;
4315 }
4316 Object.defineProperty(model, property, defun);
4317 },
4318 upper: function (name) {
4319 return name[0].toUpperCase() + name.substring(1);
4320 },
4321 _addAnnotatedListener: function (model, index, property, path, event, negated) {
4322 if (!model._bindListeners) {
4323 model._bindListeners = [];
4324 }
4325 var fn = this._notedListenerFactory(property, path, this._isStructured(path), ne gated);
4326 var eventName = event || Polymer.CaseMap.camelToDashCase(property) + '-changed';
4327 model._bindListeners.push({
4328 index: index,
4329 property: property,
4330 path: path,
4331 changedFn: fn,
4332 event: eventName
4333 });
4334 },
4335 _isStructured: function (path) {
4336 return path.indexOf('.') > 0;
4337 },
4338 _isEventBogus: function (e, target) {
4339 return e.path && e.path[0] !== target;
4340 },
4341 _notedListenerFactory: function (property, path, isStructured, negated) {
4342 return function (target, value, targetPath) {
4343 if (targetPath) {
4344 this._notifyPath(this._fixPath(path, property, targetPath), value);
4345 } else {
4346 value = target[property];
4347 if (negated) {
4348 value = !value;
4349 }
4350 if (!isStructured) {
4351 this[path] = value;
4352 } else {
4353 if (this.__data__[path] != value) {
4354 this.set(path, value);
4355 }
4356 }
4357 }
4358 };
4359 },
4360 prepareInstance: function (inst) {
4361 inst.__data__ = Object.create(null);
4362 },
4363 setupBindListeners: function (inst) {
4364 var b$ = inst._bindListeners;
4365 for (var i = 0, l = b$.length, info; i < l && (info = b$[i]); i++) {
4366 var node = inst._nodes[info.index];
4367 this._addNotifyListener(node, inst, info.event, info.changedFn);
4368 }
4369 },
4370 _addNotifyListener: function (element, context, event, changedFn) {
4371 element.addEventListener(event, function (e) {
4372 return context._notifyListener(changedFn, e);
4373 });
4374 }
4375 };
4376 Polymer.Base.extend(Polymer.Bind, {
4377 _shouldAddListener: function (effect) {
4378 return effect.name && effect.kind != 'attribute' && effect.kind != 'text' && !ef fect.isCompound && effect.parts[0].mode === '{';
4379 },
4380 _annotationEffect: function (source, value, effect) {
4381 if (source != effect.value) {
4382 value = this._get(effect.value);
4383 this.__data__[effect.value] = value;
4384 }
4385 var calc = effect.negate ? !value : value;
4386 if (!effect.customEvent || this._nodes[effect.index][effect.name] !== calc) {
4387 return this._applyEffectValue(effect, calc);
4388 }
4389 },
4390 _reflectEffect: function (source, value, effect) {
4391 this.reflectPropertyToAttribute(source, effect.attribute, value);
4392 },
4393 _notifyEffect: function (source, value, effect, old, fromAbove) {
4394 if (!fromAbove) {
4395 this._notifyChange(source, effect.event, value);
4396 }
4397 },
4398 _functionEffect: function (source, value, fn, old, fromAbove) {
4399 fn.call(this, source, value, old, fromAbove);
4400 },
4401 _observerEffect: function (source, value, effect, old) {
4402 var fn = this[effect.method];
4403 if (fn) {
4404 fn.call(this, value, old);
4405 } else {
4406 this._warn(this._logf('_observerEffect', 'observer method `' + effect.method + ' ` not defined'));
4407 }
4408 },
4409 _complexObserverEffect: function (source, value, effect) {
4410 var fn = this[effect.method];
4411 if (fn) {
4412 var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
4413 if (args) {
4414 fn.apply(this, args);
4415 }
4416 } else if (effect.dynamicFn) {
4417 } else {
4418 this._warn(this._logf('_complexObserverEffect', 'observer method `' + effect.met hod + '` not defined'));
4419 }
4420 },
4421 _computeEffect: function (source, value, effect) {
4422 var fn = this[effect.method];
4423 if (fn) {
4424 var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
4425 if (args) {
4426 var computedvalue = fn.apply(this, args);
4427 this.__setProperty(effect.name, computedvalue);
4428 }
4429 } else if (effect.dynamicFn) {
4430 } else {
4431 this._warn(this._logf('_computeEffect', 'compute method `' + effect.method + '` not defined'));
4432 }
4433 },
4434 _annotatedComputationEffect: function (source, value, effect) {
4435 var computedHost = this._rootDataHost || this;
4436 var fn = computedHost[effect.method];
4437 if (fn) {
4438 var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
4439 if (args) {
4440 var computedvalue = fn.apply(computedHost, args);
4441 if (effect.negate) {
4442 computedvalue = !computedvalue;
4443 }
4444 this._applyEffectValue(effect, computedvalue);
4445 }
4446 } else if (effect.dynamicFn) {
4447 } else {
4448 computedHost._warn(computedHost._logf('_annotatedComputationEffect', 'compute me thod `' + effect.method + '` not defined'));
4449 }
4450 },
4451 _marshalArgs: function (model, effect, path, value) {
4452 var values = [];
4453 var args = effect.args;
4454 var bailoutEarly = args.length > 1 || effect.dynamicFn;
4455 for (var i = 0, l = args.length; i < l; i++) {
4456 var arg = args[i];
4457 var name = arg.name;
4458 var v;
4459 if (arg.literal) {
4460 v = arg.value;
4461 } else if (arg.structured) {
4462 v = Polymer.Base._get(name, model);
4463 } else {
4464 v = model[name];
4465 }
4466 if (bailoutEarly && v === undefined) {
4467 return;
4468 }
4469 if (arg.wildcard) {
4470 var baseChanged = name.indexOf(path + '.') === 0;
4471 var matches = effect.trigger.name.indexOf(name) === 0 && !baseChanged;
4472 values[i] = {
4473 path: matches ? path : name,
4474 value: matches ? value : v,
4475 base: v
4476 };
4477 } else {
4478 values[i] = v;
4479 }
4480 }
4481 return values;
4482 }
4483 });
4484 Polymer.Base._addFeature({
4485 _addPropertyEffect: function (property, kind, effect) {
4486 var prop = Polymer.Bind.addPropertyEffect(this, property, kind, effect);
4487 prop.pathFn = this['_' + prop.kind + 'PathEffect'];
4488 },
4489 _prepEffects: function () {
4490 Polymer.Bind.prepareModel(this);
4491 this._addAnnotationEffects(this._notes);
4492 },
4493 _prepBindings: function () {
4494 Polymer.Bind.createBindings(this);
4495 },
4496 _addPropertyEffects: function (properties) {
4497 if (properties) {
4498 for (var p in properties) {
4499 var prop = properties[p];
4500 if (prop.observer) {
4501 this._addObserverEffect(p, prop.observer);
4502 }
4503 if (prop.computed) {
4504 prop.readOnly = true;
4505 this._addComputedEffect(p, prop.computed);
4506 }
4507 if (prop.notify) {
4508 this._addPropertyEffect(p, 'notify', { event: Polymer.CaseMap.camelToDashCase(p) + '-changed' });
4509 }
4510 if (prop.reflectToAttribute) {
4511 var attr = Polymer.CaseMap.camelToDashCase(p);
4512 if (attr[0] === '-') {
4513 this._warn(this._logf('_addPropertyEffects', 'Property ' + p + ' cannot be refle cted to attribute ' + attr + ' because "-" is not a valid starting attribute nam e. Use a lowercase first letter for the property instead.'));
4514 } else {
4515 this._addPropertyEffect(p, 'reflect', { attribute: attr });
4516 }
4517 }
4518 if (prop.readOnly) {
4519 Polymer.Bind.ensurePropertyEffects(this, p);
4520 }
4521 }
4522 }
4523 },
4524 _addComputedEffect: function (name, expression) {
4525 var sig = this._parseMethod(expression);
4526 var dynamicFn = sig.dynamicFn;
4527 for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
4528 this._addPropertyEffect(arg.model, 'compute', {
4529 method: sig.method,
4530 args: sig.args,
4531 trigger: arg,
4532 name: name,
4533 dynamicFn: dynamicFn
4534 });
4535 }
4536 if (dynamicFn) {
4537 this._addPropertyEffect(sig.method, 'compute', {
4538 method: sig.method,
4539 args: sig.args,
4540 trigger: null,
4541 name: name,
4542 dynamicFn: dynamicFn
4543 });
4544 }
4545 },
4546 _addObserverEffect: function (property, observer) {
4547 this._addPropertyEffect(property, 'observer', {
4548 method: observer,
4549 property: property
4550 });
4551 },
4552 _addComplexObserverEffects: function (observers) {
4553 if (observers) {
4554 for (var i = 0, o; i < observers.length && (o = observers[i]); i++) {
4555 this._addComplexObserverEffect(o);
4556 }
4557 }
4558 },
4559 _addComplexObserverEffect: function (observer) {
4560 var sig = this._parseMethod(observer);
4561 if (!sig) {
4562 throw new Error('Malformed observer expression \'' + observer + '\'');
4563 }
4564 var dynamicFn = sig.dynamicFn;
4565 for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
4566 this._addPropertyEffect(arg.model, 'complexObserver', {
4567 method: sig.method,
4568 args: sig.args,
4569 trigger: arg,
4570 dynamicFn: dynamicFn
4571 });
4572 }
4573 if (dynamicFn) {
4574 this._addPropertyEffect(sig.method, 'complexObserver', {
4575 method: sig.method,
4576 args: sig.args,
4577 trigger: null,
4578 dynamicFn: dynamicFn
4579 });
4580 }
4581 },
4582 _addAnnotationEffects: function (notes) {
4583 for (var i = 0, note; i < notes.length && (note = notes[i]); i++) {
4584 var b$ = note.bindings;
4585 for (var j = 0, binding; j < b$.length && (binding = b$[j]); j++) {
4586 this._addAnnotationEffect(binding, i);
4587 }
4588 }
4589 },
4590 _addAnnotationEffect: function (note, index) {
4591 if (Polymer.Bind._shouldAddListener(note)) {
4592 Polymer.Bind._addAnnotatedListener(this, index, note.name, note.parts[0].value, note.parts[0].event, note.parts[0].negate);
4593 }
4594 for (var i = 0; i < note.parts.length; i++) {
4595 var part = note.parts[i];
4596 if (part.signature) {
4597 this._addAnnotatedComputationEffect(note, part, index);
4598 } else if (!part.literal) {
4599 if (note.kind === 'attribute' && note.name[0] === '-') {
4600 this._warn(this._logf('_addAnnotationEffect', 'Cannot set attribute ' + note.nam e + ' because "-" is not a valid attribute starting character'));
4601 } else {
4602 this._addPropertyEffect(part.model, 'annotation', {
4603 kind: note.kind,
4604 index: index,
4605 name: note.name,
4606 propertyName: note.propertyName,
4607 value: part.value,
4608 isCompound: note.isCompound,
4609 compoundIndex: part.compoundIndex,
4610 event: part.event,
4611 customEvent: part.customEvent,
4612 negate: part.negate
4613 });
4614 }
4615 }
4616 }
4617 },
4618 _addAnnotatedComputationEffect: function (note, part, index) {
4619 var sig = part.signature;
4620 if (sig.static) {
4621 this.__addAnnotatedComputationEffect('__static__', index, note, part, null);
4622 } else {
4623 for (var i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
4624 if (!arg.literal) {
4625 this.__addAnnotatedComputationEffect(arg.model, index, note, part, arg);
4626 }
4627 }
4628 if (sig.dynamicFn) {
4629 this.__addAnnotatedComputationEffect(sig.method, index, note, part, null);
4630 }
4631 }
4632 },
4633 __addAnnotatedComputationEffect: function (property, index, note, part, trigger) {
4634 this._addPropertyEffect(property, 'annotatedComputation', {
4635 index: index,
4636 isCompound: note.isCompound,
4637 compoundIndex: part.compoundIndex,
4638 kind: note.kind,
4639 name: note.name,
4640 negate: part.negate,
4641 method: part.signature.method,
4642 args: part.signature.args,
4643 trigger: trigger,
4644 dynamicFn: part.signature.dynamicFn
4645 });
4646 },
4647 _parseMethod: function (expression) {
4648 var m = expression.match(/([^\s]+?)\(([\s\S]*)\)/);
4649 if (m) {
4650 var sig = {
4651 method: m[1],
4652 static: true
4653 };
4654 if (this.getPropertyInfo(sig.method) !== Polymer.nob) {
4655 sig.static = false;
4656 sig.dynamicFn = true;
4657 }
4658 if (m[2].trim()) {
4659 var args = m[2].replace(/\\,/g, '&comma;').split(',');
4660 return this._parseArgs(args, sig);
4661 } else {
4662 sig.args = Polymer.nar;
4663 return sig;
4664 }
4665 }
4666 },
4667 _parseArgs: function (argList, sig) {
4668 sig.args = argList.map(function (rawArg) {
4669 var arg = this._parseArg(rawArg);
4670 if (!arg.literal) {
4671 sig.static = false;
4672 }
4673 return arg;
4674 }, this);
4675 return sig;
4676 },
4677 _parseArg: function (rawArg) {
4678 var arg = rawArg.trim().replace(/&comma;/g, ',').replace(/\\(.)/g, '$1');
4679 var a = { name: arg };
4680 var fc = arg[0];
4681 if (fc === '-') {
4682 fc = arg[1];
4683 }
4684 if (fc >= '0' && fc <= '9') {
4685 fc = '#';
4686 }
4687 switch (fc) {
4688 case '\'':
4689 case '"':
4690 a.value = arg.slice(1, -1);
4691 a.literal = true;
4692 break;
4693 case '#':
4694 a.value = Number(arg);
4695 a.literal = true;
4696 break;
4697 }
4698 if (!a.literal) {
4699 a.model = this._modelForPath(arg);
4700 a.structured = arg.indexOf('.') > 0;
4701 if (a.structured) {
4702 a.wildcard = arg.slice(-2) == '.*';
4703 if (a.wildcard) {
4704 a.name = arg.slice(0, -2);
4705 }
4706 }
4707 }
4708 return a;
4709 },
4710 _marshalInstanceEffects: function () {
4711 Polymer.Bind.prepareInstance(this);
4712 if (this._bindListeners) {
4713 Polymer.Bind.setupBindListeners(this);
4714 }
4715 },
4716 _applyEffectValue: function (info, value) {
4717 var node = this._nodes[info.index];
4718 var property = info.name;
4719 if (info.isCompound) {
4720 var storage = node.__compoundStorage__[property];
4721 storage[info.compoundIndex] = value;
4722 value = storage.join('');
4723 }
4724 if (info.kind == 'attribute') {
4725 this.serializeValueToAttribute(value, property, node);
4726 } else {
4727 if (property === 'className') {
4728 value = this._scopeElementClass(node, value);
4729 }
4730 if (property === 'textContent' || node.localName == 'input' && property == 'valu e') {
4731 value = value == undefined ? '' : value;
4732 }
4733 var pinfo;
4734 if (!node._propertyInfo || !(pinfo = node._propertyInfo[property]) || !pinfo.rea dOnly) {
4735 this.__setProperty(property, value, false, node);
4736 }
4737 }
4738 },
4739 _executeStaticEffects: function () {
4740 if (this._propertyEffects && this._propertyEffects.__static__) {
4741 this._effectEffects('__static__', null, this._propertyEffects.__static__);
4742 }
4743 }
4744 });
4745 (function () {
4746 var usePolyfillProto = Polymer.Settings.usePolyfillProto;
4747 Polymer.Base._addFeature({
4748 _setupConfigure: function (initialConfig) {
4749 this._config = {};
4750 this._handlers = [];
4751 this._aboveConfig = null;
4752 if (initialConfig) {
4753 for (var i in initialConfig) {
4754 if (initialConfig[i] !== undefined) {
4755 this._config[i] = initialConfig[i];
4756 }
4757 }
4758 }
4759 },
4760 _marshalAttributes: function () {
4761 this._takeAttributesToModel(this._config);
4762 },
4763 _attributeChangedImpl: function (name) {
4764 var model = this._clientsReadied ? this : this._config;
4765 this._setAttributeToProperty(model, name);
4766 },
4767 _configValue: function (name, value) {
4768 var info = this._propertyInfo[name];
4769 if (!info || !info.readOnly) {
4770 this._config[name] = value;
4771 }
4772 },
4773 _beforeClientsReady: function () {
4774 this._configure();
4775 },
4776 _configure: function () {
4777 this._configureAnnotationReferences();
4778 this._aboveConfig = this.mixin({}, this._config);
4779 var config = {};
4780 for (var i = 0; i < this.behaviors.length; i++) {
4781 this._configureProperties(this.behaviors[i].properties, config);
4782 }
4783 this._configureProperties(this.properties, config);
4784 this.mixin(config, this._aboveConfig);
4785 this._config = config;
4786 if (this._clients && this._clients.length) {
4787 this._distributeConfig(this._config);
4788 }
4789 },
4790 _configureProperties: function (properties, config) {
4791 for (var i in properties) {
4792 var c = properties[i];
4793 if (!usePolyfillProto && this.hasOwnProperty(i) && this._propertyEffects && this ._propertyEffects[i]) {
4794 config[i] = this[i];
4795 delete this[i];
4796 } else if (c.value !== undefined) {
4797 var value = c.value;
4798 if (typeof value == 'function') {
4799 value = value.call(this, this._config);
4800 }
4801 config[i] = value;
4802 }
4803 }
4804 },
4805 _distributeConfig: function (config) {
4806 var fx$ = this._propertyEffects;
4807 if (fx$) {
4808 for (var p in config) {
4809 var fx = fx$[p];
4810 if (fx) {
4811 for (var i = 0, l = fx.length, x; i < l && (x = fx[i]); i++) {
4812 if (x.kind === 'annotation' && !x.isCompound) {
4813 var node = this._nodes[x.effect.index];
4814 var name = x.effect.propertyName;
4815 var isAttr = x.effect.kind == 'attribute';
4816 var hasEffect = node._propertyEffects && node._propertyEffects[name];
4817 if (node._configValue && (hasEffect || !isAttr)) {
4818 var value = p === x.effect.value ? config[p] : this._get(x.effect.value, config) ;
4819 if (isAttr) {
4820 value = node.deserialize(this.serialize(value), node._propertyInfo[name].type);
4821 }
4822 node._configValue(name, value);
4823 }
4824 }
4825 }
4826 }
4827 }
4828 }
4829 },
4830 _afterClientsReady: function () {
4831 this._executeStaticEffects();
4832 this._applyConfig(this._config, this._aboveConfig);
4833 this._flushHandlers();
4834 },
4835 _applyConfig: function (config, aboveConfig) {
4836 for (var n in config) {
4837 if (this[n] === undefined) {
4838 this.__setProperty(n, config[n], n in aboveConfig);
4839 }
4840 }
4841 },
4842 _notifyListener: function (fn, e) {
4843 if (!Polymer.Bind._isEventBogus(e, e.target)) {
4844 var value, path;
4845 if (e.detail) {
4846 value = e.detail.value;
4847 path = e.detail.path;
4848 }
4849 if (!this._clientsReadied) {
4850 this._queueHandler([
4851 fn,
4852 e.target,
4853 value,
4854 path
4855 ]);
4856 } else {
4857 return fn.call(this, e.target, value, path);
4858 }
4859 }
4860 },
4861 _queueHandler: function (args) {
4862 this._handlers.push(args);
4863 },
4864 _flushHandlers: function () {
4865 var h$ = this._handlers;
4866 for (var i = 0, l = h$.length, h; i < l && (h = h$[i]); i++) {
4867 h[0].call(this, h[1], h[2], h[3]);
4868 }
4869 this._handlers = [];
4870 }
4871 });
4872 }());
4873 (function () {
4874 'use strict';
4875 Polymer.Base._addFeature({
4876 notifyPath: function (path, value, fromAbove) {
4877 var info = {};
4878 this._get(path, this, info);
4879 if (info.path) {
4880 this._notifyPath(info.path, value, fromAbove);
4881 }
4882 },
4883 _notifyPath: function (path, value, fromAbove) {
4884 var old = this._propertySetter(path, value);
4885 if (old !== value && (old === old || value === value)) {
4886 this._pathEffector(path, value);
4887 if (!fromAbove) {
4888 this._notifyPathUp(path, value);
4889 }
4890 return true;
4891 }
4892 },
4893 _getPathParts: function (path) {
4894 if (Array.isArray(path)) {
4895 var parts = [];
4896 for (var i = 0; i < path.length; i++) {
4897 var args = path[i].toString().split('.');
4898 for (var j = 0; j < args.length; j++) {
4899 parts.push(args[j]);
4900 }
4901 }
4902 return parts;
4903 } else {
4904 return path.toString().split('.');
4905 }
4906 },
4907 set: function (path, value, root) {
4908 var prop = root || this;
4909 var parts = this._getPathParts(path);
4910 var array;
4911 var last = parts[parts.length - 1];
4912 if (parts.length > 1) {
4913 for (var i = 0; i < parts.length - 1; i++) {
4914 var part = parts[i];
4915 if (array && part[0] == '#') {
4916 prop = Polymer.Collection.get(array).getItem(part);
4917 } else {
4918 prop = prop[part];
4919 if (array && parseInt(part, 10) == part) {
4920 parts[i] = Polymer.Collection.get(array).getKey(prop);
4921 }
4922 }
4923 if (!prop) {
4924 return;
4925 }
4926 array = Array.isArray(prop) ? prop : null;
4927 }
4928 if (array) {
4929 var coll = Polymer.Collection.get(array);
4930 var old, key;
4931 if (last[0] == '#') {
4932 key = last;
4933 old = coll.getItem(key);
4934 last = array.indexOf(old);
4935 coll.setItem(key, value);
4936 } else if (parseInt(last, 10) == last) {
4937 old = prop[last];
4938 key = coll.getKey(old);
4939 parts[i] = key;
4940 coll.setItem(key, value);
4941 }
4942 }
4943 prop[last] = value;
4944 if (!root) {
4945 this._notifyPath(parts.join('.'), value);
4946 }
4947 } else {
4948 prop[path] = value;
4949 }
4950 },
4951 get: function (path, root) {
4952 return this._get(path, root);
4953 },
4954 _get: function (path, root, info) {
4955 var prop = root || this;
4956 var parts = this._getPathParts(path);
4957 var array;
4958 for (var i = 0; i < parts.length; i++) {
4959 if (!prop) {
4960 return;
4961 }
4962 var part = parts[i];
4963 if (array && part[0] == '#') {
4964 prop = Polymer.Collection.get(array).getItem(part);
4965 } else {
4966 prop = prop[part];
4967 if (info && array && parseInt(part, 10) == part) {
4968 parts[i] = Polymer.Collection.get(array).getKey(prop);
4969 }
4970 }
4971 array = Array.isArray(prop) ? prop : null;
4972 }
4973 if (info) {
4974 info.path = parts.join('.');
4975 }
4976 return prop;
4977 },
4978 _pathEffector: function (path, value) {
4979 var model = this._modelForPath(path);
4980 var fx$ = this._propertyEffects && this._propertyEffects[model];
4981 if (fx$) {
4982 for (var i = 0, fx; i < fx$.length && (fx = fx$[i]); i++) {
4983 var fxFn = fx.pathFn;
4984 if (fxFn) {
4985 fxFn.call(this, path, value, fx.effect);
4986 }
4987 }
4988 }
4989 if (this._boundPaths) {
4990 this._notifyBoundPaths(path, value);
4991 }
4992 },
4993 _annotationPathEffect: function (path, value, effect) {
4994 if (effect.value === path || effect.value.indexOf(path + '.') === 0) {
4995 Polymer.Bind._annotationEffect.call(this, path, value, effect);
4996 } else if (path.indexOf(effect.value + '.') === 0 && !effect.negate) {
4997 var node = this._nodes[effect.index];
4998 if (node && node._notifyPath) {
4999 var p = this._fixPath(effect.name, effect.value, path);
5000 node._notifyPath(p, value, true);
5001 }
5002 }
5003 },
5004 _complexObserverPathEffect: function (path, value, effect) {
5005 if (this._pathMatchesEffect(path, effect)) {
5006 Polymer.Bind._complexObserverEffect.call(this, path, value, effect);
5007 }
5008 },
5009 _computePathEffect: function (path, value, effect) {
5010 if (this._pathMatchesEffect(path, effect)) {
5011 Polymer.Bind._computeEffect.call(this, path, value, effect);
5012 }
5013 },
5014 _annotatedComputationPathEffect: function (path, value, effect) {
5015 if (this._pathMatchesEffect(path, effect)) {
5016 Polymer.Bind._annotatedComputationEffect.call(this, path, value, effect);
5017 }
5018 },
5019 _pathMatchesEffect: function (path, effect) {
5020 var effectArg = effect.trigger.name;
5021 return effectArg == path || effectArg.indexOf(path + '.') === 0 || effect.trigge r.wildcard && path.indexOf(effectArg) === 0;
5022 },
5023 linkPaths: function (to, from) {
5024 this._boundPaths = this._boundPaths || {};
5025 if (from) {
5026 this._boundPaths[to] = from;
5027 } else {
5028 this.unlinkPaths(to);
5029 }
5030 },
5031 unlinkPaths: function (path) {
5032 if (this._boundPaths) {
5033 delete this._boundPaths[path];
5034 }
5035 },
5036 _notifyBoundPaths: function (path, value) {
5037 for (var a in this._boundPaths) {
5038 var b = this._boundPaths[a];
5039 if (path.indexOf(a + '.') == 0) {
5040 this._notifyPath(this._fixPath(b, a, path), value);
5041 } else if (path.indexOf(b + '.') == 0) {
5042 this._notifyPath(this._fixPath(a, b, path), value);
5043 }
5044 }
5045 },
5046 _fixPath: function (property, root, path) {
5047 return property + path.slice(root.length);
5048 },
5049 _notifyPathUp: function (path, value) {
5050 var rootName = this._modelForPath(path);
5051 var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName);
5052 var eventName = dashCaseName + this._EVENT_CHANGED;
5053 this.fire(eventName, {
5054 path: path,
5055 value: value
5056 }, {
5057 bubbles: false,
5058 _useCache: true
5059 });
5060 },
5061 _modelForPath: function (path) {
5062 var dot = path.indexOf('.');
5063 return dot < 0 ? path : path.slice(0, dot);
5064 },
5065 _EVENT_CHANGED: '-changed',
5066 notifySplices: function (path, splices) {
5067 var info = {};
5068 var array = this._get(path, this, info);
5069 this._notifySplices(array, info.path, splices);
5070 },
5071 _notifySplices: function (array, path, splices) {
5072 var change = {
5073 keySplices: Polymer.Collection.applySplices(array, splices),
5074 indexSplices: splices
5075 };
5076 if (!array.hasOwnProperty('splices')) {
5077 Object.defineProperty(array, 'splices', {
5078 configurable: true,
5079 writable: true
5080 });
5081 }
5082 array.splices = change;
5083 this._notifyPath(path + '.splices', change);
5084 this._notifyPath(path + '.length', array.length);
5085 change.keySplices = null;
5086 change.indexSplices = null;
5087 },
5088 _notifySplice: function (array, path, index, added, removed) {
5089 this._notifySplices(array, path, [{
5090 index: index,
5091 addedCount: added,
5092 removed: removed,
5093 object: array,
5094 type: 'splice'
5095 }]);
5096 },
5097 push: function (path) {
5098 var info = {};
5099 var array = this._get(path, this, info);
5100 var args = Array.prototype.slice.call(arguments, 1);
5101 var len = array.length;
5102 var ret = array.push.apply(array, args);
5103 if (args.length) {
5104 this._notifySplice(array, info.path, len, args.length, []);
5105 }
5106 return ret;
5107 },
5108 pop: function (path) {
5109 var info = {};
5110 var array = this._get(path, this, info);
5111 var hadLength = Boolean(array.length);
5112 var args = Array.prototype.slice.call(arguments, 1);
5113 var ret = array.pop.apply(array, args);
5114 if (hadLength) {
5115 this._notifySplice(array, info.path, array.length, 0, [ret]);
5116 }
5117 return ret;
5118 },
5119 splice: function (path, start) {
5120 var info = {};
5121 var array = this._get(path, this, info);
5122 if (start < 0) {
5123 start = array.length - Math.floor(-start);
5124 } else {
5125 start = Math.floor(start);
5126 }
5127 if (!start) {
5128 start = 0;
5129 }
5130 var args = Array.prototype.slice.call(arguments, 1);
5131 var ret = array.splice.apply(array, args);
5132 var addedCount = Math.max(args.length - 2, 0);
5133 if (addedCount || ret.length) {
5134 this._notifySplice(array, info.path, start, addedCount, ret);
5135 }
5136 return ret;
5137 },
5138 shift: function (path) {
5139 var info = {};
5140 var array = this._get(path, this, info);
5141 var hadLength = Boolean(array.length);
5142 var args = Array.prototype.slice.call(arguments, 1);
5143 var ret = array.shift.apply(array, args);
5144 if (hadLength) {
5145 this._notifySplice(array, info.path, 0, 0, [ret]);
5146 }
5147 return ret;
5148 },
5149 unshift: function (path) {
5150 var info = {};
5151 var array = this._get(path, this, info);
5152 var args = Array.prototype.slice.call(arguments, 1);
5153 var ret = array.unshift.apply(array, args);
5154 if (args.length) {
5155 this._notifySplice(array, info.path, 0, args.length, []);
5156 }
5157 return ret;
5158 },
5159 prepareModelNotifyPath: function (model) {
5160 this.mixin(model, {
5161 fire: Polymer.Base.fire,
5162 _getEvent: Polymer.Base._getEvent,
5163 __eventCache: Polymer.Base.__eventCache,
5164 notifyPath: Polymer.Base.notifyPath,
5165 _get: Polymer.Base._get,
5166 _EVENT_CHANGED: Polymer.Base._EVENT_CHANGED,
5167 _notifyPath: Polymer.Base._notifyPath,
5168 _notifyPathUp: Polymer.Base._notifyPathUp,
5169 _pathEffector: Polymer.Base._pathEffector,
5170 _annotationPathEffect: Polymer.Base._annotationPathEffect,
5171 _complexObserverPathEffect: Polymer.Base._complexObserverPathEffect,
5172 _annotatedComputationPathEffect: Polymer.Base._annotatedComputationPathEffect,
5173 _computePathEffect: Polymer.Base._computePathEffect,
5174 _modelForPath: Polymer.Base._modelForPath,
5175 _pathMatchesEffect: Polymer.Base._pathMatchesEffect,
5176 _notifyBoundPaths: Polymer.Base._notifyBoundPaths,
5177 _getPathParts: Polymer.Base._getPathParts
5178 });
5179 }
5180 });
5181 }());
5182 Polymer.Base._addFeature({
5183 resolveUrl: function (url) {
5184 var module = Polymer.DomModule.import(this.is);
5185 var root = '';
5186 if (module) {
5187 var assetPath = module.getAttribute('assetpath') || '';
5188 root = Polymer.ResolveUrl.resolveUrl(assetPath, module.ownerDocument.baseURI);
5189 }
5190 return Polymer.ResolveUrl.resolveUrl(url, root);
5191 }
5192 });
5193 Polymer.CssParse = function () {
5194 return {
5195 parse: function (text) {
5196 text = this._clean(text);
5197 return this._parseCss(this._lex(text), text);
5198 },
5199 _clean: function (cssText) {
5200 return cssText.replace(this._rx.comments, '').replace(this._rx.port, '');
5201 },
5202 _lex: function (text) {
5203 var root = {
5204 start: 0,
5205 end: text.length
5206 };
5207 var n = root;
5208 for (var i = 0, l = text.length; i < l; i++) {
5209 switch (text[i]) {
5210 case this.OPEN_BRACE:
5211 if (!n.rules) {
5212 n.rules = [];
5213 }
5214 var p = n;
5215 var previous = p.rules[p.rules.length - 1];
5216 n = {
5217 start: i + 1,
5218 parent: p,
5219 previous: previous
5220 };
5221 p.rules.push(n);
5222 break;
5223 case this.CLOSE_BRACE:
5224 n.end = i + 1;
5225 n = n.parent || root;
5226 break;
5227 }
5228 }
5229 return root;
5230 },
5231 _parseCss: function (node, text) {
5232 var t = text.substring(node.start, node.end - 1);
5233 node.parsedCssText = node.cssText = t.trim();
5234 if (node.parent) {
5235 var ss = node.previous ? node.previous.end : node.parent.start;
5236 t = text.substring(ss, node.start - 1);
5237 t = this._expandUnicodeEscapes(t);
5238 t = t.replace(this._rx.multipleSpaces, ' ');
5239 t = t.substring(t.lastIndexOf(';') + 1);
5240 var s = node.parsedSelector = node.selector = t.trim();
5241 node.atRule = s.indexOf(this.AT_START) === 0;
5242 if (node.atRule) {
5243 if (s.indexOf(this.MEDIA_START) === 0) {
5244 node.type = this.types.MEDIA_RULE;
5245 } else if (s.match(this._rx.keyframesRule)) {
5246 node.type = this.types.KEYFRAMES_RULE;
5247 node.keyframesName = node.selector.split(this._rx.multipleSpaces).pop();
5248 }
5249 } else {
5250 if (s.indexOf(this.VAR_START) === 0) {
5251 node.type = this.types.MIXIN_RULE;
5252 } else {
5253 node.type = this.types.STYLE_RULE;
5254 }
5255 }
5256 }
5257 var r$ = node.rules;
5258 if (r$) {
5259 for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
5260 this._parseCss(r, text);
5261 }
5262 }
5263 return node;
5264 },
5265 _expandUnicodeEscapes: function (s) {
5266 return s.replace(/\\([0-9a-f]{1,6})\s/gi, function () {
5267 var code = arguments[1], repeat = 6 - code.length;
5268 while (repeat--) {
5269 code = '0' + code;
5270 }
5271 return '\\' + code;
5272 });
5273 },
5274 stringify: function (node, preserveProperties, text) {
5275 text = text || '';
5276 var cssText = '';
5277 if (node.cssText || node.rules) {
5278 var r$ = node.rules;
5279 if (r$ && (preserveProperties || !this._hasMixinRules(r$))) {
5280 for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
5281 cssText = this.stringify(r, preserveProperties, cssText);
5282 }
5283 } else {
5284 cssText = preserveProperties ? node.cssText : this.removeCustomProps(node.cssTex t);
5285 cssText = cssText.trim();
5286 if (cssText) {
5287 cssText = ' ' + cssText + '\n';
5288 }
5289 }
5290 }
5291 if (cssText) {
5292 if (node.selector) {
5293 text += node.selector + ' ' + this.OPEN_BRACE + '\n';
5294 }
5295 text += cssText;
5296 if (node.selector) {
5297 text += this.CLOSE_BRACE + '\n\n';
5298 }
5299 }
5300 return text;
5301 },
5302 _hasMixinRules: function (rules) {
5303 return rules[0].selector.indexOf(this.VAR_START) === 0;
5304 },
5305 removeCustomProps: function (cssText) {
5306 cssText = this.removeCustomPropAssignment(cssText);
5307 return this.removeCustomPropApply(cssText);
5308 },
5309 removeCustomPropAssignment: function (cssText) {
5310 return cssText.replace(this._rx.customProp, '').replace(this._rx.mixinProp, '');
5311 },
5312 removeCustomPropApply: function (cssText) {
5313 return cssText.replace(this._rx.mixinApply, '').replace(this._rx.varApply, '');
5314 },
5315 types: {
5316 STYLE_RULE: 1,
5317 KEYFRAMES_RULE: 7,
5318 MEDIA_RULE: 4,
5319 MIXIN_RULE: 1000
5320 },
5321 OPEN_BRACE: '{',
5322 CLOSE_BRACE: '}',
5323 _rx: {
5324 comments: /\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,
5325 port: /@import[^;]*;/gim,
5326 customProp: /(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,
5327 mixinProp: /(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,
5328 mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim,
5329 varApply: /[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,
5330 keyframesRule: /^@[^\s]*keyframes/,
5331 multipleSpaces: /\s+/g
5332 },
5333 VAR_START: '--',
5334 MEDIA_START: '@media',
5335 AT_START: '@'
5336 };
5337 }();
5338 Polymer.StyleUtil = function () {
5339 return {
5340 MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css], template',
5341 INCLUDE_ATTR: 'include',
5342 toCssText: function (rules, callback, preserveProperties) {
5343 if (typeof rules === 'string') {
5344 rules = this.parser.parse(rules);
5345 }
5346 if (callback) {
5347 this.forEachRule(rules, callback);
5348 }
5349 return this.parser.stringify(rules, preserveProperties);
5350 },
5351 forRulesInStyles: function (styles, styleRuleCallback, keyframesRuleCallback) {
5352 if (styles) {
5353 for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
5354 this.forEachRule(this.rulesForStyle(s), styleRuleCallback, keyframesRuleCallback );
5355 }
5356 }
5357 },
5358 rulesForStyle: function (style) {
5359 if (!style.__cssRules && style.textContent) {
5360 style.__cssRules = this.parser.parse(style.textContent);
5361 }
5362 return style.__cssRules;
5363 },
5364 isKeyframesSelector: function (rule) {
5365 return rule.parent && rule.parent.type === this.ruleTypes.KEYFRAMES_RULE;
5366 },
5367 forEachRule: function (node, styleRuleCallback, keyframesRuleCallback) {
5368 if (!node) {
5369 return;
5370 }
5371 var skipRules = false;
5372 if (node.type === this.ruleTypes.STYLE_RULE) {
5373 styleRuleCallback(node);
5374 } else if (keyframesRuleCallback && node.type === this.ruleTypes.KEYFRAMES_RULE) {
5375 keyframesRuleCallback(node);
5376 } else if (node.type === this.ruleTypes.MIXIN_RULE) {
5377 skipRules = true;
5378 }
5379 var r$ = node.rules;
5380 if (r$ && !skipRules) {
5381 for (var i = 0, l = r$.length, r; i < l && (r = r$[i]); i++) {
5382 this.forEachRule(r, styleRuleCallback, keyframesRuleCallback);
5383 }
5384 }
5385 },
5386 applyCss: function (cssText, moniker, target, contextNode) {
5387 var style = this.createScopeStyle(cssText, moniker);
5388 target = target || document.head;
5389 var after = contextNode && contextNode.nextSibling || target.firstChild;
5390 this.__lastHeadApplyNode = style;
5391 return target.insertBefore(style, after);
5392 },
5393 createScopeStyle: function (cssText, moniker) {
5394 var style = document.createElement('style');
5395 if (moniker) {
5396 style.setAttribute('scope', moniker);
5397 }
5398 style.textContent = cssText;
5399 return style;
5400 },
5401 __lastHeadApplyNode: null,
5402 applyStylePlaceHolder: function (moniker) {
5403 var placeHolder = document.createComment(' Shady DOM styles for ' + moniker + ' ');
5404 var after = this.__lastHeadApplyNode ? this.__lastHeadApplyNode.nextSibling : nu ll;
5405 var scope = document.head;
5406 scope.insertBefore(placeHolder, after || scope.firstChild);
5407 this.__lastHeadApplyNode = placeHolder;
5408 return placeHolder;
5409 },
5410 cssFromModules: function (moduleIds, warnIfNotFound) {
5411 var modules = moduleIds.trim().split(' ');
5412 var cssText = '';
5413 for (var i = 0; i < modules.length; i++) {
5414 cssText += this.cssFromModule(modules[i], warnIfNotFound);
5415 }
5416 return cssText;
5417 },
5418 cssFromModule: function (moduleId, warnIfNotFound) {
5419 var m = Polymer.DomModule.import(moduleId);
5420 if (m && !m._cssText) {
5421 m._cssText = this.cssFromElement(m);
5422 }
5423 if (!m && warnIfNotFound) {
5424 console.warn('Could not find style data in module named', moduleId);
5425 }
5426 return m && m._cssText || '';
5427 },
5428 cssFromElement: function (element) {
5429 var cssText = '';
5430 var content = element.content || element;
5431 var e$ = Polymer.TreeApi.arrayCopy(content.querySelectorAll(this.MODULE_STYLES_S ELECTOR));
5432 for (var i = 0, e; i < e$.length; i++) {
5433 e = e$[i];
5434 if (e.localName === 'template') {
5435 cssText += this.cssFromElement(e);
5436 } else {
5437 if (e.localName === 'style') {
5438 var include = e.getAttribute(this.INCLUDE_ATTR);
5439 if (include) {
5440 cssText += this.cssFromModules(include, true);
5441 }
5442 e = e.__appliedElement || e;
5443 e.parentNode.removeChild(e);
5444 cssText += this.resolveCss(e.textContent, element.ownerDocument);
5445 } else if (e.import && e.import.body) {
5446 cssText += this.resolveCss(e.import.body.textContent, e.import);
5447 }
5448 }
5449 }
5450 return cssText;
5451 },
5452 resolveCss: Polymer.ResolveUrl.resolveCss,
5453 parser: Polymer.CssParse,
5454 ruleTypes: Polymer.CssParse.types
5455 };
5456 }();
5457 Polymer.StyleTransformer = function () {
5458 var nativeShadow = Polymer.Settings.useNativeShadow;
5459 var styleUtil = Polymer.StyleUtil;
5460 var api = {
5461 dom: function (node, scope, useAttr, shouldRemoveScope) {
5462 this._transformDom(node, scope || '', useAttr, shouldRemoveScope);
5463 },
5464 _transformDom: function (node, selector, useAttr, shouldRemoveScope) {
5465 if (node.setAttribute) {
5466 this.element(node, selector, useAttr, shouldRemoveScope);
5467 }
5468 var c$ = Polymer.dom(node).childNodes;
5469 for (var i = 0; i < c$.length; i++) {
5470 this._transformDom(c$[i], selector, useAttr, shouldRemoveScope);
5471 }
5472 },
5473 element: function (element, scope, useAttr, shouldRemoveScope) {
5474 if (useAttr) {
5475 if (shouldRemoveScope) {
5476 element.removeAttribute(SCOPE_NAME);
5477 } else {
5478 element.setAttribute(SCOPE_NAME, scope);
5479 }
5480 } else {
5481 if (scope) {
5482 if (element.classList) {
5483 if (shouldRemoveScope) {
5484 element.classList.remove(SCOPE_NAME);
5485 element.classList.remove(scope);
5486 } else {
5487 element.classList.add(SCOPE_NAME);
5488 element.classList.add(scope);
5489 }
5490 } else if (element.getAttribute) {
5491 var c = element.getAttribute(CLASS);
5492 if (shouldRemoveScope) {
5493 if (c) {
5494 element.setAttribute(CLASS, c.replace(SCOPE_NAME, '').replace(scope, ''));
5495 }
5496 } else {
5497 element.setAttribute(CLASS, (c ? c + ' ' : '') + SCOPE_NAME + ' ' + scope);
5498 }
5499 }
5500 }
5501 }
5502 },
5503 elementStyles: function (element, callback) {
5504 var styles = element._styles;
5505 var cssText = '';
5506 for (var i = 0, l = styles.length, s; i < l && (s = styles[i]); i++) {
5507 var rules = styleUtil.rulesForStyle(s);
5508 cssText += nativeShadow ? styleUtil.toCssText(rules, callback) : this.css(rules, element.is, element.extends, callback, element._scopeCssViaAttr) + '\n\n';
5509 }
5510 return cssText.trim();
5511 },
5512 css: function (rules, scope, ext, callback, useAttr) {
5513 var hostScope = this._calcHostScope(scope, ext);
5514 scope = this._calcElementScope(scope, useAttr);
5515 var self = this;
5516 return styleUtil.toCssText(rules, function (rule) {
5517 if (!rule.isScoped) {
5518 self.rule(rule, scope, hostScope);
5519 rule.isScoped = true;
5520 }
5521 if (callback) {
5522 callback(rule, scope, hostScope);
5523 }
5524 });
5525 },
5526 _calcElementScope: function (scope, useAttr) {
5527 if (scope) {
5528 return useAttr ? CSS_ATTR_PREFIX + scope + CSS_ATTR_SUFFIX : CSS_CLASS_PREFIX + scope;
5529 } else {
5530 return '';
5531 }
5532 },
5533 _calcHostScope: function (scope, ext) {
5534 return ext ? '[is=' + scope + ']' : scope;
5535 },
5536 rule: function (rule, scope, hostScope) {
5537 this._transformRule(rule, this._transformComplexSelector, scope, hostScope);
5538 },
5539 _transformRule: function (rule, transformer, scope, hostScope) {
5540 var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP);
5541 if (!styleUtil.isKeyframesSelector(rule)) {
5542 for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) {
5543 p$[i] = transformer.call(this, p, scope, hostScope);
5544 }
5545 }
5546 rule.selector = rule.transformedSelector = p$.join(COMPLEX_SELECTOR_SEP);
5547 },
5548 _transformComplexSelector: function (selector, scope, hostScope) {
5549 var stop = false;
5550 var hostContext = false;
5551 var self = this;
5552 selector = selector.replace(CONTENT_START, HOST + ' $1');
5553 selector = selector.replace(SIMPLE_SELECTOR_SEP, function (m, c, s) {
5554 if (!stop) {
5555 var info = self._transformCompoundSelector(s, c, scope, hostScope);
5556 stop = stop || info.stop;
5557 hostContext = hostContext || info.hostContext;
5558 c = info.combinator;
5559 s = info.value;
5560 } else {
5561 s = s.replace(SCOPE_JUMP, ' ');
5562 }
5563 return c + s;
5564 });
5565 if (hostContext) {
5566 selector = selector.replace(HOST_CONTEXT_PAREN, function (m, pre, paren, post) {
5567 return pre + paren + ' ' + hostScope + post + COMPLEX_SELECTOR_SEP + ' ' + pre + hostScope + paren + post;
5568 });
5569 }
5570 return selector;
5571 },
5572 _transformCompoundSelector: function (selector, combinator, scope, hostScope) {
5573 var jumpIndex = selector.search(SCOPE_JUMP);
5574 var hostContext = false;
5575 if (selector.indexOf(HOST_CONTEXT) >= 0) {
5576 hostContext = true;
5577 } else if (selector.indexOf(HOST) >= 0) {
5578 selector = selector.replace(HOST_PAREN, function (m, host, paren) {
5579 return hostScope + paren;
5580 });
5581 selector = selector.replace(HOST, hostScope);
5582 } else if (jumpIndex !== 0) {
5583 selector = scope ? this._transformSimpleSelector(selector, scope) : selector;
5584 }
5585 if (selector.indexOf(CONTENT) >= 0) {
5586 combinator = '';
5587 }
5588 var stop;
5589 if (jumpIndex >= 0) {
5590 selector = selector.replace(SCOPE_JUMP, ' ');
5591 stop = true;
5592 }
5593 return {
5594 value: selector,
5595 combinator: combinator,
5596 stop: stop,
5597 hostContext: hostContext
5598 };
5599 },
5600 _transformSimpleSelector: function (selector, scope) {
5601 var p$ = selector.split(PSEUDO_PREFIX);
5602 p$[0] += scope;
5603 return p$.join(PSEUDO_PREFIX);
5604 },
5605 documentRule: function (rule) {
5606 rule.selector = rule.parsedSelector;
5607 this.normalizeRootSelector(rule);
5608 if (!nativeShadow) {
5609 this._transformRule(rule, this._transformDocumentSelector);
5610 }
5611 },
5612 normalizeRootSelector: function (rule) {
5613 if (rule.selector === ROOT) {
5614 rule.selector = 'body';
5615 }
5616 },
5617 _transformDocumentSelector: function (selector) {
5618 return selector.match(SCOPE_JUMP) ? this._transformComplexSelector(selector, SCO PE_DOC_SELECTOR) : this._transformSimpleSelector(selector.trim(), SCOPE_DOC_SELE CTOR);
5619 },
5620 SCOPE_NAME: 'style-scope'
5621 };
5622 var SCOPE_NAME = api.SCOPE_NAME;
5623 var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' + ':not(.' + SCOPE_NAME + ')';
5624 var COMPLEX_SELECTOR_SEP = ',';
5625 var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)((?:\[.+?\]|[^\s>+~=\[])+)/g;
5626 var HOST = ':host';
5627 var ROOT = ':root';
5628 var HOST_PAREN = /(:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;
5629 var HOST_CONTEXT = ':host-context';
5630 var HOST_CONTEXT_PAREN = /(.*)(?::host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\)) (.*)/;
5631 var CONTENT = '::content';
5632 var SCOPE_JUMP = /::content|::shadow|\/deep\//;
5633 var CSS_CLASS_PREFIX = '.';
5634 var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~=';
5635 var CSS_ATTR_SUFFIX = ']';
5636 var PSEUDO_PREFIX = ':';
5637 var CLASS = 'class';
5638 var CONTENT_START = new RegExp('^(' + CONTENT + ')');
5639 return api;
5640 }();
5641 Polymer.StyleExtends = function () {
5642 var styleUtil = Polymer.StyleUtil;
5643 return {
5644 hasExtends: function (cssText) {
5645 return Boolean(cssText.match(this.rx.EXTEND));
5646 },
5647 transform: function (style) {
5648 var rules = styleUtil.rulesForStyle(style);
5649 var self = this;
5650 styleUtil.forEachRule(rules, function (rule) {
5651 self._mapRuleOntoParent(rule);
5652 if (rule.parent) {
5653 var m;
5654 while (m = self.rx.EXTEND.exec(rule.cssText)) {
5655 var extend = m[1];
5656 var extendor = self._findExtendor(extend, rule);
5657 if (extendor) {
5658 self._extendRule(rule, extendor);
5659 }
5660 }
5661 }
5662 rule.cssText = rule.cssText.replace(self.rx.EXTEND, '');
5663 });
5664 return styleUtil.toCssText(rules, function (rule) {
5665 if (rule.selector.match(self.rx.STRIP)) {
5666 rule.cssText = '';
5667 }
5668 }, true);
5669 },
5670 _mapRuleOntoParent: function (rule) {
5671 if (rule.parent) {
5672 var map = rule.parent.map || (rule.parent.map = {});
5673 var parts = rule.selector.split(',');
5674 for (var i = 0, p; i < parts.length; i++) {
5675 p = parts[i];
5676 map[p.trim()] = rule;
5677 }
5678 return map;
5679 }
5680 },
5681 _findExtendor: function (extend, rule) {
5682 return rule.parent && rule.parent.map && rule.parent.map[extend] || this._findEx tendor(extend, rule.parent);
5683 },
5684 _extendRule: function (target, source) {
5685 if (target.parent !== source.parent) {
5686 this._cloneAndAddRuleToParent(source, target.parent);
5687 }
5688 target.extends = target.extends || [];
5689 target.extends.push(source);
5690 source.selector = source.selector.replace(this.rx.STRIP, '');
5691 source.selector = (source.selector && source.selector + ',\n') + target.selector ;
5692 if (source.extends) {
5693 source.extends.forEach(function (e) {
5694 this._extendRule(target, e);
5695 }, this);
5696 }
5697 },
5698 _cloneAndAddRuleToParent: function (rule, parent) {
5699 rule = Object.create(rule);
5700 rule.parent = parent;
5701 if (rule.extends) {
5702 rule.extends = rule.extends.slice();
5703 }
5704 parent.rules.push(rule);
5705 },
5706 rx: {
5707 EXTEND: /@extends\(([^)]*)\)\s*?;/gim,
5708 STRIP: /%[^,]*$/
5709 }
5710 };
5711 }();
5712 (function () {
5713 var prepElement = Polymer.Base._prepElement;
5714 var nativeShadow = Polymer.Settings.useNativeShadow;
5715 var styleUtil = Polymer.StyleUtil;
5716 var styleTransformer = Polymer.StyleTransformer;
5717 var styleExtends = Polymer.StyleExtends;
5718 Polymer.Base._addFeature({
5719 _prepElement: function (element) {
5720 if (this._encapsulateStyle) {
5721 styleTransformer.element(element, this.is, this._scopeCssViaAttr);
5722 }
5723 prepElement.call(this, element);
5724 },
5725 _prepStyles: function () {
5726 if (!nativeShadow) {
5727 this._scopeStyle = styleUtil.applyStylePlaceHolder(this.is);
5728 }
5729 },
5730 _prepShimStyles: function () {
5731 if (this._template) {
5732 if (this._encapsulateStyle === undefined) {
5733 this._encapsulateStyle = !nativeShadow;
5734 }
5735 this._styles = this._collectStyles();
5736 var cssText = styleTransformer.elementStyles(this);
5737 this._prepStyleProperties();
5738 if (!this._needsStyleProperties() && this._styles.length) {
5739 styleUtil.applyCss(cssText, this.is, nativeShadow ? this._template.content : nul l, this._scopeStyle);
5740 }
5741 } else {
5742 this._styles = [];
5743 }
5744 },
5745 _collectStyles: function () {
5746 var styles = [];
5747 var cssText = '', m$ = this.styleModules;
5748 if (m$) {
5749 for (var i = 0, l = m$.length, m; i < l && (m = m$[i]); i++) {
5750 cssText += styleUtil.cssFromModule(m);
5751 }
5752 }
5753 cssText += styleUtil.cssFromModule(this.is);
5754 var p = this._template && this._template.parentNode;
5755 if (this._template && (!p || p.id.toLowerCase() !== this.is)) {
5756 cssText += styleUtil.cssFromElement(this._template);
5757 }
5758 if (cssText) {
5759 var style = document.createElement('style');
5760 style.textContent = cssText;
5761 if (styleExtends.hasExtends(style.textContent)) {
5762 cssText = styleExtends.transform(style);
5763 }
5764 styles.push(style);
5765 }
5766 return styles;
5767 },
5768 _elementAdd: function (node) {
5769 if (this._encapsulateStyle) {
5770 if (node.__styleScoped) {
5771 node.__styleScoped = false;
5772 } else {
5773 styleTransformer.dom(node, this.is, this._scopeCssViaAttr);
5774 }
5775 }
5776 },
5777 _elementRemove: function (node) {
5778 if (this._encapsulateStyle) {
5779 styleTransformer.dom(node, this.is, this._scopeCssViaAttr, true);
5780 }
5781 },
5782 scopeSubtree: function (container, shouldObserve) {
5783 if (nativeShadow) {
5784 return;
5785 }
5786 var self = this;
5787 var scopify = function (node) {
5788 if (node.nodeType === Node.ELEMENT_NODE) {
5789 var className = node.getAttribute('class');
5790 node.setAttribute('class', self._scopeElementClass(node, className));
5791 var n$ = node.querySelectorAll('*');
5792 for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
5793 className = n.getAttribute('class');
5794 n.setAttribute('class', self._scopeElementClass(n, className));
5795 }
5796 }
5797 };
5798 scopify(container);
5799 if (shouldObserve) {
5800 var mo = new MutationObserver(function (mxns) {
5801 for (var i = 0, m; i < mxns.length && (m = mxns[i]); i++) {
5802 if (m.addedNodes) {
5803 for (var j = 0; j < m.addedNodes.length; j++) {
5804 scopify(m.addedNodes[j]);
5805 }
5806 }
5807 }
5808 });
5809 mo.observe(container, {
5810 childList: true,
5811 subtree: true
5812 });
5813 return mo;
5814 }
5815 }
5816 });
5817 }());
5818 Polymer.StyleProperties = function () {
5819 'use strict';
5820 var nativeShadow = Polymer.Settings.useNativeShadow;
5821 var matchesSelector = Polymer.DomApi.matchesSelector;
5822 var styleUtil = Polymer.StyleUtil;
5823 var styleTransformer = Polymer.StyleTransformer;
5824 return {
5825 decorateStyles: function (styles) {
5826 var self = this, props = {}, keyframes = [];
5827 styleUtil.forRulesInStyles(styles, function (rule) {
5828 self.decorateRule(rule);
5829 self.collectPropertiesInCssText(rule.propertyInfo.cssText, props);
5830 }, function onKeyframesRule(rule) {
5831 keyframes.push(rule);
5832 });
5833 styles._keyframes = keyframes;
5834 var names = [];
5835 for (var i in props) {
5836 names.push(i);
5837 }
5838 return names;
5839 },
5840 decorateRule: function (rule) {
5841 if (rule.propertyInfo) {
5842 return rule.propertyInfo;
5843 }
5844 var info = {}, properties = {};
5845 var hasProperties = this.collectProperties(rule, properties);
5846 if (hasProperties) {
5847 info.properties = properties;
5848 rule.rules = null;
5849 }
5850 info.cssText = this.collectCssText(rule);
5851 rule.propertyInfo = info;
5852 return info;
5853 },
5854 collectProperties: function (rule, properties) {
5855 var info = rule.propertyInfo;
5856 if (info) {
5857 if (info.properties) {
5858 Polymer.Base.mixin(properties, info.properties);
5859 return true;
5860 }
5861 } else {
5862 var m, rx = this.rx.VAR_ASSIGN;
5863 var cssText = rule.parsedCssText;
5864 var any;
5865 while (m = rx.exec(cssText)) {
5866 properties[m[1]] = (m[2] || m[3]).trim();
5867 any = true;
5868 }
5869 return any;
5870 }
5871 },
5872 collectCssText: function (rule) {
5873 return this.collectConsumingCssText(rule.parsedCssText);
5874 },
5875 collectConsumingCssText: function (cssText) {
5876 return cssText.replace(this.rx.BRACKETED, '').replace(this.rx.VAR_ASSIGN, '');
5877 },
5878 collectPropertiesInCssText: function (cssText, props) {
5879 var m;
5880 while (m = this.rx.VAR_CAPTURE.exec(cssText)) {
5881 props[m[1]] = true;
5882 var def = m[2];
5883 if (def && def.match(this.rx.IS_VAR)) {
5884 props[def] = true;
5885 }
5886 }
5887 },
5888 reify: function (props) {
5889 var names = Object.getOwnPropertyNames(props);
5890 for (var i = 0, n; i < names.length; i++) {
5891 n = names[i];
5892 props[n] = this.valueForProperty(props[n], props);
5893 }
5894 },
5895 valueForProperty: function (property, props) {
5896 if (property) {
5897 if (property.indexOf(';') >= 0) {
5898 property = this.valueForProperties(property, props);
5899 } else {
5900 var self = this;
5901 var fn = function (all, prefix, value, fallback) {
5902 var propertyValue = self.valueForProperty(props[value], props) || (props[fallbac k] ? self.valueForProperty(props[fallback], props) : fallback);
5903 return prefix + (propertyValue || '');
5904 };
5905 property = property.replace(this.rx.VAR_MATCH, fn);
5906 }
5907 }
5908 return property && property.trim() || '';
5909 },
5910 valueForProperties: function (property, props) {
5911 var parts = property.split(';');
5912 for (var i = 0, p, m; i < parts.length; i++) {
5913 if (p = parts[i]) {
5914 m = p.match(this.rx.MIXIN_MATCH);
5915 if (m) {
5916 p = this.valueForProperty(props[m[1]], props);
5917 } else {
5918 var colon = p.indexOf(':');
5919 if (colon !== -1) {
5920 var pp = p.substring(colon);
5921 pp = pp.trim();
5922 pp = this.valueForProperty(pp, props) || pp;
5923 p = p.substring(0, colon) + pp;
5924 }
5925 }
5926 parts[i] = p && p.lastIndexOf(';') === p.length - 1 ? p.slice(0, -1) : p || '';
5927 }
5928 }
5929 return parts.join(';');
5930 },
5931 applyProperties: function (rule, props) {
5932 var output = '';
5933 if (!rule.propertyInfo) {
5934 this.decorateRule(rule);
5935 }
5936 if (rule.propertyInfo.cssText) {
5937 output = this.valueForProperties(rule.propertyInfo.cssText, props);
5938 }
5939 rule.cssText = output;
5940 },
5941 applyKeyframeTransforms: function (rule, keyframeTransforms) {
5942 var input = rule.cssText;
5943 var output = rule.cssText;
5944 if (rule.hasAnimations == null) {
5945 rule.hasAnimations = this.rx.ANIMATION_MATCH.test(input);
5946 }
5947 if (rule.hasAnimations) {
5948 var transform;
5949 if (rule.keyframeNamesToTransform == null) {
5950 rule.keyframeNamesToTransform = [];
5951 for (var keyframe in keyframeTransforms) {
5952 transform = keyframeTransforms[keyframe];
5953 output = transform(input);
5954 if (input !== output) {
5955 input = output;
5956 rule.keyframeNamesToTransform.push(keyframe);
5957 }
5958 }
5959 } else {
5960 for (var i = 0; i < rule.keyframeNamesToTransform.length; ++i) {
5961 transform = keyframeTransforms[rule.keyframeNamesToTransform[i]];
5962 input = transform(input);
5963 }
5964 output = input;
5965 }
5966 }
5967 rule.cssText = output;
5968 },
5969 propertyDataFromStyles: function (styles, element) {
5970 var props = {}, self = this;
5971 var o = [], i = 0;
5972 styleUtil.forRulesInStyles(styles, function (rule) {
5973 if (!rule.propertyInfo) {
5974 self.decorateRule(rule);
5975 }
5976 if (element && rule.propertyInfo.properties && matchesSelector.call(element, rul e.transformedSelector || rule.parsedSelector)) {
5977 self.collectProperties(rule, props);
5978 addToBitMask(i, o);
5979 }
5980 i++;
5981 });
5982 return {
5983 properties: props,
5984 key: o
5985 };
5986 },
5987 scopePropertiesFromStyles: function (styles) {
5988 if (!styles._scopeStyleProperties) {
5989 styles._scopeStyleProperties = this.selectedPropertiesFromStyles(styles, this.SC OPE_SELECTORS);
5990 }
5991 return styles._scopeStyleProperties;
5992 },
5993 hostPropertiesFromStyles: function (styles) {
5994 if (!styles._hostStyleProperties) {
5995 styles._hostStyleProperties = this.selectedPropertiesFromStyles(styles, this.HOS T_SELECTORS);
5996 }
5997 return styles._hostStyleProperties;
5998 },
5999 selectedPropertiesFromStyles: function (styles, selectors) {
6000 var props = {}, self = this;
6001 styleUtil.forRulesInStyles(styles, function (rule) {
6002 if (!rule.propertyInfo) {
6003 self.decorateRule(rule);
6004 }
6005 for (var i = 0; i < selectors.length; i++) {
6006 if (rule.parsedSelector === selectors[i]) {
6007 self.collectProperties(rule, props);
6008 return;
6009 }
6010 }
6011 });
6012 return props;
6013 },
6014 transformStyles: function (element, properties, scopeSelector) {
6015 var self = this;
6016 var hostSelector = styleTransformer._calcHostScope(element.is, element.extends);
6017 var rxHostSelector = element.extends ? '\\' + hostSelector.slice(0, -1) + '\\]' : hostSelector;
6018 var hostRx = new RegExp(this.rx.HOST_PREFIX + rxHostSelector + this.rx.HOST_SUFF IX);
6019 var keyframeTransforms = this._elementKeyframeTransforms(element, scopeSelector) ;
6020 return styleTransformer.elementStyles(element, function (rule) {
6021 self.applyProperties(rule, properties);
6022 if (!nativeShadow && !Polymer.StyleUtil.isKeyframesSelector(rule) && rule.cssTex t) {
6023 self.applyKeyframeTransforms(rule, keyframeTransforms);
6024 self._scopeSelector(rule, hostRx, hostSelector, element._scopeCssViaAttr, scopeS elector);
6025 }
6026 });
6027 },
6028 _elementKeyframeTransforms: function (element, scopeSelector) {
6029 var keyframesRules = element._styles._keyframes;
6030 var keyframeTransforms = {};
6031 if (!nativeShadow && keyframesRules) {
6032 for (var i = 0, keyframesRule = keyframesRules[i]; i < keyframesRules.length; ke yframesRule = keyframesRules[++i]) {
6033 this._scopeKeyframes(keyframesRule, scopeSelector);
6034 keyframeTransforms[keyframesRule.keyframesName] = this._keyframesRuleTransformer (keyframesRule);
6035 }
6036 }
6037 return keyframeTransforms;
6038 },
6039 _keyframesRuleTransformer: function (keyframesRule) {
6040 return function (cssText) {
6041 return cssText.replace(keyframesRule.keyframesNameRx, keyframesRule.transformedK eyframesName);
6042 };
6043 },
6044 _scopeKeyframes: function (rule, scopeId) {
6045 rule.keyframesNameRx = new RegExp(rule.keyframesName, 'g');
6046 rule.transformedKeyframesName = rule.keyframesName + '-' + scopeId;
6047 rule.transformedSelector = rule.transformedSelector || rule.selector;
6048 rule.selector = rule.transformedSelector.replace(rule.keyframesName, rule.transf ormedKeyframesName);
6049 },
6050 _scopeSelector: function (rule, hostRx, hostSelector, viaAttr, scopeId) {
6051 rule.transformedSelector = rule.transformedSelector || rule.selector;
6052 var selector = rule.transformedSelector;
6053 var scope = viaAttr ? '[' + styleTransformer.SCOPE_NAME + '~=' + scopeId + ']' : '.' + scopeId;
6054 var parts = selector.split(',');
6055 for (var i = 0, l = parts.length, p; i < l && (p = parts[i]); i++) {
6056 parts[i] = p.match(hostRx) ? p.replace(hostSelector, scope) : scope + ' ' + p;
6057 }
6058 rule.selector = parts.join(',');
6059 },
6060 applyElementScopeSelector: function (element, selector, old, viaAttr) {
6061 var c = viaAttr ? element.getAttribute(styleTransformer.SCOPE_NAME) : element.ge tAttribute('class') || '';
6062 var v = old ? c.replace(old, selector) : (c ? c + ' ' : '') + this.XSCOPE_NAME + ' ' + selector;
6063 if (c !== v) {
6064 if (viaAttr) {
6065 element.setAttribute(styleTransformer.SCOPE_NAME, v);
6066 } else {
6067 element.setAttribute('class', v);
6068 }
6069 }
6070 },
6071 applyElementStyle: function (element, properties, selector, style) {
6072 var cssText = style ? style.textContent || '' : this.transformStyles(element, pr operties, selector);
6073 var s = element._customStyle;
6074 if (s && !nativeShadow && s !== style) {
6075 s._useCount--;
6076 if (s._useCount <= 0 && s.parentNode) {
6077 s.parentNode.removeChild(s);
6078 }
6079 }
6080 if (nativeShadow || (!style || !style.parentNode)) {
6081 if (nativeShadow && element._customStyle) {
6082 element._customStyle.textContent = cssText;
6083 style = element._customStyle;
6084 } else if (cssText) {
6085 style = styleUtil.applyCss(cssText, selector, nativeShadow ? element.root : null , element._scopeStyle);
6086 }
6087 }
6088 if (style) {
6089 style._useCount = style._useCount || 0;
6090 if (element._customStyle != style) {
6091 style._useCount++;
6092 }
6093 element._customStyle = style;
6094 }
6095 return style;
6096 },
6097 mixinCustomStyle: function (props, customStyle) {
6098 var v;
6099 for (var i in customStyle) {
6100 v = customStyle[i];
6101 if (v || v === 0) {
6102 props[i] = v;
6103 }
6104 }
6105 },
6106 rx: {
6107 VAR_ASSIGN: /(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}] )|$)/gi,
6108 MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/i,
6109 VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,()]*)|(?:[^;()]*\([^;)]* \)))[\s]*?\)/gi,
6110 VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi,
6111 ANIMATION_MATCH: /(animation\s*:)|(animation-name\s*:)/,
6112 IS_VAR: /^--/,
6113 BRACKETED: /\{[^}]*\}/g,
6114 HOST_PREFIX: '(?:^|[^.#[:])',
6115 HOST_SUFFIX: '($|[.:[\\s>+~])'
6116 },
6117 HOST_SELECTORS: [':host'],
6118 SCOPE_SELECTORS: [':root'],
6119 XSCOPE_NAME: 'x-scope'
6120 };
6121 function addToBitMask(n, bits) {
6122 var o = parseInt(n / 32);
6123 var v = 1 << n % 32;
6124 bits[o] = (bits[o] || 0) | v;
6125 }
6126 }();
6127 (function () {
6128 Polymer.StyleCache = function () {
6129 this.cache = {};
6130 };
6131 Polymer.StyleCache.prototype = {
6132 MAX: 100,
6133 store: function (is, data, keyValues, keyStyles) {
6134 data.keyValues = keyValues;
6135 data.styles = keyStyles;
6136 var s$ = this.cache[is] = this.cache[is] || [];
6137 s$.push(data);
6138 if (s$.length > this.MAX) {
6139 s$.shift();
6140 }
6141 },
6142 retrieve: function (is, keyValues, keyStyles) {
6143 var cache = this.cache[is];
6144 if (cache) {
6145 for (var i = cache.length - 1, data; i >= 0; i--) {
6146 data = cache[i];
6147 if (keyStyles === data.styles && this._objectsEqual(keyValues, data.keyValues)) {
6148 return data;
6149 }
6150 }
6151 }
6152 },
6153 clear: function () {
6154 this.cache = {};
6155 },
6156 _objectsEqual: function (target, source) {
6157 var t, s;
6158 for (var i in target) {
6159 t = target[i], s = source[i];
6160 if (!(typeof t === 'object' && t ? this._objectsStrictlyEqual(t, s) : t === s)) {
6161 return false;
6162 }
6163 }
6164 if (Array.isArray(target)) {
6165 return target.length === source.length;
6166 }
6167 return true;
6168 },
6169 _objectsStrictlyEqual: function (target, source) {
6170 return this._objectsEqual(target, source) && this._objectsEqual(source, target);
6171 }
6172 };
6173 }());
6174 Polymer.StyleDefaults = function () {
6175 var styleProperties = Polymer.StyleProperties;
6176 var StyleCache = Polymer.StyleCache;
6177 var api = {
6178 _styles: [],
6179 _properties: null,
6180 customStyle: {},
6181 _styleCache: new StyleCache(),
6182 addStyle: function (style) {
6183 this._styles.push(style);
6184 this._properties = null;
6185 },
6186 get _styleProperties() {
6187 if (!this._properties) {
6188 styleProperties.decorateStyles(this._styles);
6189 this._styles._scopeStyleProperties = null;
6190 this._properties = styleProperties.scopePropertiesFromStyles(this._styles);
6191 styleProperties.mixinCustomStyle(this._properties, this.customStyle);
6192 styleProperties.reify(this._properties);
6193 }
6194 return this._properties;
6195 },
6196 _needsStyleProperties: function () {
6197 },
6198 _computeStyleProperties: function () {
6199 return this._styleProperties;
6200 },
6201 updateStyles: function (properties) {
6202 this._properties = null;
6203 if (properties) {
6204 Polymer.Base.mixin(this.customStyle, properties);
6205 }
6206 this._styleCache.clear();
6207 for (var i = 0, s; i < this._styles.length; i++) {
6208 s = this._styles[i];
6209 s = s.__importElement || s;
6210 s._apply();
6211 }
6212 }
6213 };
6214 return api;
6215 }();
6216 (function () {
6217 'use strict';
6218 var serializeValueToAttribute = Polymer.Base.serializeValueToAttribute;
6219 var propertyUtils = Polymer.StyleProperties;
6220 var styleTransformer = Polymer.StyleTransformer;
6221 var styleDefaults = Polymer.StyleDefaults;
6222 var nativeShadow = Polymer.Settings.useNativeShadow;
6223 Polymer.Base._addFeature({
6224 _prepStyleProperties: function () {
6225 this._ownStylePropertyNames = this._styles && this._styles.length ? propertyUtil s.decorateStyles(this._styles) : null;
6226 },
6227 customStyle: null,
6228 getComputedStyleValue: function (property) {
6229 return this._styleProperties && this._styleProperties[property] || getComputedSt yle(this).getPropertyValue(property);
6230 },
6231 _setupStyleProperties: function () {
6232 this.customStyle = {};
6233 this._styleCache = null;
6234 this._styleProperties = null;
6235 this._scopeSelector = null;
6236 this._ownStyleProperties = null;
6237 this._customStyle = null;
6238 },
6239 _needsStyleProperties: function () {
6240 return Boolean(this._ownStylePropertyNames && this._ownStylePropertyNames.length );
6241 },
6242 _beforeAttached: function () {
6243 if (!this._scopeSelector && this._needsStyleProperties()) {
6244 this._updateStyleProperties();
6245 }
6246 },
6247 _findStyleHost: function () {
6248 var e = this, root;
6249 while (root = Polymer.dom(e).getOwnerRoot()) {
6250 if (Polymer.isInstance(root.host)) {
6251 return root.host;
6252 }
6253 e = root.host;
6254 }
6255 return styleDefaults;
6256 },
6257 _updateStyleProperties: function () {
6258 var info, scope = this._findStyleHost();
6259 if (!scope._styleCache) {
6260 scope._styleCache = new Polymer.StyleCache();
6261 }
6262 var scopeData = propertyUtils.propertyDataFromStyles(scope._styles, this);
6263 scopeData.key.customStyle = this.customStyle;
6264 info = scope._styleCache.retrieve(this.is, scopeData.key, this._styles);
6265 var scopeCached = Boolean(info);
6266 if (scopeCached) {
6267 this._styleProperties = info._styleProperties;
6268 } else {
6269 this._computeStyleProperties(scopeData.properties);
6270 }
6271 this._computeOwnStyleProperties();
6272 if (!scopeCached) {
6273 info = styleCache.retrieve(this.is, this._ownStyleProperties, this._styles);
6274 }
6275 var globalCached = Boolean(info) && !scopeCached;
6276 var style = this._applyStyleProperties(info);
6277 if (!scopeCached) {
6278 style = style && nativeShadow ? style.cloneNode(true) : style;
6279 info = {
6280 style: style,
6281 _scopeSelector: this._scopeSelector,
6282 _styleProperties: this._styleProperties
6283 };
6284 scopeData.key.customStyle = {};
6285 this.mixin(scopeData.key.customStyle, this.customStyle);
6286 scope._styleCache.store(this.is, info, scopeData.key, this._styles);
6287 if (!globalCached) {
6288 styleCache.store(this.is, Object.create(info), this._ownStyleProperties, this._s tyles);
6289 }
6290 }
6291 },
6292 _computeStyleProperties: function (scopeProps) {
6293 var scope = this._findStyleHost();
6294 if (!scope._styleProperties) {
6295 scope._computeStyleProperties();
6296 }
6297 var props = Object.create(scope._styleProperties);
6298 this.mixin(props, propertyUtils.hostPropertiesFromStyles(this._styles));
6299 scopeProps = scopeProps || propertyUtils.propertyDataFromStyles(scope._styles, t his).properties;
6300 this.mixin(props, scopeProps);
6301 this.mixin(props, propertyUtils.scopePropertiesFromStyles(this._styles));
6302 propertyUtils.mixinCustomStyle(props, this.customStyle);
6303 propertyUtils.reify(props);
6304 this._styleProperties = props;
6305 },
6306 _computeOwnStyleProperties: function () {
6307 var props = {};
6308 for (var i = 0, n; i < this._ownStylePropertyNames.length; i++) {
6309 n = this._ownStylePropertyNames[i];
6310 props[n] = this._styleProperties[n];
6311 }
6312 this._ownStyleProperties = props;
6313 },
6314 _scopeCount: 0,
6315 _applyStyleProperties: function (info) {
6316 var oldScopeSelector = this._scopeSelector;
6317 this._scopeSelector = info ? info._scopeSelector : this.is + '-' + this.__proto_ _._scopeCount++;
6318 var style = propertyUtils.applyElementStyle(this, this._styleProperties, this._s copeSelector, info && info.style);
6319 if (!nativeShadow) {
6320 propertyUtils.applyElementScopeSelector(this, this._scopeSelector, oldScopeSelec tor, this._scopeCssViaAttr);
6321 }
6322 return style;
6323 },
6324 serializeValueToAttribute: function (value, attribute, node) {
6325 node = node || this;
6326 if (attribute === 'class' && !nativeShadow) {
6327 var host = node === this ? this.domHost || this.dataHost : this;
6328 if (host) {
6329 value = host._scopeElementClass(node, value);
6330 }
6331 }
6332 node = this.shadyRoot && this.shadyRoot._hasDistributed ? Polymer.dom(node) : no de;
6333 serializeValueToAttribute.call(this, value, attribute, node);
6334 },
6335 _scopeElementClass: function (element, selector) {
6336 if (!nativeShadow && !this._scopeCssViaAttr) {
6337 selector = (selector ? selector + ' ' : '') + SCOPE_NAME + ' ' + this.is + (elem ent._scopeSelector ? ' ' + XSCOPE_NAME + ' ' + element._scopeSelector : '');
6338 }
6339 return selector;
6340 },
6341 updateStyles: function (properties) {
6342 if (this.isAttached) {
6343 if (properties) {
6344 this.mixin(this.customStyle, properties);
6345 }
6346 if (this._needsStyleProperties()) {
6347 this._updateStyleProperties();
6348 } else {
6349 this._styleProperties = null;
6350 }
6351 if (this._styleCache) {
6352 this._styleCache.clear();
6353 }
6354 this._updateRootStyles();
6355 }
6356 },
6357 _updateRootStyles: function (root) {
6358 root = root || this.root;
6359 var c$ = Polymer.dom(root)._query(function (e) {
6360 return e.shadyRoot || e.shadowRoot;
6361 });
6362 for (var i = 0, l = c$.length, c; i < l && (c = c$[i]); i++) {
6363 if (c.updateStyles) {
6364 c.updateStyles();
6365 }
6366 }
6367 }
6368 });
6369 Polymer.updateStyles = function (properties) {
6370 styleDefaults.updateStyles(properties);
6371 Polymer.Base._updateRootStyles(document);
6372 };
6373 var styleCache = new Polymer.StyleCache();
6374 Polymer.customStyleCache = styleCache;
6375 var SCOPE_NAME = styleTransformer.SCOPE_NAME;
6376 var XSCOPE_NAME = propertyUtils.XSCOPE_NAME;
6377 }());
6378 Polymer.Base._addFeature({
6379 _registerFeatures: function () {
6380 this._prepIs();
6381 this._prepConstructor();
6382 this._prepStyles();
6383 },
6384 _finishRegisterFeatures: function () {
6385 this._prepTemplate();
6386 this._prepShimStyles();
6387 this._prepAnnotations();
6388 this._prepEffects();
6389 this._prepBehaviors();
6390 this._prepPropertyInfo();
6391 this._prepBindings();
6392 this._prepShady();
6393 },
6394 _prepBehavior: function (b) {
6395 this._addPropertyEffects(b.properties);
6396 this._addComplexObserverEffects(b.observers);
6397 this._addHostAttributes(b.hostAttributes);
6398 },
6399 _initFeatures: function () {
6400 this._setupGestures();
6401 this._setupConfigure();
6402 this._setupStyleProperties();
6403 this._setupDebouncers();
6404 this._setupShady();
6405 this._registerHost();
6406 if (this._template) {
6407 this._poolContent();
6408 this._beginHosting();
6409 this._stampTemplate();
6410 this._endHosting();
6411 this._marshalAnnotationReferences();
6412 }
6413 this._marshalInstanceEffects();
6414 this._marshalBehaviors();
6415 this._marshalHostAttributes();
6416 this._marshalAttributes();
6417 this._tryReady();
6418 },
6419 _marshalBehavior: function (b) {
6420 if (b.listeners) {
6421 this._listenListeners(b.listeners);
6422 }
6423 }
6424 });
6425 (function () {
6426 var propertyUtils = Polymer.StyleProperties;
6427 var styleUtil = Polymer.StyleUtil;
6428 var cssParse = Polymer.CssParse;
6429 var styleDefaults = Polymer.StyleDefaults;
6430 var styleTransformer = Polymer.StyleTransformer;
6431 Polymer({
6432 is: 'custom-style',
6433 extends: 'style',
6434 _template: null,
6435 properties: { include: String },
6436 ready: function () {
6437 this._tryApply();
6438 },
6439 attached: function () {
6440 this._tryApply();
6441 },
6442 _tryApply: function () {
6443 if (!this._appliesToDocument) {
6444 if (this.parentNode && this.parentNode.localName !== 'dom-module') {
6445 this._appliesToDocument = true;
6446 var e = this.__appliedElement || this;
6447 styleDefaults.addStyle(e);
6448 if (e.textContent || this.include) {
6449 this._apply(true);
6450 } else {
6451 var self = this;
6452 var observer = new MutationObserver(function () {
6453 observer.disconnect();
6454 self._apply(true);
6455 });
6456 observer.observe(e, { childList: true });
6457 }
6458 }
6459 }
6460 },
6461 _apply: function (deferProperties) {
6462 var e = this.__appliedElement || this;
6463 if (this.include) {
6464 e.textContent = styleUtil.cssFromModules(this.include, true) + e.textContent;
6465 }
6466 if (e.textContent) {
6467 styleUtil.forEachRule(styleUtil.rulesForStyle(e), function (rule) {
6468 styleTransformer.documentRule(rule);
6469 });
6470 var self = this;
6471 var fn = function fn() {
6472 self._applyCustomProperties(e);
6473 };
6474 if (this._pendingApplyProperties) {
6475 cancelAnimationFrame(this._pendingApplyProperties);
6476 this._pendingApplyProperties = null;
6477 }
6478 if (deferProperties) {
6479 this._pendingApplyProperties = requestAnimationFrame(fn);
6480 } else {
6481 fn();
6482 }
6483 }
6484 },
6485 _applyCustomProperties: function (element) {
6486 this._computeStyleProperties();
6487 var props = this._styleProperties;
6488 var rules = styleUtil.rulesForStyle(element);
6489 element.textContent = styleUtil.toCssText(rules, function (rule) {
6490 var css = rule.cssText = rule.parsedCssText;
6491 if (rule.propertyInfo && rule.propertyInfo.cssText) {
6492 css = cssParse.removeCustomPropAssignment(css);
6493 rule.cssText = propertyUtils.valueForProperties(css, props);
6494 }
6495 });
6496 }
6497 });
6498 }());
6499 Polymer.Templatizer = {
6500 properties: { __hideTemplateChildren__: { observer: '_showHideChildren' } },
6501 _instanceProps: Polymer.nob,
6502 _parentPropPrefix: '_parent_',
6503 templatize: function (template) {
6504 this._templatized = template;
6505 if (!template._content) {
6506 template._content = template.content;
6507 }
6508 if (template._content._ctor) {
6509 this.ctor = template._content._ctor;
6510 this._prepParentProperties(this.ctor.prototype, template);
6511 return;
6512 }
6513 var archetype = Object.create(Polymer.Base);
6514 this._customPrepAnnotations(archetype, template);
6515 this._prepParentProperties(archetype, template);
6516 archetype._prepEffects();
6517 this._customPrepEffects(archetype);
6518 archetype._prepBehaviors();
6519 archetype._prepPropertyInfo();
6520 archetype._prepBindings();
6521 archetype._notifyPathUp = this._notifyPathUpImpl;
6522 archetype._scopeElementClass = this._scopeElementClassImpl;
6523 archetype.listen = this._listenImpl;
6524 archetype._showHideChildren = this._showHideChildrenImpl;
6525 archetype.__setPropertyOrig = this.__setProperty;
6526 archetype.__setProperty = this.__setPropertyImpl;
6527 var _constructor = this._constructorImpl;
6528 var ctor = function TemplateInstance(model, host) {
6529 _constructor.call(this, model, host);
6530 };
6531 ctor.prototype = archetype;
6532 archetype.constructor = ctor;
6533 template._content._ctor = ctor;
6534 this.ctor = ctor;
6535 },
6536 _getRootDataHost: function () {
6537 return this.dataHost && this.dataHost._rootDataHost || this.dataHost;
6538 },
6539 _showHideChildrenImpl: function (hide) {
6540 var c = this._children;
6541 for (var i = 0; i < c.length; i++) {
6542 var n = c[i];
6543 if (Boolean(hide) != Boolean(n.__hideTemplateChildren__)) {
6544 if (n.nodeType === Node.TEXT_NODE) {
6545 if (hide) {
6546 n.__polymerTextContent__ = n.textContent;
6547 n.textContent = '';
6548 } else {
6549 n.textContent = n.__polymerTextContent__;
6550 }
6551 } else if (n.style) {
6552 if (hide) {
6553 n.__polymerDisplay__ = n.style.display;
6554 n.style.display = 'none';
6555 } else {
6556 n.style.display = n.__polymerDisplay__;
6557 }
6558 }
6559 }
6560 n.__hideTemplateChildren__ = hide;
6561 }
6562 },
6563 __setPropertyImpl: function (property, value, fromAbove, node) {
6564 if (node && node.__hideTemplateChildren__ && property == 'textContent') {
6565 property = '__polymerTextContent__';
6566 }
6567 this.__setPropertyOrig(property, value, fromAbove, node);
6568 },
6569 _debounceTemplate: function (fn) {
6570 Polymer.dom.addDebouncer(this.debounce('_debounceTemplate', fn));
6571 },
6572 _flushTemplates: function () {
6573 Polymer.dom.flush();
6574 },
6575 _customPrepEffects: function (archetype) {
6576 var parentProps = archetype._parentProps;
6577 for (var prop in parentProps) {
6578 archetype._addPropertyEffect(prop, 'function', this._createHostPropEffector(prop ));
6579 }
6580 for (prop in this._instanceProps) {
6581 archetype._addPropertyEffect(prop, 'function', this._createInstancePropEffector( prop));
6582 }
6583 },
6584 _customPrepAnnotations: function (archetype, template) {
6585 archetype._template = template;
6586 var c = template._content;
6587 if (!c._notes) {
6588 var rootDataHost = archetype._rootDataHost;
6589 if (rootDataHost) {
6590 Polymer.Annotations.prepElement = function () {
6591 rootDataHost._prepElement();
6592 };
6593 }
6594 c._notes = Polymer.Annotations.parseAnnotations(template);
6595 Polymer.Annotations.prepElement = null;
6596 this._processAnnotations(c._notes);
6597 }
6598 archetype._notes = c._notes;
6599 archetype._parentProps = c._parentProps;
6600 },
6601 _prepParentProperties: function (archetype, template) {
6602 var parentProps = this._parentProps = archetype._parentProps;
6603 if (this._forwardParentProp && parentProps) {
6604 var proto = archetype._parentPropProto;
6605 var prop;
6606 if (!proto) {
6607 for (prop in this._instanceProps) {
6608 delete parentProps[prop];
6609 }
6610 proto = archetype._parentPropProto = Object.create(null);
6611 if (template != this) {
6612 Polymer.Bind.prepareModel(proto);
6613 Polymer.Base.prepareModelNotifyPath(proto);
6614 }
6615 for (prop in parentProps) {
6616 var parentProp = this._parentPropPrefix + prop;
6617 var effects = [
6618 {
6619 kind: 'function',
6620 effect: this._createForwardPropEffector(prop),
6621 fn: Polymer.Bind._functionEffect
6622 },
6623 {
6624 kind: 'notify',
6625 fn: Polymer.Bind._notifyEffect,
6626 effect: { event: Polymer.CaseMap.camelToDashCase(parentProp) + '-changed' }
6627 }
6628 ];
6629 Polymer.Bind._createAccessors(proto, parentProp, effects);
6630 }
6631 }
6632 var self = this;
6633 if (template != this) {
6634 Polymer.Bind.prepareInstance(template);
6635 template._forwardParentProp = function (source, value) {
6636 self._forwardParentProp(source, value);
6637 };
6638 }
6639 this._extendTemplate(template, proto);
6640 template._pathEffector = function (path, value, fromAbove) {
6641 return self._pathEffectorImpl(path, value, fromAbove);
6642 };
6643 }
6644 },
6645 _createForwardPropEffector: function (prop) {
6646 return function (source, value) {
6647 this._forwardParentProp(prop, value);
6648 };
6649 },
6650 _createHostPropEffector: function (prop) {
6651 var prefix = this._parentPropPrefix;
6652 return function (source, value) {
6653 this.dataHost._templatized[prefix + prop] = value;
6654 };
6655 },
6656 _createInstancePropEffector: function (prop) {
6657 return function (source, value, old, fromAbove) {
6658 if (!fromAbove) {
6659 this.dataHost._forwardInstanceProp(this, prop, value);
6660 }
6661 };
6662 },
6663 _extendTemplate: function (template, proto) {
6664 var n$ = Object.getOwnPropertyNames(proto);
6665 if (proto._propertySetter) {
6666 template._propertySetter = proto._propertySetter;
6667 }
6668 for (var i = 0, n; i < n$.length && (n = n$[i]); i++) {
6669 var val = template[n];
6670 var pd = Object.getOwnPropertyDescriptor(proto, n);
6671 Object.defineProperty(template, n, pd);
6672 if (val !== undefined) {
6673 template._propertySetter(n, val);
6674 }
6675 }
6676 },
6677 _showHideChildren: function (hidden) {
6678 },
6679 _forwardInstancePath: function (inst, path, value) {
6680 },
6681 _forwardInstanceProp: function (inst, prop, value) {
6682 },
6683 _notifyPathUpImpl: function (path, value) {
6684 var dataHost = this.dataHost;
6685 var dot = path.indexOf('.');
6686 var root = dot < 0 ? path : path.slice(0, dot);
6687 dataHost._forwardInstancePath.call(dataHost, this, path, value);
6688 if (root in dataHost._parentProps) {
6689 dataHost._templatized.notifyPath(dataHost._parentPropPrefix + path, value);
6690 }
6691 },
6692 _pathEffectorImpl: function (path, value, fromAbove) {
6693 if (this._forwardParentPath) {
6694 if (path.indexOf(this._parentPropPrefix) === 0) {
6695 var subPath = path.substring(this._parentPropPrefix.length);
6696 var model = this._modelForPath(subPath);
6697 if (model in this._parentProps) {
6698 this._forwardParentPath(subPath, value);
6699 }
6700 }
6701 }
6702 Polymer.Base._pathEffector.call(this._templatized, path, value, fromAbove);
6703 },
6704 _constructorImpl: function (model, host) {
6705 this._rootDataHost = host._getRootDataHost();
6706 this._setupConfigure(model);
6707 this._registerHost(host);
6708 this._beginHosting();
6709 this.root = this.instanceTemplate(this._template);
6710 this.root.__noContent = !this._notes._hasContent;
6711 this.root.__styleScoped = true;
6712 this._endHosting();
6713 this._marshalAnnotatedNodes();
6714 this._marshalInstanceEffects();
6715 this._marshalAnnotatedListeners();
6716 var children = [];
6717 for (var n = this.root.firstChild; n; n = n.nextSibling) {
6718 children.push(n);
6719 n._templateInstance = this;
6720 }
6721 this._children = children;
6722 if (host.__hideTemplateChildren__) {
6723 this._showHideChildren(true);
6724 }
6725 this._tryReady();
6726 },
6727 _listenImpl: function (node, eventName, methodName) {
6728 var model = this;
6729 var host = this._rootDataHost;
6730 var handler = host._createEventHandler(node, eventName, methodName);
6731 var decorated = function (e) {
6732 e.model = model;
6733 handler(e);
6734 };
6735 host._listen(node, eventName, decorated);
6736 },
6737 _scopeElementClassImpl: function (node, value) {
6738 var host = this._rootDataHost;
6739 if (host) {
6740 return host._scopeElementClass(node, value);
6741 }
6742 },
6743 stamp: function (model) {
6744 model = model || {};
6745 if (this._parentProps) {
6746 var templatized = this._templatized;
6747 for (var prop in this._parentProps) {
6748 if (model[prop] === undefined) {
6749 model[prop] = templatized[this._parentPropPrefix + prop];
6750 }
6751 }
6752 }
6753 return new this.ctor(model, this);
6754 },
6755 modelForElement: function (el) {
6756 var model;
6757 while (el) {
6758 if (model = el._templateInstance) {
6759 if (model.dataHost != this) {
6760 el = model.dataHost;
6761 } else {
6762 return model;
6763 }
6764 } else {
6765 el = el.parentNode;
6766 }
6767 }
6768 }
6769 };
6770 Polymer({
6771 is: 'dom-template',
6772 extends: 'template',
6773 _template: null,
6774 behaviors: [Polymer.Templatizer],
6775 ready: function () {
6776 this.templatize(this);
6777 }
6778 });
6779 Polymer._collections = new WeakMap();
6780 Polymer.Collection = function (userArray) {
6781 Polymer._collections.set(userArray, this);
6782 this.userArray = userArray;
6783 this.store = userArray.slice();
6784 this.initMap();
6785 };
6786 Polymer.Collection.prototype = {
6787 constructor: Polymer.Collection,
6788 initMap: function () {
6789 var omap = this.omap = new WeakMap();
6790 var pmap = this.pmap = {};
6791 var s = this.store;
6792 for (var i = 0; i < s.length; i++) {
6793 var item = s[i];
6794 if (item && typeof item == 'object') {
6795 omap.set(item, i);
6796 } else {
6797 pmap[item] = i;
6798 }
6799 }
6800 },
6801 add: function (item) {
6802 var key = this.store.push(item) - 1;
6803 if (item && typeof item == 'object') {
6804 this.omap.set(item, key);
6805 } else {
6806 this.pmap[item] = key;
6807 }
6808 return '#' + key;
6809 },
6810 removeKey: function (key) {
6811 if (key = this._parseKey(key)) {
6812 this._removeFromMap(this.store[key]);
6813 delete this.store[key];
6814 }
6815 },
6816 _removeFromMap: function (item) {
6817 if (item && typeof item == 'object') {
6818 this.omap.delete(item);
6819 } else {
6820 delete this.pmap[item];
6821 }
6822 },
6823 remove: function (item) {
6824 var key = this.getKey(item);
6825 this.removeKey(key);
6826 return key;
6827 },
6828 getKey: function (item) {
6829 var key;
6830 if (item && typeof item == 'object') {
6831 key = this.omap.get(item);
6832 } else {
6833 key = this.pmap[item];
6834 }
6835 if (key != undefined) {
6836 return '#' + key;
6837 }
6838 },
6839 getKeys: function () {
6840 return Object.keys(this.store).map(function (key) {
6841 return '#' + key;
6842 });
6843 },
6844 _parseKey: function (key) {
6845 if (key && key[0] == '#') {
6846 return key.slice(1);
6847 }
6848 },
6849 setItem: function (key, item) {
6850 if (key = this._parseKey(key)) {
6851 var old = this.store[key];
6852 if (old) {
6853 this._removeFromMap(old);
6854 }
6855 if (item && typeof item == 'object') {
6856 this.omap.set(item, key);
6857 } else {
6858 this.pmap[item] = key;
6859 }
6860 this.store[key] = item;
6861 }
6862 },
6863 getItem: function (key) {
6864 if (key = this._parseKey(key)) {
6865 return this.store[key];
6866 }
6867 },
6868 getItems: function () {
6869 var items = [], store = this.store;
6870 for (var key in store) {
6871 items.push(store[key]);
6872 }
6873 return items;
6874 },
6875 _applySplices: function (splices) {
6876 var keyMap = {}, key;
6877 for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
6878 s.addedKeys = [];
6879 for (var j = 0; j < s.removed.length; j++) {
6880 key = this.getKey(s.removed[j]);
6881 keyMap[key] = keyMap[key] ? null : -1;
6882 }
6883 for (j = 0; j < s.addedCount; j++) {
6884 var item = this.userArray[s.index + j];
6885 key = this.getKey(item);
6886 key = key === undefined ? this.add(item) : key;
6887 keyMap[key] = keyMap[key] ? null : 1;
6888 s.addedKeys.push(key);
6889 }
6890 }
6891 var removed = [];
6892 var added = [];
6893 for (key in keyMap) {
6894 if (keyMap[key] < 0) {
6895 this.removeKey(key);
6896 removed.push(key);
6897 }
6898 if (keyMap[key] > 0) {
6899 added.push(key);
6900 }
6901 }
6902 return [{
6903 removed: removed,
6904 added: added
6905 }];
6906 }
6907 };
6908 Polymer.Collection.get = function (userArray) {
6909 return Polymer._collections.get(userArray) || new Polymer.Collection(userArray);
6910 };
6911 Polymer.Collection.applySplices = function (userArray, splices) {
6912 var coll = Polymer._collections.get(userArray);
6913 return coll ? coll._applySplices(splices) : null;
6914 };
6915 Polymer({
6916 is: 'dom-repeat',
6917 extends: 'template',
6918 _template: null,
6919 properties: {
6920 items: { type: Array },
6921 as: {
6922 type: String,
6923 value: 'item'
6924 },
6925 indexAs: {
6926 type: String,
6927 value: 'index'
6928 },
6929 sort: {
6930 type: Function,
6931 observer: '_sortChanged'
6932 },
6933 filter: {
6934 type: Function,
6935 observer: '_filterChanged'
6936 },
6937 observe: {
6938 type: String,
6939 observer: '_observeChanged'
6940 },
6941 delay: Number,
6942 renderedItemCount: {
6943 type: Number,
6944 notify: true,
6945 readOnly: true
6946 },
6947 initialCount: {
6948 type: Number,
6949 observer: '_initializeChunking'
6950 },
6951 targetFramerate: {
6952 type: Number,
6953 value: 20
6954 },
6955 _targetFrameTime: {
6956 type: Number,
6957 computed: '_computeFrameTime(targetFramerate)'
6958 }
6959 },
6960 behaviors: [Polymer.Templatizer],
6961 observers: ['_itemsChanged(items.*)'],
6962 created: function () {
6963 this._instances = [];
6964 this._pool = [];
6965 this._limit = Infinity;
6966 var self = this;
6967 this._boundRenderChunk = function () {
6968 self._renderChunk();
6969 };
6970 },
6971 detached: function () {
6972 this.__isDetached = true;
6973 for (var i = 0; i < this._instances.length; i++) {
6974 this._detachInstance(i);
6975 }
6976 },
6977 attached: function () {
6978 if (this.__isDetached) {
6979 this.__isDetached = false;
6980 var parent = Polymer.dom(Polymer.dom(this).parentNode);
6981 for (var i = 0; i < this._instances.length; i++) {
6982 this._attachInstance(i, parent);
6983 }
6984 }
6985 },
6986 ready: function () {
6987 this._instanceProps = { __key__: true };
6988 this._instanceProps[this.as] = true;
6989 this._instanceProps[this.indexAs] = true;
6990 if (!this.ctor) {
6991 this.templatize(this);
6992 }
6993 },
6994 _sortChanged: function (sort) {
6995 var dataHost = this._getRootDataHost();
6996 this._sortFn = sort && (typeof sort == 'function' ? sort : function () {
6997 return dataHost[sort].apply(dataHost, arguments);
6998 });
6999 this._needFullRefresh = true;
7000 if (this.items) {
7001 this._debounceTemplate(this._render);
7002 }
7003 },
7004 _filterChanged: function (filter) {
7005 var dataHost = this._getRootDataHost();
7006 this._filterFn = filter && (typeof filter == 'function' ? filter : function () {
7007 return dataHost[filter].apply(dataHost, arguments);
7008 });
7009 this._needFullRefresh = true;
7010 if (this.items) {
7011 this._debounceTemplate(this._render);
7012 }
7013 },
7014 _computeFrameTime: function (rate) {
7015 return Math.ceil(1000 / rate);
7016 },
7017 _initializeChunking: function () {
7018 if (this.initialCount) {
7019 this._limit = this.initialCount;
7020 this._chunkCount = this.initialCount;
7021 this._lastChunkTime = performance.now();
7022 }
7023 },
7024 _tryRenderChunk: function () {
7025 if (this.items && this._limit < this.items.length) {
7026 this.debounce('renderChunk', this._requestRenderChunk);
7027 }
7028 },
7029 _requestRenderChunk: function () {
7030 requestAnimationFrame(this._boundRenderChunk);
7031 },
7032 _renderChunk: function () {
7033 var currChunkTime = performance.now();
7034 var ratio = this._targetFrameTime / (currChunkTime - this._lastChunkTime);
7035 this._chunkCount = Math.round(this._chunkCount * ratio) || 1;
7036 this._limit += this._chunkCount;
7037 this._lastChunkTime = currChunkTime;
7038 this._debounceTemplate(this._render);
7039 },
7040 _observeChanged: function () {
7041 this._observePaths = this.observe && this.observe.replace('.*', '.').split(' ');
7042 },
7043 _itemsChanged: function (change) {
7044 if (change.path == 'items') {
7045 if (Array.isArray(this.items)) {
7046 this.collection = Polymer.Collection.get(this.items);
7047 } else if (!this.items) {
7048 this.collection = null;
7049 } else {
7050 this._error(this._logf('dom-repeat', 'expected array for `items`,' + ' found', t his.items));
7051 }
7052 this._keySplices = [];
7053 this._indexSplices = [];
7054 this._needFullRefresh = true;
7055 this._initializeChunking();
7056 this._debounceTemplate(this._render);
7057 } else if (change.path == 'items.splices') {
7058 this._keySplices = this._keySplices.concat(change.value.keySplices);
7059 this._indexSplices = this._indexSplices.concat(change.value.indexSplices);
7060 this._debounceTemplate(this._render);
7061 } else {
7062 var subpath = change.path.slice(6);
7063 this._forwardItemPath(subpath, change.value);
7064 this._checkObservedPaths(subpath);
7065 }
7066 },
7067 _checkObservedPaths: function (path) {
7068 if (this._observePaths) {
7069 path = path.substring(path.indexOf('.') + 1);
7070 var paths = this._observePaths;
7071 for (var i = 0; i < paths.length; i++) {
7072 if (path.indexOf(paths[i]) === 0) {
7073 this._needFullRefresh = true;
7074 if (this.delay) {
7075 this.debounce('render', this._render, this.delay);
7076 } else {
7077 this._debounceTemplate(this._render);
7078 }
7079 return;
7080 }
7081 }
7082 }
7083 },
7084 render: function () {
7085 this._needFullRefresh = true;
7086 this._debounceTemplate(this._render);
7087 this._flushTemplates();
7088 },
7089 _render: function () {
7090 if (this._needFullRefresh) {
7091 this._applyFullRefresh();
7092 this._needFullRefresh = false;
7093 } else if (this._keySplices.length) {
7094 if (this._sortFn) {
7095 this._applySplicesUserSort(this._keySplices);
7096 } else {
7097 if (this._filterFn) {
7098 this._applyFullRefresh();
7099 } else {
7100 this._applySplicesArrayOrder(this._indexSplices);
7101 }
7102 }
7103 } else {
7104 }
7105 this._keySplices = [];
7106 this._indexSplices = [];
7107 var keyToIdx = this._keyToInstIdx = {};
7108 for (var i = this._instances.length - 1; i >= 0; i--) {
7109 var inst = this._instances[i];
7110 if (inst.isPlaceholder && i < this._limit) {
7111 inst = this._insertInstance(i, inst.__key__);
7112 } else if (!inst.isPlaceholder && i >= this._limit) {
7113 inst = this._downgradeInstance(i, inst.__key__);
7114 }
7115 keyToIdx[inst.__key__] = i;
7116 if (!inst.isPlaceholder) {
7117 inst.__setProperty(this.indexAs, i, true);
7118 }
7119 }
7120 this._pool.length = 0;
7121 this._setRenderedItemCount(this._instances.length);
7122 this.fire('dom-change');
7123 this._tryRenderChunk();
7124 },
7125 _applyFullRefresh: function () {
7126 var c = this.collection;
7127 var keys;
7128 if (this._sortFn) {
7129 keys = c ? c.getKeys() : [];
7130 } else {
7131 keys = [];
7132 var items = this.items;
7133 if (items) {
7134 for (var i = 0; i < items.length; i++) {
7135 keys.push(c.getKey(items[i]));
7136 }
7137 }
7138 }
7139 var self = this;
7140 if (this._filterFn) {
7141 keys = keys.filter(function (a) {
7142 return self._filterFn(c.getItem(a));
7143 });
7144 }
7145 if (this._sortFn) {
7146 keys.sort(function (a, b) {
7147 return self._sortFn(c.getItem(a), c.getItem(b));
7148 });
7149 }
7150 for (i = 0; i < keys.length; i++) {
7151 var key = keys[i];
7152 var inst = this._instances[i];
7153 if (inst) {
7154 inst.__key__ = key;
7155 if (!inst.isPlaceholder && i < this._limit) {
7156 inst.__setProperty(this.as, c.getItem(key), true);
7157 }
7158 } else if (i < this._limit) {
7159 this._insertInstance(i, key);
7160 } else {
7161 this._insertPlaceholder(i, key);
7162 }
7163 }
7164 for (var j = this._instances.length - 1; j >= i; j--) {
7165 this._detachAndRemoveInstance(j);
7166 }
7167 },
7168 _numericSort: function (a, b) {
7169 return a - b;
7170 },
7171 _applySplicesUserSort: function (splices) {
7172 var c = this.collection;
7173 var keyMap = {};
7174 var key;
7175 for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
7176 for (var j = 0; j < s.removed.length; j++) {
7177 key = s.removed[j];
7178 keyMap[key] = keyMap[key] ? null : -1;
7179 }
7180 for (j = 0; j < s.added.length; j++) {
7181 key = s.added[j];
7182 keyMap[key] = keyMap[key] ? null : 1;
7183 }
7184 }
7185 var removedIdxs = [];
7186 var addedKeys = [];
7187 for (key in keyMap) {
7188 if (keyMap[key] === -1) {
7189 removedIdxs.push(this._keyToInstIdx[key]);
7190 }
7191 if (keyMap[key] === 1) {
7192 addedKeys.push(key);
7193 }
7194 }
7195 if (removedIdxs.length) {
7196 removedIdxs.sort(this._numericSort);
7197 for (i = removedIdxs.length - 1; i >= 0; i--) {
7198 var idx = removedIdxs[i];
7199 if (idx !== undefined) {
7200 this._detachAndRemoveInstance(idx);
7201 }
7202 }
7203 }
7204 var self = this;
7205 if (addedKeys.length) {
7206 if (this._filterFn) {
7207 addedKeys = addedKeys.filter(function (a) {
7208 return self._filterFn(c.getItem(a));
7209 });
7210 }
7211 addedKeys.sort(function (a, b) {
7212 return self._sortFn(c.getItem(a), c.getItem(b));
7213 });
7214 var start = 0;
7215 for (i = 0; i < addedKeys.length; i++) {
7216 start = this._insertRowUserSort(start, addedKeys[i]);
7217 }
7218 }
7219 },
7220 _insertRowUserSort: function (start, key) {
7221 var c = this.collection;
7222 var item = c.getItem(key);
7223 var end = this._instances.length - 1;
7224 var idx = -1;
7225 while (start <= end) {
7226 var mid = start + end >> 1;
7227 var midKey = this._instances[mid].__key__;
7228 var cmp = this._sortFn(c.getItem(midKey), item);
7229 if (cmp < 0) {
7230 start = mid + 1;
7231 } else if (cmp > 0) {
7232 end = mid - 1;
7233 } else {
7234 idx = mid;
7235 break;
7236 }
7237 }
7238 if (idx < 0) {
7239 idx = end + 1;
7240 }
7241 this._insertPlaceholder(idx, key);
7242 return idx;
7243 },
7244 _applySplicesArrayOrder: function (splices) {
7245 for (var i = 0, s; i < splices.length && (s = splices[i]); i++) {
7246 for (var j = 0; j < s.removed.length; j++) {
7247 this._detachAndRemoveInstance(s.index);
7248 }
7249 for (j = 0; j < s.addedKeys.length; j++) {
7250 this._insertPlaceholder(s.index + j, s.addedKeys[j]);
7251 }
7252 }
7253 },
7254 _detachInstance: function (idx) {
7255 var inst = this._instances[idx];
7256 if (!inst.isPlaceholder) {
7257 for (var i = 0; i < inst._children.length; i++) {
7258 var el = inst._children[i];
7259 Polymer.dom(inst.root).appendChild(el);
7260 }
7261 return inst;
7262 }
7263 },
7264 _attachInstance: function (idx, parent) {
7265 var inst = this._instances[idx];
7266 if (!inst.isPlaceholder) {
7267 parent.insertBefore(inst.root, this);
7268 }
7269 },
7270 _detachAndRemoveInstance: function (idx) {
7271 var inst = this._detachInstance(idx);
7272 if (inst) {
7273 this._pool.push(inst);
7274 }
7275 this._instances.splice(idx, 1);
7276 },
7277 _insertPlaceholder: function (idx, key) {
7278 this._instances.splice(idx, 0, {
7279 isPlaceholder: true,
7280 __key__: key
7281 });
7282 },
7283 _stampInstance: function (idx, key) {
7284 var model = { __key__: key };
7285 model[this.as] = this.collection.getItem(key);
7286 model[this.indexAs] = idx;
7287 return this.stamp(model);
7288 },
7289 _insertInstance: function (idx, key) {
7290 var inst = this._pool.pop();
7291 if (inst) {
7292 inst.__setProperty(this.as, this.collection.getItem(key), true);
7293 inst.__setProperty('__key__', key, true);
7294 } else {
7295 inst = this._stampInstance(idx, key);
7296 }
7297 var beforeRow = this._instances[idx + 1];
7298 var beforeNode = beforeRow && !beforeRow.isPlaceholder ? beforeRow._children[0] : this;
7299 var parentNode = Polymer.dom(this).parentNode;
7300 Polymer.dom(parentNode).insertBefore(inst.root, beforeNode);
7301 this._instances[idx] = inst;
7302 return inst;
7303 },
7304 _downgradeInstance: function (idx, key) {
7305 var inst = this._detachInstance(idx);
7306 if (inst) {
7307 this._pool.push(inst);
7308 }
7309 inst = {
7310 isPlaceholder: true,
7311 __key__: key
7312 };
7313 this._instances[idx] = inst;
7314 return inst;
7315 },
7316 _showHideChildren: function (hidden) {
7317 for (var i = 0; i < this._instances.length; i++) {
7318 this._instances[i]._showHideChildren(hidden);
7319 }
7320 },
7321 _forwardInstanceProp: function (inst, prop, value) {
7322 if (prop == this.as) {
7323 var idx;
7324 if (this._sortFn || this._filterFn) {
7325 idx = this.items.indexOf(this.collection.getItem(inst.__key__));
7326 } else {
7327 idx = inst[this.indexAs];
7328 }
7329 this.set('items.' + idx, value);
7330 }
7331 },
7332 _forwardInstancePath: function (inst, path, value) {
7333 if (path.indexOf(this.as + '.') === 0) {
7334 this._notifyPath('items.' + inst.__key__ + '.' + path.slice(this.as.length + 1), value);
7335 }
7336 },
7337 _forwardParentProp: function (prop, value) {
7338 var i$ = this._instances;
7339 for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) {
7340 if (!inst.isPlaceholder) {
7341 inst.__setProperty(prop, value, true);
7342 }
7343 }
7344 },
7345 _forwardParentPath: function (path, value) {
7346 var i$ = this._instances;
7347 for (var i = 0, inst; i < i$.length && (inst = i$[i]); i++) {
7348 if (!inst.isPlaceholder) {
7349 inst._notifyPath(path, value, true);
7350 }
7351 }
7352 },
7353 _forwardItemPath: function (path, value) {
7354 if (this._keyToInstIdx) {
7355 var dot = path.indexOf('.');
7356 var key = path.substring(0, dot < 0 ? path.length : dot);
7357 var idx = this._keyToInstIdx[key];
7358 var inst = this._instances[idx];
7359 if (inst && !inst.isPlaceholder) {
7360 if (dot >= 0) {
7361 path = this.as + '.' + path.substring(dot + 1);
7362 inst._notifyPath(path, value, true);
7363 } else {
7364 inst.__setProperty(this.as, value, true);
7365 }
7366 }
7367 }
7368 },
7369 itemForElement: function (el) {
7370 var instance = this.modelForElement(el);
7371 return instance && instance[this.as];
7372 },
7373 keyForElement: function (el) {
7374 var instance = this.modelForElement(el);
7375 return instance && instance.__key__;
7376 },
7377 indexForElement: function (el) {
7378 var instance = this.modelForElement(el);
7379 return instance && instance[this.indexAs];
7380 }
7381 });
7382 Polymer({
7383 is: 'array-selector',
7384 _template: null,
7385 properties: {
7386 items: {
7387 type: Array,
7388 observer: 'clearSelection'
7389 },
7390 multi: {
7391 type: Boolean,
7392 value: false,
7393 observer: 'clearSelection'
7394 },
7395 selected: {
7396 type: Object,
7397 notify: true
7398 },
7399 selectedItem: {
7400 type: Object,
7401 notify: true
7402 },
7403 toggle: {
7404 type: Boolean,
7405 value: false
7406 }
7407 },
7408 clearSelection: function () {
7409 if (Array.isArray(this.selected)) {
7410 for (var i = 0; i < this.selected.length; i++) {
7411 this.unlinkPaths('selected.' + i);
7412 }
7413 } else {
7414 this.unlinkPaths('selected');
7415 this.unlinkPaths('selectedItem');
7416 }
7417 if (this.multi) {
7418 if (!this.selected || this.selected.length) {
7419 this.selected = [];
7420 this._selectedColl = Polymer.Collection.get(this.selected);
7421 }
7422 } else {
7423 this.selected = null;
7424 this._selectedColl = null;
7425 }
7426 this.selectedItem = null;
7427 },
7428 isSelected: function (item) {
7429 if (this.multi) {
7430 return this._selectedColl.getKey(item) !== undefined;
7431 } else {
7432 return this.selected == item;
7433 }
7434 },
7435 deselect: function (item) {
7436 if (this.multi) {
7437 if (this.isSelected(item)) {
7438 var skey = this._selectedColl.getKey(item);
7439 this.arrayDelete('selected', item);
7440 this.unlinkPaths('selected.' + skey);
7441 }
7442 } else {
7443 this.selected = null;
7444 this.selectedItem = null;
7445 this.unlinkPaths('selected');
7446 this.unlinkPaths('selectedItem');
7447 }
7448 },
7449 select: function (item) {
7450 var icol = Polymer.Collection.get(this.items);
7451 var key = icol.getKey(item);
7452 if (this.multi) {
7453 if (this.isSelected(item)) {
7454 if (this.toggle) {
7455 this.deselect(item);
7456 }
7457 } else {
7458 this.push('selected', item);
7459 var skey = this._selectedColl.getKey(item);
7460 this.linkPaths('selected.' + skey, 'items.' + key);
7461 }
7462 } else {
7463 if (this.toggle && item == this.selected) {
7464 this.deselect();
7465 } else {
7466 this.selected = item;
7467 this.selectedItem = item;
7468 this.linkPaths('selected', 'items.' + key);
7469 this.linkPaths('selectedItem', 'items.' + key);
7470 }
7471 }
7472 }
7473 });
7474 Polymer({
7475 is: 'dom-if',
7476 extends: 'template',
7477 _template: null,
7478 properties: {
7479 'if': {
7480 type: Boolean,
7481 value: false,
7482 observer: '_queueRender'
7483 },
7484 restamp: {
7485 type: Boolean,
7486 value: false,
7487 observer: '_queueRender'
7488 }
7489 },
7490 behaviors: [Polymer.Templatizer],
7491 _queueRender: function () {
7492 this._debounceTemplate(this._render);
7493 },
7494 detached: function () {
7495 if (!this.parentNode || this.parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE && (!Polymer.Settings.hasShadow || !(this.parentNode instanceof ShadowRoot))) {
7496 this._teardownInstance();
7497 }
7498 },
7499 attached: function () {
7500 if (this.if && this.ctor) {
7501 this.async(this._ensureInstance);
7502 }
7503 },
7504 render: function () {
7505 this._flushTemplates();
7506 },
7507 _render: function () {
7508 if (this.if) {
7509 if (!this.ctor) {
7510 this.templatize(this);
7511 }
7512 this._ensureInstance();
7513 this._showHideChildren();
7514 } else if (this.restamp) {
7515 this._teardownInstance();
7516 }
7517 if (!this.restamp && this._instance) {
7518 this._showHideChildren();
7519 }
7520 if (this.if != this._lastIf) {
7521 this.fire('dom-change');
7522 this._lastIf = this.if;
7523 }
7524 },
7525 _ensureInstance: function () {
7526 var parentNode = Polymer.dom(this).parentNode;
7527 if (parentNode) {
7528 var parent = Polymer.dom(parentNode);
7529 if (!this._instance) {
7530 this._instance = this.stamp();
7531 var root = this._instance.root;
7532 parent.insertBefore(root, this);
7533 } else {
7534 var c$ = this._instance._children;
7535 if (c$ && c$.length) {
7536 var lastChild = Polymer.dom(this).previousSibling;
7537 if (lastChild !== c$[c$.length - 1]) {
7538 for (var i = 0, n; i < c$.length && (n = c$[i]); i++) {
7539 parent.insertBefore(n, this);
7540 }
7541 }
7542 }
7543 }
7544 }
7545 },
7546 _teardownInstance: function () {
7547 if (this._instance) {
7548 var c$ = this._instance._children;
7549 if (c$ && c$.length) {
7550 var parent = Polymer.dom(Polymer.dom(c$[0]).parentNode);
7551 for (var i = 0, n; i < c$.length && (n = c$[i]); i++) {
7552 parent.removeChild(n);
7553 }
7554 }
7555 this._instance = null;
7556 }
7557 },
7558 _showHideChildren: function () {
7559 var hidden = this.__hideTemplateChildren__ || !this.if;
7560 if (this._instance) {
7561 this._instance._showHideChildren(hidden);
7562 }
7563 },
7564 _forwardParentProp: function (prop, value) {
7565 if (this._instance) {
7566 this._instance[prop] = value;
7567 }
7568 },
7569 _forwardParentPath: function (path, value) {
7570 if (this._instance) {
7571 this._instance._notifyPath(path, value, true);
7572 }
7573 }
7574 });
7575 Polymer({
7576 is: 'dom-bind',
7577 extends: 'template',
7578 _template: null,
7579 created: function () {
7580 var self = this;
7581 Polymer.RenderStatus.whenReady(function () {
7582 if (document.readyState == 'loading') {
7583 document.addEventListener('DOMContentLoaded', function () {
7584 self._markImportsReady();
7585 });
7586 } else {
7587 self._markImportsReady();
7588 }
7589 });
7590 },
7591 _ensureReady: function () {
7592 if (!this._readied) {
7593 this._readySelf();
7594 }
7595 },
7596 _markImportsReady: function () {
7597 this._importsReady = true;
7598 this._ensureReady();
7599 },
7600 _registerFeatures: function () {
7601 this._prepConstructor();
7602 },
7603 _insertChildren: function () {
7604 var parentDom = Polymer.dom(Polymer.dom(this).parentNode);
7605 parentDom.insertBefore(this.root, this);
7606 },
7607 _removeChildren: function () {
7608 if (this._children) {
7609 for (var i = 0; i < this._children.length; i++) {
7610 this.root.appendChild(this._children[i]);
7611 }
7612 }
7613 },
7614 _initFeatures: function () {
7615 },
7616 _scopeElementClass: function (element, selector) {
7617 if (this.dataHost) {
7618 return this.dataHost._scopeElementClass(element, selector);
7619 } else {
7620 return selector;
7621 }
7622 },
7623 _prepConfigure: function () {
7624 var config = {};
7625 for (var prop in this._propertyEffects) {
7626 config[prop] = this[prop];
7627 }
7628 var setupConfigure = this._setupConfigure;
7629 this._setupConfigure = function () {
7630 setupConfigure.call(this, config);
7631 };
7632 },
7633 attached: function () {
7634 if (this._importsReady) {
7635 this.render();
7636 }
7637 },
7638 detached: function () {
7639 this._removeChildren();
7640 },
7641 render: function () {
7642 this._ensureReady();
7643 if (!this._children) {
7644 this._template = this;
7645 this._prepAnnotations();
7646 this._prepEffects();
7647 this._prepBehaviors();
7648 this._prepConfigure();
7649 this._prepBindings();
7650 this._prepPropertyInfo();
7651 Polymer.Base._initFeatures.call(this);
7652 this._children = Polymer.TreeApi.arrayCopyChildNodes(this.root);
7653 }
7654 this._insertChildren();
7655 this.fire('dom-change');
7656 }
7657 });</script>
7658 <script>function MakePromise (asap) {
7659 function Promise(fn) {
7660 if (typeof this !== 'object' || typeof fn !== 'function') throw new TypeError();
7661 this._state = null;
7662 this._value = null;
7663 this._deferreds = []
7664
7665 doResolve(fn, resolve.bind(this), reject.bind(this));
7666 }
7667
7668 function handle(deferred) {
7669 var me = this;
7670 if (this._state === null) {
7671 this._deferreds.push(deferred);
7672 return
7673 }
7674 asap(function() {
7675 var cb = me._state ? deferred.onFulfilled : deferred.onR ejected
7676 if (typeof cb !== 'function') {
7677 (me._state ? deferred.resolve : deferred.reject) (me._value);
7678 return;
7679 }
7680 var ret;
7681 try {
7682 ret = cb(me._value);
7683 }
7684 catch (e) {
7685 deferred.reject(e);
7686 return;
7687 }
7688 deferred.resolve(ret);
7689 })
7690 }
7691
7692 function resolve(newValue) {
7693 try { //Promise Resolution Procedure: https://github.com/promise s-aplus/promises-spec#the-promise-resolution-procedure
7694 if (newValue === this) throw new TypeError();
7695 if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
7696 var then = newValue.then;
7697 if (typeof then === 'function') {
7698 doResolve(then.bind(newValue), resolve.b ind(this), reject.bind(this));
7699 return;
7700 }
7701 }
7702 this._state = true;
7703 this._value = newValue;
7704 finale.call(this);
7705 } catch (e) { reject.call(this, e); }
7706 }
7707
7708 function reject(newValue) {
7709 this._state = false;
7710 this._value = newValue;
7711 finale.call(this);
7712 }
7713
7714 function finale() {
7715 for (var i = 0, len = this._deferreds.length; i < len; i++) {
7716 handle.call(this, this._deferreds[i]);
7717 }
7718 this._deferreds = null;
7719 }
7720
7721 /**
7722 * Take a potentially misbehaving resolver function and make sure
7723 * onFulfilled and onRejected are only called once.
7724 *
7725 * Makes no guarantees about asynchrony.
7726 */
7727 function doResolve(fn, onFulfilled, onRejected) {
7728 var done = false;
7729 try {
7730 fn(function (value) {
7731 if (done) return;
7732 done = true;
7733 onFulfilled(value);
7734 }, function (reason) {
7735 if (done) return;
7736 done = true;
7737 onRejected(reason);
7738 })
7739 } catch (ex) {
7740 if (done) return;
7741 done = true;
7742 onRejected(ex);
7743 }
7744 }
7745
7746 Promise.prototype['catch'] = function (onRejected) {
7747 return this.then(null, onRejected);
7748 };
7749
7750 Promise.prototype.then = function(onFulfilled, onRejected) {
7751 var me = this;
7752 return new Promise(function(resolve, reject) {
7753 handle.call(me, {
7754 onFulfilled: onFulfilled,
7755 onRejected: onRejected,
7756 resolve: resolve,
7757 reject: reject
7758 });
7759 })
7760 };
7761
7762 Promise.resolve = function (value) {
7763 if (value && typeof value === 'object' && value.constructor === Promise) {
7764 return value;
7765 }
7766
7767 return new Promise(function (resolve) {
7768 resolve(value);
7769 });
7770 };
7771
7772 Promise.reject = function (value) {
7773 return new Promise(function (resolve, reject) {
7774 reject(value);
7775 });
7776 };
7777
7778
7779 return Promise;
7780 }
7781
7782 if (typeof module !== 'undefined') {
7783 module.exports = MakePromise;
7784 }
7785
7786 </script>
7787 <script>
7788 if (!window.Promise) {
7789 window.Promise = MakePromise(Polymer.Base.async);
7790 }
7791 </script>
7792 <script>
7793 'use strict';
7794
7795 Polymer({
7796 is: 'iron-request',
7797
7798 hostAttributes: {
7799 hidden: true
7800 },
7801
7802 properties: {
7803
7804 /**
7805 * A reference to the XMLHttpRequest instance used to generate the
7806 * network request.
7807 *
7808 * @type {XMLHttpRequest}
7809 */
7810 xhr: {
7811 type: Object,
7812 notify: true,
7813 readOnly: true,
7814 value: function() {
7815 return new XMLHttpRequest();
7816 }
7817 },
7818
7819 /**
7820 * A reference to the parsed response body, if the `xhr` has completely
7821 * resolved.
7822 *
7823 * @type {*}
7824 * @default null
7825 */
7826 response: {
7827 type: Object,
7828 notify: true,
7829 readOnly: true,
7830 value: function() {
7831 return null;
7832 }
7833 },
7834
7835 /**
7836 * A reference to the status code, if the `xhr` has completely resolved.
7837 */
7838 status: {
7839 type: Number,
7840 notify: true,
7841 readOnly: true,
7842 value: 0
7843 },
7844
7845 /**
7846 * A reference to the status text, if the `xhr` has completely resolved.
7847 */
7848 statusText: {
7849 type: String,
7850 notify: true,
7851 readOnly: true,
7852 value: ''
7853 },
7854
7855 /**
7856 * A promise that resolves when the `xhr` response comes back, or rejects
7857 * if there is an error before the `xhr` completes.
7858 *
7859 * @type {Promise}
7860 */
7861 completes: {
7862 type: Object,
7863 readOnly: true,
7864 notify: true,
7865 value: function() {
7866 return new Promise(function (resolve, reject) {
7867 this.resolveCompletes = resolve;
7868 this.rejectCompletes = reject;
7869 }.bind(this));
7870 }
7871 },
7872
7873 /**
7874 * An object that contains progress information emitted by the XHR if
7875 * available.
7876 *
7877 * @default {}
7878 */
7879 progress: {
7880 type: Object,
7881 notify: true,
7882 readOnly: true,
7883 value: function() {
7884 return {};
7885 }
7886 },
7887
7888 /**
7889 * Aborted will be true if an abort of the request is attempted.
7890 */
7891 aborted: {
7892 type: Boolean,
7893 notify: true,
7894 readOnly: true,
7895 value: false,
7896 },
7897
7898 /**
7899 * Errored will be true if the browser fired an error event from the
7900 * XHR object (mainly network errors).
7901 */
7902 errored: {
7903 type: Boolean,
7904 notify: true,
7905 readOnly: true,
7906 value: false
7907 },
7908
7909 /**
7910 * TimedOut will be true if the XHR threw a timeout event.
7911 */
7912 timedOut: {
7913 type: Boolean,
7914 notify: true,
7915 readOnly: true,
7916 value: false
7917 }
7918 },
7919
7920 /**
7921 * Succeeded is true if the request succeeded. The request succeeded if it
7922 * loaded without error, wasn't aborted, and the status code is ≥ 200, and
7923 * < 300, or if the status code is 0.
7924 *
7925 * The status code 0 is accepted as a success because some schemes - e.g.
7926 * file:// - don't provide status codes.
7927 *
7928 * @return {boolean}
7929 */
7930 get succeeded() {
7931 if (this.errored || this.aborted || this.timedOut) {
7932 return false;
7933 }
7934 var status = this.xhr.status || 0;
7935
7936 // Note: if we are using the file:// protocol, the status code will be 0
7937 // for all outcomes (successful or otherwise).
7938 return status === 0 ||
7939 (status >= 200 && status < 300);
7940 },
7941
7942 /**
7943 * Sends an HTTP request to the server and returns the XHR object.
7944 *
7945 * The handling of the `body` parameter will vary based on the Content-Type
7946 * header. See the docs for iron-ajax's `body` param for details.
7947 *
7948 * @param {{
7949 * url: string,
7950 * method: (string|undefined),
7951 * async: (boolean|undefined),
7952 * body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|u ndefined|Object),
7953 * headers: (Object|undefined),
7954 * handleAs: (string|undefined),
7955 * jsonPrefix: (string|undefined),
7956 * withCredentials: (boolean|undefined)}} options -
7957 * url The url to which the request is sent.
7958 * method The HTTP method to use, default is GET.
7959 * async By default, all requests are sent asynchronously. To send synch ronous requests,
7960 * set to true.
7961 * body The content for the request body for POST method.
7962 * headers HTTP request headers.
7963 * handleAs The response type. Default is 'text'.
7964 * withCredentials Whether or not to send credentials on the request. De fault is false.
7965 * timeout: (Number|undefined)
7966 * @return {Promise}
7967 */
7968 send: function (options) {
7969 var xhr = this.xhr;
7970
7971 if (xhr.readyState > 0) {
7972 return null;
7973 }
7974
7975 xhr.addEventListener('progress', function (progress) {
7976 this._setProgress({
7977 lengthComputable: progress.lengthComputable,
7978 loaded: progress.loaded,
7979 total: progress.total
7980 });
7981 }.bind(this))
7982
7983 xhr.addEventListener('error', function (error) {
7984 this._setErrored(true);
7985 this._updateStatus();
7986 this.rejectCompletes(error);
7987 }.bind(this));
7988
7989 xhr.addEventListener('timeout', function (error) {
7990 this._setTimedOut(true);
7991 this._updateStatus();
7992 this.rejectCompletes(error);
7993 }.bind(this));
7994
7995 xhr.addEventListener('abort', function () {
7996 this._updateStatus();
7997 this.rejectCompletes(new Error('Request aborted.'));
7998 }.bind(this));
7999
8000
8001 // Called after all of the above.
8002 xhr.addEventListener('loadend', function () {
8003 this._updateStatus();
8004
8005 if (!this.succeeded) {
8006 this.rejectCompletes(new Error('The request failed with status code: ' + this.xhr.status));
8007 return;
8008 }
8009
8010 this._setResponse(this.parseResponse());
8011 this.resolveCompletes(this);
8012 }.bind(this));
8013
8014 this.url = options.url;
8015 xhr.open(
8016 options.method || 'GET',
8017 options.url,
8018 options.async !== false
8019 );
8020
8021 var acceptType = {
8022 'json': 'application/json',
8023 'text': 'text/plain',
8024 'html': 'text/html',
8025 'xml': 'application/xml',
8026 'arraybuffer': 'application/octet-stream'
8027 }[options.handleAs];
8028 var headers = options.headers || Object.create(null);
8029 var newHeaders = Object.create(null);
8030 for (var key in headers) {
8031 newHeaders[key.toLowerCase()] = headers[key];
8032 }
8033 headers = newHeaders;
8034
8035 if (acceptType && !headers['accept']) {
8036 headers['accept'] = acceptType;
8037 }
8038 Object.keys(headers).forEach(function (requestHeader) {
8039 if (/[A-Z]/.test(requestHeader)) {
8040 console.error('Headers must be lower case, got', requestHeader);
8041 }
8042 xhr.setRequestHeader(
8043 requestHeader,
8044 headers[requestHeader]
8045 );
8046 }, this);
8047
8048 if (options.async !== false) {
8049 var handleAs = options.handleAs;
8050
8051 // If a JSON prefix is present, the responseType must be 'text' or the
8052 // browser won’t be able to parse the response.
8053 if (!!options.jsonPrefix || !handleAs) {
8054 handleAs = 'text';
8055 }
8056
8057 // In IE, `xhr.responseType` is an empty string when the response
8058 // returns. Hence, caching it as `xhr._responseType`.
8059 xhr.responseType = xhr._responseType = handleAs;
8060
8061 // Cache the JSON prefix, if it exists.
8062 if (!!options.jsonPrefix) {
8063 xhr._jsonPrefix = options.jsonPrefix;
8064 }
8065 }
8066
8067 xhr.withCredentials = !!options.withCredentials;
8068 xhr.timeout = options.timeout;
8069
8070 var body = this._encodeBodyObject(options.body, headers['content-type']);
8071
8072 xhr.send(
8073 /** @type {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|
8074 null|string|undefined} */
8075 (body));
8076
8077 return this.completes;
8078 },
8079
8080 /**
8081 * Attempts to parse the response body of the XHR. If parsing succeeds,
8082 * the value returned will be deserialized based on the `responseType`
8083 * set on the XHR.
8084 *
8085 * @return {*} The parsed response,
8086 * or undefined if there was an empty response or parsing failed.
8087 */
8088 parseResponse: function () {
8089 var xhr = this.xhr;
8090 var responseType = xhr.responseType || xhr._responseType;
8091 var preferResponseText = !this.xhr.responseType;
8092 var prefixLen = (xhr._jsonPrefix && xhr._jsonPrefix.length) || 0;
8093
8094 try {
8095 switch (responseType) {
8096 case 'json':
8097 // If the xhr object doesn't have a natural `xhr.responseType`,
8098 // we can assume that the browser hasn't parsed the response for us,
8099 // and so parsing is our responsibility. Likewise if response is
8100 // undefined, as there's no way to encode undefined in JSON.
8101 if (preferResponseText || xhr.response === undefined) {
8102 // Try to emulate the JSON section of the response body section of
8103 // the spec: https://xhr.spec.whatwg.org/#response-body
8104 // That is to say, we try to parse as JSON, but if anything goes
8105 // wrong return null.
8106 try {
8107 return JSON.parse(xhr.responseText);
8108 } catch (_) {
8109 return null;
8110 }
8111 }
8112
8113 return xhr.response;
8114 case 'xml':
8115 return xhr.responseXML;
8116 case 'blob':
8117 case 'document':
8118 case 'arraybuffer':
8119 return xhr.response;
8120 case 'text':
8121 default: {
8122 // If `prefixLen` is set, it implies the response should be parsed
8123 // as JSON once the prefix of length `prefixLen` is stripped from
8124 // it. Emulate the behavior above where null is returned on failure
8125 // to parse.
8126 if (prefixLen) {
8127 try {
8128 return JSON.parse(xhr.responseText.substring(prefixLen));
8129 } catch (_) {
8130 return null;
8131 }
8132 }
8133 return xhr.responseText;
8134 }
8135 }
8136 } catch (e) {
8137 this.rejectCompletes(new Error('Could not parse response. ' + e.message) );
8138 }
8139 },
8140
8141 /**
8142 * Aborts the request.
8143 */
8144 abort: function () {
8145 this._setAborted(true);
8146 this.xhr.abort();
8147 },
8148
8149 /**
8150 * @param {*} body The given body of the request to try and encode.
8151 * @param {?string} contentType The given content type, to infer an encoding
8152 * from.
8153 * @return {*} Either the encoded body as a string, if successful,
8154 * or the unaltered body object if no encoding could be inferred.
8155 */
8156 _encodeBodyObject: function(body, contentType) {
8157 if (typeof body == 'string') {
8158 return body; // Already encoded.
8159 }
8160 var bodyObj = /** @type {Object} */ (body);
8161 switch(contentType) {
8162 case('application/json'):
8163 return JSON.stringify(bodyObj);
8164 case('application/x-www-form-urlencoded'):
8165 return this._wwwFormUrlEncode(bodyObj);
8166 }
8167 return body;
8168 },
8169
8170 /**
8171 * @param {Object} object The object to encode as x-www-form-urlencoded.
8172 * @return {string} .
8173 */
8174 _wwwFormUrlEncode: function(object) {
8175 if (!object) {
8176 return '';
8177 }
8178 var pieces = [];
8179 Object.keys(object).forEach(function(key) {
8180 // TODO(rictic): handle array values here, in a consistent way with
8181 // iron-ajax params.
8182 pieces.push(
8183 this._wwwFormUrlEncodePiece(key) + '=' +
8184 this._wwwFormUrlEncodePiece(object[key]));
8185 }, this);
8186 return pieces.join('&');
8187 },
8188
8189 /**
8190 * @param {*} str A key or value to encode as x-www-form-urlencoded.
8191 * @return {string} .
8192 */
8193 _wwwFormUrlEncodePiece: function(str) {
8194 // Spec says to normalize newlines to \r\n and replace %20 spaces with +.
8195 // jQuery does this as well, so this is likely to be widely compatible.
8196 return encodeURIComponent(str.toString().replace(/\r?\n/g, '\r\n'))
8197 .replace(/%20/g, '+');
8198 },
8199
8200 /**
8201 * Updates the status code and status text.
8202 */
8203 _updateStatus: function() {
8204 this._setStatus(this.xhr.status);
8205 this._setStatusText((this.xhr.statusText === undefined) ? '' : this.xhr.st atusText);
8206 }
8207 });
8208 </script>
8209
8210 <script>
8211 'use strict';
8212
8213 Polymer({
8214
8215 is: 'iron-ajax',
8216
8217 /**
8218 * Fired when a request is sent.
8219 *
8220 * @event request
8221 */
8222
8223 /**
8224 * Fired when a response is received.
8225 *
8226 * @event response
8227 */
8228
8229 /**
8230 * Fired when an error is received.
8231 *
8232 * @event error
8233 */
8234
8235 hostAttributes: {
8236 hidden: true
8237 },
8238
8239 properties: {
8240 /**
8241 * The URL target of the request.
8242 */
8243 url: {
8244 type: String
8245 },
8246
8247 /**
8248 * An object that contains query parameters to be appended to the
8249 * specified `url` when generating a request. If you wish to set the body
8250 * content when making a POST request, you should use the `body` property
8251 * instead.
8252 */
8253 params: {
8254 type: Object,
8255 value: function() {
8256 return {};
8257 }
8258 },
8259
8260 /**
8261 * The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'.
8262 * Default is 'GET'.
8263 */
8264 method: {
8265 type: String,
8266 value: 'GET'
8267 },
8268
8269 /**
8270 * HTTP request headers to send.
8271 *
8272 * Example:
8273 *
8274 * <iron-ajax
8275 * auto
8276 * url="http://somesite.com"
8277 * headers='{"X-Requested-With": "XMLHttpRequest"}'
8278 * handle-as="json"></iron-ajax>
8279 *
8280 * Note: setting a `Content-Type` header here will override the value
8281 * specified by the `contentType` property of this element.
8282 */
8283 headers: {
8284 type: Object,
8285 value: function() {
8286 return {};
8287 }
8288 },
8289
8290 /**
8291 * Content type to use when sending data. If the `contentType` property
8292 * is set and a `Content-Type` header is specified in the `headers`
8293 * property, the `headers` property value will take precedence.
8294 *
8295 * Varies the handling of the `body` param.
8296 */
8297 contentType: {
8298 type: String,
8299 value: null
8300 },
8301
8302 /**
8303 * Body content to send with the request, typically used with "POST"
8304 * requests.
8305 *
8306 * If body is a string it will be sent unmodified.
8307 *
8308 * If Content-Type is set to a value listed below, then
8309 * the body will be encoded accordingly.
8310 *
8311 * * `content-type="application/json"`
8312 * * body is encoded like `{"foo":"bar baz","x":1}`
8313 * * `content-type="application/x-www-form-urlencoded"`
8314 * * body is encoded like `foo=bar+baz&x=1`
8315 *
8316 * Otherwise the body will be passed to the browser unmodified, and it
8317 * will handle any encoding (e.g. for FormData, Blob, ArrayBuffer).
8318 *
8319 * @type (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|u ndefined|Object)
8320 */
8321 body: {
8322 type: Object,
8323 value: null
8324 },
8325
8326 /**
8327 * Toggle whether XHR is synchronous or asynchronous. Don't change this
8328 * to true unless You Know What You Are Doing™.
8329 */
8330 sync: {
8331 type: Boolean,
8332 value: false
8333 },
8334
8335 /**
8336 * Specifies what data to store in the `response` property, and
8337 * to deliver as `event.detail.response` in `response` events.
8338 *
8339 * One of:
8340 *
8341 * `text`: uses `XHR.responseText`.
8342 *
8343 * `xml`: uses `XHR.responseXML`.
8344 *
8345 * `json`: uses `XHR.responseText` parsed as JSON.
8346 *
8347 * `arraybuffer`: uses `XHR.response`.
8348 *
8349 * `blob`: uses `XHR.response`.
8350 *
8351 * `document`: uses `XHR.response`.
8352 */
8353 handleAs: {
8354 type: String,
8355 value: 'json'
8356 },
8357
8358 /**
8359 * Set the withCredentials flag on the request.
8360 */
8361 withCredentials: {
8362 type: Boolean,
8363 value: false
8364 },
8365
8366 /**
8367 * Set the timeout flag on the request.
8368 */
8369 timeout: {
8370 type: Number,
8371 value: 0
8372 },
8373
8374 /**
8375 * If true, automatically performs an Ajax request when either `url` or
8376 * `params` changes.
8377 */
8378 auto: {
8379 type: Boolean,
8380 value: false
8381 },
8382
8383 /**
8384 * If true, error messages will automatically be logged to the console.
8385 */
8386 verbose: {
8387 type: Boolean,
8388 value: false
8389 },
8390
8391 /**
8392 * The most recent request made by this iron-ajax element.
8393 */
8394 lastRequest: {
8395 type: Object,
8396 notify: true,
8397 readOnly: true
8398 },
8399
8400 /**
8401 * True while lastRequest is in flight.
8402 */
8403 loading: {
8404 type: Boolean,
8405 notify: true,
8406 readOnly: true
8407 },
8408
8409 /**
8410 * lastRequest's response.
8411 *
8412 * Note that lastResponse and lastError are set when lastRequest finishes,
8413 * so if loading is true, then lastResponse and lastError will correspond
8414 * to the result of the previous request.
8415 *
8416 * The type of the response is determined by the value of `handleAs` at
8417 * the time that the request was generated.
8418 *
8419 * @type {Object}
8420 */
8421 lastResponse: {
8422 type: Object,
8423 notify: true,
8424 readOnly: true
8425 },
8426
8427 /**
8428 * lastRequest's error, if any.
8429 *
8430 * @type {Object}
8431 */
8432 lastError: {
8433 type: Object,
8434 notify: true,
8435 readOnly: true
8436 },
8437
8438 /**
8439 * An Array of all in-flight requests originating from this iron-ajax
8440 * element.
8441 */
8442 activeRequests: {
8443 type: Array,
8444 notify: true,
8445 readOnly: true,
8446 value: function() {
8447 return [];
8448 }
8449 },
8450
8451 /**
8452 * Length of time in milliseconds to debounce multiple automatically gener ated requests.
8453 */
8454 debounceDuration: {
8455 type: Number,
8456 value: 0,
8457 notify: true
8458 },
8459
8460 /**
8461 * Prefix to be stripped from a JSON response before parsing it.
8462 *
8463 * In order to prevent an attack using CSRF with Array responses
8464 * (http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnera bility.aspx/)
8465 * many backends will mitigate this by prefixing all JSON response bodies
8466 * with a string that would be nonsensical to a JavaScript parser.
8467 *
8468 */
8469 jsonPrefix: {
8470 type: String,
8471 value: ''
8472 },
8473
8474 /**
8475 * By default, these events do not bubble largely because the `error` even t has special
8476 * meaning in the window object. Setting this attribute will cause iron-aj ax's request,
8477 * response, and error events to bubble to the window object.
8478 */
8479 bubbles: {
8480 type: Boolean,
8481 value: false
8482 },
8483
8484 _boundHandleResponse: {
8485 type: Function,
8486 value: function() {
8487 return this._handleResponse.bind(this);
8488 }
8489 }
8490 },
8491
8492 observers: [
8493 '_requestOptionsChanged(url, method, params.*, headers, contentType, ' +
8494 'body, sync, handleAs, jsonPrefix, withCredentials, timeout, auto)'
8495 ],
8496
8497 /**
8498 * The query string that should be appended to the `url`, serialized from
8499 * the current value of `params`.
8500 *
8501 * @return {string}
8502 */
8503 get queryString () {
8504 var queryParts = [];
8505 var param;
8506 var value;
8507
8508 for (param in this.params) {
8509 value = this.params[param];
8510 param = window.encodeURIComponent(param);
8511
8512 if (Array.isArray(value)) {
8513 for (var i = 0; i < value.length; i++) {
8514 queryParts.push(param + '=' + window.encodeURIComponent(value[i]));
8515 }
8516 } else if (value !== null) {
8517 queryParts.push(param + '=' + window.encodeURIComponent(value));
8518 } else {
8519 queryParts.push(param);
8520 }
8521 }
8522
8523 return queryParts.join('&');
8524 },
8525
8526 /**
8527 * The `url` with query string (if `params` are specified), suitable for
8528 * providing to an `iron-request` instance.
8529 *
8530 * @return {string}
8531 */
8532 get requestUrl() {
8533 var queryString = this.queryString;
8534
8535 if (queryString) {
8536 var bindingChar = this.url.indexOf('?') >= 0 ? '&' : '?';
8537 return this.url + bindingChar + queryString;
8538 }
8539
8540 return this.url;
8541 },
8542
8543 /**
8544 * An object that maps header names to header values, first applying the
8545 * the value of `Content-Type` and then overlaying the headers specified
8546 * in the `headers` property.
8547 *
8548 * @return {Object}
8549 */
8550 get requestHeaders() {
8551 var headers = {};
8552 var contentType = this.contentType;
8553 if (contentType == null && (typeof this.body === 'string')) {
8554 contentType = 'application/x-www-form-urlencoded';
8555 }
8556 if (contentType) {
8557 headers['content-type'] = contentType;
8558 }
8559 var header;
8560
8561 if (this.headers instanceof Object) {
8562 for (header in this.headers) {
8563 headers[header] = this.headers[header].toString();
8564 }
8565 }
8566
8567 return headers;
8568 },
8569
8570 /**
8571 * Request options suitable for generating an `iron-request` instance based
8572 * on the current state of the `iron-ajax` instance's properties.
8573 *
8574 * @return {{
8575 * url: string,
8576 * method: (string|undefined),
8577 * async: (boolean|undefined),
8578 * body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|u ndefined|Object),
8579 * headers: (Object|undefined),
8580 * handleAs: (string|undefined),
8581 * jsonPrefix: (string|undefined),
8582 * withCredentials: (boolean|undefined)}}
8583 */
8584 toRequestOptions: function() {
8585 return {
8586 url: this.requestUrl || '',
8587 method: this.method,
8588 headers: this.requestHeaders,
8589 body: this.body,
8590 async: !this.sync,
8591 handleAs: this.handleAs,
8592 jsonPrefix: this.jsonPrefix,
8593 withCredentials: this.withCredentials,
8594 timeout: this.timeout
8595 };
8596 },
8597
8598 /**
8599 * Performs an AJAX request to the specified URL.
8600 *
8601 * @return {!IronRequestElement}
8602 */
8603 generateRequest: function() {
8604 var request = /** @type {!IronRequestElement} */ (document.createElement(' iron-request'));
8605 var requestOptions = this.toRequestOptions();
8606
8607 this.activeRequests.push(request);
8608
8609 request.completes.then(
8610 this._boundHandleResponse
8611 ).catch(
8612 this._handleError.bind(this, request)
8613 ).then(
8614 this._discardRequest.bind(this, request)
8615 );
8616
8617 request.send(requestOptions);
8618
8619 this._setLastRequest(request);
8620 this._setLoading(true);
8621
8622 this.fire('request', {
8623 request: request,
8624 options: requestOptions
8625 }, {bubbles: this.bubbles});
8626
8627 return request;
8628 },
8629
8630 _handleResponse: function(request) {
8631 if (request === this.lastRequest) {
8632 this._setLastResponse(request.response);
8633 this._setLastError(null);
8634 this._setLoading(false);
8635 }
8636 this.fire('response', request, {bubbles: this.bubbles});
8637 },
8638
8639 _handleError: function(request, error) {
8640 if (this.verbose) {
8641 console.error(error);
8642 }
8643
8644 if (request === this.lastRequest) {
8645 this._setLastError({
8646 request: request,
8647 error: error
8648 });
8649 this._setLastResponse(null);
8650 this._setLoading(false);
8651 }
8652 this.fire('error', {
8653 request: request,
8654 error: error
8655 }, {bubbles: this.bubbles});
8656 },
8657
8658 _discardRequest: function(request) {
8659 var requestIndex = this.activeRequests.indexOf(request);
8660
8661 if (requestIndex > -1) {
8662 this.activeRequests.splice(requestIndex, 1);
8663 }
8664 },
8665
8666 _requestOptionsChanged: function() {
8667 this.debounce('generate-request', function() {
8668 if (this.url == null) {
8669 return;
8670 }
8671
8672 if (this.auto) {
8673 this.generateRequest();
8674 }
8675 }, this.debounceDuration);
8676 },
8677
8678 });
8679 </script>
8680
8681
8682 <script>
8683 (function() {
8684 "use strict";
8685 /**
8686 `Polymer.IronJsonpLibraryBehavior` loads a jsonp library.
8687 Multiple components can request same library, only one copy will load.
8688
8689 Some libraries require a specific global function be defined.
8690 If this is the case, specify the `callbackName` property.
8691
8692 You should use an HTML Import to load library dependencies
8693 when possible instead of using this element.
8694
8695 @hero hero.svg
8696 @demo demo/index.html
8697 @polymerBehavior
8698 */
8699 Polymer.IronJsonpLibraryBehavior = {
8700
8701 properties: {
8702 /**
8703 * True if library has been successfully loaded
8704 */
8705 libraryLoaded: {
8706 type: Boolean,
8707 value: false,
8708 notify: true,
8709 readOnly: true
8710 },
8711 /**
8712 * Not null if library has failed to load
8713 */
8714 libraryErrorMessage: {
8715 type: String,
8716 value: null,
8717 notify: true,
8718 readOnly: true
8719 }
8720 // Following properties are to be set by behavior users
8721 /**
8722 * Library url. Must contain string `%%callback%%`.
8723 *
8724 * `%%callback%%` is a placeholder for jsonp wrapper function name
8725 *
8726 * Ex: https://maps.googleapis.com/maps/api/js?callback=%%callback%%
8727 * @property libraryUrl
8728 */
8729 /**
8730 * Set if library requires specific callback name.
8731 * Name will be automatically generated if not set.
8732 * @property callbackName
8733 */
8734 /**
8735 * name of event to be emitted when library loads. Standard is `api-load`
8736 * @property notifyEvent
8737 */
8738 /**
8739 * event with name specified in `notifyEvent` attribute
8740 * will fire upon successful load2
8741 * @event `notifyEvent`
8742 */
8743 },
8744
8745 observers: [
8746 '_libraryUrlChanged(libraryUrl)'
8747 ],
8748
8749 _libraryUrlChanged: function(libraryUrl) {
8750 // can't load before ready because notifyEvent might not be set
8751 if (this._isReady && this.libraryUrl)
8752 this._loadLibrary();
8753 },
8754
8755 _libraryLoadCallback: function(err, result) {
8756 if (err) {
8757 console.warn("Library load failed:", err.message);
8758 this._setLibraryErrorMessage(err.message);
8759 }
8760 else {
8761 this._setLibraryErrorMessage(null);
8762 this._setLibraryLoaded(true);
8763 if (this.notifyEvent)
8764 this.fire(this.notifyEvent, result);
8765 }
8766 },
8767
8768 /** loads the library, and fires this.notifyEvent upon completion */
8769 _loadLibrary: function() {
8770 LoaderMap.require(
8771 this.libraryUrl,
8772 this._libraryLoadCallback.bind(this),
8773 this.callbackName
8774 );
8775 },
8776
8777 ready: function() {
8778 this._isReady = true;
8779 if (this.libraryUrl)
8780 this._loadLibrary();
8781 }
8782 };
8783
8784 /**
8785 * LoaderMap keeps track of all Loaders
8786 */
8787 var LoaderMap = {
8788 apiMap: {}, // { hash -> Loader }
8789
8790 /**
8791 * @param {Function} notifyCallback loaded callback fn(result)
8792 * @param {string} jsonpCallbackName name of jsonpcallback. If API does not provide it, leave empty. Optional.
8793 */
8794 require: function(url, notifyCallback, jsonpCallbackName) {
8795
8796 // make hashable string form url
8797 var name = this.nameFromUrl(url);
8798
8799 // create a loader as needed
8800 if (!this.apiMap[name])
8801 this.apiMap[name] = new Loader(name, url, jsonpCallbackName);
8802
8803 // ask for notification
8804 this.apiMap[name].requestNotify(notifyCallback);
8805 },
8806
8807 nameFromUrl: function(url) {
8808 return url.replace(/[\:\/\%\?\&\.\=\-\,]/g, '_') + '_api';
8809 }
8810 };
8811
8812 /** @constructor */
8813 var Loader = function(name, url, callbackName) {
8814 this.notifiers = []; // array of notifyFn [ notifyFn* ]
8815
8816 // callback is specified either as callback name
8817 // or computed dynamically if url has callbackMacro in it
8818 if (!callbackName) {
8819 if (url.indexOf(this.callbackMacro) >= 0) {
8820 callbackName = name + '_loaded';
8821 url = url.replace(this.callbackMacro, callbackName);
8822 } else {
8823 this.error = new Error('IronJsonpLibraryBehavior a %%callback%% paramete r is required in libraryUrl');
8824 // TODO(sjmiles): we should probably fallback to listening to script.loa d
8825 return;
8826 }
8827 }
8828 this.callbackName = callbackName;
8829 window[this.callbackName] = this.success.bind(this);
8830 this.addScript(url);
8831 };
8832
8833 Loader.prototype = {
8834
8835 callbackMacro: '%%callback%%',
8836 loaded: false,
8837
8838 addScript: function(src) {
8839 var script = document.createElement('script');
8840 script.src = src;
8841 script.onerror = this.handleError.bind(this);
8842 var s = document.querySelector('script') || document.body;
8843 s.parentNode.insertBefore(script, s);
8844 this.script = script;
8845 },
8846
8847 removeScript: function() {
8848 if (this.script.parentNode) {
8849 this.script.parentNode.removeChild(this.script);
8850 }
8851 this.script = null;
8852 },
8853
8854 handleError: function(ev) {
8855 this.error = new Error("Library failed to load");
8856 this.notifyAll();
8857 this.cleanup();
8858 },
8859
8860 success: function() {
8861 this.loaded = true;
8862 this.result = Array.prototype.slice.call(arguments);
8863 this.notifyAll();
8864 this.cleanup();
8865 },
8866
8867 cleanup: function() {
8868 delete window[this.callbackName];
8869 },
8870
8871 notifyAll: function() {
8872 this.notifiers.forEach( function(notifyCallback) {
8873 notifyCallback(this.error, this.result);
8874 }.bind(this));
8875 this.notifiers = [];
8876 },
8877
8878 requestNotify: function(notifyCallback) {
8879 if (this.loaded || this.error) {
8880 notifyCallback( this.error, this.result);
8881 } else {
8882 this.notifiers.push(notifyCallback);
8883 }
8884 }
8885 };
8886 })();
8887 </script>
8888
8889
8890 <script>
8891 Polymer({
8892
8893 is: 'iron-jsonp-library',
8894
8895 behaviors: [ Polymer.IronJsonpLibraryBehavior ],
8896
8897 properties: {
8898 /**
8899 * Library url. Must contain string `%%callback%%`.
8900 *
8901 * `%%callback%%` is a placeholder for jsonp wrapper function name
8902 *
8903 * Ex: https://maps.googleapis.com/maps/api/js?callback=%%callback%%
8904 */
8905 libraryUrl: String,
8906 /**
8907 * Set if library requires specific callback name.
8908 * Name will be automatically generated if not set.
8909 */
8910 callbackName: String,
8911 /**
8912 * event with name specified in 'notifyEvent' attribute
8913 * will fire upon successful load
8914 */
8915 notifyEvent: String
8916 /**
8917 * event with name specified in 'notifyEvent' attribute
8918 * will fire upon successful load
8919 * @event `notifyEvent`
8920 */
8921
8922 }
8923 });
8924
8925 </script>
8926 <script>
8927 Polymer({
8928
8929 is: 'google-js-api',
8930
8931 behaviors: [
8932 Polymer.IronJsonpLibraryBehavior
8933 ],
8934
8935 properties: {
8936
8937 /** @private */
8938 libraryUrl: {
8939 type: String,
8940 value: 'https://apis.google.com/js/api.js?onload=%%callback%%'
8941 },
8942
8943 /**
8944 * Fired when the API library is loaded and available.
8945 * @event js-api-load
8946 */
8947 /**
8948 * Name of event fired when library is loaded and available.
8949 */
8950 notifyEvent: {
8951 type: String,
8952 value: 'js-api-load'
8953 },
8954 },
8955
8956 get api() {
8957 return gapi;
8958 }
8959
8960 });
8961 </script>
8962
8963 <script>
8964 (function() {
8965
8966 /**
8967 * Enum of attributes to be passed through to the login API call.
8968 * @readonly
8969 * @enum {string}
8970 */
8971 var ProxyLoginAttributes = {
8972 'appPackageName': 'apppackagename',
8973 'clientId': 'clientid',
8974 'cookiePolicy': 'cookiepolicy',
8975 'hostedDomain': 'hostedDomain',
8976 'openidPrompt': 'prompt',
8977 'requestVisibleActions': 'requestvisibleactions'
8978 };
8979
8980 /**
8981 * AuthEngine does all interactions with gapi.auth2
8982 *
8983 * It is tightly coupled with <google-signin-aware> element
8984 * The elements configure AuthEngine.
8985 * AuthEngine propagates all authentication events to all google-signin-awar e elements
8986 *
8987 * API used: https://developers.google.com/identity/sign-in/web/reference
8988 *
8989 */
8990 var AuthEngine = {
8991
8992 /**
8993 * oauth2 argument, set by google-signin-aware
8994 */
8995 _clientId: null,
8996
8997 get clientId() {
8998 return this._clientId;
8999 },
9000
9001 set clientId(val) {
9002 if (this._clientId && val && val != this._clientId) {
9003 throw new Error('clientId cannot change. Values do not match. New: ' + val + ' Old:' + this._clientId);
9004 }
9005 if (val && val != this._clientId) {
9006 this._clientId = val;
9007 this.initAuth2();
9008 }
9009 },
9010
9011 /**
9012 * oauth2 argument, set by google-signin-aware
9013 */
9014 _cookiePolicy: 'single_host_origin',
9015
9016 get cookiePolicy() {
9017 return this._cookiePolicy;
9018 },
9019
9020 set cookiePolicy(val) {
9021 if (val) {
9022 this._cookiePolicy = val;
9023 }
9024 },
9025
9026 /**
9027 * oauth2 argument, set by google-signin-aware
9028 */
9029 _appPackageName: '',
9030
9031 get appPackageName() {
9032 return this._appPackageName;
9033 },
9034
9035 set appPackageName(val) {
9036 if (this._appPackageName && val && val != this._appPackageName) {
9037 throw new Error('appPackageName cannot change. Values do not match. Ne w: ' + val + ' Old: ' + this._appPackageName);
9038 }
9039 if (val) {
9040 this._appPackageName = val;
9041 }
9042 },
9043
9044 /**
9045 * oauth2 argument, set by google-signin-aware
9046 */
9047 _requestVisibleActions: '',
9048
9049 get requestVisibleactions() {
9050 return this._requestVisibleActions;
9051 },
9052
9053 set requestVisibleactions(val) {
9054 if (this._requestVisibleActions && val && val != this._requestVisibleAct ions) {
9055 throw new Error('requestVisibleactions cannot change. Values do not ma tch. New: ' + val + ' Old: ' + this._requestVisibleActions);
9056 }
9057 if (val)
9058 this._requestVisibleActions = val;
9059 },
9060
9061 /**
9062 * oauth2 argument, set by google-signin-aware
9063 */
9064 _hostedDomain: '',
9065
9066 get hostedDomain() {
9067 return this._hostedDomain;
9068 },
9069
9070 set hostedDomain(val) {
9071 if (this._hostedDomain && val && val != this._hostedDomain) {
9072 throw new Error('hostedDomain cannot change. Values do not match. New: ' + val + ' Old: ' + this._hostedDomain);
9073 }
9074 if (val)
9075 this._hostedDomain = val;
9076 },
9077
9078 /**
9079 * oauth2 argument, set by google-signin-aware
9080 */
9081 _openidPrompt: '',
9082
9083 get openidPrompt() {
9084 return this._openidPrompt;
9085 },
9086
9087 set openidPrompt(val) {
9088 if (typeof val !== 'string') {
9089 throw new Error(
9090 'openidPrompt must be a string. Received ' + typeof val);
9091 }
9092 if (val) {
9093 var values = val.split(' ');
9094 values = values.map(function(v) {
9095 return v.trim();
9096 });
9097 values = values.filter(function(v) {
9098 return v;
9099 });
9100 var validValues = {none: 0, login: 0, consent: 0, select_account: 0};
9101 values.forEach(function(v) {
9102 if (v == 'none' && values.length > 1) {
9103 throw new Error(
9104 'none cannot be combined with other openidPrompt values');
9105 }
9106 if (!(v in validValues)) {
9107 throw new Error(
9108 'invalid openidPrompt value ' + v +
9109 '. Valid values: ' + Object.keys(validValues).join(', '));
9110 }
9111 });
9112 }
9113 this._openidPrompt = val;
9114 },
9115
9116 /** Is offline access currently enabled in the google-signin-aware element ? */
9117 _offline: false,
9118
9119 get offline() {
9120 return this._offline;
9121 },
9122
9123 set offline(val) {
9124 this._offline = val;
9125 this.updateAdditionalAuth();
9126 },
9127
9128 /** Should we force a re-prompt for offline access? */
9129 _offlineAlwaysPrompt: false,
9130
9131 get offlineAlwaysPrompt() {
9132 return this._offlineAlwaysPrompt;
9133 },
9134
9135 set offlineAlwaysPrompt(val) {
9136 this._offlineAlwaysPrompt = val;
9137 this.updateAdditionalAuth();
9138 },
9139
9140 /** Have we already gotten offline access from Google during this session? */
9141 offlineGranted: false,
9142
9143 /** <google-js-api> */
9144 _apiLoader: null,
9145
9146 /** an array of wanted scopes. oauth2 argument */
9147 _requestedScopeArray: [],
9148
9149 /** _requestedScopeArray as string */
9150 get requestedScopes() {
9151 return this._requestedScopeArray.join(' ');
9152 },
9153
9154 /** Is user signed in? */
9155 _signedIn: false,
9156
9157 /** Currently granted scopes */
9158 _grantedScopeArray: [],
9159
9160 /** True if additional authorization is required */
9161 _needAdditionalAuth: true,
9162
9163 /** True if have google+ scopes */
9164 _hasPlusScopes: false,
9165
9166 /**
9167 * array of <google-signin-aware>
9168 * state changes are broadcast to them
9169 */
9170 signinAwares: [],
9171
9172 init: function() {
9173 this._apiLoader = document.createElement('google-js-api');
9174 this._apiLoader.addEventListener('js-api-load', this.loadAuth2.bind(this ));
9175 },
9176
9177 loadAuth2: function() {
9178 gapi.load('auth2', this.initAuth2.bind(this));
9179 },
9180
9181 initAuth2: function() {
9182 if (!('gapi' in window) || !('auth2' in window.gapi) || !this.clientId) {
9183 return;
9184 }
9185 var auth = gapi.auth2.init({
9186 'client_id': this.clientId,
9187 'cookie_policy': this.cookiePolicy,
9188 'scope': this.requestedScopes,
9189 'hosted_domain': this.hostedDomain
9190 });
9191
9192 auth['currentUser'].listen(this.handleUserUpdate.bind(this));
9193
9194 auth.then(
9195 function onFulfilled() {
9196 // Let the current user listener trigger the changes.
9197 },
9198 function onRejected(error) {
9199 console.error(error);
9200 }
9201 );
9202 },
9203
9204 handleUserUpdate: function(newPrimaryUser) {
9205 // update and broadcast currentUser
9206 var isSignedIn = newPrimaryUser.isSignedIn();
9207 if (isSignedIn != this._signedIn) {
9208 this._signedIn = isSignedIn;
9209 for (var i=0; i<this.signinAwares.length; i++) {
9210 this.signinAwares[i]._setSignedIn(isSignedIn);
9211 }
9212 }
9213
9214 // update granted scopes
9215 this._grantedScopeArray = this.strToScopeArray(
9216 newPrimaryUser.getGrantedScopes());
9217 // console.log(this._grantedScopeArray);
9218 this.updateAdditionalAuth();
9219
9220 var response = newPrimaryUser.getAuthResponse();
9221 for (var i=0; i<this.signinAwares.length; i++) {
9222 this.signinAwares[i]._updateScopeStatus(response);
9223 }
9224 },
9225
9226 setOfflineCode: function(code) {
9227 for (var i=0; i<this.signinAwares.length; i++) {
9228 this.signinAwares[i]._updateOfflineCode(code);
9229 }
9230 },
9231
9232 /** convert scope string to scope array */
9233 strToScopeArray: function(str) {
9234 if (!str) {
9235 return [];
9236 }
9237 // remove extra spaces, then split
9238 var scopes = str.replace(/\ +/g, ' ').trim().split(' ');
9239 for (var i=0; i<scopes.length; i++) {
9240 scopes[i] = scopes[i].toLowerCase();
9241 // Handle scopes that will be deprecated but are still returned with their old value
9242 if (scopes[i] === 'https://www.googleapis.com/auth/userinfo.profile') {
9243 scopes[i] = 'profile';
9244 }
9245 if (scopes[i] === 'https://www.googleapis.com/auth/userinfo.email') {
9246 scopes[i] = 'email';
9247 }
9248 }
9249 // return with duplicates filtered out
9250 return scopes.filter( function(value, index, self) {
9251 return self.indexOf(value) === index;
9252 });
9253 },
9254
9255 /** true if scopes have google+ scopes */
9256 isPlusScope: function(scope) {
9257 return (scope.indexOf('/auth/games') > -1)
9258 || (scope.indexOf('auth/plus.') > -1 && scope.indexOf('auth/plus.me' ) < 0);
9259 },
9260
9261 /** true if scopes have been granted */
9262 hasGrantedScopes: function(scopeStr) {
9263 var scopes = this.strToScopeArray(scopeStr);
9264 for (var i=0; i< scopes.length; i++) {
9265 if (this._grantedScopeArray.indexOf(scopes[i]) === -1)
9266 return false;
9267 }
9268 return true;
9269 },
9270
9271 /** request additional scopes */
9272 requestScopes: function(newScopeStr) {
9273 var newScopes = this.strToScopeArray(newScopeStr);
9274 var scopesUpdated = false;
9275 for (var i=0; i<newScopes.length; i++) {
9276 if (this._requestedScopeArray.indexOf(newScopes[i]) === -1) {
9277 this._requestedScopeArray.push(newScopes[i]);
9278 scopesUpdated = true;
9279 }
9280 }
9281 if (scopesUpdated) {
9282 this.updateAdditionalAuth();
9283 this.updatePlusScopes();
9284 }
9285 },
9286
9287 /** update status of _needAdditionalAuth */
9288 updateAdditionalAuth: function() {
9289 var needMoreAuth = false;
9290 if ((this.offlineAlwaysPrompt || this.offline ) && !this.offlineGranted) {
9291 needMoreAuth = true;
9292 } else {
9293 for (var i=0; i<this._requestedScopeArray.length; i++) {
9294 if (this._grantedScopeArray.indexOf(this._requestedScopeArray[i]) == = -1) {
9295 needMoreAuth = true;
9296 break;
9297 }
9298 }
9299 }
9300 if (this._needAdditionalAuth != needMoreAuth) {
9301 this._needAdditionalAuth = needMoreAuth;
9302 // broadcast new value
9303 for (var i=0; i<this.signinAwares.length; i++) {
9304 this.signinAwares[i]._setNeedAdditionalAuth(needMoreAuth);
9305 }
9306 }
9307 },
9308
9309 updatePlusScopes: function() {
9310 var hasPlusScopes = false;
9311 for (var i = 0; i < this._requestedScopeArray.length; i++) {
9312 if (this.isPlusScope(this._requestedScopeArray[i])) {
9313 hasPlusScopes = true;
9314 break;
9315 }
9316 }
9317 if (this._hasPlusScopes != hasPlusScopes) {
9318 this._hasPlusScopes = hasPlusScopes;
9319 for (var i=0; i<this.signinAwares.length; i++) {
9320 this.signinAwares[i]._setHasPlusScopes(hasPlusScopes);
9321 }
9322 }
9323 },
9324 /**
9325 * attached <google-signin-aware>
9326 * @param {!GoogleSigninAwareElement} aware element to add
9327 */
9328 attachSigninAware: function(aware) {
9329 if (this.signinAwares.indexOf(aware) == -1) {
9330 this.signinAwares.push(aware);
9331 // Initialize aware properties
9332 aware._setNeedAdditionalAuth(this._needAdditionalAuth);
9333 aware._setSignedIn(this._signedIn);
9334 aware._setHasPlusScopes(this._hasPlusScopes);
9335 } else {
9336 console.warn('signinAware attached more than once', aware);
9337 }
9338 },
9339
9340 detachSigninAware: function(aware) {
9341 var index = this.signinAwares.indexOf(aware);
9342 if (index != -1) {
9343 this.signinAwares.splice(index, 1);
9344 } else {
9345 console.warn('Trying to detach unattached signin-aware');
9346 }
9347 },
9348
9349 /** returns scopes not granted */
9350 getMissingScopes: function() {
9351 return this._requestedScopeArray.filter( function(scope) {
9352 return this._grantedScopeArray.indexOf(scope) === -1;
9353 }.bind(this)).join(' ');
9354 },
9355
9356 assertAuthInitialized: function() {
9357 if (!this.clientId) {
9358 throw new Error("AuthEngine not initialized. clientId has not been con figured.");
9359 }
9360 if (!('gapi' in window)) {
9361 throw new Error("AuthEngine not initialized. gapi has not loaded.");
9362 }
9363 if (!('auth2' in window.gapi)) {
9364 throw new Error("AuthEngine not initialized. auth2 not loaded.");
9365 }
9366 },
9367
9368 /** pops up sign-in dialog */
9369 signIn: function() {
9370 this.assertAuthInitialized();
9371 var params = {
9372 'scope': this.getMissingScopes()
9373 };
9374
9375 // Proxy specific attributes through to the signIn options.
9376 Object.keys(ProxyLoginAttributes).forEach(function(key) {
9377 if (this[key] && this[key] !== '') {
9378 params[ProxyLoginAttributes[key]] = this[key];
9379 }
9380 }, this);
9381
9382 var promise;
9383 var user = gapi.auth2.getAuthInstance()['currentUser'].get();
9384 if (!(this.offline || this.offlineAlwaysPrompt)) {
9385 if (user.getGrantedScopes()) {
9386 // additional auth, skip multiple account dialog
9387 promise = user.grant(params);
9388 } else {
9389 // initial signin
9390 promise = gapi.auth2.getAuthInstance().signIn(params);
9391 }
9392 } else {
9393 params.redirect_uri = 'postmessage';
9394 if (this.offlineAlwaysPrompt) {
9395 params.approval_prompt = 'force';
9396 }
9397
9398 // Despite being documented at https://goo.gl/tiO0Bk
9399 // It doesn't seem like user.grantOfflineAccess() actually exists in
9400 // the current version of the Google Sign-In JS client we're using
9401 // through GoogleWebComponents. So in the offline case, we will not
9402 // distinguish between a first auth and an additional one.
9403 promise = gapi.auth2.getAuthInstance().grantOfflineAccess(params);
9404 }
9405 promise.then(
9406 function onFulfilled(response) {
9407 // If login was offline, response contains one string "code"
9408 // Otherwise it contains the user object already
9409 var newUser;
9410 if (response.code) {
9411 AuthEngine.offlineGranted = true;
9412 newUser = gapi.auth2.getAuthInstance()['currentUser'].get();
9413 AuthEngine.setOfflineCode(response.code);
9414 } else {
9415 newUser = response;
9416 }
9417
9418 var authResponse = newUser.getAuthResponse();
9419 // Let the current user listener trigger the changes.
9420 },
9421 function onRejected(error) {
9422 // Access denied is not an error, user hit cancel
9423 if ("Access denied." !== error.reason) {
9424 this.signinAwares.forEach(function(awareInstance) {
9425 awareInstance.errorNotify(error);
9426 });
9427 }
9428 }.bind(this)
9429 );
9430 },
9431
9432 /** signs user out */
9433 signOut: function() {
9434 this.assertAuthInitialized();
9435 gapi.auth2.getAuthInstance().signOut().then(
9436 function onFulfilled() {
9437 // Let the current user listener trigger the changes.
9438 },
9439 function onRejected(error) {
9440 console.error(error);
9441 }
9442 );
9443 }
9444 };
9445
9446 AuthEngine.init();
9447
9448 /**
9449 `google-signin-aware` is used to enable authentication in custom elements by
9450 interacting with a google-signin element that needs to be present somewhere
9451 on the page.
9452
9453 The `scopes` attribute allows you to specify which scope permissions are require d
9454 (e.g do you want to allow interaction with the Google Drive API).
9455
9456 The `google-signin-aware-success` event is triggered when a user successfully
9457 authenticates. If either `offline` or `offlineAlwaysPrompt` is set to true, succ essful
9458 authentication will also trigger the `google-signin-offline-success`event.
9459 The `google-signin-aware-signed-out` event is triggered when a user explicitly
9460 signs out via the google-signin element.
9461
9462 You can bind to `isAuthorized` property to monitor authorization state.
9463 ##### Example
9464
9465 <google-signin-aware scopes="https://www.googleapis.com/auth/drive"></google -signin-aware>
9466
9467
9468 ##### Example with offline
9469 <template id="awareness" is="dom-bind">
9470 <google-signin-aware
9471 scopes="https://www.googleapis.com/auth/drive"
9472 offline
9473 on-google-signin-aware-success="handleSignin"
9474 on-google-signin-offline-success="handleOffline"></google-signin-aware >
9475 <\/template>
9476 <script>
9477 var aware = document.querySelector('#awareness');
9478 aware.handleSignin = function(response) {
9479 var user = gapi.auth2.getAuthInstance()['currentUser'].get();
9480 console.log('User name: ' + user.getBasicProfile().getName());
9481 };
9482 aware.handleOffline = function(response) {
9483 console.log('Offline code received: ' + response.detail.code);
9484 // Here you would POST response.detail.code to your webserver, which can
9485 // exchange the authorization code for an access token. More info at:
9486 // https://developers.google.com/identity/protocols/OAuth2WebServer
9487 };
9488 <\/script>
9489 */
9490 Polymer({
9491
9492 is: 'google-signin-aware',
9493
9494 /**
9495 * Fired when this scope has been authorized
9496 * @param {Object} result Authorization result.
9497 * @event google-signin-aware-success
9498 */
9499
9500 /**
9501 * Fired when an offline authorization is successful.
9502 * @param {{code: string}} detail -
9503 * code: The one-time authorization code from Google.
9504 * Your application can exchange this for an `access_token` and `r efresh_token`
9505 * @event google-signin-offline-success
9506 */
9507
9508 /**
9509 * Fired when this scope is not authorized
9510 * @event google-signin-aware-signed-out
9511 */
9512
9513 /**
9514 * Fired when there is an error during the signin flow.
9515 * @param {Object} detail The error object returned from the OAuth 2 flow.
9516 * @event google-signin-aware-error
9517 */
9518
9519 /**
9520 * This block is needed so the previous @param is not assigned to the next property.
9521 */
9522
9523 properties: {
9524 /**
9525 * App package name for android over-the-air installs.
9526 * See the relevant [docs](https://developers.google.com/+/web/signin/an droid-app-installs)
9527 */
9528 appPackageName: {
9529 type: String,
9530 observer: '_appPackageNameChanged'
9531 },
9532
9533 /**
9534 * a Google Developers clientId reference
9535 */
9536 clientId: {
9537 type: String,
9538 observer: '_clientIdChanged'
9539 },
9540
9541 /**
9542 * The cookie policy defines what URIs have access to the session cookie
9543 * remembering the user's sign-in state.
9544 * See the relevant [docs](https://developers.google.com/+/web/signin/re ference#determining_a_value_for_cookie_policy) for more information.
9545 * @default 'single_host_origin'
9546 */
9547 cookiePolicy: {
9548 type: String,
9549 observer: '_cookiePolicyChanged'
9550 },
9551
9552 /**
9553 * The app activity types you want to write on behalf of the user
9554 * (e.g http://schemas.google.com/AddActivity)
9555 *
9556 */
9557 requestVisibleActions: {
9558 type: String,
9559 observer: '_requestVisibleActionsChanged'
9560 },
9561
9562 /**
9563 * The Google Apps domain to which users must belong to sign in.
9564 * See the relevant [docs](https://developers.google.com/identity/sign-i n/web/reference) for more information.
9565 */
9566 hostedDomain: {
9567 type: String,
9568 observer: '_hostedDomainChanged'
9569 },
9570
9571 /**
9572 * Allows for offline `access_token` retrieval during the signin process .
9573 * See also `offlineAlwaysPrompt`. You only need to set one of the two; if both
9574 * are set, the behavior of `offlineAlwaysPrompt` will override `offline `.
9575 */
9576 offline: {
9577 type: Boolean,
9578 value: false,
9579 observer: '_offlineChanged'
9580 },
9581
9582 /**
9583 * Works the same as `offline` with the addition that it will always
9584 * force a re-prompt to the user, guaranteeing that you will get a
9585 * refresh_token even if the user has already granted offline access to
9586 * this application. You only need to set one of `offline` or
9587 * `offlineAlwaysPrompt`, not both.
9588 */
9589 offlineAlwaysPrompt: {
9590 type: Boolean,
9591 value: false,
9592 observer: '_offlineAlwaysPromptChanged'
9593 },
9594
9595 /**
9596 * The scopes to provide access to (e.g https://www.googleapis.com/auth/ drive)
9597 * and should be space-delimited.
9598 */
9599 scopes: {
9600 type: String,
9601 value: 'profile',
9602 observer: '_scopesChanged'
9603 },
9604
9605 /**
9606 * Space-delimited, case-sensitive list of strings that
9607 * specifies whether the the user is prompted for reauthentication
9608 * and/or consent. The defined values are:
9609 * none: do not display authentication or consent pages.
9610 * This value is mutually exclusive with the rest.
9611 * login: always prompt the user for reauthentication.
9612 * consent: always show consent screen.
9613 * select_account: always show account selection page.
9614 * This enables a user who has multiple accounts to select amongst
9615 * the multiple accounts that they might have current sessions for.
9616 * For more information, see "prompt" parameter description in
9617 * https://openid.net/specs/openid-connect-basic-1_0.html#RequestParamet ers
9618 */
9619 openidPrompt: {
9620 type: String,
9621 value: '',
9622 observer: '_openidPromptChanged'
9623 },
9624
9625 /**
9626 * True if user is signed in
9627 */
9628 signedIn: {
9629 type: Boolean,
9630 notify: true,
9631 readOnly: true
9632 },
9633
9634 /**
9635 * True if authorizations for *this* element have been granted
9636 */
9637 isAuthorized: {
9638 type: Boolean,
9639 notify: true,
9640 readOnly: true,
9641 value: false
9642 },
9643
9644 /**
9645 * True if additional authorizations for *any* element are required
9646 */
9647 needAdditionalAuth: {
9648 type: Boolean,
9649 notify: true,
9650 readOnly: true
9651 },
9652
9653 /**
9654 * True if *any* element has google+ scopes
9655 */
9656 hasPlusScopes: {
9657 type: Boolean,
9658 value: false,
9659 notify: true,
9660 readOnly: true
9661 }
9662 },
9663
9664 attached: function() {
9665 AuthEngine.attachSigninAware(this);
9666 },
9667
9668 detached: function() {
9669 AuthEngine.detachSigninAware(this);
9670 },
9671
9672 /** pops up the authorization dialog */
9673 signIn: function() {
9674 AuthEngine.signIn();
9675 },
9676
9677 /** signs user out */
9678 signOut: function() {
9679 AuthEngine.signOut();
9680 },
9681
9682 errorNotify: function(error) {
9683 this.fire('google-signin-aware-error', error);
9684 },
9685
9686 _appPackageNameChanged: function(newName, oldName) {
9687 AuthEngine.appPackageName = newName;
9688 },
9689
9690 _clientIdChanged: function(newId, oldId) {
9691 AuthEngine.clientId = newId;
9692 },
9693
9694 _cookiePolicyChanged: function(newPolicy, oldPolicy) {
9695 AuthEngine.cookiePolicy = newPolicy;
9696 },
9697
9698 _requestVisibleActionsChanged: function(newVal, oldVal) {
9699 AuthEngine.requestVisibleActions = newVal;
9700 },
9701
9702 _hostedDomainChanged: function(newVal, oldVal) {
9703 AuthEngine.hostedDomain = newVal;
9704 },
9705
9706 _offlineChanged: function(newVal, oldVal) {
9707 AuthEngine.offline = newVal;
9708 },
9709
9710 _offlineAlwaysPromptChanged: function(newVal, oldVal) {
9711 AuthEngine.offlineAlwaysPrompt = newVal;
9712 },
9713
9714 _scopesChanged: function(newVal, oldVal) {
9715 AuthEngine.requestScopes(newVal);
9716 this._updateScopeStatus(undefined);
9717 },
9718
9719 _openidPromptChanged: function(newVal, oldVal) {
9720 AuthEngine.openidPrompt = newVal;
9721 },
9722
9723 _updateScopeStatus: function(user) {
9724 var newAuthorized = this.signedIn && AuthEngine.hasGrantedScopes(this.sc opes);
9725 if (newAuthorized !== this.isAuthorized) {
9726 this._setIsAuthorized(newAuthorized);
9727 if (newAuthorized) {
9728 this.fire('google-signin-aware-success', user);
9729 }
9730 else {
9731 this.fire('google-signin-aware-signed-out', user);
9732 }
9733 }
9734 },
9735
9736 _updateOfflineCode: function(code) {
9737 if (code) {
9738 this.fire('google-signin-offline-success', {code: code});
9739 }
9740 }
9741 });
9742 })();
9743 </script>
9744
9745 <dom-module id="auth-signin" assetpath="common/">
9746 <template>
9747 <style>
9748 #avatar {
9749 border-radius: 5px;
9750 }
9751 #signinContainer {
9752 margin-top: 14px;
9753 }
9754 </style>
9755
9756 <google-signin-aware id="aware" client-id="[[clientId]]" scopes="email" on-g oogle-signin-aware-success="_onSignin" on-google-signin-aware-signed-out="_onSig nout"></google-signin-aware>
9757
9758 <template is="dom-if" if="[[!signedIn]]">
9759 <div id="signinContainer">
9760 <a on-tap="signIn" href="#">Sign in</a>
9761 </div>
9762 </template>
9763
9764 <template is="dom-if" if="[[signedIn]]">
9765 <img id="avatar" src="[[profile.imageUrl]]" width="30" height="30">
9766 <span>[[profile.email]]</span>
9767 <span>|</span>
9768 <a on-tap="signOut" href="#">Sign out</a>
9769 </template>
9770 </template>
9771 <script>
9772 'use strict';
9773 Polymer({
9774 is: 'auth-signin',
9775 properties: {
9776 authHeaders: {
9777 type: Object,
9778 computed: "_makeHeader(authResponse)",
9779 notify: true,
9780 },
9781 authResponse: {
9782 type: Object,
9783 },
9784 clientId: {
9785 type: String,
9786 },
9787 profile: {
9788 type: Object,
9789 readOnly: true
9790 },
9791 signedIn: {
9792 type: Boolean,
9793 readOnly: true,
9794 value: false
9795 }
9796 },
9797 _onSignin: function(e) {
9798 this._setSignedIn(true);
9799 var user = gapi.auth2.getAuthInstance().currentUser.get();
9800 var profile = user.getBasicProfile();
9801 this._setProfile({
9802 email: profile.getEmail(),
9803 imageUrl: profile.getImageUrl()
9804 });
9805 this.set("authResponse", user.getAuthResponse());
9806 this.fire("auth-signin");
9807 },
9808 _onSignout: function(e) {
9809 this._setSignedIn(false);
9810 this._setProfile(null);
9811 },
9812 _makeHeader: function(authResponse) {
9813 if (!authResponse) {
9814 return {};
9815 }
9816 return {
9817 "authorization": authResponse.token_type + " " + authResponse.access_t oken
9818
9819 };
9820 },
9821 signIn: function() {
9822 this.$.aware.signIn();
9823 },
9824 signOut: function() {
9825 this.$.aware.signOut();
9826 }
9827 });
9828 </script>
9829 </dom-module><dom-module id="swarming-index" assetpath="index/">
9830 <template>
9831 <style>
9832 :host {
9833 display: block;
9834 }
9835 </style>
9836
9837 <h1>HELLO WORLD 2</h1><h1>
9838
9839 <auth-signin auth-headers="{{auth}}" client-id="20770472288-t5smpbpjptka4nd8 88fv0ctd23ftba2o.apps.googleusercontent.com" on-auth-signin="signIn">
9840 </auth-signin>
9841
9842 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers="[ [auth]]" handle-as="json" on-response="handleResponse"></iron-ajax>
9843
9844 </h1></template>
9845 <script>
9846 Polymer({
9847 is: 'swarming-index',
9848
9849 signIn: function(){
9850 console.log("Hello signin");
9851 this.$.request.generateRequest();
9852 },
9853
9854 handleResponse: function(a,b){
9855 console.log("handle response", a, b);
9856 console.log(this.$.request.lastResponse);
9857 }
9858 });
9859 </script>
9860 </dom-module></div>
9861
9862 <swarming-index></swarming-index>
9863
9864
9865
9866 </body></html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698