| OLD | NEW | 
|---|
| 1 <!DOCTYPE html><html><head><!-- | 1 <!DOCTYPE html><html><head><!-- | 
| 2 @license | 2 @license | 
| 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. | 3 Copyright (c) 2016 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 | 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 | 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 | 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 | 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 | 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
       TS.txt | 
| 9 --><!-- | 9 --><!-- | 
| 10 @license | 10 @license | 
| (...skipping 12213 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 12224        * | 12224        * | 
| 12225        * @method getScrollState | 12225        * @method getScrollState | 
| 12226        * @return {Object} | 12226        * @return {Object} | 
| 12227        */ | 12227        */ | 
| 12228       getScrollState: function() { | 12228       getScrollState: function() { | 
| 12229         return { progress: this._progress }; | 12229         return { progress: this._progress }; | 
| 12230       } | 12230       } | 
| 12231     }); | 12231     }); | 
| 12232   </script> | 12232   </script> | 
| 12233 </dom-module> | 12233 </dom-module> | 
|  | 12234 | 
|  | 12235 <dom-module id="iron-flex" assetpath="/res/imp/bower_components/iron-flex-layout
       /"> | 
|  | 12236   <template> | 
|  | 12237     <style> | 
|  | 12238       .layout.horizontal, | 
|  | 12239       .layout.vertical { | 
|  | 12240         display: -ms-flexbox; | 
|  | 12241         display: -webkit-flex; | 
|  | 12242         display: flex; | 
|  | 12243       } | 
|  | 12244 | 
|  | 12245       .layout.inline { | 
|  | 12246         display: -ms-inline-flexbox; | 
|  | 12247         display: -webkit-inline-flex; | 
|  | 12248         display: inline-flex; | 
|  | 12249       } | 
|  | 12250 | 
|  | 12251       .layout.horizontal { | 
|  | 12252         -ms-flex-direction: row; | 
|  | 12253         -webkit-flex-direction: row; | 
|  | 12254         flex-direction: row; | 
|  | 12255       } | 
|  | 12256 | 
|  | 12257       .layout.vertical { | 
|  | 12258         -ms-flex-direction: column; | 
|  | 12259         -webkit-flex-direction: column; | 
|  | 12260         flex-direction: column; | 
|  | 12261       } | 
|  | 12262 | 
|  | 12263       .layout.wrap { | 
|  | 12264         -ms-flex-wrap: wrap; | 
|  | 12265         -webkit-flex-wrap: wrap; | 
|  | 12266         flex-wrap: wrap; | 
|  | 12267       } | 
|  | 12268 | 
|  | 12269       .layout.center, | 
|  | 12270       .layout.center-center { | 
|  | 12271         -ms-flex-align: center; | 
|  | 12272         -webkit-align-items: center; | 
|  | 12273         align-items: center; | 
|  | 12274       } | 
|  | 12275 | 
|  | 12276       .layout.center-justified, | 
|  | 12277       .layout.center-center { | 
|  | 12278         -ms-flex-pack: center; | 
|  | 12279         -webkit-justify-content: center; | 
|  | 12280         justify-content: center; | 
|  | 12281       } | 
|  | 12282 | 
|  | 12283       .flex { | 
|  | 12284         -ms-flex: 1 1 0.000000001px; | 
|  | 12285         -webkit-flex: 1; | 
|  | 12286         flex: 1; | 
|  | 12287         -webkit-flex-basis: 0.000000001px; | 
|  | 12288         flex-basis: 0.000000001px; | 
|  | 12289       } | 
|  | 12290 | 
|  | 12291       .flex-auto { | 
|  | 12292         -ms-flex: 1 1 auto; | 
|  | 12293         -webkit-flex: 1 1 auto; | 
|  | 12294         flex: 1 1 auto; | 
|  | 12295       } | 
|  | 12296 | 
|  | 12297       .flex-none { | 
|  | 12298         -ms-flex: none; | 
|  | 12299         -webkit-flex: none; | 
|  | 12300         flex: none; | 
|  | 12301       } | 
|  | 12302     </style> | 
|  | 12303   </template> | 
|  | 12304 </dom-module> | 
|  | 12305 | 
|  | 12306 | 
|  | 12307 <dom-module id="iron-flex-reverse" assetpath="/res/imp/bower_components/iron-fle
       x-layout/"> | 
|  | 12308   <template> | 
|  | 12309     <style> | 
|  | 12310       .layout.horizontal-reverse, | 
|  | 12311       .layout.vertical-reverse { | 
|  | 12312         display: -ms-flexbox; | 
|  | 12313         display: -webkit-flex; | 
|  | 12314         display: flex; | 
|  | 12315       } | 
|  | 12316 | 
|  | 12317       .layout.horizontal-reverse { | 
|  | 12318         -ms-flex-direction: row-reverse; | 
|  | 12319         -webkit-flex-direction: row-reverse; | 
|  | 12320         flex-direction: row-reverse; | 
|  | 12321       } | 
|  | 12322 | 
|  | 12323       .layout.vertical-reverse { | 
|  | 12324         -ms-flex-direction: column-reverse; | 
|  | 12325         -webkit-flex-direction: column-reverse; | 
|  | 12326         flex-direction: column-reverse; | 
|  | 12327       } | 
|  | 12328 | 
|  | 12329       .layout.wrap-reverse { | 
|  | 12330         -ms-flex-wrap: wrap-reverse; | 
|  | 12331         -webkit-flex-wrap: wrap-reverse; | 
|  | 12332         flex-wrap: wrap-reverse; | 
|  | 12333       } | 
|  | 12334     </style> | 
|  | 12335   </template> | 
|  | 12336 </dom-module> | 
|  | 12337 | 
|  | 12338 | 
|  | 12339 <dom-module id="iron-flex-alignment" assetpath="/res/imp/bower_components/iron-f
       lex-layout/"> | 
|  | 12340   <template> | 
|  | 12341     <style> | 
|  | 12342       /** | 
|  | 12343        * Alignment in cross axis. | 
|  | 12344        */ | 
|  | 12345       .layout.start { | 
|  | 12346         -ms-flex-align: start; | 
|  | 12347         -webkit-align-items: flex-start; | 
|  | 12348         align-items: flex-start; | 
|  | 12349       } | 
|  | 12350 | 
|  | 12351       .layout.center, | 
|  | 12352       .layout.center-center { | 
|  | 12353         -ms-flex-align: center; | 
|  | 12354         -webkit-align-items: center; | 
|  | 12355         align-items: center; | 
|  | 12356       } | 
|  | 12357 | 
|  | 12358       .layout.end { | 
|  | 12359         -ms-flex-align: end; | 
|  | 12360         -webkit-align-items: flex-end; | 
|  | 12361         align-items: flex-end; | 
|  | 12362       } | 
|  | 12363 | 
|  | 12364       .layout.baseline { | 
|  | 12365         -ms-flex-align: baseline; | 
|  | 12366         -webkit-align-items: baseline; | 
|  | 12367         align-items: baseline; | 
|  | 12368       } | 
|  | 12369 | 
|  | 12370       /** | 
|  | 12371        * Alignment in main axis. | 
|  | 12372        */ | 
|  | 12373       .layout.start-justified { | 
|  | 12374         -ms-flex-pack: start; | 
|  | 12375         -webkit-justify-content: flex-start; | 
|  | 12376         justify-content: flex-start; | 
|  | 12377       } | 
|  | 12378 | 
|  | 12379       .layout.center-justified, | 
|  | 12380       .layout.center-center { | 
|  | 12381         -ms-flex-pack: center; | 
|  | 12382         -webkit-justify-content: center; | 
|  | 12383         justify-content: center; | 
|  | 12384       } | 
|  | 12385 | 
|  | 12386       .layout.end-justified { | 
|  | 12387         -ms-flex-pack: end; | 
|  | 12388         -webkit-justify-content: flex-end; | 
|  | 12389         justify-content: flex-end; | 
|  | 12390       } | 
|  | 12391 | 
|  | 12392       .layout.around-justified { | 
|  | 12393         -ms-flex-pack: distribute; | 
|  | 12394         -webkit-justify-content: space-around; | 
|  | 12395         justify-content: space-around; | 
|  | 12396       } | 
|  | 12397 | 
|  | 12398       .layout.justified { | 
|  | 12399         -ms-flex-pack: justify; | 
|  | 12400         -webkit-justify-content: space-between; | 
|  | 12401         justify-content: space-between; | 
|  | 12402       } | 
|  | 12403 | 
|  | 12404       /** | 
|  | 12405        * Self alignment. | 
|  | 12406        */ | 
|  | 12407       .self-start { | 
|  | 12408         -ms-align-self: flex-start; | 
|  | 12409         -webkit-align-self: flex-start; | 
|  | 12410         align-self: flex-start; | 
|  | 12411       } | 
|  | 12412 | 
|  | 12413       .self-center { | 
|  | 12414         -ms-align-self: center; | 
|  | 12415         -webkit-align-self: center; | 
|  | 12416         align-self: center; | 
|  | 12417       } | 
|  | 12418 | 
|  | 12419       .self-end { | 
|  | 12420         -ms-align-self: flex-end; | 
|  | 12421         -webkit-align-self: flex-end; | 
|  | 12422         align-self: flex-end; | 
|  | 12423       } | 
|  | 12424 | 
|  | 12425       .self-stretch { | 
|  | 12426         -ms-align-self: stretch; | 
|  | 12427         -webkit-align-self: stretch; | 
|  | 12428         align-self: stretch; | 
|  | 12429       } | 
|  | 12430 | 
|  | 12431       .self-baseline { | 
|  | 12432         -ms-align-self: baseline; | 
|  | 12433         -webkit-align-self: baseline; | 
|  | 12434         align-self: baseline; | 
|  | 12435       }; | 
|  | 12436 | 
|  | 12437       /** | 
|  | 12438        * multi-line alignment in main axis. | 
|  | 12439        */ | 
|  | 12440       .layout.start-aligned { | 
|  | 12441         -ms-flex-line-pack: start;  /* IE10 */ | 
|  | 12442         -ms-align-content: flex-start; | 
|  | 12443         -webkit-align-content: flex-start; | 
|  | 12444         align-content: flex-start; | 
|  | 12445       } | 
|  | 12446 | 
|  | 12447       .layout.end-aligned { | 
|  | 12448         -ms-flex-line-pack: end;  /* IE10 */ | 
|  | 12449         -ms-align-content: flex-end; | 
|  | 12450         -webkit-align-content: flex-end; | 
|  | 12451         align-content: flex-end; | 
|  | 12452       } | 
|  | 12453 | 
|  | 12454       .layout.center-aligned { | 
|  | 12455         -ms-flex-line-pack: center;  /* IE10 */ | 
|  | 12456         -ms-align-content: center; | 
|  | 12457         -webkit-align-content: center; | 
|  | 12458         align-content: center; | 
|  | 12459       } | 
|  | 12460 | 
|  | 12461       .layout.between-aligned { | 
|  | 12462         -ms-flex-line-pack: justify;  /* IE10 */ | 
|  | 12463         -ms-align-content: space-between; | 
|  | 12464         -webkit-align-content: space-between; | 
|  | 12465         align-content: space-between; | 
|  | 12466       } | 
|  | 12467 | 
|  | 12468       .layout.around-aligned { | 
|  | 12469         -ms-flex-line-pack: distribute;  /* IE10 */ | 
|  | 12470         -ms-align-content: space-around; | 
|  | 12471         -webkit-align-content: space-around; | 
|  | 12472         align-content: space-around; | 
|  | 12473       } | 
|  | 12474     </style> | 
|  | 12475   </template> | 
|  | 12476 </dom-module> | 
|  | 12477 | 
|  | 12478 <dom-module id="iron-flex-factors" assetpath="/res/imp/bower_components/iron-fle
       x-layout/"> | 
|  | 12479   <template> | 
|  | 12480     <style> | 
|  | 12481       .flex, | 
|  | 12482       .flex-1 { | 
|  | 12483         -ms-flex: 1 1 0.000000001px; | 
|  | 12484         -webkit-flex: 1; | 
|  | 12485         flex: 1; | 
|  | 12486         -webkit-flex-basis: 0.000000001px; | 
|  | 12487         flex-basis: 0.000000001px; | 
|  | 12488       } | 
|  | 12489 | 
|  | 12490       .flex-2 { | 
|  | 12491         -ms-flex: 2; | 
|  | 12492         -webkit-flex: 2; | 
|  | 12493         flex: 2; | 
|  | 12494       } | 
|  | 12495 | 
|  | 12496       .flex-3 { | 
|  | 12497         -ms-flex: 3; | 
|  | 12498         -webkit-flex: 3; | 
|  | 12499         flex: 3; | 
|  | 12500       } | 
|  | 12501 | 
|  | 12502       .flex-4 { | 
|  | 12503         -ms-flex: 4; | 
|  | 12504         -webkit-flex: 4; | 
|  | 12505         flex: 4; | 
|  | 12506       } | 
|  | 12507 | 
|  | 12508       .flex-5 { | 
|  | 12509         -ms-flex: 5; | 
|  | 12510         -webkit-flex: 5; | 
|  | 12511         flex: 5; | 
|  | 12512       } | 
|  | 12513 | 
|  | 12514       .flex-6 { | 
|  | 12515         -ms-flex: 6; | 
|  | 12516         -webkit-flex: 6; | 
|  | 12517         flex: 6; | 
|  | 12518       } | 
|  | 12519 | 
|  | 12520       .flex-7 { | 
|  | 12521         -ms-flex: 7; | 
|  | 12522         -webkit-flex: 7; | 
|  | 12523         flex: 7; | 
|  | 12524       } | 
|  | 12525 | 
|  | 12526       .flex-8 { | 
|  | 12527         -ms-flex: 8; | 
|  | 12528         -webkit-flex: 8; | 
|  | 12529         flex: 8; | 
|  | 12530       } | 
|  | 12531 | 
|  | 12532       .flex-9 { | 
|  | 12533         -ms-flex: 9; | 
|  | 12534         -webkit-flex: 9; | 
|  | 12535         flex: 9; | 
|  | 12536       } | 
|  | 12537 | 
|  | 12538       .flex-10 { | 
|  | 12539         -ms-flex: 10; | 
|  | 12540         -webkit-flex: 10; | 
|  | 12541         flex: 10; | 
|  | 12542       } | 
|  | 12543 | 
|  | 12544       .flex-11 { | 
|  | 12545         -ms-flex: 11; | 
|  | 12546         -webkit-flex: 11; | 
|  | 12547         flex: 11; | 
|  | 12548       } | 
|  | 12549 | 
|  | 12550       .flex-12 { | 
|  | 12551         -ms-flex: 12; | 
|  | 12552         -webkit-flex: 12; | 
|  | 12553         flex: 12; | 
|  | 12554       } | 
|  | 12555     </style> | 
|  | 12556   </template> | 
|  | 12557 </dom-module> | 
|  | 12558 | 
|  | 12559 | 
|  | 12560 <dom-module id="iron-positioning" assetpath="/res/imp/bower_components/iron-flex
       -layout/"> | 
|  | 12561   <template> | 
|  | 12562     <style> | 
|  | 12563       .block { | 
|  | 12564         display: block; | 
|  | 12565       } | 
|  | 12566 | 
|  | 12567       /* IE 10 support for HTML5 hidden attr */ | 
|  | 12568       [hidden] { | 
|  | 12569         display: none !important; | 
|  | 12570       } | 
|  | 12571 | 
|  | 12572       .invisible { | 
|  | 12573         visibility: hidden !important; | 
|  | 12574       } | 
|  | 12575 | 
|  | 12576       .relative { | 
|  | 12577         position: relative; | 
|  | 12578       } | 
|  | 12579 | 
|  | 12580       .fit { | 
|  | 12581         position: absolute; | 
|  | 12582         top: 0; | 
|  | 12583         right: 0; | 
|  | 12584         bottom: 0; | 
|  | 12585         left: 0; | 
|  | 12586       } | 
|  | 12587 | 
|  | 12588       body.fullbleed { | 
|  | 12589         margin: 0; | 
|  | 12590         height: 100vh; | 
|  | 12591       } | 
|  | 12592 | 
|  | 12593       .scroll { | 
|  | 12594         -webkit-overflow-scrolling: touch; | 
|  | 12595         overflow: auto; | 
|  | 12596       } | 
|  | 12597 | 
|  | 12598       /* fixed position */ | 
|  | 12599       .fixed-bottom, | 
|  | 12600       .fixed-left, | 
|  | 12601       .fixed-right, | 
|  | 12602       .fixed-top { | 
|  | 12603         position: fixed; | 
|  | 12604       } | 
|  | 12605 | 
|  | 12606       .fixed-top { | 
|  | 12607         top: 0; | 
|  | 12608         left: 0; | 
|  | 12609         right: 0; | 
|  | 12610       } | 
|  | 12611 | 
|  | 12612       .fixed-right { | 
|  | 12613         top: 0; | 
|  | 12614         right: 0; | 
|  | 12615         bottom: 0; | 
|  | 12616       } | 
|  | 12617 | 
|  | 12618       .fixed-bottom { | 
|  | 12619         right: 0; | 
|  | 12620         bottom: 0; | 
|  | 12621         left: 0; | 
|  | 12622       } | 
|  | 12623 | 
|  | 12624       .fixed-left { | 
|  | 12625         top: 0; | 
|  | 12626         bottom: 0; | 
|  | 12627         left: 0; | 
|  | 12628       } | 
|  | 12629     </style> | 
|  | 12630   </template> | 
|  | 12631 </dom-module> | 
| 12234 <style is="custom-style"> | 12632 <style is="custom-style"> | 
| 12235 | 12633 | 
| 12236   :root { | 12634   :root { | 
| 12237 | 12635 | 
| 12238     /* Material Design color palette for Google products */ | 12636     /* Material Design color palette for Google products */ | 
| 12239 | 12637 | 
| 12240     --google-red-100: #f4c7c3; | 12638     --google-red-100: #f4c7c3; | 
| 12241     --google-red-300: #e67c73; | 12639     --google-red-300: #e67c73; | 
| 12242     --google-red-500: #db4437; | 12640     --google-red-500: #db4437; | 
| 12243     --google-red-700: #c53929; | 12641     --google-red-700: #c53929; | 
| (...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 12975   <script> | 13373   <script> | 
| 12976     Polymer({ | 13374     Polymer({ | 
| 12977       is: 'paper-spinner-lite', | 13375       is: 'paper-spinner-lite', | 
| 12978 | 13376 | 
| 12979       behaviors: [ | 13377       behaviors: [ | 
| 12980         Polymer.PaperSpinnerBehavior | 13378         Polymer.PaperSpinnerBehavior | 
| 12981       ] | 13379       ] | 
| 12982     }); | 13380     }); | 
| 12983   </script> | 13381   </script> | 
| 12984 </dom-module> | 13382 </dom-module> | 
| 12985 |  | 
| 12986 <dom-module id="iron-flex" assetpath="/res/imp/bower_components/iron-flex-layout
       /"> |  | 
| 12987   <template> |  | 
| 12988     <style> |  | 
| 12989       .layout.horizontal, |  | 
| 12990       .layout.vertical { |  | 
| 12991         display: -ms-flexbox; |  | 
| 12992         display: -webkit-flex; |  | 
| 12993         display: flex; |  | 
| 12994       } |  | 
| 12995 |  | 
| 12996       .layout.inline { |  | 
| 12997         display: -ms-inline-flexbox; |  | 
| 12998         display: -webkit-inline-flex; |  | 
| 12999         display: inline-flex; |  | 
| 13000       } |  | 
| 13001 |  | 
| 13002       .layout.horizontal { |  | 
| 13003         -ms-flex-direction: row; |  | 
| 13004         -webkit-flex-direction: row; |  | 
| 13005         flex-direction: row; |  | 
| 13006       } |  | 
| 13007 |  | 
| 13008       .layout.vertical { |  | 
| 13009         -ms-flex-direction: column; |  | 
| 13010         -webkit-flex-direction: column; |  | 
| 13011         flex-direction: column; |  | 
| 13012       } |  | 
| 13013 |  | 
| 13014       .layout.wrap { |  | 
| 13015         -ms-flex-wrap: wrap; |  | 
| 13016         -webkit-flex-wrap: wrap; |  | 
| 13017         flex-wrap: wrap; |  | 
| 13018       } |  | 
| 13019 |  | 
| 13020       .layout.center, |  | 
| 13021       .layout.center-center { |  | 
| 13022         -ms-flex-align: center; |  | 
| 13023         -webkit-align-items: center; |  | 
| 13024         align-items: center; |  | 
| 13025       } |  | 
| 13026 |  | 
| 13027       .layout.center-justified, |  | 
| 13028       .layout.center-center { |  | 
| 13029         -ms-flex-pack: center; |  | 
| 13030         -webkit-justify-content: center; |  | 
| 13031         justify-content: center; |  | 
| 13032       } |  | 
| 13033 |  | 
| 13034       .flex { |  | 
| 13035         -ms-flex: 1 1 0.000000001px; |  | 
| 13036         -webkit-flex: 1; |  | 
| 13037         flex: 1; |  | 
| 13038         -webkit-flex-basis: 0.000000001px; |  | 
| 13039         flex-basis: 0.000000001px; |  | 
| 13040       } |  | 
| 13041 |  | 
| 13042       .flex-auto { |  | 
| 13043         -ms-flex: 1 1 auto; |  | 
| 13044         -webkit-flex: 1 1 auto; |  | 
| 13045         flex: 1 1 auto; |  | 
| 13046       } |  | 
| 13047 |  | 
| 13048       .flex-none { |  | 
| 13049         -ms-flex: none; |  | 
| 13050         -webkit-flex: none; |  | 
| 13051         flex: none; |  | 
| 13052       } |  | 
| 13053     </style> |  | 
| 13054   </template> |  | 
| 13055 </dom-module> |  | 
| 13056 |  | 
| 13057 |  | 
| 13058 <dom-module id="iron-flex-reverse" assetpath="/res/imp/bower_components/iron-fle
       x-layout/"> |  | 
| 13059   <template> |  | 
| 13060     <style> |  | 
| 13061       .layout.horizontal-reverse, |  | 
| 13062       .layout.vertical-reverse { |  | 
| 13063         display: -ms-flexbox; |  | 
| 13064         display: -webkit-flex; |  | 
| 13065         display: flex; |  | 
| 13066       } |  | 
| 13067 |  | 
| 13068       .layout.horizontal-reverse { |  | 
| 13069         -ms-flex-direction: row-reverse; |  | 
| 13070         -webkit-flex-direction: row-reverse; |  | 
| 13071         flex-direction: row-reverse; |  | 
| 13072       } |  | 
| 13073 |  | 
| 13074       .layout.vertical-reverse { |  | 
| 13075         -ms-flex-direction: column-reverse; |  | 
| 13076         -webkit-flex-direction: column-reverse; |  | 
| 13077         flex-direction: column-reverse; |  | 
| 13078       } |  | 
| 13079 |  | 
| 13080       .layout.wrap-reverse { |  | 
| 13081         -ms-flex-wrap: wrap-reverse; |  | 
| 13082         -webkit-flex-wrap: wrap-reverse; |  | 
| 13083         flex-wrap: wrap-reverse; |  | 
| 13084       } |  | 
| 13085     </style> |  | 
| 13086   </template> |  | 
| 13087 </dom-module> |  | 
| 13088 |  | 
| 13089 |  | 
| 13090 <dom-module id="iron-flex-alignment" assetpath="/res/imp/bower_components/iron-f
       lex-layout/"> |  | 
| 13091   <template> |  | 
| 13092     <style> |  | 
| 13093       /** |  | 
| 13094        * Alignment in cross axis. |  | 
| 13095        */ |  | 
| 13096       .layout.start { |  | 
| 13097         -ms-flex-align: start; |  | 
| 13098         -webkit-align-items: flex-start; |  | 
| 13099         align-items: flex-start; |  | 
| 13100       } |  | 
| 13101 |  | 
| 13102       .layout.center, |  | 
| 13103       .layout.center-center { |  | 
| 13104         -ms-flex-align: center; |  | 
| 13105         -webkit-align-items: center; |  | 
| 13106         align-items: center; |  | 
| 13107       } |  | 
| 13108 |  | 
| 13109       .layout.end { |  | 
| 13110         -ms-flex-align: end; |  | 
| 13111         -webkit-align-items: flex-end; |  | 
| 13112         align-items: flex-end; |  | 
| 13113       } |  | 
| 13114 |  | 
| 13115       .layout.baseline { |  | 
| 13116         -ms-flex-align: baseline; |  | 
| 13117         -webkit-align-items: baseline; |  | 
| 13118         align-items: baseline; |  | 
| 13119       } |  | 
| 13120 |  | 
| 13121       /** |  | 
| 13122        * Alignment in main axis. |  | 
| 13123        */ |  | 
| 13124       .layout.start-justified { |  | 
| 13125         -ms-flex-pack: start; |  | 
| 13126         -webkit-justify-content: flex-start; |  | 
| 13127         justify-content: flex-start; |  | 
| 13128       } |  | 
| 13129 |  | 
| 13130       .layout.center-justified, |  | 
| 13131       .layout.center-center { |  | 
| 13132         -ms-flex-pack: center; |  | 
| 13133         -webkit-justify-content: center; |  | 
| 13134         justify-content: center; |  | 
| 13135       } |  | 
| 13136 |  | 
| 13137       .layout.end-justified { |  | 
| 13138         -ms-flex-pack: end; |  | 
| 13139         -webkit-justify-content: flex-end; |  | 
| 13140         justify-content: flex-end; |  | 
| 13141       } |  | 
| 13142 |  | 
| 13143       .layout.around-justified { |  | 
| 13144         -ms-flex-pack: distribute; |  | 
| 13145         -webkit-justify-content: space-around; |  | 
| 13146         justify-content: space-around; |  | 
| 13147       } |  | 
| 13148 |  | 
| 13149       .layout.justified { |  | 
| 13150         -ms-flex-pack: justify; |  | 
| 13151         -webkit-justify-content: space-between; |  | 
| 13152         justify-content: space-between; |  | 
| 13153       } |  | 
| 13154 |  | 
| 13155       /** |  | 
| 13156        * Self alignment. |  | 
| 13157        */ |  | 
| 13158       .self-start { |  | 
| 13159         -ms-align-self: flex-start; |  | 
| 13160         -webkit-align-self: flex-start; |  | 
| 13161         align-self: flex-start; |  | 
| 13162       } |  | 
| 13163 |  | 
| 13164       .self-center { |  | 
| 13165         -ms-align-self: center; |  | 
| 13166         -webkit-align-self: center; |  | 
| 13167         align-self: center; |  | 
| 13168       } |  | 
| 13169 |  | 
| 13170       .self-end { |  | 
| 13171         -ms-align-self: flex-end; |  | 
| 13172         -webkit-align-self: flex-end; |  | 
| 13173         align-self: flex-end; |  | 
| 13174       } |  | 
| 13175 |  | 
| 13176       .self-stretch { |  | 
| 13177         -ms-align-self: stretch; |  | 
| 13178         -webkit-align-self: stretch; |  | 
| 13179         align-self: stretch; |  | 
| 13180       } |  | 
| 13181 |  | 
| 13182       .self-baseline { |  | 
| 13183         -ms-align-self: baseline; |  | 
| 13184         -webkit-align-self: baseline; |  | 
| 13185         align-self: baseline; |  | 
| 13186       }; |  | 
| 13187 |  | 
| 13188       /** |  | 
| 13189        * multi-line alignment in main axis. |  | 
| 13190        */ |  | 
| 13191       .layout.start-aligned { |  | 
| 13192         -ms-flex-line-pack: start;  /* IE10 */ |  | 
| 13193         -ms-align-content: flex-start; |  | 
| 13194         -webkit-align-content: flex-start; |  | 
| 13195         align-content: flex-start; |  | 
| 13196       } |  | 
| 13197 |  | 
| 13198       .layout.end-aligned { |  | 
| 13199         -ms-flex-line-pack: end;  /* IE10 */ |  | 
| 13200         -ms-align-content: flex-end; |  | 
| 13201         -webkit-align-content: flex-end; |  | 
| 13202         align-content: flex-end; |  | 
| 13203       } |  | 
| 13204 |  | 
| 13205       .layout.center-aligned { |  | 
| 13206         -ms-flex-line-pack: center;  /* IE10 */ |  | 
| 13207         -ms-align-content: center; |  | 
| 13208         -webkit-align-content: center; |  | 
| 13209         align-content: center; |  | 
| 13210       } |  | 
| 13211 |  | 
| 13212       .layout.between-aligned { |  | 
| 13213         -ms-flex-line-pack: justify;  /* IE10 */ |  | 
| 13214         -ms-align-content: space-between; |  | 
| 13215         -webkit-align-content: space-between; |  | 
| 13216         align-content: space-between; |  | 
| 13217       } |  | 
| 13218 |  | 
| 13219       .layout.around-aligned { |  | 
| 13220         -ms-flex-line-pack: distribute;  /* IE10 */ |  | 
| 13221         -ms-align-content: space-around; |  | 
| 13222         -webkit-align-content: space-around; |  | 
| 13223         align-content: space-around; |  | 
| 13224       } |  | 
| 13225     </style> |  | 
| 13226   </template> |  | 
| 13227 </dom-module> |  | 
| 13228 |  | 
| 13229 <dom-module id="iron-flex-factors" assetpath="/res/imp/bower_components/iron-fle
       x-layout/"> |  | 
| 13230   <template> |  | 
| 13231     <style> |  | 
| 13232       .flex, |  | 
| 13233       .flex-1 { |  | 
| 13234         -ms-flex: 1 1 0.000000001px; |  | 
| 13235         -webkit-flex: 1; |  | 
| 13236         flex: 1; |  | 
| 13237         -webkit-flex-basis: 0.000000001px; |  | 
| 13238         flex-basis: 0.000000001px; |  | 
| 13239       } |  | 
| 13240 |  | 
| 13241       .flex-2 { |  | 
| 13242         -ms-flex: 2; |  | 
| 13243         -webkit-flex: 2; |  | 
| 13244         flex: 2; |  | 
| 13245       } |  | 
| 13246 |  | 
| 13247       .flex-3 { |  | 
| 13248         -ms-flex: 3; |  | 
| 13249         -webkit-flex: 3; |  | 
| 13250         flex: 3; |  | 
| 13251       } |  | 
| 13252 |  | 
| 13253       .flex-4 { |  | 
| 13254         -ms-flex: 4; |  | 
| 13255         -webkit-flex: 4; |  | 
| 13256         flex: 4; |  | 
| 13257       } |  | 
| 13258 |  | 
| 13259       .flex-5 { |  | 
| 13260         -ms-flex: 5; |  | 
| 13261         -webkit-flex: 5; |  | 
| 13262         flex: 5; |  | 
| 13263       } |  | 
| 13264 |  | 
| 13265       .flex-6 { |  | 
| 13266         -ms-flex: 6; |  | 
| 13267         -webkit-flex: 6; |  | 
| 13268         flex: 6; |  | 
| 13269       } |  | 
| 13270 |  | 
| 13271       .flex-7 { |  | 
| 13272         -ms-flex: 7; |  | 
| 13273         -webkit-flex: 7; |  | 
| 13274         flex: 7; |  | 
| 13275       } |  | 
| 13276 |  | 
| 13277       .flex-8 { |  | 
| 13278         -ms-flex: 8; |  | 
| 13279         -webkit-flex: 8; |  | 
| 13280         flex: 8; |  | 
| 13281       } |  | 
| 13282 |  | 
| 13283       .flex-9 { |  | 
| 13284         -ms-flex: 9; |  | 
| 13285         -webkit-flex: 9; |  | 
| 13286         flex: 9; |  | 
| 13287       } |  | 
| 13288 |  | 
| 13289       .flex-10 { |  | 
| 13290         -ms-flex: 10; |  | 
| 13291         -webkit-flex: 10; |  | 
| 13292         flex: 10; |  | 
| 13293       } |  | 
| 13294 |  | 
| 13295       .flex-11 { |  | 
| 13296         -ms-flex: 11; |  | 
| 13297         -webkit-flex: 11; |  | 
| 13298         flex: 11; |  | 
| 13299       } |  | 
| 13300 |  | 
| 13301       .flex-12 { |  | 
| 13302         -ms-flex: 12; |  | 
| 13303         -webkit-flex: 12; |  | 
| 13304         flex: 12; |  | 
| 13305       } |  | 
| 13306     </style> |  | 
| 13307   </template> |  | 
| 13308 </dom-module> |  | 
| 13309 |  | 
| 13310 |  | 
| 13311 <dom-module id="iron-positioning" assetpath="/res/imp/bower_components/iron-flex
       -layout/"> |  | 
| 13312   <template> |  | 
| 13313     <style> |  | 
| 13314       .block { |  | 
| 13315         display: block; |  | 
| 13316       } |  | 
| 13317 |  | 
| 13318       /* IE 10 support for HTML5 hidden attr */ |  | 
| 13319       [hidden] { |  | 
| 13320         display: none !important; |  | 
| 13321       } |  | 
| 13322 |  | 
| 13323       .invisible { |  | 
| 13324         visibility: hidden !important; |  | 
| 13325       } |  | 
| 13326 |  | 
| 13327       .relative { |  | 
| 13328         position: relative; |  | 
| 13329       } |  | 
| 13330 |  | 
| 13331       .fit { |  | 
| 13332         position: absolute; |  | 
| 13333         top: 0; |  | 
| 13334         right: 0; |  | 
| 13335         bottom: 0; |  | 
| 13336         left: 0; |  | 
| 13337       } |  | 
| 13338 |  | 
| 13339       body.fullbleed { |  | 
| 13340         margin: 0; |  | 
| 13341         height: 100vh; |  | 
| 13342       } |  | 
| 13343 |  | 
| 13344       .scroll { |  | 
| 13345         -webkit-overflow-scrolling: touch; |  | 
| 13346         overflow: auto; |  | 
| 13347       } |  | 
| 13348 |  | 
| 13349       /* fixed position */ |  | 
| 13350       .fixed-bottom, |  | 
| 13351       .fixed-left, |  | 
| 13352       .fixed-right, |  | 
| 13353       .fixed-top { |  | 
| 13354         position: fixed; |  | 
| 13355       } |  | 
| 13356 |  | 
| 13357       .fixed-top { |  | 
| 13358         top: 0; |  | 
| 13359         left: 0; |  | 
| 13360         right: 0; |  | 
| 13361       } |  | 
| 13362 |  | 
| 13363       .fixed-right { |  | 
| 13364         top: 0; |  | 
| 13365         right: 0; |  | 
| 13366         bottom: 0; |  | 
| 13367       } |  | 
| 13368 |  | 
| 13369       .fixed-bottom { |  | 
| 13370         right: 0; |  | 
| 13371         bottom: 0; |  | 
| 13372         left: 0; |  | 
| 13373       } |  | 
| 13374 |  | 
| 13375       .fixed-left { |  | 
| 13376         top: 0; |  | 
| 13377         bottom: 0; |  | 
| 13378         left: 0; |  | 
| 13379       } |  | 
| 13380     </style> |  | 
| 13381   </template> |  | 
| 13382 </dom-module> |  | 
| 13383 <script> | 13383 <script> | 
| 13384 (function() { | 13384 (function() { | 
| 13385   "use strict"; | 13385   "use strict"; | 
| 13386   /** | 13386   /** | 
| 13387     `Polymer.IronJsonpLibraryBehavior` loads a jsonp library. | 13387     `Polymer.IronJsonpLibraryBehavior` loads a jsonp library. | 
| 13388     Multiple components can request same library, only one copy will load. | 13388     Multiple components can request same library, only one copy will load. | 
| 13389 | 13389 | 
| 13390     Some libraries require a specific global function be defined. | 13390     Some libraries require a specific global function be defined. | 
| 13391     If this is the case, specify the `callbackName` property. | 13391     If this is the case, specify the `callbackName` property. | 
| 13392 | 13392 | 
| (...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 14540     <style include="iron-flex"> | 14540     <style include="iron-flex"> | 
| 14541       :host { | 14541       :host { | 
| 14542         position: absolute; | 14542         position: absolute; | 
| 14543         top: 0; | 14543         top: 0; | 
| 14544         bottom: 0; | 14544         bottom: 0; | 
| 14545         left: 0; | 14545         left: 0; | 
| 14546         right: 0; | 14546         right: 0; | 
| 14547       } | 14547       } | 
| 14548 | 14548 | 
| 14549       app-toolbar { | 14549       app-toolbar { | 
| 14550         background-color: #4285f4; | 14550         background-color: #1F78B4; | 
| 14551         color: #fff; | 14551         color: #fff; | 
| 14552       } | 14552       } | 
| 14553 | 14553 | 
| 14554       app-toolbar a { | 14554       app-toolbar a { | 
| 14555         color: #fff; | 14555         color: #fff; | 
| 14556       } | 14556       } | 
| 14557       .left { | 14557       .left { | 
| 14558         margin-right:15px; | 14558         margin-right:15px; | 
| 14559       } | 14559       } | 
| 14560       .right { | 14560       .right { | 
| 14561         margin-left:15px; | 14561         margin-left:15px; | 
| 14562       } | 14562       } | 
| 14563       .main-content { | 14563       .main-content { | 
| 14564         padding: 3px; | 14564         padding: 3px; | 
| 14565       } | 14565       } | 
| 14566 | 14566 | 
|  | 14567       .main-content a { | 
|  | 14568         color: #1F78B4; | 
|  | 14569       } | 
|  | 14570 | 
| 14567       paper-spinner-lite { | 14571       paper-spinner-lite { | 
| 14568         --paper-spinner-color: var(--google-yellow-500); | 14572         --paper-spinner-color: var(--google-yellow-500); | 
| 14569       } | 14573       } | 
| 14570     </style> | 14574     </style> | 
| 14571     <app-header-layout> | 14575     <app-header-layout> | 
| 14572       <app-header fixed=""> | 14576       <app-header fixed=""> | 
| 14573         <app-toolbar> | 14577         <app-toolbar> | 
| 14574           <div class="title left">[[name]]</div> | 14578           <div class="title left">[[name]]</div> | 
| 14575           <paper-spinner-lite class="left" active="[[busy]]"></paper-spinner-lit
       e> | 14579           <paper-spinner-lite class="left" active="[[busy]]"></paper-spinner-lit
       e> | 
| 14576 | 14580 | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 14599         busy: { | 14603         busy: { | 
| 14600           type: Boolean, | 14604           type: Boolean, | 
| 14601         }, | 14605         }, | 
| 14602         name: { | 14606         name: { | 
| 14603           type: String, | 14607           type: String, | 
| 14604         }, | 14608         }, | 
| 14605       }, | 14609       }, | 
| 14606 | 14610 | 
| 14607     }); | 14611     }); | 
| 14608   </script> | 14612   </script> | 
|  | 14613 </dom-module> | 
|  | 14614 | 
|  | 14615 <dom-module id="swarming-app-style" assetpath="/res/imp/common/"> | 
|  | 14616   <style> | 
|  | 14617       * { | 
|  | 14618         font-family: sans-serif; | 
|  | 14619       } | 
|  | 14620       /* Only style anchor tags that are actually linking somewhere.*/ | 
|  | 14621       a[href] { | 
|  | 14622         color: #1F78B4; | 
|  | 14623       } | 
|  | 14624   </style> | 
| 14609 </dom-module><dom-module id="swarming-index" assetpath="/res/imp/index/"> | 14625 </dom-module><dom-module id="swarming-index" assetpath="/res/imp/index/"> | 
| 14610   <template> | 14626   <template> | 
| 14611     <style> | 14627     <style include="swarming-app-style"> | 
| 14612       :host { | 14628 | 
| 14613         display: block; |  | 
| 14614       } |  | 
| 14615     </style> | 14629     </style> | 
| 14616 | 14630 | 
| 14617     <swarming-app auth_headers="{{auth_headers}}" name="Swarming" busy="[[busy]]
       "> | 14631     <swarming-app auth_headers="{{auth_headers}}" name="Swarming" busy="[[busy]]
       "> | 
| 14618 | 14632 | 
| 14619       <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers=
       "[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{
       {busy}}"> | 14633       <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers=
       "[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{
       {busy}}"> | 
| 14620       </iron-ajax> | 14634       </iron-ajax> | 
| 14621 | 14635 | 
| 14622       <h1>HELLO WORLD</h1> | 14636       <h1>HELLO WORLD</h1> | 
| 14623 | 14637 | 
| 14624       <div>Server Version: [[serverDetails.server_version]]</div> | 14638       <div>Server Version: [[serverDetails.server_version]]</div> | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 14640           type: String, | 14654           type: String, | 
| 14641         } | 14655         } | 
| 14642       }, | 14656       }, | 
| 14643 | 14657 | 
| 14644       signIn: function(){ | 14658       signIn: function(){ | 
| 14645         this.$.request.generateRequest(); | 14659         this.$.request.generateRequest(); | 
| 14646       }, | 14660       }, | 
| 14647 | 14661 | 
| 14648     }); | 14662     }); | 
| 14649   </script> | 14663   </script> | 
|  | 14664 </dom-module> | 
|  | 14665 | 
|  | 14666 <script> | 
|  | 14667 | 
|  | 14668   (function() { | 
|  | 14669 | 
|  | 14670     // monostate data | 
|  | 14671     var metaDatas = {}; | 
|  | 14672     var metaArrays = {}; | 
|  | 14673     var singleton = null; | 
|  | 14674 | 
|  | 14675     Polymer.IronMeta = Polymer({ | 
|  | 14676 | 
|  | 14677       is: 'iron-meta', | 
|  | 14678 | 
|  | 14679       properties: { | 
|  | 14680 | 
|  | 14681         /** | 
|  | 14682          * The type of meta-data.  All meta-data of the same type is stored | 
|  | 14683          * together. | 
|  | 14684          */ | 
|  | 14685         type: { | 
|  | 14686           type: String, | 
|  | 14687           value: 'default', | 
|  | 14688           observer: '_typeChanged' | 
|  | 14689         }, | 
|  | 14690 | 
|  | 14691         /** | 
|  | 14692          * The key used to store `value` under the `type` namespace. | 
|  | 14693          */ | 
|  | 14694         key: { | 
|  | 14695           type: String, | 
|  | 14696           observer: '_keyChanged' | 
|  | 14697         }, | 
|  | 14698 | 
|  | 14699         /** | 
|  | 14700          * The meta-data to store or retrieve. | 
|  | 14701          */ | 
|  | 14702         value: { | 
|  | 14703           type: Object, | 
|  | 14704           notify: true, | 
|  | 14705           observer: '_valueChanged' | 
|  | 14706         }, | 
|  | 14707 | 
|  | 14708         /** | 
|  | 14709          * If true, `value` is set to the iron-meta instance itself. | 
|  | 14710          */ | 
|  | 14711          self: { | 
|  | 14712           type: Boolean, | 
|  | 14713           observer: '_selfChanged' | 
|  | 14714         }, | 
|  | 14715 | 
|  | 14716         /** | 
|  | 14717          * Array of all meta-data values for the given type. | 
|  | 14718          */ | 
|  | 14719         list: { | 
|  | 14720           type: Array, | 
|  | 14721           notify: true | 
|  | 14722         } | 
|  | 14723 | 
|  | 14724       }, | 
|  | 14725 | 
|  | 14726       hostAttributes: { | 
|  | 14727         hidden: true | 
|  | 14728       }, | 
|  | 14729 | 
|  | 14730       /** | 
|  | 14731        * Only runs if someone invokes the factory/constructor directly | 
|  | 14732        * e.g. `new Polymer.IronMeta()` | 
|  | 14733        * | 
|  | 14734        * @param {{type: (string|undefined), key: (string|undefined), value}=} co
       nfig | 
|  | 14735        */ | 
|  | 14736       factoryImpl: function(config) { | 
|  | 14737         if (config) { | 
|  | 14738           for (var n in config) { | 
|  | 14739             switch(n) { | 
|  | 14740               case 'type': | 
|  | 14741               case 'key': | 
|  | 14742               case 'value': | 
|  | 14743                 this[n] = config[n]; | 
|  | 14744                 break; | 
|  | 14745             } | 
|  | 14746           } | 
|  | 14747         } | 
|  | 14748       }, | 
|  | 14749 | 
|  | 14750       created: function() { | 
|  | 14751         // TODO(sjmiles): good for debugging? | 
|  | 14752         this._metaDatas = metaDatas; | 
|  | 14753         this._metaArrays = metaArrays; | 
|  | 14754       }, | 
|  | 14755 | 
|  | 14756       _keyChanged: function(key, old) { | 
|  | 14757         this._resetRegistration(old); | 
|  | 14758       }, | 
|  | 14759 | 
|  | 14760       _valueChanged: function(value) { | 
|  | 14761         this._resetRegistration(this.key); | 
|  | 14762       }, | 
|  | 14763 | 
|  | 14764       _selfChanged: function(self) { | 
|  | 14765         if (self) { | 
|  | 14766           this.value = this; | 
|  | 14767         } | 
|  | 14768       }, | 
|  | 14769 | 
|  | 14770       _typeChanged: function(type) { | 
|  | 14771         this._unregisterKey(this.key); | 
|  | 14772         if (!metaDatas[type]) { | 
|  | 14773           metaDatas[type] = {}; | 
|  | 14774         } | 
|  | 14775         this._metaData = metaDatas[type]; | 
|  | 14776         if (!metaArrays[type]) { | 
|  | 14777           metaArrays[type] = []; | 
|  | 14778         } | 
|  | 14779         this.list = metaArrays[type]; | 
|  | 14780         this._registerKeyValue(this.key, this.value); | 
|  | 14781       }, | 
|  | 14782 | 
|  | 14783       /** | 
|  | 14784        * Retrieves meta data value by key. | 
|  | 14785        * | 
|  | 14786        * @method byKey | 
|  | 14787        * @param {string} key The key of the meta-data to be returned. | 
|  | 14788        * @return {*} | 
|  | 14789        */ | 
|  | 14790       byKey: function(key) { | 
|  | 14791         return this._metaData && this._metaData[key]; | 
|  | 14792       }, | 
|  | 14793 | 
|  | 14794       _resetRegistration: function(oldKey) { | 
|  | 14795         this._unregisterKey(oldKey); | 
|  | 14796         this._registerKeyValue(this.key, this.value); | 
|  | 14797       }, | 
|  | 14798 | 
|  | 14799       _unregisterKey: function(key) { | 
|  | 14800         this._unregister(key, this._metaData, this.list); | 
|  | 14801       }, | 
|  | 14802 | 
|  | 14803       _registerKeyValue: function(key, value) { | 
|  | 14804         this._register(key, value, this._metaData, this.list); | 
|  | 14805       }, | 
|  | 14806 | 
|  | 14807       _register: function(key, value, data, list) { | 
|  | 14808         if (key && data && value !== undefined) { | 
|  | 14809           data[key] = value; | 
|  | 14810           list.push(value); | 
|  | 14811         } | 
|  | 14812       }, | 
|  | 14813 | 
|  | 14814       _unregister: function(key, data, list) { | 
|  | 14815         if (key && data) { | 
|  | 14816           if (key in data) { | 
|  | 14817             var value = data[key]; | 
|  | 14818             delete data[key]; | 
|  | 14819             this.arrayDelete(list, value); | 
|  | 14820           } | 
|  | 14821         } | 
|  | 14822       } | 
|  | 14823 | 
|  | 14824     }); | 
|  | 14825 | 
|  | 14826     Polymer.IronMeta.getIronMeta = function getIronMeta() { | 
|  | 14827        if (singleton === null) { | 
|  | 14828          singleton = new Polymer.IronMeta(); | 
|  | 14829        } | 
|  | 14830        return singleton; | 
|  | 14831      }; | 
|  | 14832 | 
|  | 14833     /** | 
|  | 14834     `iron-meta-query` can be used to access infomation stored in `iron-meta`. | 
|  | 14835 | 
|  | 14836     Examples: | 
|  | 14837 | 
|  | 14838     If I create an instance like this: | 
|  | 14839 | 
|  | 14840         <iron-meta key="info" value="foo/bar"></iron-meta> | 
|  | 14841 | 
|  | 14842     Note that value="foo/bar" is the metadata I've defined. I could define more | 
|  | 14843     attributes or use child nodes to define additional metadata. | 
|  | 14844 | 
|  | 14845     Now I can access that element (and it's metadata) from any `iron-meta-query`
        instance: | 
|  | 14846 | 
|  | 14847          var value = new Polymer.IronMetaQuery({key: 'info'}).value; | 
|  | 14848 | 
|  | 14849     @group Polymer Iron Elements | 
|  | 14850     @element iron-meta-query | 
|  | 14851     */ | 
|  | 14852     Polymer.IronMetaQuery = Polymer({ | 
|  | 14853 | 
|  | 14854       is: 'iron-meta-query', | 
|  | 14855 | 
|  | 14856       properties: { | 
|  | 14857 | 
|  | 14858         /** | 
|  | 14859          * The type of meta-data.  All meta-data of the same type is stored | 
|  | 14860          * together. | 
|  | 14861          */ | 
|  | 14862         type: { | 
|  | 14863           type: String, | 
|  | 14864           value: 'default', | 
|  | 14865           observer: '_typeChanged' | 
|  | 14866         }, | 
|  | 14867 | 
|  | 14868         /** | 
|  | 14869          * Specifies a key to use for retrieving `value` from the `type` | 
|  | 14870          * namespace. | 
|  | 14871          */ | 
|  | 14872         key: { | 
|  | 14873           type: String, | 
|  | 14874           observer: '_keyChanged' | 
|  | 14875         }, | 
|  | 14876 | 
|  | 14877         /** | 
|  | 14878          * The meta-data to store or retrieve. | 
|  | 14879          */ | 
|  | 14880         value: { | 
|  | 14881           type: Object, | 
|  | 14882           notify: true, | 
|  | 14883           readOnly: true | 
|  | 14884         }, | 
|  | 14885 | 
|  | 14886         /** | 
|  | 14887          * Array of all meta-data values for the given type. | 
|  | 14888          */ | 
|  | 14889         list: { | 
|  | 14890           type: Array, | 
|  | 14891           notify: true | 
|  | 14892         } | 
|  | 14893 | 
|  | 14894       }, | 
|  | 14895 | 
|  | 14896       /** | 
|  | 14897        * Actually a factory method, not a true constructor. Only runs if | 
|  | 14898        * someone invokes it directly (via `new Polymer.IronMeta()`); | 
|  | 14899        * | 
|  | 14900        * @param {{type: (string|undefined), key: (string|undefined)}=} config | 
|  | 14901        */ | 
|  | 14902       factoryImpl: function(config) { | 
|  | 14903         if (config) { | 
|  | 14904           for (var n in config) { | 
|  | 14905             switch(n) { | 
|  | 14906               case 'type': | 
|  | 14907               case 'key': | 
|  | 14908                 this[n] = config[n]; | 
|  | 14909                 break; | 
|  | 14910             } | 
|  | 14911           } | 
|  | 14912         } | 
|  | 14913       }, | 
|  | 14914 | 
|  | 14915       created: function() { | 
|  | 14916         // TODO(sjmiles): good for debugging? | 
|  | 14917         this._metaDatas = metaDatas; | 
|  | 14918         this._metaArrays = metaArrays; | 
|  | 14919       }, | 
|  | 14920 | 
|  | 14921       _keyChanged: function(key) { | 
|  | 14922         this._setValue(this._metaData && this._metaData[key]); | 
|  | 14923       }, | 
|  | 14924 | 
|  | 14925       _typeChanged: function(type) { | 
|  | 14926         this._metaData = metaDatas[type]; | 
|  | 14927         this.list = metaArrays[type]; | 
|  | 14928         if (this.key) { | 
|  | 14929           this._keyChanged(this.key); | 
|  | 14930         } | 
|  | 14931       }, | 
|  | 14932 | 
|  | 14933       /** | 
|  | 14934        * Retrieves meta data value by key. | 
|  | 14935        * @param {string} key The key of the meta-data to be returned. | 
|  | 14936        * @return {*} | 
|  | 14937        */ | 
|  | 14938       byKey: function(key) { | 
|  | 14939         return this._metaData && this._metaData[key]; | 
|  | 14940       } | 
|  | 14941 | 
|  | 14942     }); | 
|  | 14943 | 
|  | 14944   })(); | 
|  | 14945 </script> | 
|  | 14946 | 
|  | 14947 | 
|  | 14948 <dom-module id="iron-icon" assetpath="/res/imp/bower_components/iron-icon/"> | 
|  | 14949   <template> | 
|  | 14950     <style> | 
|  | 14951       :host { | 
|  | 14952         @apply(--layout-inline); | 
|  | 14953         @apply(--layout-center-center); | 
|  | 14954         position: relative; | 
|  | 14955 | 
|  | 14956         vertical-align: middle; | 
|  | 14957 | 
|  | 14958         fill: var(--iron-icon-fill-color, currentcolor); | 
|  | 14959         stroke: var(--iron-icon-stroke-color, none); | 
|  | 14960 | 
|  | 14961         width: var(--iron-icon-width, 24px); | 
|  | 14962         height: var(--iron-icon-height, 24px); | 
|  | 14963       } | 
|  | 14964     </style> | 
|  | 14965   </template> | 
|  | 14966 | 
|  | 14967   <script> | 
|  | 14968 | 
|  | 14969     Polymer({ | 
|  | 14970 | 
|  | 14971       is: 'iron-icon', | 
|  | 14972 | 
|  | 14973       properties: { | 
|  | 14974 | 
|  | 14975         /** | 
|  | 14976          * The name of the icon to use. The name should be of the form: | 
|  | 14977          * `iconset_name:icon_name`. | 
|  | 14978          */ | 
|  | 14979         icon: { | 
|  | 14980           type: String, | 
|  | 14981           observer: '_iconChanged' | 
|  | 14982         }, | 
|  | 14983 | 
|  | 14984         /** | 
|  | 14985          * The name of the theme to used, if one is specified by the | 
|  | 14986          * iconset. | 
|  | 14987          */ | 
|  | 14988         theme: { | 
|  | 14989           type: String, | 
|  | 14990           observer: '_updateIcon' | 
|  | 14991         }, | 
|  | 14992 | 
|  | 14993         /** | 
|  | 14994          * If using iron-icon without an iconset, you can set the src to be | 
|  | 14995          * the URL of an individual icon image file. Note that this will take | 
|  | 14996          * precedence over a given icon attribute. | 
|  | 14997          */ | 
|  | 14998         src: { | 
|  | 14999           type: String, | 
|  | 15000           observer: '_srcChanged' | 
|  | 15001         }, | 
|  | 15002 | 
|  | 15003         /** | 
|  | 15004          * @type {!Polymer.IronMeta} | 
|  | 15005          */ | 
|  | 15006         _meta: { | 
|  | 15007           value: Polymer.Base.create('iron-meta', {type: 'iconset'}), | 
|  | 15008           observer: '_updateIcon' | 
|  | 15009         } | 
|  | 15010 | 
|  | 15011       }, | 
|  | 15012 | 
|  | 15013       _DEFAULT_ICONSET: 'icons', | 
|  | 15014 | 
|  | 15015       _iconChanged: function(icon) { | 
|  | 15016         var parts = (icon || '').split(':'); | 
|  | 15017         this._iconName = parts.pop(); | 
|  | 15018         this._iconsetName = parts.pop() || this._DEFAULT_ICONSET; | 
|  | 15019         this._updateIcon(); | 
|  | 15020       }, | 
|  | 15021 | 
|  | 15022       _srcChanged: function(src) { | 
|  | 15023         this._updateIcon(); | 
|  | 15024       }, | 
|  | 15025 | 
|  | 15026       _usesIconset: function() { | 
|  | 15027         return this.icon || !this.src; | 
|  | 15028       }, | 
|  | 15029 | 
|  | 15030       /** @suppress {visibility} */ | 
|  | 15031       _updateIcon: function() { | 
|  | 15032         if (this._usesIconset()) { | 
|  | 15033           if (this._img && this._img.parentNode) { | 
|  | 15034             Polymer.dom(this.root).removeChild(this._img); | 
|  | 15035           } | 
|  | 15036           if (this._iconName === "") { | 
|  | 15037             if (this._iconset) { | 
|  | 15038               this._iconset.removeIcon(this); | 
|  | 15039             } | 
|  | 15040           } else if (this._iconsetName && this._meta) { | 
|  | 15041             this._iconset = /** @type {?Polymer.Iconset} */ ( | 
|  | 15042               this._meta.byKey(this._iconsetName)); | 
|  | 15043             if (this._iconset) { | 
|  | 15044               this._iconset.applyIcon(this, this._iconName, this.theme); | 
|  | 15045               this.unlisten(window, 'iron-iconset-added', '_updateIcon'); | 
|  | 15046             } else { | 
|  | 15047               this.listen(window, 'iron-iconset-added', '_updateIcon'); | 
|  | 15048             } | 
|  | 15049           } | 
|  | 15050         } else { | 
|  | 15051           if (this._iconset) { | 
|  | 15052             this._iconset.removeIcon(this); | 
|  | 15053           } | 
|  | 15054           if (!this._img) { | 
|  | 15055             this._img = document.createElement('img'); | 
|  | 15056             this._img.style.width = '100%'; | 
|  | 15057             this._img.style.height = '100%'; | 
|  | 15058             this._img.draggable = false; | 
|  | 15059           } | 
|  | 15060           this._img.src = this.src; | 
|  | 15061           Polymer.dom(this.root).appendChild(this._img); | 
|  | 15062         } | 
|  | 15063       } | 
|  | 15064 | 
|  | 15065     }); | 
|  | 15066 | 
|  | 15067   </script> | 
|  | 15068 | 
|  | 15069 </dom-module> | 
|  | 15070 <script> | 
|  | 15071   /** | 
|  | 15072    * The `iron-iconset-svg` element allows users to define their own icon sets | 
|  | 15073    * that contain svg icons. The svg icon elements should be children of the | 
|  | 15074    * `iron-iconset-svg` element. Multiple icons should be given distinct id's. | 
|  | 15075    * | 
|  | 15076    * Using svg elements to create icons has a few advantages over traditional | 
|  | 15077    * bitmap graphics like jpg or png. Icons that use svg are vector based so | 
|  | 15078    * they are resolution independent and should look good on any device. They | 
|  | 15079    * are stylable via css. Icons can be themed, colorized, and even animated. | 
|  | 15080    * | 
|  | 15081    * Example: | 
|  | 15082    * | 
|  | 15083    *     <iron-iconset-svg name="my-svg-icons" size="24"> | 
|  | 15084    *       <svg> | 
|  | 15085    *         <defs> | 
|  | 15086    *           <g id="shape"> | 
|  | 15087    *             <rect x="12" y="0" width="12" height="24" /> | 
|  | 15088    *             <circle cx="12" cy="12" r="12" /> | 
|  | 15089    *           </g> | 
|  | 15090    *         </defs> | 
|  | 15091    *       </svg> | 
|  | 15092    *     </iron-iconset-svg> | 
|  | 15093    * | 
|  | 15094    * This will automatically register the icon set "my-svg-icons" to the iconset | 
|  | 15095    * database.  To use these icons from within another element, make a | 
|  | 15096    * `iron-iconset` element and call the `byId` method | 
|  | 15097    * to retrieve a given iconset. To apply a particular icon inside an | 
|  | 15098    * element use the `applyIcon` method. For example: | 
|  | 15099    * | 
|  | 15100    *     iconset.applyIcon(iconNode, 'car'); | 
|  | 15101    * | 
|  | 15102    * @element iron-iconset-svg | 
|  | 15103    * @demo demo/index.html | 
|  | 15104    * @implements {Polymer.Iconset} | 
|  | 15105    */ | 
|  | 15106   Polymer({ | 
|  | 15107     is: 'iron-iconset-svg', | 
|  | 15108 | 
|  | 15109     properties: { | 
|  | 15110 | 
|  | 15111       /** | 
|  | 15112        * The name of the iconset. | 
|  | 15113        */ | 
|  | 15114       name: { | 
|  | 15115         type: String, | 
|  | 15116         observer: '_nameChanged' | 
|  | 15117       }, | 
|  | 15118 | 
|  | 15119       /** | 
|  | 15120        * The size of an individual icon. Note that icons must be square. | 
|  | 15121        */ | 
|  | 15122       size: { | 
|  | 15123         type: Number, | 
|  | 15124         value: 24 | 
|  | 15125       } | 
|  | 15126 | 
|  | 15127     }, | 
|  | 15128 | 
|  | 15129     attached: function() { | 
|  | 15130       this.style.display = 'none'; | 
|  | 15131     }, | 
|  | 15132 | 
|  | 15133     /** | 
|  | 15134      * Construct an array of all icon names in this iconset. | 
|  | 15135      * | 
|  | 15136      * @return {!Array} Array of icon names. | 
|  | 15137      */ | 
|  | 15138     getIconNames: function() { | 
|  | 15139       this._icons = this._createIconMap(); | 
|  | 15140       return Object.keys(this._icons).map(function(n) { | 
|  | 15141         return this.name + ':' + n; | 
|  | 15142       }, this); | 
|  | 15143     }, | 
|  | 15144 | 
|  | 15145     /** | 
|  | 15146      * Applies an icon to the given element. | 
|  | 15147      * | 
|  | 15148      * An svg icon is prepended to the element's shadowRoot if it exists, | 
|  | 15149      * otherwise to the element itself. | 
|  | 15150      * | 
|  | 15151      * @method applyIcon | 
|  | 15152      * @param {Element} element Element to which the icon is applied. | 
|  | 15153      * @param {string} iconName Name of the icon to apply. | 
|  | 15154      * @return {?Element} The svg element which renders the icon. | 
|  | 15155      */ | 
|  | 15156     applyIcon: function(element, iconName) { | 
|  | 15157       // insert svg element into shadow root, if it exists | 
|  | 15158       element = element.root || element; | 
|  | 15159       // Remove old svg element | 
|  | 15160       this.removeIcon(element); | 
|  | 15161       // install new svg element | 
|  | 15162       var svg = this._cloneIcon(iconName); | 
|  | 15163       if (svg) { | 
|  | 15164         var pde = Polymer.dom(element); | 
|  | 15165         pde.insertBefore(svg, pde.childNodes[0]); | 
|  | 15166         return element._svgIcon = svg; | 
|  | 15167       } | 
|  | 15168       return null; | 
|  | 15169     }, | 
|  | 15170 | 
|  | 15171     /** | 
|  | 15172      * Remove an icon from the given element by undoing the changes effected | 
|  | 15173      * by `applyIcon`. | 
|  | 15174      * | 
|  | 15175      * @param {Element} element The element from which the icon is removed. | 
|  | 15176      */ | 
|  | 15177     removeIcon: function(element) { | 
|  | 15178       // Remove old svg element | 
|  | 15179       if (element._svgIcon) { | 
|  | 15180         Polymer.dom(element).removeChild(element._svgIcon); | 
|  | 15181         element._svgIcon = null; | 
|  | 15182       } | 
|  | 15183     }, | 
|  | 15184 | 
|  | 15185     /** | 
|  | 15186      * | 
|  | 15187      * When name is changed, register iconset metadata | 
|  | 15188      * | 
|  | 15189      */ | 
|  | 15190     _nameChanged: function() { | 
|  | 15191       new Polymer.IronMeta({type: 'iconset', key: this.name, value: this}); | 
|  | 15192       this.async(function() { | 
|  | 15193         this.fire('iron-iconset-added', this, {node: window}); | 
|  | 15194       }); | 
|  | 15195     }, | 
|  | 15196 | 
|  | 15197     /** | 
|  | 15198      * Create a map of child SVG elements by id. | 
|  | 15199      * | 
|  | 15200      * @return {!Object} Map of id's to SVG elements. | 
|  | 15201      */ | 
|  | 15202     _createIconMap: function() { | 
|  | 15203       // Objects chained to Object.prototype (`{}`) have members. Specifically, | 
|  | 15204       // on FF there is a `watch` method that confuses the icon map, so we | 
|  | 15205       // need to use a null-based object here. | 
|  | 15206       var icons = Object.create(null); | 
|  | 15207       Polymer.dom(this).querySelectorAll('[id]') | 
|  | 15208         .forEach(function(icon) { | 
|  | 15209           icons[icon.id] = icon; | 
|  | 15210         }); | 
|  | 15211       return icons; | 
|  | 15212     }, | 
|  | 15213 | 
|  | 15214     /** | 
|  | 15215      * Produce installable clone of the SVG element matching `id` in this | 
|  | 15216      * iconset, or `undefined` if there is no matching element. | 
|  | 15217      * | 
|  | 15218      * @return {Element} Returns an installable clone of the SVG element | 
|  | 15219      * matching `id`. | 
|  | 15220      */ | 
|  | 15221     _cloneIcon: function(id) { | 
|  | 15222       // create the icon map on-demand, since the iconset itself has no discrete | 
|  | 15223       // signal to know when it's children are fully parsed | 
|  | 15224       this._icons = this._icons || this._createIconMap(); | 
|  | 15225       return this._prepareSvgClone(this._icons[id], this.size); | 
|  | 15226     }, | 
|  | 15227 | 
|  | 15228     /** | 
|  | 15229      * @param {Element} sourceSvg | 
|  | 15230      * @param {number} size | 
|  | 15231      * @return {Element} | 
|  | 15232      */ | 
|  | 15233     _prepareSvgClone: function(sourceSvg, size) { | 
|  | 15234       if (sourceSvg) { | 
|  | 15235         var content = sourceSvg.cloneNode(true), | 
|  | 15236             svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), | 
|  | 15237             viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + s
       ize; | 
|  | 15238         svg.setAttribute('viewBox', viewBox); | 
|  | 15239         svg.setAttribute('preserveAspectRatio', 'xMidYMid meet'); | 
|  | 15240         // TODO(dfreedm): `pointer-events: none` works around https://crbug.com/
       370136 | 
|  | 15241         // TODO(sjmiles): inline style may not be ideal, but avoids requiring a 
       shadow-root | 
|  | 15242         svg.style.cssText = 'pointer-events: none; display: block; width: 100%; 
       height: 100%;'; | 
|  | 15243         svg.appendChild(content).removeAttribute('id'); | 
|  | 15244         return svg; | 
|  | 15245       } | 
|  | 15246       return null; | 
|  | 15247     } | 
|  | 15248 | 
|  | 15249   }); | 
|  | 15250 </script> | 
|  | 15251 <iron-iconset-svg name="icons" size="24"> | 
|  | 15252 <svg><defs> | 
|  | 15253 <g id="3d-rotation"><path d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 1
       9.16 5.71 24 12 24l.66-.03-3.81-3.81-1.33 1.32zm.89-6.52c-.19 0-.37-.03-.52-.08-
       .16-.06-.29-.13-.4-.24-.11-.1-.2-.22-.26-.37-.06-.14-.09-.3-.09-.47h-1.3c0 .36.0
       7.68.21.95.14.27.33.5.56.69.24.18.51.32.82.41.3.1.62.15.96.15.37 0 .72-.05 1.03-
       .15.32-.1.6-.25.83-.44s.42-.43.55-.72c.13-.29.2-.61.2-.97 0-.19-.02-.38-.07-.56-
       .05-.18-.12-.35-.23-.51-.1-.16-.24-.3-.4-.43-.17-.13-.37-.23-.61-.31.2-.09.37-.2
       .52-.33.15-.13.27-.27.37-.42.1-.15.17-.3.22-.46.05-.16.07-.32.07-.48 0-.36-.06-.
       68-.18-.96-.12-.28-.29-.51-.51-.69-.2-.19-.47-.33-.77-.43C9.1 8.05 8.76 8 8.39 8
       c-.36 0-.69.05-1 .16-.3.11-.57.26-.79.45-.21.19-.38.41-.51.67-.12.26-.18.54-.18.
       85h1.3c0-.17.03-.32.09-.45s.14-.25.25-.34c.11-.09.23-.17.38-.22.15-.05.3-.08.48-
       .08.4 0 .7.1.89.31.19.2.29.49.29.86 0 .18-.03.34-.08.49-.05.15-.14.27-.25.37-.11
       .1-.25.18-.41.24-.16.06-.36.09-.58.09H7.5v1.03h.77c.22 0 .42.02.6.07s.33.13.45.2
       3c.12.11.22.24.29.4.07.16.1.35.1.57 0 .41-.12.72-.35.93-.23.23-.55.33-.95.33zm8.
       55-5.92c-.32-.33-.7-.59-1.14-.77-.43-.18-.92-.27-1.46-.27H12v8h2.3c.55 0 1.06-.0
       9 1.51-.27.45-.18.84-.43 1.16-.76.32-.33.57-.73.74-1.19.17-.47.26-.99.26-1.57v-.
       4c0-.58-.09-1.1-.26-1.57-.18-.47-.43-.87-.75-1.2zm-.39 3.16c0 .42-.05.79-.14 1.1
       3-.1.33-.24.62-.43.85-.19.23-.43.41-.71.53-.29.12-.62.18-.99.18h-.91V9.12h.97c.7
       2 0 1.27.23 1.64.69.38.46.57 1.12.57 1.99v.4zM12 0l-.66.03 3.81 3.81 1.33-1.33c3
       .27 1.55 5.61 4.72 5.96 8.48h1.5C23.44 4.84 18.29 0 12 0z"></path></g> | 
|  | 15254 <g id="accessibility"><path d="M12 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2z
       m9 7h-6v13h-2v-6h-2v6H9V9H3V7h18v2z"></path></g> | 
|  | 15255 <g id="accessible"><circle cx="12" cy="4" r="2"></circle><path d="M19 13v-2c-1.5
       4.02-3.09-.75-4.07-1.83l-1.29-1.43c-.17-.19-.38-.34-.61-.45-.01 0-.01-.01-.02-.0
       1H13c-.35-.2-.75-.3-1.19-.26C10.76 7.11 10 8.04 10 9.09V15c0 1.1.9 2 2 2h5v5h2v-
       5.5c0-1.1-.9-2-2-2h-3v-3.45c1.29 1.07 3.25 1.94 5 1.95zm-6.17 5c-.41 1.16-1.52 2
       -2.83 2-1.66 0-3-1.34-3-3 0-1.31.84-2.41 2-2.83V12.1c-2.28.46-4 2.48-4 4.9 0 2.7
       6 2.24 5 5 5 2.42 0 4.44-1.72 4.9-4h-2.07z"></path></g> | 
|  | 15256 <g id="account-balance"><path d="M4 10v7h3v-7H4zm6 0v7h3v-7h-3zM2 22h19v-3H2v3zm
       14-12v7h3v-7h-3zm-4.5-9L2 6v2h19V6l-9.5-5z"></path></g> | 
|  | 15257 <g id="account-balance-wallet"><path d="M21 18v1c0 1.1-.9 2-2 2H5c-1.11 0-2-.9-2
       -2V5c0-1.1.89-2 2-2h14c1.1 0 2 .9 2 2v1h-9c-1.11 0-2 .9-2 2v8c0 1.1.89 2 2 2h9zm
       -9-2h10V8H12v8zm4-2.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 
       1.5-1.5 1.5z"></path></g> | 
|  | 15258 <g id="account-box"><path d="M3 5v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9
       -2-2-2H5c-1.11 0-2 .9-2 2zm12 4c0 1.66-1.34 3-3 3s-3-1.34-3-3 1.34-3 3-3 3 1.34 
       3 3zm-9 8c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6v-1z"></path></g> | 
|  | 15259 <g id="account-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 1
       0-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14
       .2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.
       94-3.5 3.22-6 3.22z"></path></g> | 
|  | 15260 <g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g> | 
|  | 15261 <g id="add-alert"><path d="M10.01 21.01c0 1.1.89 1.99 1.99 1.99s1.99-.89 1.99-1.
       99h-3.98zm8.87-4.19V11c0-3.25-2.25-5.97-5.29-6.69v-.72C13.59 2.71 12.88 2 12 2s-
       1.59.71-1.59 1.59v.72C7.37 5.03 5.12 7.75 5.12 11v5.82L3 18.94V20h18v-1.06l-2.12
       -2.12zM16 13.01h-3v3h-2v-3H8V11h3V8h2v3h3v2.01z"></path></g> | 
|  | 15262 <g id="add-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.
       9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"></path></g> | 
|  | 15263 <g id="add-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10
       S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"></path></g> | 
|  | 15264 <g id="add-circle-outline"><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.48
        2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8
       s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"></path></g> | 
|  | 15265 <g id="add-shopping-cart"><path d="M11 9h2V6h3V4h-3V1h-2v3H8v2h3v3zm-4 9c-1.1 0-
       1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zm10 0c-1.1 0-1.99.9-1.99 2s.89 2 1.9
       9 2 2-.9 2-2-.9-2-2-2zm-9.83-3.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3
       .86-7.01L19.42 4h-.01l-1.1 2-2.76 5H8.53l-.13-.27L6.16 6l-.95-2-.94-2H1v2h2l3.6 
       7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.13 0-.25-.11-.25
       -.25z"></path></g> | 
|  | 15266 <g id="alarm"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L
       6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12 
       4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.
       13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"></path></g> | 
|  | 15267 <g id="alarm-add"><path d="M7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM22 5.
       72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97
        0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-
       7 7zm1-11h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"></path></g> | 
|  | 15268 <g id="alarm-off"><path d="M12 6c3.87 0 7 3.13 7 7 0 .84-.16 1.65-.43 2.4l1.52 1
       .52c.58-1.19.91-2.51.91-3.92 0-4.97-4.03-9-9-9-1.41 0-2.73.33-3.92.91L9.6 6.43C1
       0.35 6.16 11.16 6 12 6zm10-.28l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM2.92 2.29L1
       .65 3.57 2.98 4.9l-1.11.93 1.42 1.42 1.11-.94.8.8C3.83 8.69 3 10.75 3 13c0 4.97 
       4.02 9 9 9 2.25 0 4.31-.83 5.89-2.2l2.2 2.2 1.27-1.27L3.89 3.27l-.97-.98zm13.55 
       16.1C15.26 19.39 13.7 20 12 20c-3.87 0-7-3.13-7-7 0-1.7.61-3.26 1.61-4.47l9.86 9
       .86zM8.02 3.28L6.6 1.86l-.86.71 1.42 1.42.86-.71z"></path></g> | 
|  | 15269 <g id="alarm-on"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.
       39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 
       0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7
        7zm-1.46-5.47L8.41 12.4l-1.06 1.06 3.18 3.18 6-6-1.06-1.06-4.93 4.95z"></path><
       /g> | 
|  | 15270 <g id="all-out"><path d="M16.21 4.16l4 4v-4zm4 12l-4 4h4zm-12 4l-4-4v4zm-4-12l4-
       4h-4zm12.95-.95c-2.73-2.73-7.17-2.73-9.9 0s-2.73 7.17 0 9.9 7.17 2.73 9.9 0 2.73
       -7.16 0-9.9zm-1.1 8.8c-2.13 2.13-5.57 2.13-7.7 0s-2.13-5.57 0-7.7 5.57-2.13 7.7 
       0 2.13 5.57 0 7.7z"></path></g> | 
|  | 15271 <g id="android"><path d="M6 18c0 .55.45 1 1 1h1v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67
        1.5-1.5V19h2v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h1c.55 0 1-.45 1-1V8H6v
       10zM3.5 8C2.67 8 2 8.67 2 9.5v7c0 .83.67 1.5 1.5 1.5S5 17.33 5 16.5v-7C5 8.67 4.
       33 8 3.5 8zm17 0c-.83 0-1.5.67-1.5 1.5v7c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-7
       c0-.83-.67-1.5-1.5-1.5zm-4.97-5.84l1.3-1.3c.2-.2.2-.51 0-.71-.2-.2-.51-.2-.71 0l
       -1.48 1.48C13.85 1.23 12.95 1 12 1c-.96 0-1.86.23-2.66.63L7.85.15c-.2-.2-.51-.2-
       .71 0-.2.2-.2.51 0 .71l1.31 1.31C6.97 3.26 6 5.01 6 7h12c0-1.99-.97-3.75-2.47-4.
       84zM10 5H9V4h1v1zm5 0h-1V4h1v1z"></path></g> | 
|  | 15272 <g id="announcement"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.
       9 2-2V4c0-1.1-.9-2-2-2zm-7 9h-2V5h2v6zm0 4h-2v-2h2v2z"></path></g> | 
|  | 15273 <g id="apps"><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4z
       m6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"></p
       ath></g> | 
|  | 15274 <g id="archive"><path d="M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0
       -.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 
       2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81
       -1h12l.94 1H5.12z"></path></g> | 
|  | 15275 <g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 1
       3H20v-2z"></path></g> | 
|  | 15276 <g id="arrow-downward"><path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59
       L4 12l8 8 8-8z"></path></g> | 
|  | 15277 <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g> | 
|  | 15278 <g id="arrow-drop-down-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 1
       0-4.48 10-10S17.52 2 12 2zm0 12l-4-4h8l-4 4z"></path></g> | 
|  | 15279 <g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"></path></g> | 
|  | 15280 <g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12
        20l8-8z"></path></g> | 
|  | 15281 <g id="arrow-upward"><path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l
       -8-8-8 8z"></path></g> | 
|  | 15282 <g id="aspect-ratio"><path d="M19 12h-2v3h-3v2h5v-5zM7 9h3V7H5v5h2V9zm14-6H3c-1.
       1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99
       h18v14.02z"></path></g> | 
|  | 15283 <g id="assessment"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-
       .9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"></path></
       g> | 
|  | 15284 <g id="assignment"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82
        2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.
       55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4
       H7V7h10v2z"></path></g> | 
|  | 15285 <g id="assignment-ind"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-
       2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7
        0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 4c1.66 0 3 1.34 3 3s-1.34 3
       -3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1.4c0-2 4-3.1 6-3.1s6 1.1 6 3.1V19z"></path>
       </g> | 
|  | 15286 <g id="assignment-late"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84
       -2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-
       6 15h-2v-2h2v2zm0-4h-2V8h2v6zm-1-9c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 
       1z"></path></g> | 
|  | 15287 <g id="assignment-return"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.
       84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z
       m-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm4 12h-4v3l-5-5 5-5v3h4v4z"
       ></path></g> | 
|  | 15288 <g id="assignment-returned"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.
       4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-
       2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 15l-5-5h3V9h4v4h3l-5 5
       z"></path></g> | 
|  | 15289 <g id="assignment-turned-in"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2
       .4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2
       -2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm-2 14l-4-4 1.41-1.41L10
        14.17l6.59-6.59L18 9l-8 8z"></path></g> | 
|  | 15290 <g id="attachment"><path d="M2 12.5C2 9.46 4.46 7 7.5 7H18c2.21 0 4 1.79 4 4s-1.
       79 4-4 4H9.5C8.12 15 7 13.88 7 12.5S8.12 10 9.5 10H17v2H9.41c-.55 0-.55 1 0 1H18
       c1.1 0 2-.9 2-2s-.9-2-2-2H7.5C5.57 9 4 10.57 4 12.5S5.57 16 7.5 16H17v2H7.5C4.46
        18 2 15.54 2 12.5z"></path></g> | 
|  | 15291 <g id="autorenew"><path d="M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1
       .24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c
       .44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.4
       6-3.03-1.24-4.26z"></path></g> | 
|  | 15292 <g id="backspace"><path d="M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.11c.36.53.
       9.89 1.59.89h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.4
       1 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z
       "></path></g> | 
|  | 15293 <g id="backup"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.3
       5 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05
       -4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"></path></g> | 
|  | 15294 <g id="block"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.5
       2 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 
       13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 
       4.42-3.58 8-8 8z"></path></g> | 
|  | 15295 <g id="book"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2
       V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"></path></g> | 
|  | 15296 <g id="bookmark"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2
       -2-2z"></path></g> | 
|  | 15297 <g id="bookmark-border"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1
       .1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"></path></g> | 
|  | 15298 <g id="bug-report"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.
       59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62
        1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.0
       4.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.
       09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v
       2z"></path></g> | 
|  | 15299 <g id="build"><path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 
       6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1
       .4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z"></path></g> | 
|  | 15300 <g id="cached"><path d="M19 8l-4 4h3c0 3.31-2.69 6-6 6-1.01 0-1.97-.25-2.8-.7l-1
       .46 1.46C8.97 19.54 10.43 20 12 20c4.42 0 8-3.58 8-8h3l-4-4zM6 12c0-3.31 2.69-6 
       6-6 1.01 0 1.97.25 2.8.7l1.46-1.46C15.03 4.46 13.57 4 12 4c-4.42 0-8 3.58-8 8H1l
       4 4 4-4H6z"></path></g> | 
|  | 15301 <g id="camera-enhance"><path d="M9 3L7.17 5H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h1
       6c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2h-3.17L15 3H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5
       -5 5 2.24 5 5-2.24 5-5 5zm0-1l1.25-2.75L16 13l-2.75-1.25L12 9l-1.25 2.75L8 13l2.
       75 1.25z"></path></g> | 
|  | 15302 <g id="cancel"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.
       53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 1
       0.59 15.59 7 17 8.41 13.41 12 17 15.59z"></path></g> | 
|  | 15303 <g id="card-giftcard"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3
       -1.05 0-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c
       0 .35.07.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2
       -2V8c0-1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c
       .55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 
       10.83 8.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"></path></g> | 
|  | 15304 <g id="card-membership"><path d="M20 2H4c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h4v
       5l4-2 4 2v-5h4c1.11 0 2-.89 2-2V4c0-1.11-.89-2-2-2zm0 13H4v-2h16v2zm0-5H4V4h16v6
       z"></path></g> | 
|  | 15305 <g id="card-travel"><path d="M20 6h-3V4c0-1.11-.89-2-2-2H9c-1.11 0-2 .89-2 2v2H4
       c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zM9 
       4h6v2H9V4zm11 15H4v-2h16v2zm0-5H4V8h3v2h2V8h6v2h2V8h3v6z"></path></g> | 
|  | 15306 <g id="change-history"><path d="M12 7.77L18.39 18H5.61L12 7.77M12 4L2 20h20L12 4
       z"></path></g> | 
|  | 15307 <g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path
       ></g> | 
|  | 15308 <g id="check-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 
       2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z">
       </path></g> | 
|  | 15309 <g id="check-box-outline-blank"><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v1
       4c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path></g> | 
|  | 15310 <g id="check-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-
       10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path></g> | 
|  | 15311 <g id="chevron-left"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"></p
       ath></g> | 
|  | 15312 <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"><
       /path></g> | 
|  | 15313 <g id="chrome-reader-mode"><path d="M13 12h7v1.5h-7zm0-2.5h7V11h-7zm0 5h7V16h-7z
       M21 4H3c-1.1 0-2 .9-2 2v13c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 1
       5h-9V6h9v13z"></path></g> | 
|  | 15314 <g id="class"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-
       2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"></path></g> | 
|  | 15315 <g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 
       6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g> | 
|  | 15316 <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 
       6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g> | 
|  | 15317 <g id="cloud"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35
        8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-
       4.78-4.65-4.96z"></path></g> | 
|  | 15318 <g id="cloud-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-
       10S17.52 2 12 2zm4.5 14H8c-1.66 0-3-1.34-3-3s1.34-3 3-3l.14.01C8.58 8.28 10.13 7
        12 7c2.21 0 4 1.79 4 4h.5c1.38 0 2.5 1.12 2.5 2.5S17.88 16 16.5 16z"></path></g
       > | 
|  | 15319 <g id="cloud-done"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64
        5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-
       2.05-4.78-4.65-4.96zM10 17l-3.5-3.5 1.41-1.41L10 14.17 15.18 9l1.41 1.41L10 17z"
       ></path></g> | 
|  | 15320 <g id="cloud-download"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 
       5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2
       .64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"></path></g> | 
|  | 15321 <g id="cloud-off"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4c-1.48 0-2.85.43-
       4.01 1.17l1.46 1.46C10.21 6.23 11.08 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0
        3 1.34 3 3 0 1.13-.64 2.11-1.56 2.62l1.45 1.45C23.16 18.16 24 16.68 24 15c0-2.6
       4-2.05-4.78-4.65-4.96zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14c0 3.31 2.69 6 6 6
       h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h1
       .73z"></path></g> | 
|  | 15322 <g id="cloud-queue"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.6
       4 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64
       -2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h.71C7.37 7.69 9.48 6
        12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3s-1.34 3-3 3z"></path></g> | 
|  | 15323 <g id="cloud-upload"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.
       64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.6
       4-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"></path></g> | 
|  | 15324 <g id="code"><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4
       .6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"></path></g> | 
|  | 15325 <g id="compare-arrows"><path d="M9.01 14H2v2h7.01v3L13 15l-3.99-4v3zm5.98-1v-3H2
       2V8h-7.01V5L11 9l3.99 4z"></path></g> | 
|  | 15326 <g id="content-copy"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-
       2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"><
       /path></g> | 
|  | 15327 <g id="content-cut"><path d="M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4
       S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59 
       14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7
        7h3v-1L9.64 7.64zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm0 12c-1.1 0
       -2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.
       22.5.5-.22.5-.5.5zM19 3l-6 6 2 2 7-7V3z"></path></g> | 
|  | 15328 <g id="content-paste"><path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.8
       2 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c
       .55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"></path>
       </g> | 
|  | 15329 <g id="copyright"><path d="M10.08 10.86c.05-.33.16-.62.3-.87s.34-.46.59-.62c.24-
       .15.54-.22.91-.23.23.01.44.05.63.13.2.09.38.21.52.36s.25.33.34.53.13.42.14.64h1.
       79c-.02-.47-.11-.9-.28-1.29s-.4-.73-.7-1.01-.66-.5-1.08-.66-.88-.23-1.39-.23c-.6
       5 0-1.22.11-1.7.34s-.88.53-1.2.92-.56.84-.71 1.36S8 11.29 8 11.87v.27c0 .58.08 1
       .12.23 1.64s.39.97.71 1.35.72.69 1.2.91 1.05.34 1.7.34c.47 0 .91-.08 1.32-.23s.7
       7-.36 1.08-.63.56-.58.74-.94.29-.74.3-1.15h-1.79c-.01.21-.06.4-.15.58s-.21.33-.3
       6.46-.32.23-.52.3c-.19.07-.39.09-.6.1-.36-.01-.66-.08-.89-.23-.25-.16-.45-.37-.5
       9-.62s-.25-.55-.3-.88-.08-.67-.08-1v-.27c0-.35.03-.68.08-1.01zM12 2C6.48 2 2 6.4
       8 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 
       8-8 8 3.59 8 8-3.59 8-8 8z"></path></g> | 
|  | 15330 <g id="create"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.
       04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.
       75 1.83-1.83z"></path></g> | 
|  | 15331 <g id="create-new-folder"><path d="M20 6h-8l-2-2H4c-1.11 0-1.99.89-1.99 2L2 18c0
        1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-1 8h-3v3h-2v-3h-3v-2h3V9
       h2v3h3v2z"></path></g> | 
|  | 15332 <g id="credit-card"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2
       h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"></path>
       </g> | 
|  | 15333 <g id="dashboard"><path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6
       h8V3h-8z"></path></g> | 
|  | 15334 <g id="date-range"><path d="M9 11H7v2h2v-2zm4 0h-2v2h2v-2zm4 0h-2v2h2v-2zm2-7h-1
       V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c
       0-1.1-.9-2-2-2zm0 16H5V9h14v11z"></path></g> | 
|  | 15335 <g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-
       1-1h-5l-1 1H5v2h14V4z"></path></g> | 
|  | 15336 <g id="description"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2
       H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"></p
       ath></g> | 
|  | 15337 <g id="dns"><path d="M20 13H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1
       -1v-6c0-.55-.45-1-1-1zM7 19c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM20 3H4c-
       .55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zM7 9c-1.1 
       0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"></path></g> | 
|  | 15338 <g id="done"><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"></path
       ></g> | 
|  | 15339 <g id="done-all"><path d="M18 7l-1.41-1.41-6.34 6.34 1.41 1.41L18 7zm4.24-1.41L1
       1.66 16.17 7.48 12l-1.41 1.41L11.66 19l12-12-1.42-1.41zM.41 13.41L6 19l1.41-1.41
       L1.83 12 .41 13.41z"></path></g> | 
|  | 15340 <g id="donut-large"><path d="M11 5.08V2c-5 .5-9 4.81-9 10s4 9.5 9 10v-3.08c-3-.4
       8-6-3.4-6-6.92s3-6.44 6-6.92zM18.97 11H22c-.47-5-4-8.53-9-9v3.08C16 5.51 18.54 8
        18.97 11zM13 18.92V22c5-.47 8.53-4 9-9h-3.03c-.43 3-2.97 5.49-5.97 5.92z"></pat
       h></g> | 
|  | 15341 <g id="donut-small"><path d="M11 9.16V2c-5 .5-9 4.79-9 10s4 9.5 9 10v-7.16c-1-.4
       1-2-1.52-2-2.84s1-2.43 2-2.84zM14.86 11H22c-.48-4.75-4-8.53-9-9v7.16c1 .3 1.52.9
       8 1.86 1.84zM13 14.84V22c5-.47 8.52-4.25 9-9h-7.14c-.34.86-.86 1.54-1.86 1.84z">
       </path></g> | 
|  | 15342 <g id="drafts"><path d="M21.99 8c0-.72-.37-1.35-.94-1.7L12 1 2.95 6.3C2.38 6.65 
       2 7.28 2 8v10c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2l-.01-10zM12 13L3.74 7.84 12 3l8.26
        4.84L12 13z"></path></g> | 
|  | 15343 <g id="eject"><path d="M5 17h14v2H5zm7-12L5.33 15h13.34z"></path></g> | 
|  | 15344 <g id="error"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.5
       2 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></g> | 
|  | 15345 <g id="error-outline"><path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 
       12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58
       -8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g> | 
|  | 15346 <g id="event"><path d="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L
       3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z"
       ></path></g> | 
|  | 15347 <g id="event-seat"><path d="M4 18v3h3v-3h10v3h3v-6H4zm15-8h3v3h-3zM2 10h3v3H2zm1
       5 3H7V5c0-1.1.9-2 2-2h6c1.1 0 2 .9 2 2v8z"></path></g> | 
|  | 15348 <g id="exit-to-app"><path d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2
       h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14
       c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path></g> | 
|  | 15349 <g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"></p
       ath></g> | 
|  | 15350 <g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"></pat
       h></g> | 
|  | 15351 <g id="explore"><path d="M12 10.9c-.61 0-1.1.49-1.1 1.1s.49 1.1 1.1 1.1c.61 0 1.
       1-.49 1.1-1.1s-.49-1.1-1.1-1.1zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10
       -10S17.52 2 12 2zm2.19 12.19L6 18l3.81-8.19L18 6l-3.81 8.19z"></path></g> | 
|  | 15352 <g id="extension"><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 1
       0.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.2
       1 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.2
       1 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"
       ></path></g> | 
|  | 15353 <g id="face"><path d="M9 11.75c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.25 1.25-
       .56 1.25-1.25-.56-1.25-1.25-1.25zm6 0c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.2
       5 1.25-.56 1.25-1.25-.56-1.25-1.25-1.25zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 1
       0-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8 0-.29.02-.58.05-.86 2.36-1.05
        4.23-2.98 5.21-5.37C11.07 8.33 14.05 10 17.42 10c.78 0 1.53-.09 2.25-.26.21.71.
       33 1.47.33 2.26 0 4.41-3.59 8-8 8z"></path></g> | 
|  | 15354 <g id="favorite"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.
       42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 
       8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"></path></g> | 
|  | 15355 <g id="favorite-border"><path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.2
       4 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6
        15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24
        4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 
       5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"></path></g> | 
|  | 15356 <g id="feedback"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-
       2V4c0-1.1-.9-2-2-2zm-7 12h-2v-2h2v2zm0-4h-2V6h2v4z"></path></g> | 
|  | 15357 <g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path
       ></g> | 
|  | 15358 <g id="file-upload"><path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"></path></g> | 
|  | 15359 <g id="filter-list"><path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"></p
       ath></g> | 
|  | 15360 <g id="find-in-page"><path d="M20 19.59V8l-6-6H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1
       .89 2 1.99 2H18c.45 0 .85-.15 1.19-.4l-4.43-4.43c-.8.52-1.74.83-2.76.83-2.76 0-5
       -2.24-5-5s2.24-5 5-5 5 2.24 5 5c0 1.02-.31 1.96-.83 2.75L20 19.59zM9 13c0 1.66 1
       .34 3 3 3s3-1.34 3-3-1.34-3-3-3-3 1.34-3 3z"></path></g> | 
|  | 15361 <g id="find-replace"><path d="M11 6c1.38 0 2.63.56 3.54 1.46L12 10h6V4l-2.05 2.0
       5C14.68 4.78 12.93 4 11 4c-3.53 0-6.43 2.61-6.92 6H6.1c.46-2.28 2.48-4 4.9-4zm5.
       64 9.14c.66-.9 1.12-1.97 1.28-3.14H15.9c-.46 2.28-2.48 4-4.9 4-1.38 0-2.63-.56-3
       .54-1.46L10 12H4v6l2.05-2.05C7.32 17.22 9.07 18 11 18c1.55 0 2.98-.51 4.14-1.36L
       20 21.49 21.49 20l-4.85-4.86z"></path></g> | 
|  | 15362 <g id="fingerprint"><path d="M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 
       12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.8
       2 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.
       44.28zM3.5 9.72c-.1 0-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4 2.25-2.5 3.75
       -3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25.16.22.11.54-.12.7-
       .23.16-.54.11-.7-.12-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36
       .7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21zm6.25 12.07c-.13 0-.26-.05-.35-.15-.87-
       .87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s
       5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39-2.
       57 0-4.66 1.97-4.66 4.39 0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2
       .19.51 0 .71-.11.1-.24.15-.37.15zm7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.
       38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54
       .71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1
       .07.12-1.21.12zM14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-
       1.39-2.17-3.24-2.17-5.22 0-1.62 1.38-2.94 3.08-2.94 1.7 0 3.08 1.32 3.08 2.94 0 
       1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44
        1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64
       -.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96 0-1.2.23-2.29.68-3.24 1.33-2.7
       9 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-
       1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87 
       4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38z"></path><
       /g> | 
|  | 15363 <g id="flag"><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"></path></g> | 
|  | 15364 <g id="flight-land"><path d="M2.5 19h19v2h-19zm7.18-5.73l4.35 1.16 5.31 1.42c.8.
       21 1.62-.26 1.84-1.06.21-.8-.26-1.62-1.06-1.84l-5.31-1.42-2.76-9.02L10.12 2v8.28
       L5.15 8.95l-.93-2.32-1.45-.39v5.17l1.6.43 5.31 1.43z"></path></g> | 
|  | 15365 <g id="flight-takeoff"><path d="M2.5 19h19v2h-19zm19.57-9.36c-.21-.8-1.04-1.28-1
       .84-1.06L14.92 10l-6.9-6.43-1.93.51 4.14 7.17-4.97 1.33-1.97-1.54-1.45.39 1.82 3
       .16.77 1.33 1.6-.43 5.31-1.42 4.35-1.16L21 11.49c.81-.23 1.28-1.05 1.07-1.85z"><
       /path></g> | 
|  | 15366 <g id="flip-to-back"><path d="M9 7H7v2h2V7zm0 4H7v2h2v-2zm0-8c-1.11 0-2 .9-2 2h2
       V3zm4 12h-2v2h2v-2zm6-12v2h2c0-1.1-.9-2-2-2zm-6 0h-2v2h2V3zM9 17v-2H7c0 1.1.89 2
        2 2zm10-4h2v-2h-2v2zm0-4h2V7h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zM5 7H3v12c0 1.1.89 2
        2 2h12v-2H5V7zm10-2h2V3h-2v2zm0 12h2v-2h-2v2z"></path></g> | 
|  | 15367 <g id="flip-to-front"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm2 4v-2H3c0 1.1.89 2
        2 2zM3 9h2V7H3v2zm12 12h2v-2h-2v2zm4-18H9c-1.11 0-2 .9-2 2v10c0 1.1.89 2 2 2h10
       c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12H9V5h10v10zm-8 6h2v-2h-2v2zm-4 0h2v-2H7v2z
       "></path></g> | 
|  | 15368 <g id="folder"><path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0
        2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"></path></g> | 
|  | 15369 <g id="folder-open"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2
        2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"></path></g> | 
|  | 15370 <g id="folder-shared"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9
        2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-5 3c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-
       2 .9-2 2-2zm4 8h-8v-1c0-1.33 2.67-2 4-2s4 .67 4 2v1z"></path></g> | 
|  | 15371 <g id="font-download"><path d="M9.93 13.5h4.14L12 7.98zM20 2H4c-1.1 0-2 .9-2 2v1
       6c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-4.05 16.5l-1.14-3H9.17l-1.1
       2 3H5.96l5.11-13h1.86l5.11 13h-2.09z"></path></g> | 
|  | 15372 <g id="forward"><path d="M12 8V4l8 8-8 8v-4H4V8z"></path></g> | 
|  | 15373 <g id="fullscreen"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-
       5h-2v3zM14 5v2h3v3h2V5h-5z"></path></g> | 
|  | 15374 <g id="fullscreen-exit"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h
       3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"></path></g> | 
|  | 15375 <g id="gavel"><path d="M1 21h12v2H1zM5.245 8.07l2.83-2.827 14.14 14.142-2.828 2.
       828zM12.317 1l5.657 5.656-2.83 2.83-5.654-5.66zM3.825 9.485l5.657 5.657-2.828 2.
       828-5.657-5.657z"></path></g> | 
|  | 15376 <g id="gesture"><path d="M4.59 6.89c.7-.71 1.4-1.35 1.71-1.22.5.2 0 1.03-.3 1.52
       -.25.42-2.86 3.89-2.86 6.31 0 1.28.48 2.34 1.34 2.98.75.56 1.74.73 2.64.46 1.07-
       .31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-
       3.78.64-5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1H
       21v-2.5h-2.47c-.15-1.65-1.09-4.2-4.03-4.2-2.25 0-4.18 1.91-4.94 2.84-.58.73-2.06
        2.48-2.29 2.72-.25.3-.68.84-1.11.84-.45 0-.72-.83-.36-1.92.35-1.09 1.4-2.86 1.8
       5-3.52.78-1.14 1.3-1.92 1.3-3.28C8.95 3.69 7.31 3 6.44 3 5.12 3 3.97 4 3.72 4.25
       c-.36.36-.66.66-.88.93l1.75 1.71zm9.29 11.66c-.31 0-.74-.26-.74-.72 0-.6.73-2.2 
       2.87-2.76-.3 2.69-1.43 3.48-2.13 3.48z"></path></g> | 
|  | 15377 <g id="get-app"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></g> | 
|  | 15378 <g id="gif"><path d="M11.5 9H13v6h-1.5zM9 9H6c-.6 0-1 .5-1 1v4c0 .5.4 1 1 1h3c.6
        0 1-.5 1-1v-2H8.5v1.5h-2v-3H10V10c0-.5-.4-1-1-1zm10 1.5V9h-4.5v6H16v-2h2v-1.5h-
       2v-1z"></path></g> | 
|  | 15379 <g id="grade"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19
        8.63 2 9.24l5.46 4.73L5.82 21z"></path></g> | 
|  | 15380 <g id="group-work"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10
       S17.52 2 12 2zM8 17.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5
       -1.12 2.5-2.5 2.5zM9.5 8c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5-1.12 2.5-2.5 2
       .5S9.5 9.38 9.5 8zm6.5 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.
       5 2.5-1.12 2.5-2.5 2.5z"></path></g> | 
|  | 15381 <g id="help"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52
        2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.
       45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2
       .21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"></path></g> | 
|  | 15382 <g id="help-outline"><path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 
       10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-
       3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-
       2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"></path></g> | 
|  | 15383 <g id="highlight-off"><path d="M14.59 8L12 10.59 9.41 8 8 9.41 10.59 12 8 14.59 
       9.41 16 12 13.41 14.59 16 16 14.59 13.41 12 16 9.41 14.59 8zM12 2C6.47 2 2 6.47 
       2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-
       8 8 3.59 8 8-3.59 8-8 8z"></path></g> | 
|  | 15384 <g id="history"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.8
       7 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19
       .99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2
       .08V8H12z"></path></g> | 
|  | 15385 <g id="home"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path></g> | 
|  | 15386 <g id="hourglass-empty"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.
       99h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6zm10 14.5V20H8v-3.5l4-4 4 4zm-4-5l-4-4V4
       h8v3.5l-4 4z"></path></g> | 
|  | 15387 <g id="hourglass-full"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.9
       9h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6z"></path></g> | 
|  | 15388 <g id="http"><path d="M4.5 11h-2V9H1v6h1.5v-2.5h2V15H6V9H4.5v2zm2.5-.5h1.5V15H10
       v-4.5h1.5V9H7v1.5zm5.5 0H14V15h1.5v-4.5H17V9h-4.5v1.5zm9-1.5H18v6h1.5v-2h2c.8 0 
       1.5-.7 1.5-1.5v-1c0-.8-.7-1.5-1.5-1.5zm0 2.5h-2v-1h2v1z"></path></g> | 
|  | 15389 <g id="https"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2
        2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9
       -2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.
       1 3.1v2z"></path></g> | 
|  | 15390 <g id="important-devices"><path d="M23 11.01L18 11c-.55 0-1 .45-1 1v9c0 .55.45 1
        1 1h5c.55 0 1-.45 1-1v-9c0-.55-.45-.99-1-.99zM23 20h-5v-7h5v7zM20 2H2C.89 2 0 2
       .89 0 4v12c0 1.1.89 2 2 2h7v2H7v2h8v-2h-2v-2h2v-2H2V4h18v5h2V4c0-1.11-.9-2-2-2zm
       -8.03 7L11 6l-.97 3H7l2.47 1.76-.94 2.91 2.47-1.8 2.47 1.8-.94-2.91L15 9h-3.03z"
       ></path></g> | 
|  | 15391 <g id="inbox"><path d="M19 3H4.99c-1.11 0-1.98.89-1.98 2L3 19c0 1.1.88 2 1.99 2H
       19c1.1 0 2-.9 2-2V5c0-1.11-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3H4.99V
       5H19v10z"></path></g> | 
|  | 15392 <g id="indeterminate-check-box"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 
       2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10H7v-2h10v2z"></path></g> | 
|  | 15393 <g id="info"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52
        2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"></path></g> | 
|  | 15394 <g id="info-outline"><path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 
       10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-
       3.59 8-8 8zM11 9h2V7h-2v2z"></path></g> | 
|  | 15395 <g id="input"><path d="M21 3.01H3c-1.1 0-2 .9-2 2V9h2V4.99h18v14.03H3V15H1v4.01c
       0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98v-14c0-1.11-.9-2-2-2zM11 16l4-4-4-4v3H1
       v2h10v3z"></path></g> | 
|  | 15396 <g id="invert-colors"><path d="M17.66 7.93L12 2.27 6.34 7.93c-3.12 3.12-3.12 8.1
       9 0 11.31C7.9 20.8 9.95 21.58 12 21.58c2.05 0 4.1-.78 5.66-2.34 3.12-3.12 3.12-8
       .19 0-11.31zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3
       .11 1.76-4.24L12 5.1v14.49z"></path></g> | 
|  | 15397 <g id="label"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9
        3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"></p
       ath></g> | 
|  | 15398 <g id="label-outline"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.
       01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.
       16zM16 17H5V7h11l3.55 5L16 17z"></path></g> | 
|  | 15399 <g id="language"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 2
       2 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63
        3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.
       76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-
       .14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.
       37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8
       .03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96z
       M14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16
        2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.4
       9 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64
       .26 1.31.26 2s-.1 1.36-.26 2h-3.38z"></path></g> | 
|  | 15400 <g id="launch"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1
       .1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></pa
       th></g> | 
|  | 15401 <g id="lightbulb-outline"><path d="M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1
       zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45
        1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.
       3l-.85-.6C7.8 12.16 7 10.63 7 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15
        4.1z"></path></g> | 
|  | 15402 <g id="line-style"><path d="M3 16h5v-2H3v2zm6.5 0h5v-2h-5v2zm6.5 0h5v-2h-5v2zM3 
       20h2v-2H3v2zm4 0h2v-2H7v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zM3 12h8v-
       2H3v2zm10 0h8v-2h-8v2zM3 4v4h18V4H3z"></path></g> | 
|  | 15403 <g id="line-weight"><path d="M3 17h18v-2H3v2zm0 3h18v-1H3v1zm0-7h18v-3H3v3zm0-9v
       4h18V4H3z"></path></g> | 
|  | 15404 <g id="link"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2
       .24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 
       3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"></pat
       h></g> | 
|  | 15405 <g id="list"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm
       0 4h14v-2H7v2zM7 7v2h14V7H7z"></path></g> | 
|  | 15406 <g id="lock"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 
       2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-
       2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1
        3.1v2z"></path></g> | 
|  | 15407 <g id="lock-open"><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-
       9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 
       3.1 3.1v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2
       zm0 12H6V10h12v10z"></path></g> | 
|  | 15408 <g id="lock-outline"><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z
       m6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1
       .1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM8.9 6c0-1.71 1.39-3.1 3.1-3.1s3.1 1.39 3.1 3.1v
       2H8.9V6zM18 20H6V10h12v10z"></path></g> | 
|  | 15409 <g id="loyalty"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9
       -2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7
       c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 
       4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7zm11.77 8.27L13 19.54l-4.27-4.27C8.28 14.81 8 1
       4.19 8 13.5c0-1.38 1.12-2.5 2.5-2.5.69 0 1.32.28 1.77.74l.73.72.73-.73c.45-.45 1
       .08-.73 1.77-.73 1.38 0 2.5 1.12 2.5 2.5 0 .69-.28 1.32-.73 1.77z"></path></g> | 
|  | 15410 <g id="mail"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2
       -.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"></path></g> | 
|  | 15411 <g id="markunread"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1
       .1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"></path></g> | 
|  | 15412 <g id="markunread-mailbox"><path d="M20 6H10v6H8V4h6V0H6v6H4c-1.1 0-2 .9-2 2v12c
       0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2z"></path></g> | 
|  | 15413 <g id="menu"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></g> | 
|  | 15414 <g id="more-horiz"><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12
        0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.
       9 2-2-.9-2-2-2z"></path></g> | 
|  | 15415 <g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2
       c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2
       -2-.9-2-2-2z"></path></g> | 
|  | 15416 <g id="motorcycle"><path d="M19.44 9.03L15.41 5H11v2h3.59l2 2H5c-2.8 0-5 2.2-5 5
       s2.2 5 5 5c2.46 0 4.45-1.69 4.9-4h1.65l2.77-2.77c-.21.54-.32 1.14-.32 1.77 0 2.8
        2.2 5 5 5s5-2.2 5-5c0-2.65-1.97-4.77-4.56-4.97zM7.82 15C7.4 16.15 6.28 17 5 17c
       -1.63 0-3-1.37-3-3s1.37-3 3-3c1.28 0 2.4.85 2.82 2H5v2h2.82zM19 17c-1.66 0-3-1.3
       4-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z"></path></g> | 
|  | 15417 <g id="move-to-inbox"><path d="M19 3H4.99c-1.11 0-1.98.9-1.98 2L3 19c0 1.1.88 2 
       1.99 2H19c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3
       H4.99V5H19v10zm-3-5h-2V7h-4v3H8l4 4 4-4z"></path></g> | 
|  | 15418 <g id="next-week"><path d="M20 7h-4V5c0-.55-.22-1.05-.59-1.41C15.05 3.22 14.55 3
        14 3h-4c-1.1 0-2 .9-2 2v2H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V
       9c0-1.1-.9-2-2-2zM10 5h4v2h-4V5zm1 13.5l-1-1 3-3-3-3 1-1 4 4-4 4z"></path></g> | 
|  | 15419 <g id="note-add"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18
       c1.1 0 2-.9 2-2V8l-6-6zm2 14h-3v3h-2v-3H8v-2h3v-3h2v3h3v2zm-3-7V3.5L18.5 9H13z">
       </path></g> | 
|  | 15420 <g id="offline-pin"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17
       .5 2 12 2zm5 16H7v-2h10v2zm-6.7-4L7 10.7l1.4-1.4 1.9 1.9 5.3-5.3L17 7.3 10.3 14z
       "></path></g> | 
|  | 15421 <g id="opacity"><path d="M17.66 8L12 2.35 6.34 8C4.78 9.56 4 11.64 4 13.64s.78 4
       .11 2.34 5.67 3.61 2.35 5.66 2.35 4.1-.79 5.66-2.35S20 15.64 20 13.64 19.22 9.56
        17.66 8zM6 14c.01-2 .62-3.27 1.76-4.4L12 5.27l4.24 4.38C17.38 10.77 17.99 12 18
        14H6z"></path></g> | 
|  | 15422 <g id="open-in-browser"><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2
       H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z">
       </path></g> | 
|  | 15423 <g id="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2
       h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
       ></path></g> | 
|  | 15424 <g id="open-with"><path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm
       14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"></path></g> | 
|  | 15425 <g id="pageview"><path d="M11.5 9C10.12 9 9 10.12 9 11.5s1.12 2.5 2.5 2.5 2.5-1.
       12 2.5-2.5S12.88 9 11.5 9zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9
        2-2V6c0-1.1-.9-2-2-2zm-3.21 14.21l-2.91-2.91c-.69.44-1.51.7-2.39.7C9.01 16 7 13
       .99 7 11.5S9.01 7 11.5 7 16 9.01 16 11.5c0 .88-.26 1.69-.7 2.39l2.91 2.9-1.42 1.
       42z"></path></g> | 
|  | 15426 <g id="pan-tool"><path d="M23 5.5V20c0 2.2-1.8 4-4 4h-7.3c-1.08 0-2.1-.43-2.85-1
       .19L1 14.83s1.26-1.23 1.3-1.25c.22-.19.49-.29.79-.29.22 0 .42.06.6.16.04.01 4.31
        2.46 4.31 2.46V4c0-.83.67-1.5 1.5-1.5S11 3.17 11 4v7h1V1.5c0-.83.67-1.5 1.5-1.5
       S15 .67 15 1.5V11h1V2.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V11h1V5.5c0-.83.67-1.
       5 1.5-1.5s1.5.67 1.5 1.5z"></path></g> | 
|  | 15427 <g id="payment"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c
       1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"></path></g> | 
|  | 15428 <g id="perm-camera-mic"><path d="M20 5h-3.17L15 3H9L7.17 5H4c-1.1 0-2 .9-2 2v12c
       0 1.1.9 2 2 2h7v-2.09c-2.83-.48-5-2.94-5-5.91h2c0 2.21 1.79 4 4 4s4-1.79 4-4h2c0
        2.97-2.17 5.43-5 5.91V21h7c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-6 8c0 1.1-.9 2-2 2
       s-2-.9-2-2V9c0-1.1.9-2 2-2s2 .9 2 2v4z"></path></g> | 
|  | 15429 <g id="perm-contact-calendar"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-2 .9-2 
       2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 3c1.66 0 3 1.34 3 3s-
       1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1z"></pa
       th></g> | 
|  | 15430 <g id="perm-data-setting"><path d="M18.99 11.5c.34 0 .67.03 1 .07L20 0 0 20h11.5
       6c-.04-.33-.07-.66-.07-1 0-4.14 3.36-7.5 7.5-7.5zm3.71 7.99c.02-.16.04-.32.04-.4
       9 0-.17-.01-.33-.04-.49l1.06-.83c.09-.08.12-.21.06-.32l-1-1.73c-.06-.11-.19-.15-
       .31-.11l-1.24.5c-.26-.2-.54-.37-.85-.49l-.19-1.32c-.01-.12-.12-.21-.24-.21h-2c-.
       12 0-.23.09-.25.21l-.19 1.32c-.3.13-.59.29-.85.49l-1.24-.5c-.11-.04-.24 0-.31.11
       l-1 1.73c-.06.11-.04.24.06.32l1.06.83c-.02.16-.03.32-.03.49 0 .17.01.33.03.49l-1
       .06.83c-.09.08-.12.21-.06.32l1 1.73c.06.11.19.15.31.11l1.24-.5c.26.2.54.37.85.49
       l.19 1.32c.02.12.12.21.25.21h2c.12 0 .23-.09.25-.21l.19-1.32c.3-.13.59-.29.84-.4
       9l1.25.5c.11.04.24 0 .31-.11l1-1.73c.06-.11.03-.24-.06-.32l-1.07-.83zm-3.71 1.01
       c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path>
       </g> | 
|  | 15431 <g id="perm-device-information"><path d="M13 7h-2v2h2V7zm0 4h-2v6h2v-6zm4-9.99L7
        1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17
        19H7V5h10v14z"></path></g> | 
|  | 15432 <g id="perm-identity"><path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.
       9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2
       .1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-
       8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z"></path></g> | 
|  | 15433 <g id="perm-media"><path d="M2 6H0v5h.01L0 20c0 1.1.9 2 2 2h18v-2H2V6zm20-2h-8l-
       2-2H6c-1.1 0-1.99.9-1.99 2L4 16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2
       zM7 15l4.5-6 3.5 4.51 2.5-3.01L21 15H7z"></path></g> | 
|  | 15434 <g id="perm-phone-msg"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.0
       3-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2-2.21c.28-.27.36-.66.25-1.0
       1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 1
       7 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM12 3v10l3-3h6V3h-9z"></path></g> | 
|  | 15435 <g id="perm-scan-wifi"><path d="M12 3C6.95 3 3.15 4.85 0 7.23L12 22 24 7.25C20.8
       5 4.87 17.05 3 12 3zm1 13h-2v-6h2v6zm-2-8V6h2v2h-2z"></path></g> | 
|  | 15436 <g id="pets"><circle cx="4.5" cy="9.5" r="2.5"></circle><circle cx="9" cy="5.5" 
       r="2.5"></circle><circle cx="15" cy="5.5" r="2.5"></circle><circle cx="19.5" cy=
       "9.5" r="2.5"></circle><path d="M17.34 14.86c-.87-1.02-1.6-1.89-2.48-2.91-.46-.5
       4-1.05-1.08-1.75-1.32-.11-.04-.22-.07-.33-.09-.25-.04-.52-.04-.78-.04s-.53 0-.79
       .05c-.11.02-.22.05-.33.09-.7.24-1.28.78-1.75 1.32-.87 1.02-1.6 1.89-2.48 2.91-1.
       31 1.31-2.92 2.76-2.62 4.79.29 1.02 1.02 2.03 2.33 2.32.73.15 3.06-.44 5.54-.44h
       .18c2.48 0 4.81.58 5.54.44 1.31-.29 2.04-1.31 2.33-2.32.31-2.04-1.3-3.49-2.61-4.
       8z"></path></g> | 
|  | 15437 <g id="picture-in-picture"><path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1
       .1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03
       z"></path></g> | 
|  | 15438 <g id="picture-in-picture-alt"><path d="M19 11h-8v6h8v-6zm4 8V4.98C23 3.88 22.1 
       3 21 3H3c-1.1 0-2 .88-2 1.98V19c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zm-2 .02H3V4.97h1
       8v14.05z"></path></g> | 
|  | 15439 <g id="play-for-work"><path d="M11 5v5.59H7.5l4.5 4.5 4.5-4.5H13V5h-2zm-5 9c0 3.
       31 2.69 6 6 6s6-2.69 6-6h-2c0 2.21-1.79 4-4 4s-4-1.79-4-4H6z"></path></g> | 
|  | 15440 <g id="polymer"><path d="M19 4h-4L7.11 16.63 4.5 12 9 4H5L.5 12 5 20h4l7.89-12.6
       3L19.5 12 15 20h4l4.5-8z"></path></g> | 
|  | 15441 <g id="power-settings-new"><path d="M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99 
       7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17
        5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6
       .83z"></path></g> | 
|  | 15442 <g id="pregnant-woman"><path d="M9 4c0-1.11.89-2 2-2s2 .89 2 2-.89 2-2 2-2-.89-2
       -2zm7 9c-.01-1.34-.83-2.51-2-3 0-1.66-1.34-3-3-3s-3 1.34-3 3v7h2v5h3v-5h3v-4z"><
       /path></g> | 
|  | 15443 <g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3
       -3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6
       v4h12V3z"></path></g> | 
|  | 15444 <g id="query-builder"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52
        22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8
        8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"></path></g> | 
|  | 15445 <g id="question-answer"><path d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.4
       5-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"><
       /path></g> | 
|  | 15446 <g id="radio-button-checked"><path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24
        5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2
       zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g> | 
|  | 15447 <g id="radio-button-unchecked"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 1
       0-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-
       8 8z"></path></g> | 
|  | 15448 <g id="receipt"><path d="M18 17H6v-2h12v2zm0-4H6v-2h12v2zm0-4H6V7h12v2zM3 22l1.5
       -1.5L6 22l1.5-1.5L9 22l1.5-1.5L12 22l1.5-1.5L15 22l1.5-1.5L18 22l1.5-1.5L21 22V2
       l-1.5 1.5L18 2l-1.5 1.5L15 2l-1.5 1.5L12 2l-1.5 1.5L9 2 7.5 3.5 6 2 4.5 3.5 3 2v
       20z"></path></g> | 
|  | 15449 <g id="record-voice-over"><circle cx="9" cy="9" r="4"></circle><path d="M9 15c-2
       .67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4zm7.76-9.64l-1.68 1.69c.84 1.18.84 2.7
       1 0 3.89l1.68 1.69c2.02-2.02 2.02-5.07 0-7.27zM20.07 2l-1.63 1.63c2.77 3.02 2.77
        7.56 0 10.74L20.07 16c3.9-3.89 3.91-9.95 0-14z"></path></g> | 
|  | 15450 <g id="redeem"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3-1.05 0
       -1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 .35.0
       7.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-
       1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c.55 0 1
        .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8
       .62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"></path></g> | 
|  | 15451 <g id="redo"><path d="M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.9
       6 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6
        3.6z"></path></g> | 
|  | 15452 <g id="refresh"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.9
       9 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6
       -2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"></path></g> | 
|  | 15453 <g id="remove"><path d="M19 13H5v-2h14v2z"></path></g> | 
|  | 15454 <g id="remove-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10
       -10S17.52 2 12 2zm5 11H7v-2h10v2z"></path></g> | 
|  | 15455 <g id="remove-circle-outline"><path d="M7 11v2h10v-2H7zm5-9C6.48 2 2 6.48 2 12s4
       .48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.
       59 8 8-3.59 8-8 8z"></path></g> | 
|  | 15456 <g id="reorder"><path d="M3 15h18v-2H3v2zm0 4h18v-2H3v2zm0-8h18V9H3v2zm0-6v2h18V
       5H3z"></path></g> | 
|  | 15457 <g id="reply"><path d="M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"
       ></path></g> | 
|  | 15458 <g id="reply-all"><path d="M7 8V5l-7 7 7 7v-3l-4-4 4-4zm6 1V5l-7 7 7 7v-4.1c5 0 
       8.5 1.6 11 5.1-1-5-4-10-11-11z"></path></g> | 
|  | 15459 <g id="report"><path d="M15.73 3H8.27L3 8.27v7.46L8.27 21h7.46L21 15.73V8.27L15.
       73 3zM12 17.3c-.72 0-1.3-.58-1.3-1.3 0-.72.58-1.3 1.3-1.3.72 0 1.3.58 1.3 1.3 0 
       .72-.58 1.3-1.3 1.3zm1-4.3h-2V7h2v6z"></path></g> | 
|  | 15460 <g id="report-problem"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v
       4z"></path></g> | 
|  | 15461 <g id="restore"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.8
       7 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19
       .99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2
       .08V8H12z"></path></g> | 
|  | 15462 <g id="room"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.8
       7-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1
       .12 2.5-2.5 2.5z"></path></g> | 
|  | 15463 <g id="rounded-corner"><path d="M19 19h2v2h-2v-2zm0-2h2v-2h-2v2zM3 13h2v-2H3v2zm
       0 4h2v-2H3v2zm0-8h2V7H3v2zm0-4h2V3H3v2zm4 0h2V3H7v2zm8 16h2v-2h-2v2zm-4 0h2v-2h-
       2v2zm4 0h2v-2h-2v2zm-8 0h2v-2H7v2zm-4 0h2v-2H3v2zM21 8c0-2.76-2.24-5-5-5h-5v2h5c
       1.65 0 3 1.35 3 3v5h2V8z"></path></g> | 
|  | 15464 <g id="rowing"><path d="M8.5 14.5L4 19l1.5 1.5L9 17h2l-2.5-2.5zM15 1c-1.1 0-2 .9
       -2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 20.01L18 24l-2.99-3.01V19.5l-7.1-7.09c-.31.05
       -.61.07-.91.07v-2.16c1.66.03 3.61-.87 4.67-2.04l1.4-1.55c.19-.21.43-.38.69-.5.29
       -.14.62-.23.96-.23h.03C15.99 6.01 17 7.02 17 8.26v5.75c0 .84-.35 1.61-.92 2.16l-
       3.58-3.58v-2.27c-.63.52-1.43 1.02-2.29 1.39L16.5 18H18l3 3.01z"></path></g> | 
|  | 15465 <g id="save"><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2
       -2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h1
       0v4z"></path></g> | 
|  | 15466 <g id="schedule"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 2
       2 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.
       58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"></path></g> | 
|  | 15467 <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.
       91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.7
       9l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.
       5 11.99 14 9.5 14z"></path></g> | 
|  | 15468 <g id="select-all"><path d="M3 5h2V3c-1.1 0-2 .9-2 2zm0 8h2v-2H3v2zm4 8h2v-2H7v2
       zM3 9h2V7H3v2zm10-6h-2v2h2V3zm6 0v2h2c0-1.1-.9-2-2-2zM5 21v-2H3c0 1.1.9 2 2 2zm-
       2-4h2v-2H3v2zM9 3H7v2h2V3zm2 18h2v-2h-2v2zm8-8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v
       2zm0-12h2V7h-2v2zm0 8h2v-2h-2v2zm-4 4h2v-2h-2v2zm0-16h2V3h-2v2zM7 17h10V7H7v10zm
       2-8h6v6H9V9z"></path></g> | 
|  | 15469 <g id="send"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"></path></g> | 
|  | 15470 <g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.
       11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.
       08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2
       .65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49
       .12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.1
       2.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42
       .49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.4
       9 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3
       .5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g> | 
|  | 15471 <g id="settings-applications"><path d="M12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-
       .9-2-2-2zm7-7H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.8
       9-2-2-2zm-1.75 9c0 .23-.02.46-.05.68l1.48 1.16c.13.11.17.3.08.45l-1.4 2.42c-.09.
       15-.27.21-.43.15l-1.74-.7c-.36.28-.76.51-1.18.69l-.26 1.85c-.03.17-.18.3-.35.3h-
       2.8c-.17 0-.32-.13-.35-.29l-.26-1.85c-.43-.18-.82-.41-1.18-.69l-1.74.7c-.16.06-.
       34 0-.43-.15l-1.4-2.42c-.09-.15-.05-.34.08-.45l1.48-1.16c-.03-.23-.05-.46-.05-.6
       9 0-.23.02-.46.05-.68l-1.48-1.16c-.13-.11-.17-.3-.08-.45l1.4-2.42c.09-.15.27-.21
       .43-.15l1.74.7c.36-.28.76-.51 1.18-.69l.26-1.85c.03-.17.18-.3.35-.3h2.8c.17 0 .3
       2.13.35.29l.26 1.85c.43.18.82.41 1.18.69l1.74-.7c.16-.06.34 0 .43.15l1.4 2.42c.0
       9.15.05.34-.08.45l-1.48 1.16c.03.23.05.46.05.69z"></path></g> | 
|  | 15472 <g id="settings-backup-restore"><path d="M14 12c0-1.1-.9-2-2-2s-2 .9-2 2 .9 2 2 
       2 2-.9 2-2zm-2-9c-4.97 0-9 4.03-9 9H0l4 4 4-4H5c0-3.87 3.13-7 7-7s7 3.13 7 7-3.1
       3 7-7 7c-1.51 0-2.91-.49-4.06-1.3l-1.42 1.44C8.04 20.3 9.94 21 12 21c4.97 0 9-4.
       03 9-9s-4.03-9-9-9z"></path></g> | 
|  | 15473 <g id="settings-bluetooth"><path d="M11 24h2v-2h-2v2zm-4 0h2v-2H7v2zm8 0h2v-2h-2
       v2zm2.71-18.29L12 0h-1v7.59L6.41 3 5 4.41 10.59 10 5 15.59 6.41 17 11 12.41V20h1
       l5.71-5.71-4.3-4.29 4.3-4.29zM13 3.83l1.88 1.88L13 7.59V3.83zm1.88 10.46L13 16.1
       7v-3.76l1.88 1.88z"></path></g> | 
|  | 15474 <g id="settings-brightness"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18
       c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02zM8 16h2.5l1.5 1.5 1.5-
       1.5H16v-2.5l1.5-1.5-1.5-1.5V8h-2.5L12 6.5 10.5 8H8v2.5L6.5 12 8 13.5V16zm4-7c1.6
       6 0 3 1.34 3 3s-1.34 3-3 3V9z"></path></g> | 
|  | 15475 <g id="settings-cell"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zM16 
       .01L8 0C6.9 0 6 .9 6 2v16c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V2c0-1.1-.9-1.99-2-1.99z
       M16 16H8V4h8v12z"></path></g> | 
|  | 15476 <g id="settings-ethernet"><path d="M7.77 6.76L6.23 5.48.82 12l5.41 6.52 1.54-1.2
       8L3.42 12l4.35-5.24zM7 13h2v-2H7v2zm10-2h-2v2h2v-2zm-6 2h2v-2h-2v2zm6.77-7.52l-1
       .54 1.28L20.58 12l-4.35 5.24 1.54 1.28L23.18 12l-5.41-6.52z"></path></g> | 
|  | 15477 <g id="settings-input-antenna"><path d="M12 5c-3.87 0-7 3.13-7 7h2c0-2.76 2.24-5
        5-5s5 2.24 5 5h2c0-3.87-3.13-7-7-7zm1 9.29c.88-.39 1.5-1.26 1.5-2.29 0-1.38-1.1
       2-2.5-2.5-2.5S9.5 10.62 9.5 12c0 1.02.62 1.9 1.5 2.29v3.3L7.59 21 9 22.41l3-3 3 
       3L16.41 21 13 17.59v-3.3zM12 1C5.93 1 1 5.93 1 12h2c0-4.97 4.03-9 9-9s9 4.03 9 9
       h2c0-6.07-4.93-11-11-11z"></path></g> | 
|  | 15478 <g id="settings-input-component"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h
       6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0
       c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1
       -1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4
        14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"></path></g> | 
|  | 15479 <g id="settings-input-composite"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h
       6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0
       c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1
       -1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4
        14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"></path></g> | 
|  | 15480 <g id="settings-input-hdmi"><path d="M18 7V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v3H
       5v6l3 6v3h8v-3l3-6V7h-1zM8 4h8v3h-2V5h-1v2h-2V5h-1v2H8V4z"></path></g> | 
|  | 15481 <g id="settings-input-svideo"><path d="M8 11.5c0-.83-.67-1.5-1.5-1.5S5 10.67 5 1
       1.5 5.67 13 6.5 13 8 12.33 8 11.5zm7-5c0-.83-.67-1.5-1.5-1.5h-3C9.67 5 9 5.67 9 
       6.5S9.67 8 10.5 8h3c.83 0 1.5-.67 1.5-1.5zM8.5 15c-.83 0-1.5.67-1.5 1.5S7.67 18 
       8.5 18s1.5-.67 1.5-1.5S9.33 15 8.5 15zM12 1C5.93 1 1 5.93 1 12s4.93 11 11 11 11-
       4.93 11-11S18.07 1 12 1zm0 20c-4.96 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9 
       9zm5.5-11c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z
       m-2 5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"></
       path></g> | 
|  | 15482 <g id="settings-overscan"><path d="M12.01 5.5L10 8h4l-1.99-2.5zM18 10v4l2.5-1.99
       L18 10zM6 10l-2.5 2.01L6 14v-4zm8 6h-4l2.01 2.5L14 16zm7-13H3c-1.1 0-2 .9-2 2v14
       c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"></p
       ath></g> | 
|  | 15483 <g id="settings-phone"><path d="M13 9h-2v2h2V9zm4 0h-2v2h2V9zm3 6.5c-1.25 0-2.45
       -.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2
       -2.21c.28-.27.36-.66.25-1.01C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 
       .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 9v2h2V9h-2
       z"></path></g> | 
|  | 15484 <g id="settings-power"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm2-22h-2v10h2V2zm3
       .56 2.44l-1.45 1.45C16.84 6.94 18 8.83 18 11c0 3.31-2.69 6-6 6s-6-2.69-6-6c0-2.1
       7 1.16-4.06 2.88-5.12L7.44 4.44C5.36 5.88 4 8.28 4 11c0 4.42 3.58 8 8 8s8-3.58 8
       -8c0-2.72-1.36-5.12-3.44-6.56zM15 24h2v-2h-2v2z"></path></g> | 
|  | 15485 <g id="settings-remote"><path d="M15 9H9c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h6c.5
       5 0 1-.45 1-1V10c0-.55-.45-1-1-1zm-3 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 
       2zM7.05 6.05l1.41 1.41C9.37 6.56 10.62 6 12 6s2.63.56 3.54 1.46l1.41-1.41C15.68 
       4.78 13.93 4 12 4s-3.68.78-4.95 2.05zM12 0C8.96 0 6.21 1.23 4.22 3.22l1.41 1.41C
       7.26 3.01 9.51 2 12 2s4.74 1.01 6.36 2.64l1.41-1.41C17.79 1.23 15.04 0 12 0z"></
       path></g> | 
|  | 15486 <g id="settings-voice"><path d="M7 24h2v-2H7v2zm5-11c1.66 0 2.99-1.34 2.99-3L15 
       4c0-1.66-1.34-3-3-3S9 2.34 9 4v6c0 1.66 1.34 3 3 3zm-1 11h2v-2h-2v2zm4 0h2v-2h-2
       v2zm4-14h-1.7c0 3-2.54 5.1-5.3 5.1S6.7 13 6.7 10H5c0 3.41 2.72 6.23 6 6.72V20h2v
       -3.28c3.28-.49 6-3.31 6-6.72z"></path></g> | 
|  | 15487 <g id="shop"><path d="M16 6V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H2v13c0 1.1
       1.89 2 2 2h16c1.11 0 2-.89 2-2V6h-6zm-6-2h4v2h-4V4zM9 18V9l7.5 4L9 18z"></path><
       /g> | 
|  | 15488 <g id="shop-two"><path d="M3 9H1v11c0 1.11.89 2 2 2h14c1.11 0 2-.89 2-2H3V9zm15-
       4V3c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H5v11c0 1.11.89 2 2 2h14c1.11 0 2-.89
        2-2V5h-5zm-6-2h4v2h-4V3zm0 12V8l5.5 3-5.5 4z"></path></g> | 
|  | 15489 <g id="shopping-basket"><path d="M17.21 9l-4.38-6.56c-.19-.28-.51-.42-.83-.42-.3
       2 0-.64.14-.83.43L6.79 9H2c-.55 0-1 .45-1 1 0 .09.01.18.04.27l2.54 9.27c.23.84 1
        1.46 1.92 1.46h13c.92 0 1.69-.62 1.93-1.46l2.54-9.27L23 10c0-.55-.45-1-1-1h-4.7
       9zM9 9l3-4.4L15 9H9zm3 8c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"></path></g
       > | 
|  | 15490 <g id="shopping-cart"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.
       9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.
       42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49
       c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2
       s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"></path></g> | 
|  | 15491 <g id="sort"><path d="M3 18h6v-2H3v2zM3 6v2h18V6H3zm0 7h12v-2H3v2z"></path></g> | 
|  | 15492 <g id="speaker-notes"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-
       .9 2-2V4c0-1.1-.9-2-2-2zM8 14H6v-2h2v2zm0-3H6V9h2v2zm0-3H6V6h2v2zm7 6h-5v-2h5v2z
       m3-3h-8V9h8v2zm0-3h-8V6h8v2z"></path></g> | 
|  | 15493 <g id="spellcheck"><path d="M12.45 16h2.09L9.43 3H7.57L2.46 16h2.09l1.12-3h5.64l
       1.14 3zm-6.02-5L8.5 5.48 10.57 11H6.43zm15.16.59l-8.09 8.09L9.83 16l-1.41 1.41 5
       .09 5.09L23 13l-1.41-1.41z"></path></g> | 
|  | 15494 <g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 
       8.63 2 9.24l5.46 4.73L5.82 21z"></path></g> | 
|  | 15495 <g id="star-border"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L
       5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.8
       8 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"></path></g> | 
|  | 15496 <g id="star-half"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.
       82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4V6.1l1.71 4.04 4.38.38-3.32 2
       .88 1 4.28L12 15.4z"></path></g> | 
|  | 15497 <g id="stars"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 1
       7.52 22 12S17.52 2 11.99 2zm4.24 16L12 15.45 7.77 18l1.12-4.81-3.73-3.23 4.92-.4
       2L12 5l1.92 4.53 4.92.42-3.73 3.23L16.23 18z"></path></g> | 
|  | 15498 <g id="store"><path d="M20 4H4v2h16V4zm1 10v-2l-1-5H4l-1 5v2h1v6h10v-6h4v6h2v-6h
       1zm-9 4H6v-4h6v4z"></path></g> | 
|  | 15499 <g id="subdirectory-arrow-left"><path d="M11 9l1.42 1.42L8.83 14H18V4h2v12H8.83l
       3.59 3.58L11 21l-6-6 6-6z"></path></g> | 
|  | 15500 <g id="subdirectory-arrow-right"><path d="M19 15l-6 6-1.42-1.42L15.17 16H4V4h2v1
       0h9.17l-3.59-3.58L13 9l6 6z"></path></g> | 
|  | 15501 <g id="subject"><path d="M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h1
       6V5H4z"></path></g> | 
|  | 15502 <g id="supervisor-account"><path d="M16.5 12c1.38 0 2.49-1.12 2.49-2.5S17.88 7 1
       6.5 7C15.12 7 14 8.12 14 9.5s1.12 2.5 2.5 2.5zM9 11c1.66 0 2.99-1.34 2.99-3S10.6
       6 5 9 5C7.34 5 6 6.34 6 8s1.34 3 3 3zm7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c
       0-1.83-3.67-2.75-5.5-2.75zM9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.
       37-3.47C10.5 13.1 9.66 13 9 13z"></path></g> | 
|  | 15503 <g id="swap-horiz"><path d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v
       3H10v2h7.01v3L21 9z"></path></g> | 
|  | 15504 <g id="swap-vert"><path d="M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3zM9 3L5 6.99h3
       V14h2V6.99h3L9 3z"></path></g> | 
|  | 15505 <g id="swap-vertical-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-
       4.48 10-10S17.52 2 12 2zM6.5 9L10 5.5 13.5 9H11v4H9V9H6.5zm11 6L14 18.5 10.5 15H
       13v-4h2v4h2.5z"></path></g> | 
|  | 15506 <g id="system-update-alt"><path d="M12 16.5l4-4h-3v-9h-2v9H8l4 4zm9-13h-6v1.99h6
       v14.03H3V5.49h6V3.5H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2v-14c0-1
       .1-.9-2-2-2z"></path></g> | 
|  | 15507 <g id="tab"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V
       5c0-1.1-.9-2-2-2zm0 16H3V5h10v4h8v10z"></path></g> | 
|  | 15508 <g id="tab-unselected"><path d="M1 9h2V7H1v2zm0 4h2v-2H1v2zm0-8h2V3c-1.1 0-2 .9-
       2 2zm8 16h2v-2H9v2zm-8-4h2v-2H1v2zm2 4v-2H1c0 1.1.9 2 2 2zM21 3h-8v6h10V5c0-1.1-
       .9-2-2-2zm0 14h2v-2h-2v2zM9 5h2V3H9v2zM5 21h2v-2H5v2zM5 5h2V3H5v2zm16 16c1.1 0 2
       -.9 2-2h-2v2zm0-8h2v-2h-2v2zm-8 8h2v-2h-2v2zm4 0h2v-2h-2v2z"></path></g> | 
|  | 15509 <g id="text-format"><path d="M5 17v2h14v-2H5zm4.5-4.2h5l.9 2.2h2.1L12.75 4h-1.5L
       6.5 15h2.1l.9-2.2zM12 5.98L13.87 11h-3.74L12 5.98z"></path></g> | 
|  | 15510 <g id="theaters"><path d="M18 3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3h-2zM8 
       17H6v-2h2v2zm0-4H6v-2h2v2zm0-4H6V7h2v2zm10 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V7h
       2v2z"></path></g> | 
|  | 15511 <g id="thumb-down"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.
       14.47-.14.73v1.91l.01.01L1 14c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44
        1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"
       ></path></g> | 
|  | 15512 <g id="thumb-up"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03
       -.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 
       2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-1.91l-.01-.01L23 
       10z"></path></g> | 
|  | 15513 <g id="thumbs-up-down"><path d="M12 6c0-.55-.45-1-1-1H5.82l.66-3.18.02-.23c0-.31
       -.13-.59-.33-.8L5.38 0 .44 4.94C.17 5.21 0 5.59 0 6v6.5c0 .83.67 1.5 1.5 1.5h6.7
       5c.62 0 1.15-.38 1.38-.91l2.26-5.29c.07-.17.11-.36.11-.55V6zm10.5 4h-6.75c-.62 0
       -1.15.38-1.38.91l-2.26 5.29c-.07.17-.11.36-.11.55V18c0 .55.45 1 1 1h5.18l-.66 3.
       18-.02.24c0 .31.13.59.33.8l.79.78 4.94-4.94c.27-.27.44-.65.44-1.06v-6.5c0-.83-.6
       7-1.5-1.5-1.5z"></path></g> | 
|  | 15514 <g id="timeline"><path d="M23 8c0 1.1-.9 2-2 2-.18 0-.35-.02-.51-.07l-3.56 3.55c
       .05.16.07.34.07.52 0 1.1-.9 2-2 2s-2-.9-2-2c0-.18.02-.36.07-.52l-2.55-2.55c-.16.
       05-.34.07-.52.07s-.36-.02-.52-.07l-4.55 4.56c.05.16.07.33.07.51 0 1.1-.9 2-2 2s-
       2-.9-2-2 .9-2 2-2c.18 0 .35.02.51.07l4.56-4.55C8.02 9.36 8 9.18 8 9c0-1.1.9-2 2-
       2s2 .9 2 2c0 .18-.02.36-.07.52l2.55 2.55c.16-.05.34-.07.52-.07s.36.02.52.07l3.55
       -3.56C19.02 8.35 19 8.18 19 8c0-1.1.9-2 2-2s2 .9 2 2z"></path></g> | 
|  | 15515 <g id="toc"><path d="M3 9h14V7H3v2zm0 4h14v-2H3v2zm0 4h14v-2H3v2zm16 0h2v-2h-2v2
       zm0-10v2h2V7h-2zm0 6h2v-2h-2v2z"></path></g> | 
|  | 15516 <g id="today"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.
       1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"></pa
       th></g> | 
|  | 15517 <g id="toll"><path d="M15 4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8z
       m0 14c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zM3 12c0-2.61 1.67-4.83
        4-5.65V4.26C3.55 5.15 1 8.27 1 12s2.55 6.85 6 7.74v-2.09c-2.33-.82-4-3.04-4-5.6
       5z"></path></g> | 
|  | 15518 <g id="touch-app"><path d="M9 11.24V7.5C9 6.12 10.12 5 11.5 5S14 6.12 14 7.5v3.7
       4c1.21-.81 2-2.18 2-3.74C16 5.01 13.99 3 11.5 3S7 5.01 7 7.5c0 1.56.79 2.93 2 3.
       74zm9.84 4.63l-4.54-2.26c-.17-.07-.35-.11-.54-.11H13v-6c0-.83-.67-1.5-1.5-1.5S10
        6.67 10 7.5v10.74l-3.43-.72c-.08-.01-.15-.03-.24-.03-.31 0-.59.13-.79.33l-.79.8
        4.94 4.94c.27.27.65.44 1.06.44h6.79c.75 0 1.33-.55 1.44-1.28l.75-5.27c.01-.07.0
       2-.14.02-.2 0-.62-.38-1.16-.91-1.38z"></path></g> | 
|  | 15519 <g id="track-changes"><path d="M19.07 4.93l-1.41 1.41C19.1 7.79 20 9.79 20 12c0 
       4.42-3.58 8-8 8s-8-3.58-8-8c0-4.08 3.05-7.44 7-7.93v2.02C8.16 6.57 6 9.03 6 12c0
        3.31 2.69 6 6 6s6-2.69 6-6c0-1.66-.67-3.16-1.76-4.24l-1.41 1.41C15.55 9.9 16 10
       .9 16 12c0 2.21-1.79 4-4 4s-4-1.79-4-4c0-1.86 1.28-3.41 3-3.86v2.14c-.6.35-1 .98
       -1 1.72 0 1.1.9 2 2 2s2-.9 2-2c0-.74-.4-1.38-1-1.72V2h-1C6.48 2 2 6.48 2 12s4.48
        10 10 10 10-4.48 10-10c0-2.76-1.12-5.26-2.93-7.07z"></path></g> | 
|  | 15520 <g id="translate"><path d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.
       71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9
       .19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04
       zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.
       24z"></path></g> | 
|  | 15521 <g id="trending-down"><path d="M16 18l2.29-2.29-4.88-4.88-4 4L2 7.41 3.41 6l6 6 
       4-4 6.3 6.29L22 12v6z"></path></g> | 
|  | 15522 <g id="trending-flat"><path d="M22 12l-4-4v3H3v2h15v3z"></path></g> | 
|  | 15523 <g id="trending-up"><path d="M16 6l2.29 2.29-4.88 4.88-4-4L2 16.59 3.41 18l6-6 4
        4 6.3-6.29L22 12V6z"></path></g> | 
|  | 15524 <g id="turned-in"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-
       2-2-2z"></path></g> | 
|  | 15525 <g id="turned-in-not"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1
       -.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"></path></g> | 
|  | 15526 <g id="unarchive"><path d="M20.55 5.22l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47
        0-.88.21-1.15.55L3.46 5.22C3.17 5.57 3 6.01 3 6.5V19c0 1.1.89 2 2 2h14c1.1 0 2-
       .9 2-2V6.5c0-.49-.17-.93-.45-1.28zM12 9.5l5.5 5.5H14v2h-4v-2H6.5L12 9.5zM5.12 5l
       .82-1h12l.93 1H5.12z"></path></g> | 
|  | 15527 <g id="undo"><path d="M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.
       16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.
       5 8z"></path></g> | 
|  | 15528 <g id="unfold-less"><path d="M7.41 18.59L8.83 20 12 16.83 15.17 20l1.41-1.41L12 
       14l-4.59 4.59zm9.18-13.18L15.17 4 12 7.17 8.83 4 7.41 5.41 12 10l4.59-4.59z"></p
       ath></g> | 
|  | 15529 <g id="unfold-more"><path d="M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12
        5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z"></path></g
       > | 
|  | 15530 <g id="update"><path d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.7
       3 2.71-2.73 7.08 0 9.79 2.73 2.71 7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h
       2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-1
       2.58 3.51-3.47 9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V
       8h1.5z"></path></g> | 
|  | 15531 <g id="verified-user"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.
       45 9-12V5l-9-4zm-2 16l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"></path></g> | 
|  | 15532 <g id="view-agenda"><path d="M20 13H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0
        1-.45 1-1v-6c0-.55-.45-1-1-1zm0-10H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0
        1-.45 1-1V4c0-.55-.45-1-1-1z"></path></g> | 
|  | 15533 <g id="view-array"><path d="M4 18h3V5H4v13zM18 5v13h3V5h-3zM8 18h9V5H8v13z"></pa
       th></g> | 
|  | 15534 <g id="view-carousel"><path d="M7 19h10V4H7v15zm-5-2h4V6H2v11zM18 6v11h4V6h-4z">
       </path></g> | 
|  | 15535 <g id="view-column"><path d="M10 18h5V5h-5v13zm-6 0h5V5H4v13zM16 5v13h5V5h-5z"><
       /path></g> | 
|  | 15536 <g id="view-day"><path d="M2 21h19v-3H2v3zM20 8H3c-.55 0-1 .45-1 1v6c0 .55.45 1 
       1 1h17c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1zM2 3v3h19V3H2z"></path></g> | 
|  | 15537 <g id="view-headline"><path d="M4 15h16v-2H4v2zm0 4h16v-2H4v2zm0-8h16V9H4v2zm0-6
       v2h16V5H4z"></path></g> | 
|  | 15538 <g id="view-list"><path d="M4 14h4v-4H4v4zm0 5h4v-4H4v4zM4 9h4V5H4v4zm5 5h12v-4H
       9v4zm0 5h12v-4H9v4zM9 5v4h12V5H9z"></path></g> | 
|  | 15539 <g id="view-module"><path d="M4 11h5V5H4v6zm0 7h5v-6H4v6zm6 0h5v-6h-5v6zm6 0h5v-
       6h-5v6zm-6-7h5V5h-5v6zm6-6v6h5V5h-5z"></path></g> | 
|  | 15540 <g id="view-quilt"><path d="M10 18h5v-6h-5v6zm-6 0h5V5H4v13zm12 0h5v-6h-5v6zM10 
       5v6h11V5H10z"></path></g> | 
|  | 15541 <g id="view-stream"><path d="M4 18h17v-6H4v6zM4 5v6h17V5H4z"></path></g> | 
|  | 15542 <g id="view-week"><path d="M6 5H3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.
       45 1-1V6c0-.55-.45-1-1-1zm14 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.
       45 1-1V6c0-.55-.45-1-1-1zm-7 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.
       45 1-1V6c0-.55-.45-1-1-1z"></path></g> | 
|  | 15543 <g id="visibility"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s
       9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 
       2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"><
       /path></g> | 
|  | 15544 <g id="visibility-off"><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l
       2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98
       .7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02
        1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.
       27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .4
       4-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-
       2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"></path></g> | 
|  | 15545 <g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></p
       ath></g> | 
|  | 15546 <g id="watch-later"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17
       .5 2 12 2zm4.2 14.2L11 13V7h1.5v5.2l4.5 2.7-.8 1.3z"></path></g> | 
|  | 15547 <g id="weekend"><path d="M21 10c-1.1 0-2 .9-2 2v3H5v-3c0-1.1-.9-2-2-2s-2 .9-2 2v
       5c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2v-5c0-1.1-.9-2-2-2zm-3-5H6c-1.1 0-2 .9-2 2v2.15
       c1.16.41 2 1.51 2 2.82V14h12v-2.03c0-1.3.84-2.4 2-2.82V7c0-1.1-.9-2-2-2z"></path
       ></g> | 
|  | 15548 <g id="work"><path d="M20 6h-4V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H4c-1.11
        0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-
       6 0h-4V4h4v2z"></path></g> | 
|  | 15549 <g id="youtube-searched-for"><path d="M17.01 14h-.8l-.27-.27c.98-1.14 1.57-2.61 
       1.57-4.23 0-3.59-2.91-6.5-6.5-6.5s-6.5 3-6.5 6.5H2l3.84 4 4.16-4H6.51C6.51 7 8.5
       3 5 11.01 5s4.5 2.01 4.5 4.5c0 2.48-2.02 4.5-4.5 4.5-.65 0-1.26-.14-1.82-.38L7.7
       1 15.1c.97.57 2.09.9 3.3.9 1.61 0 3.08-.59 4.22-1.57l.27.27v.79l5.01 4.99L22 19l
       -4.99-5z"></path></g> | 
|  | 15550 <g id="zoom-in"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5
       .91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.
       79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9
       .5 11.99 14 9.5 14zm2.5-4h-2v2H9v-2H7V9h2V7h1v2h2v1z"></path></g> | 
|  | 15551 <g id="zoom-out"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 
       5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v
       .79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 
       9.5 11.99 14 9.5 14zM7 9h5v1H7z"></path></g> | 
|  | 15552 </defs></svg> | 
|  | 15553 </iron-iconset-svg> | 
|  | 15554 <dom-module id="sort-toggle" assetpath="/res/imp/common/"> | 
|  | 15555   <template> | 
|  | 15556     <style> | 
|  | 15557       :host { | 
|  | 15558         display: inline-block; | 
|  | 15559         position: relative; | 
|  | 15560         min-width: 20px; | 
|  | 15561         min-height: 16px; | 
|  | 15562         vertical-align: middle; | 
|  | 15563       } | 
|  | 15564       iron-icon { | 
|  | 15565         position: absolute; | 
|  | 15566         left: 0; | 
|  | 15567         cursor: pointer; | 
|  | 15568       } | 
|  | 15569       .hidden { | 
|  | 15570         visibility: hidden; | 
|  | 15571       } | 
|  | 15572     </style> | 
|  | 15573 | 
|  | 15574     <span on-click="toggle"> | 
|  | 15575       <iron-icon style="top:0" class$="[[_hidden(direction,'asc')]]" icon="icons
       :arrow-drop-down"> | 
|  | 15576       </iron-icon> | 
|  | 15577       <iron-icon style="bottom:0" class$="[[_hidden(direction,'desc')]]" icon="i
       cons:arrow-drop-up"> | 
|  | 15578       </iron-icon> | 
|  | 15579     </span> | 
|  | 15580 | 
|  | 15581   </template> | 
|  | 15582   <script> | 
|  | 15583     Polymer({ | 
|  | 15584       is: "sort-toggle", | 
|  | 15585       properties: { | 
|  | 15586         current: { | 
|  | 15587           type: Object, | 
|  | 15588           observer: "_resetSort", | 
|  | 15589         }, | 
|  | 15590         name: { | 
|  | 15591           type: String, | 
|  | 15592           observer: "_resetSort", | 
|  | 15593         }, | 
|  | 15594 | 
|  | 15595         direction: { | 
|  | 15596           type: String, | 
|  | 15597           value: "", | 
|  | 15598           notify: true, | 
|  | 15599         }, | 
|  | 15600       }, | 
|  | 15601 | 
|  | 15602       toggle: function() { | 
|  | 15603         if (this.direction === "asc") { | 
|  | 15604           this.set("direction", "desc"); | 
|  | 15605         } else { | 
|  | 15606           this.set("direction", "asc"); | 
|  | 15607         } | 
|  | 15608         this.fire("sort_change", {direction: this.direction, name: this.name}); | 
|  | 15609       }, | 
|  | 15610 | 
|  | 15611       _hidden: function(num, compare) { | 
|  | 15612         if (num === compare) { | 
|  | 15613           return "hidden"; | 
|  | 15614         } | 
|  | 15615         return ""; | 
|  | 15616       }, | 
|  | 15617 | 
|  | 15618       _resetSort: function() { | 
|  | 15619         // Because of how Polymer inserts and moves elements around, we need to | 
|  | 15620         // update the direction value if the name changes so the ascending sort | 
|  | 15621         // by "os" doesn't become the ascending sort by "gpu" if a column gets | 
|  | 15622         // added before "os", for example.  Additionally, this makes sure that | 
|  | 15623         // only one sort-toggle is active at a given time. | 
|  | 15624         if (this.current && this.current.name === this.name) { | 
|  | 15625           this.set("direction", this.current.direction); | 
|  | 15626         } else { | 
|  | 15627           this.set("direction", ""); | 
|  | 15628         } | 
|  | 15629 | 
|  | 15630       }, | 
|  | 15631     }); | 
|  | 15632   </script> | 
|  | 15633 </dom-module><script> | 
|  | 15634 | 
|  | 15635   /** | 
|  | 15636    * @param {!Function} selectCallback | 
|  | 15637    * @constructor | 
|  | 15638    */ | 
|  | 15639   Polymer.IronSelection = function(selectCallback) { | 
|  | 15640     this.selection = []; | 
|  | 15641     this.selectCallback = selectCallback; | 
|  | 15642   }; | 
|  | 15643 | 
|  | 15644   Polymer.IronSelection.prototype = { | 
|  | 15645 | 
|  | 15646     /** | 
|  | 15647      * Retrieves the selected item(s). | 
|  | 15648      * | 
|  | 15649      * @method get | 
|  | 15650      * @returns Returns the selected item(s). If the multi property is true, | 
|  | 15651      * `get` will return an array, otherwise it will return | 
|  | 15652      * the selected item or undefined if there is no selection. | 
|  | 15653      */ | 
|  | 15654     get: function() { | 
|  | 15655       return this.multi ? this.selection.slice() : this.selection[0]; | 
|  | 15656     }, | 
|  | 15657 | 
|  | 15658     /** | 
|  | 15659      * Clears all the selection except the ones indicated. | 
|  | 15660      * | 
|  | 15661      * @method clear | 
|  | 15662      * @param {Array} excludes items to be excluded. | 
|  | 15663      */ | 
|  | 15664     clear: function(excludes) { | 
|  | 15665       this.selection.slice().forEach(function(item) { | 
|  | 15666         if (!excludes || excludes.indexOf(item) < 0) { | 
|  | 15667           this.setItemSelected(item, false); | 
|  | 15668         } | 
|  | 15669       }, this); | 
|  | 15670     }, | 
|  | 15671 | 
|  | 15672     /** | 
|  | 15673      * Indicates if a given item is selected. | 
|  | 15674      * | 
|  | 15675      * @method isSelected | 
|  | 15676      * @param {*} item The item whose selection state should be checked. | 
|  | 15677      * @returns Returns true if `item` is selected. | 
|  | 15678      */ | 
|  | 15679     isSelected: function(item) { | 
|  | 15680       return this.selection.indexOf(item) >= 0; | 
|  | 15681     }, | 
|  | 15682 | 
|  | 15683     /** | 
|  | 15684      * Sets the selection state for a given item to either selected or deselecte
       d. | 
|  | 15685      * | 
|  | 15686      * @method setItemSelected | 
|  | 15687      * @param {*} item The item to select. | 
|  | 15688      * @param {boolean} isSelected True for selected, false for deselected. | 
|  | 15689      */ | 
|  | 15690     setItemSelected: function(item, isSelected) { | 
|  | 15691       if (item != null) { | 
|  | 15692         if (isSelected !== this.isSelected(item)) { | 
|  | 15693           // proceed to update selection only if requested state differs from cu
       rrent | 
|  | 15694           if (isSelected) { | 
|  | 15695             this.selection.push(item); | 
|  | 15696           } else { | 
|  | 15697             var i = this.selection.indexOf(item); | 
|  | 15698             if (i >= 0) { | 
|  | 15699               this.selection.splice(i, 1); | 
|  | 15700             } | 
|  | 15701           } | 
|  | 15702           if (this.selectCallback) { | 
|  | 15703             this.selectCallback(item, isSelected); | 
|  | 15704           } | 
|  | 15705         } | 
|  | 15706       } | 
|  | 15707     }, | 
|  | 15708 | 
|  | 15709     /** | 
|  | 15710      * Sets the selection state for a given item. If the `multi` property | 
|  | 15711      * is true, then the selected state of `item` will be toggled; otherwise | 
|  | 15712      * the `item` will be selected. | 
|  | 15713      * | 
|  | 15714      * @method select | 
|  | 15715      * @param {*} item The item to select. | 
|  | 15716      */ | 
|  | 15717     select: function(item) { | 
|  | 15718       if (this.multi) { | 
|  | 15719         this.toggle(item); | 
|  | 15720       } else if (this.get() !== item) { | 
|  | 15721         this.setItemSelected(this.get(), false); | 
|  | 15722         this.setItemSelected(item, true); | 
|  | 15723       } | 
|  | 15724     }, | 
|  | 15725 | 
|  | 15726     /** | 
|  | 15727      * Toggles the selection state for `item`. | 
|  | 15728      * | 
|  | 15729      * @method toggle | 
|  | 15730      * @param {*} item The item to toggle. | 
|  | 15731      */ | 
|  | 15732     toggle: function(item) { | 
|  | 15733       this.setItemSelected(item, !this.isSelected(item)); | 
|  | 15734     } | 
|  | 15735 | 
|  | 15736   }; | 
|  | 15737 | 
|  | 15738 </script> | 
|  | 15739 <script> | 
|  | 15740 | 
|  | 15741   /** @polymerBehavior */ | 
|  | 15742   Polymer.IronSelectableBehavior = { | 
|  | 15743 | 
|  | 15744       /** | 
|  | 15745        * Fired when iron-selector is activated (selected or deselected). | 
|  | 15746        * It is fired before the selected items are changed. | 
|  | 15747        * Cancel the event to abort selection. | 
|  | 15748        * | 
|  | 15749        * @event iron-activate | 
|  | 15750        */ | 
|  | 15751 | 
|  | 15752       /** | 
|  | 15753        * Fired when an item is selected | 
|  | 15754        * | 
|  | 15755        * @event iron-select | 
|  | 15756        */ | 
|  | 15757 | 
|  | 15758       /** | 
|  | 15759        * Fired when an item is deselected | 
|  | 15760        * | 
|  | 15761        * @event iron-deselect | 
|  | 15762        */ | 
|  | 15763 | 
|  | 15764       /** | 
|  | 15765        * Fired when the list of selectable items changes (e.g., items are | 
|  | 15766        * added or removed). The detail of the event is a mutation record that | 
|  | 15767        * describes what changed. | 
|  | 15768        * | 
|  | 15769        * @event iron-items-changed | 
|  | 15770        */ | 
|  | 15771 | 
|  | 15772     properties: { | 
|  | 15773 | 
|  | 15774       /** | 
|  | 15775        * If you want to use an attribute value or property of an element for | 
|  | 15776        * `selected` instead of the index, set this to the name of the attribute | 
|  | 15777        * or property. Hyphenated values are converted to camel case when used to | 
|  | 15778        * look up the property of a selectable element. Camel cased values are | 
|  | 15779        * *not* converted to hyphenated values for attribute lookup. It's | 
|  | 15780        * recommended that you provide the hyphenated form of the name so that | 
|  | 15781        * selection works in both cases. (Use `attr-or-property-name` instead of | 
|  | 15782        * `attrOrPropertyName`.) | 
|  | 15783        */ | 
|  | 15784       attrForSelected: { | 
|  | 15785         type: String, | 
|  | 15786         value: null | 
|  | 15787       }, | 
|  | 15788 | 
|  | 15789       /** | 
|  | 15790        * Gets or sets the selected element. The default is to use the index of t
       he item. | 
|  | 15791        * @type {string|number} | 
|  | 15792        */ | 
|  | 15793       selected: { | 
|  | 15794         type: String, | 
|  | 15795         notify: true | 
|  | 15796       }, | 
|  | 15797 | 
|  | 15798       /** | 
|  | 15799        * Returns the currently selected item. | 
|  | 15800        * | 
|  | 15801        * @type {?Object} | 
|  | 15802        */ | 
|  | 15803       selectedItem: { | 
|  | 15804         type: Object, | 
|  | 15805         readOnly: true, | 
|  | 15806         notify: true | 
|  | 15807       }, | 
|  | 15808 | 
|  | 15809       /** | 
|  | 15810        * The event that fires from items when they are selected. Selectable | 
|  | 15811        * will listen for this event from items and update the selection state. | 
|  | 15812        * Set to empty string to listen to no events. | 
|  | 15813        */ | 
|  | 15814       activateEvent: { | 
|  | 15815         type: String, | 
|  | 15816         value: 'tap', | 
|  | 15817         observer: '_activateEventChanged' | 
|  | 15818       }, | 
|  | 15819 | 
|  | 15820       /** | 
|  | 15821        * This is a CSS selector string.  If this is set, only items that match t
       he CSS selector | 
|  | 15822        * are selectable. | 
|  | 15823        */ | 
|  | 15824       selectable: String, | 
|  | 15825 | 
|  | 15826       /** | 
|  | 15827        * The class to set on elements when selected. | 
|  | 15828        */ | 
|  | 15829       selectedClass: { | 
|  | 15830         type: String, | 
|  | 15831         value: 'iron-selected' | 
|  | 15832       }, | 
|  | 15833 | 
|  | 15834       /** | 
|  | 15835        * The attribute to set on elements when selected. | 
|  | 15836        */ | 
|  | 15837       selectedAttribute: { | 
|  | 15838         type: String, | 
|  | 15839         value: null | 
|  | 15840       }, | 
|  | 15841 | 
|  | 15842       /** | 
|  | 15843        * Default fallback if the selection based on selected with `attrForSelect
       ed` | 
|  | 15844        * is not found. | 
|  | 15845        */ | 
|  | 15846       fallbackSelection: { | 
|  | 15847         type: String, | 
|  | 15848         value: null | 
|  | 15849       }, | 
|  | 15850 | 
|  | 15851       /** | 
|  | 15852        * The list of items from which a selection can be made. | 
|  | 15853        */ | 
|  | 15854       items: { | 
|  | 15855         type: Array, | 
|  | 15856         readOnly: true, | 
|  | 15857         notify: true, | 
|  | 15858         value: function() { | 
|  | 15859           return []; | 
|  | 15860         } | 
|  | 15861       }, | 
|  | 15862 | 
|  | 15863       /** | 
|  | 15864        * The set of excluded elements where the key is the `localName` | 
|  | 15865        * of the element that will be ignored from the item list. | 
|  | 15866        * | 
|  | 15867        * @default {template: 1} | 
|  | 15868        */ | 
|  | 15869       _excludedLocalNames: { | 
|  | 15870         type: Object, | 
|  | 15871         value: function() { | 
|  | 15872           return { | 
|  | 15873             'template': 1 | 
|  | 15874           }; | 
|  | 15875         } | 
|  | 15876       } | 
|  | 15877     }, | 
|  | 15878 | 
|  | 15879     observers: [ | 
|  | 15880       '_updateAttrForSelected(attrForSelected)', | 
|  | 15881       '_updateSelected(selected)', | 
|  | 15882       '_checkFallback(fallbackSelection)' | 
|  | 15883     ], | 
|  | 15884 | 
|  | 15885     created: function() { | 
|  | 15886       this._bindFilterItem = this._filterItem.bind(this); | 
|  | 15887       this._selection = new Polymer.IronSelection(this._applySelection.bind(this
       )); | 
|  | 15888     }, | 
|  | 15889 | 
|  | 15890     attached: function() { | 
|  | 15891       this._observer = this._observeItems(this); | 
|  | 15892       this._updateItems(); | 
|  | 15893       if (!this._shouldUpdateSelection) { | 
|  | 15894         this._updateSelected(); | 
|  | 15895       } | 
|  | 15896       this._addListener(this.activateEvent); | 
|  | 15897     }, | 
|  | 15898 | 
|  | 15899     detached: function() { | 
|  | 15900       if (this._observer) { | 
|  | 15901         Polymer.dom(this).unobserveNodes(this._observer); | 
|  | 15902       } | 
|  | 15903       this._removeListener(this.activateEvent); | 
|  | 15904     }, | 
|  | 15905 | 
|  | 15906     /** | 
|  | 15907      * Returns the index of the given item. | 
|  | 15908      * | 
|  | 15909      * @method indexOf | 
|  | 15910      * @param {Object} item | 
|  | 15911      * @returns Returns the index of the item | 
|  | 15912      */ | 
|  | 15913     indexOf: function(item) { | 
|  | 15914       return this.items.indexOf(item); | 
|  | 15915     }, | 
|  | 15916 | 
|  | 15917     /** | 
|  | 15918      * Selects the given value. | 
|  | 15919      * | 
|  | 15920      * @method select | 
|  | 15921      * @param {string|number} value the value to select. | 
|  | 15922      */ | 
|  | 15923     select: function(value) { | 
|  | 15924       this.selected = value; | 
|  | 15925     }, | 
|  | 15926 | 
|  | 15927     /** | 
|  | 15928      * Selects the previous item. | 
|  | 15929      * | 
|  | 15930      * @method selectPrevious | 
|  | 15931      */ | 
|  | 15932     selectPrevious: function() { | 
|  | 15933       var length = this.items.length; | 
|  | 15934       var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % len
       gth; | 
|  | 15935       this.selected = this._indexToValue(index); | 
|  | 15936     }, | 
|  | 15937 | 
|  | 15938     /** | 
|  | 15939      * Selects the next item. | 
|  | 15940      * | 
|  | 15941      * @method selectNext | 
|  | 15942      */ | 
|  | 15943     selectNext: function() { | 
|  | 15944       var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.l
       ength; | 
|  | 15945       this.selected = this._indexToValue(index); | 
|  | 15946     }, | 
|  | 15947 | 
|  | 15948     /** | 
|  | 15949      * Selects the item at the given index. | 
|  | 15950      * | 
|  | 15951      * @method selectIndex | 
|  | 15952      */ | 
|  | 15953     selectIndex: function(index) { | 
|  | 15954       this.select(this._indexToValue(index)); | 
|  | 15955     }, | 
|  | 15956 | 
|  | 15957     /** | 
|  | 15958      * Force a synchronous update of the `items` property. | 
|  | 15959      * | 
|  | 15960      * NOTE: Consider listening for the `iron-items-changed` event to respond to | 
|  | 15961      * updates to the set of selectable items after updates to the DOM list and | 
|  | 15962      * selection state have been made. | 
|  | 15963      * | 
|  | 15964      * WARNING: If you are using this method, you should probably consider an | 
|  | 15965      * alternate approach. Synchronously querying for items is potentially | 
|  | 15966      * slow for many use cases. The `items` property will update asynchronously | 
|  | 15967      * on its own to reflect selectable items in the DOM. | 
|  | 15968      */ | 
|  | 15969     forceSynchronousItemUpdate: function() { | 
|  | 15970       this._updateItems(); | 
|  | 15971     }, | 
|  | 15972 | 
|  | 15973     get _shouldUpdateSelection() { | 
|  | 15974       return this.selected != null; | 
|  | 15975     }, | 
|  | 15976 | 
|  | 15977     _checkFallback: function() { | 
|  | 15978       if (this._shouldUpdateSelection) { | 
|  | 15979         this._updateSelected(); | 
|  | 15980       } | 
|  | 15981     }, | 
|  | 15982 | 
|  | 15983     _addListener: function(eventName) { | 
|  | 15984       this.listen(this, eventName, '_activateHandler'); | 
|  | 15985     }, | 
|  | 15986 | 
|  | 15987     _removeListener: function(eventName) { | 
|  | 15988       this.unlisten(this, eventName, '_activateHandler'); | 
|  | 15989     }, | 
|  | 15990 | 
|  | 15991     _activateEventChanged: function(eventName, old) { | 
|  | 15992       this._removeListener(old); | 
|  | 15993       this._addListener(eventName); | 
|  | 15994     }, | 
|  | 15995 | 
|  | 15996     _updateItems: function() { | 
|  | 15997       var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || 
       '*'); | 
|  | 15998       nodes = Array.prototype.filter.call(nodes, this._bindFilterItem); | 
|  | 15999       this._setItems(nodes); | 
|  | 16000     }, | 
|  | 16001 | 
|  | 16002     _updateAttrForSelected: function() { | 
|  | 16003       if (this._shouldUpdateSelection) { | 
|  | 16004         this.selected = this._indexToValue(this.indexOf(this.selectedItem)); | 
|  | 16005       } | 
|  | 16006     }, | 
|  | 16007 | 
|  | 16008     _updateSelected: function() { | 
|  | 16009       this._selectSelected(this.selected); | 
|  | 16010     }, | 
|  | 16011 | 
|  | 16012     _selectSelected: function(selected) { | 
|  | 16013       this._selection.select(this._valueToItem(this.selected)); | 
|  | 16014       // Check for items, since this array is populated only when attached | 
|  | 16015       // Since Number(0) is falsy, explicitly check for undefined | 
|  | 16016       if (this.fallbackSelection && this.items.length && (this._selection.get() 
       === undefined)) { | 
|  | 16017         this.selected = this.fallbackSelection; | 
|  | 16018       } | 
|  | 16019     }, | 
|  | 16020 | 
|  | 16021     _filterItem: function(node) { | 
|  | 16022       return !this._excludedLocalNames[node.localName]; | 
|  | 16023     }, | 
|  | 16024 | 
|  | 16025     _valueToItem: function(value) { | 
|  | 16026       return (value == null) ? null : this.items[this._valueToIndex(value)]; | 
|  | 16027     }, | 
|  | 16028 | 
|  | 16029     _valueToIndex: function(value) { | 
|  | 16030       if (this.attrForSelected) { | 
|  | 16031         for (var i = 0, item; item = this.items[i]; i++) { | 
|  | 16032           if (this._valueForItem(item) == value) { | 
|  | 16033             return i; | 
|  | 16034           } | 
|  | 16035         } | 
|  | 16036       } else { | 
|  | 16037         return Number(value); | 
|  | 16038       } | 
|  | 16039     }, | 
|  | 16040 | 
|  | 16041     _indexToValue: function(index) { | 
|  | 16042       if (this.attrForSelected) { | 
|  | 16043         var item = this.items[index]; | 
|  | 16044         if (item) { | 
|  | 16045           return this._valueForItem(item); | 
|  | 16046         } | 
|  | 16047       } else { | 
|  | 16048         return index; | 
|  | 16049       } | 
|  | 16050     }, | 
|  | 16051 | 
|  | 16052     _valueForItem: function(item) { | 
|  | 16053       var propValue = item[Polymer.CaseMap.dashToCamelCase(this.attrForSelected)
       ]; | 
|  | 16054       return propValue != undefined ? propValue : item.getAttribute(this.attrFor
       Selected); | 
|  | 16055     }, | 
|  | 16056 | 
|  | 16057     _applySelection: function(item, isSelected) { | 
|  | 16058       if (this.selectedClass) { | 
|  | 16059         this.toggleClass(this.selectedClass, isSelected, item); | 
|  | 16060       } | 
|  | 16061       if (this.selectedAttribute) { | 
|  | 16062         this.toggleAttribute(this.selectedAttribute, isSelected, item); | 
|  | 16063       } | 
|  | 16064       this._selectionChange(); | 
|  | 16065       this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item}); | 
|  | 16066     }, | 
|  | 16067 | 
|  | 16068     _selectionChange: function() { | 
|  | 16069       this._setSelectedItem(this._selection.get()); | 
|  | 16070     }, | 
|  | 16071 | 
|  | 16072     // observe items change under the given node. | 
|  | 16073     _observeItems: function(node) { | 
|  | 16074       return Polymer.dom(node).observeNodes(function(mutation) { | 
|  | 16075         this._updateItems(); | 
|  | 16076 | 
|  | 16077         if (this._shouldUpdateSelection) { | 
|  | 16078           this._updateSelected(); | 
|  | 16079         } | 
|  | 16080 | 
|  | 16081         // Let other interested parties know about the change so that | 
|  | 16082         // we don't have to recreate mutation observers everywhere. | 
|  | 16083         this.fire('iron-items-changed', mutation, { | 
|  | 16084           bubbles: false, | 
|  | 16085           cancelable: false | 
|  | 16086         }); | 
|  | 16087       }); | 
|  | 16088     }, | 
|  | 16089 | 
|  | 16090     _activateHandler: function(e) { | 
|  | 16091       var t = e.target; | 
|  | 16092       var items = this.items; | 
|  | 16093       while (t && t != this) { | 
|  | 16094         var i = items.indexOf(t); | 
|  | 16095         if (i >= 0) { | 
|  | 16096           var value = this._indexToValue(i); | 
|  | 16097           this._itemActivate(value, t); | 
|  | 16098           return; | 
|  | 16099         } | 
|  | 16100         t = t.parentNode; | 
|  | 16101       } | 
|  | 16102     }, | 
|  | 16103 | 
|  | 16104     _itemActivate: function(value, item) { | 
|  | 16105       if (!this.fire('iron-activate', | 
|  | 16106           {selected: value, item: item}, {cancelable: true}).defaultPrevented) { | 
|  | 16107         this.select(value); | 
|  | 16108       } | 
|  | 16109     } | 
|  | 16110 | 
|  | 16111   }; | 
|  | 16112 | 
|  | 16113 </script> | 
|  | 16114 <script> | 
|  | 16115   /** @polymerBehavior Polymer.IronMultiSelectableBehavior */ | 
|  | 16116   Polymer.IronMultiSelectableBehaviorImpl = { | 
|  | 16117     properties: { | 
|  | 16118 | 
|  | 16119       /** | 
|  | 16120        * If true, multiple selections are allowed. | 
|  | 16121        */ | 
|  | 16122       multi: { | 
|  | 16123         type: Boolean, | 
|  | 16124         value: false, | 
|  | 16125         observer: 'multiChanged' | 
|  | 16126       }, | 
|  | 16127 | 
|  | 16128       /** | 
|  | 16129        * Gets or sets the selected elements. This is used instead of `selected` 
       when `multi` | 
|  | 16130        * is true. | 
|  | 16131        */ | 
|  | 16132       selectedValues: { | 
|  | 16133         type: Array, | 
|  | 16134         notify: true | 
|  | 16135       }, | 
|  | 16136 | 
|  | 16137       /** | 
|  | 16138        * Returns an array of currently selected items. | 
|  | 16139        */ | 
|  | 16140       selectedItems: { | 
|  | 16141         type: Array, | 
|  | 16142         readOnly: true, | 
|  | 16143         notify: true | 
|  | 16144       }, | 
|  | 16145 | 
|  | 16146     }, | 
|  | 16147 | 
|  | 16148     observers: [ | 
|  | 16149       '_updateSelected(selectedValues.splices)' | 
|  | 16150     ], | 
|  | 16151 | 
|  | 16152     /** | 
|  | 16153      * Selects the given value. If the `multi` property is true, then the select
       ed state of the | 
|  | 16154      * `value` will be toggled; otherwise the `value` will be selected. | 
|  | 16155      * | 
|  | 16156      * @method select | 
|  | 16157      * @param {string|number} value the value to select. | 
|  | 16158      */ | 
|  | 16159     select: function(value) { | 
|  | 16160       if (this.multi) { | 
|  | 16161         if (this.selectedValues) { | 
|  | 16162           this._toggleSelected(value); | 
|  | 16163         } else { | 
|  | 16164           this.selectedValues = [value]; | 
|  | 16165         } | 
|  | 16166       } else { | 
|  | 16167         this.selected = value; | 
|  | 16168       } | 
|  | 16169     }, | 
|  | 16170 | 
|  | 16171     multiChanged: function(multi) { | 
|  | 16172       this._selection.multi = multi; | 
|  | 16173     }, | 
|  | 16174 | 
|  | 16175     get _shouldUpdateSelection() { | 
|  | 16176       return this.selected != null || | 
|  | 16177         (this.selectedValues != null && this.selectedValues.length); | 
|  | 16178     }, | 
|  | 16179 | 
|  | 16180     _updateAttrForSelected: function() { | 
|  | 16181       if (!this.multi) { | 
|  | 16182         Polymer.IronSelectableBehavior._updateAttrForSelected.apply(this); | 
|  | 16183       } else if (this._shouldUpdateSelection) { | 
|  | 16184         this.selectedValues = this.selectedItems.map(function(selectedItem) { | 
|  | 16185           return this._indexToValue(this.indexOf(selectedItem)); | 
|  | 16186         }, this).filter(function(unfilteredValue) { | 
|  | 16187           return unfilteredValue != null; | 
|  | 16188         }, this); | 
|  | 16189       } | 
|  | 16190     }, | 
|  | 16191 | 
|  | 16192     _updateSelected: function() { | 
|  | 16193       if (this.multi) { | 
|  | 16194         this._selectMulti(this.selectedValues); | 
|  | 16195       } else { | 
|  | 16196         this._selectSelected(this.selected); | 
|  | 16197       } | 
|  | 16198     }, | 
|  | 16199 | 
|  | 16200     _selectMulti: function(values) { | 
|  | 16201       if (values) { | 
|  | 16202         var selectedItems = this._valuesToItems(values); | 
|  | 16203         // clear all but the current selected items | 
|  | 16204         this._selection.clear(selectedItems); | 
|  | 16205         // select only those not selected yet | 
|  | 16206         for (var i = 0; i < selectedItems.length; i++) { | 
|  | 16207           this._selection.setItemSelected(selectedItems[i], true); | 
|  | 16208         } | 
|  | 16209         // Check for items, since this array is populated only when attached | 
|  | 16210         if (this.fallbackSelection && this.items.length && !this._selection.get(
       ).length) { | 
|  | 16211           var fallback = this._valueToItem(this.fallbackSelection); | 
|  | 16212           if (fallback) { | 
|  | 16213             this.selectedValues = [this.fallbackSelection]; | 
|  | 16214           } | 
|  | 16215         } | 
|  | 16216       } else { | 
|  | 16217         this._selection.clear(); | 
|  | 16218       } | 
|  | 16219     }, | 
|  | 16220 | 
|  | 16221     _selectionChange: function() { | 
|  | 16222       var s = this._selection.get(); | 
|  | 16223       if (this.multi) { | 
|  | 16224         this._setSelectedItems(s); | 
|  | 16225       } else { | 
|  | 16226         this._setSelectedItems([s]); | 
|  | 16227         this._setSelectedItem(s); | 
|  | 16228       } | 
|  | 16229     }, | 
|  | 16230 | 
|  | 16231     _toggleSelected: function(value) { | 
|  | 16232       var i = this.selectedValues.indexOf(value); | 
|  | 16233       var unselected = i < 0; | 
|  | 16234       if (unselected) { | 
|  | 16235         this.push('selectedValues',value); | 
|  | 16236       } else { | 
|  | 16237         this.splice('selectedValues',i,1); | 
|  | 16238       } | 
|  | 16239     }, | 
|  | 16240 | 
|  | 16241     _valuesToItems: function(values) { | 
|  | 16242       return (values == null) ? null : values.map(function(value) { | 
|  | 16243         return this._valueToItem(value); | 
|  | 16244       }, this); | 
|  | 16245     } | 
|  | 16246   }; | 
|  | 16247 | 
|  | 16248   /** @polymerBehavior */ | 
|  | 16249   Polymer.IronMultiSelectableBehavior = [ | 
|  | 16250     Polymer.IronSelectableBehavior, | 
|  | 16251     Polymer.IronMultiSelectableBehaviorImpl | 
|  | 16252   ]; | 
|  | 16253 | 
|  | 16254 </script> | 
|  | 16255 <script> | 
|  | 16256   /** | 
|  | 16257   `iron-selector` is an element which can be used to manage a list of elements | 
|  | 16258   that can be selected.  Tapping on the item will make the item selected.  The `
       selected` indicates | 
|  | 16259   which item is being selected.  The default is to use the index of the item. | 
|  | 16260 | 
|  | 16261   Example: | 
|  | 16262 | 
|  | 16263       <iron-selector selected="0"> | 
|  | 16264         <div>Item 1</div> | 
|  | 16265         <div>Item 2</div> | 
|  | 16266         <div>Item 3</div> | 
|  | 16267       </iron-selector> | 
|  | 16268 | 
|  | 16269   If you want to use the attribute value of an element for `selected` instead of
        the index, | 
|  | 16270   set `attrForSelected` to the name of the attribute.  For example, if you want 
       to select item by | 
|  | 16271   `name`, set `attrForSelected` to `name`. | 
|  | 16272 | 
|  | 16273   Example: | 
|  | 16274 | 
|  | 16275       <iron-selector attr-for-selected="name" selected="foo"> | 
|  | 16276         <div name="foo">Foo</div> | 
|  | 16277         <div name="bar">Bar</div> | 
|  | 16278         <div name="zot">Zot</div> | 
|  | 16279       </iron-selector> | 
|  | 16280 | 
|  | 16281   You can specify a default fallback with `fallbackSelection` in case the `selec
       ted` attribute does | 
|  | 16282   not match the `attrForSelected` attribute of any elements. | 
|  | 16283 | 
|  | 16284   Example: | 
|  | 16285 | 
|  | 16286         <iron-selector attr-for-selected="name" selected="non-existing" | 
|  | 16287                        fallback-selection="default"> | 
|  | 16288           <div name="foo">Foo</div> | 
|  | 16289           <div name="bar">Bar</div> | 
|  | 16290           <div name="default">Default</div> | 
|  | 16291         </iron-selector> | 
|  | 16292 | 
|  | 16293   Note: When the selector is multi, the selection will set to `fallbackSelection
       ` iff | 
|  | 16294   the number of matching elements is zero. | 
|  | 16295 | 
|  | 16296   `iron-selector` is not styled. Use the `iron-selected` CSS class to style the 
       selected element. | 
|  | 16297 | 
|  | 16298   Example: | 
|  | 16299 | 
|  | 16300       <style> | 
|  | 16301         .iron-selected { | 
|  | 16302           background: #eee; | 
|  | 16303         } | 
|  | 16304       </style> | 
|  | 16305 | 
|  | 16306       ... | 
|  | 16307 | 
|  | 16308       <iron-selector selected="0"> | 
|  | 16309         <div>Item 1</div> | 
|  | 16310         <div>Item 2</div> | 
|  | 16311         <div>Item 3</div> | 
|  | 16312       </iron-selector> | 
|  | 16313 | 
|  | 16314   @demo demo/index.html | 
|  | 16315   */ | 
|  | 16316 | 
|  | 16317   Polymer({ | 
|  | 16318 | 
|  | 16319     is: 'iron-selector', | 
|  | 16320 | 
|  | 16321     behaviors: [ | 
|  | 16322       Polymer.IronMultiSelectableBehavior | 
|  | 16323     ] | 
|  | 16324 | 
|  | 16325   }); | 
|  | 16326 | 
|  | 16327 </script> | 
|  | 16328 | 
|  | 16329 | 
|  | 16330 <style is="custom-style"> | 
|  | 16331 | 
|  | 16332   :root { | 
|  | 16333     /* | 
|  | 16334      * You can use these generic variables in your elements for easy theming. | 
|  | 16335      * For example, if all your elements use `--primary-text-color` as its main | 
|  | 16336      * color, then switching from a light to a dark theme is just a matter of | 
|  | 16337      * changing the value of `--primary-text-color` in your application. | 
|  | 16338      */ | 
|  | 16339     --primary-text-color: var(--light-theme-text-color); | 
|  | 16340     --primary-background-color: var(--light-theme-background-color); | 
|  | 16341     --secondary-text-color: var(--light-theme-secondary-color); | 
|  | 16342     --disabled-text-color: var(--light-theme-disabled-color); | 
|  | 16343     --divider-color: var(--light-theme-divider-color); | 
|  | 16344     --error-color: var(--paper-deep-orange-a700); | 
|  | 16345 | 
|  | 16346     /* | 
|  | 16347      * Primary and accent colors. Also see color.html for more colors. | 
|  | 16348      */ | 
|  | 16349     --primary-color: var(--paper-indigo-500); | 
|  | 16350     --light-primary-color: var(--paper-indigo-100); | 
|  | 16351     --dark-primary-color: var(--paper-indigo-700); | 
|  | 16352 | 
|  | 16353     --accent-color: var(--paper-pink-a200); | 
|  | 16354     --light-accent-color: var(--paper-pink-a100); | 
|  | 16355     --dark-accent-color: var(--paper-pink-a400); | 
|  | 16356 | 
|  | 16357 | 
|  | 16358     /* | 
|  | 16359      * Material Design Light background theme | 
|  | 16360      */ | 
|  | 16361     --light-theme-background-color: #ffffff; | 
|  | 16362     --light-theme-base-color: #000000; | 
|  | 16363     --light-theme-text-color: var(--paper-grey-900); | 
|  | 16364     --light-theme-secondary-color: #737373;  /* for secondary text and icons */ | 
|  | 16365     --light-theme-disabled-color: #9b9b9b;  /* disabled/hint text */ | 
|  | 16366     --light-theme-divider-color: #dbdbdb; | 
|  | 16367 | 
|  | 16368     /* | 
|  | 16369      * Material Design Dark background theme | 
|  | 16370      */ | 
|  | 16371     --dark-theme-background-color: var(--paper-grey-900); | 
|  | 16372     --dark-theme-base-color: #ffffff; | 
|  | 16373     --dark-theme-text-color: #ffffff; | 
|  | 16374     --dark-theme-secondary-color: #bcbcbc;  /* for secondary text and icons */ | 
|  | 16375     --dark-theme-disabled-color: #646464;  /* disabled/hint text */ | 
|  | 16376     --dark-theme-divider-color: #3c3c3c; | 
|  | 16377 | 
|  | 16378     /* | 
|  | 16379      * Deprecated values because of their confusing names. | 
|  | 16380      */ | 
|  | 16381     --text-primary-color: var(--dark-theme-text-color); | 
|  | 16382     --default-primary-color: var(--primary-color); | 
|  | 16383 | 
|  | 16384   } | 
|  | 16385 | 
|  | 16386 </style> | 
|  | 16387 <script> | 
|  | 16388   /** | 
|  | 16389    * Singleton IronMeta instance. | 
|  | 16390    */ | 
|  | 16391   Polymer.IronValidatableBehaviorMeta = null; | 
|  | 16392 | 
|  | 16393   /** | 
|  | 16394    * `Use Polymer.IronValidatableBehavior` to implement an element that validate
       s user input. | 
|  | 16395    * Use the related `Polymer.IronValidatorBehavior` to add custom validation lo
       gic to an iron-input. | 
|  | 16396    * | 
|  | 16397    * By default, an `<iron-form>` element validates its fields when the user pre
       sses the submit button. | 
|  | 16398    * To validate a form imperatively, call the form's `validate()` method, which
        in turn will | 
|  | 16399    * call `validate()` on all its children. By using `Polymer.IronValidatableBeh
       avior`, your | 
|  | 16400    * custom element will get a public `validate()`, which | 
|  | 16401    * will return the validity of the element, and a corresponding `invalid` attr
       ibute, | 
|  | 16402    * which can be used for styling. | 
|  | 16403    * | 
|  | 16404    * To implement the custom validation logic of your element, you must override | 
|  | 16405    * the protected `_getValidity()` method of this behaviour, rather than `valid
       ate()`. | 
|  | 16406    * See [this](https://github.com/PolymerElements/iron-form/blob/master/demo/si
       mple-element.html) | 
|  | 16407    * for an example. | 
|  | 16408    * | 
|  | 16409    * ### Accessibility | 
|  | 16410    * | 
|  | 16411    * Changing the `invalid` property, either manually or by calling `validate()`
        will update the | 
|  | 16412    * `aria-invalid` attribute. | 
|  | 16413    * | 
|  | 16414    * @demo demo/index.html | 
|  | 16415    * @polymerBehavior | 
|  | 16416    */ | 
|  | 16417   Polymer.IronValidatableBehavior = { | 
|  | 16418 | 
|  | 16419     properties: { | 
|  | 16420 | 
|  | 16421       /** | 
|  | 16422        * Name of the validator to use. | 
|  | 16423        */ | 
|  | 16424       validator: { | 
|  | 16425         type: String | 
|  | 16426       }, | 
|  | 16427 | 
|  | 16428       /** | 
|  | 16429        * True if the last call to `validate` is invalid. | 
|  | 16430        */ | 
|  | 16431       invalid: { | 
|  | 16432         notify: true, | 
|  | 16433         reflectToAttribute: true, | 
|  | 16434         type: Boolean, | 
|  | 16435         value: false | 
|  | 16436       }, | 
|  | 16437 | 
|  | 16438       /** | 
|  | 16439        * This property is deprecated and should not be used. Use the global | 
|  | 16440        * validator meta singleton, `Polymer.IronValidatableBehaviorMeta` instead
       . | 
|  | 16441        */ | 
|  | 16442       _validatorMeta: { | 
|  | 16443         type: Object | 
|  | 16444       }, | 
|  | 16445 | 
|  | 16446       /** | 
|  | 16447        * Namespace for this validator. This property is deprecated and should | 
|  | 16448        * not be used. For all intents and purposes, please consider it a | 
|  | 16449        * read-only, config-time property. | 
|  | 16450        */ | 
|  | 16451       validatorType: { | 
|  | 16452         type: String, | 
|  | 16453         value: 'validator' | 
|  | 16454       }, | 
|  | 16455 | 
|  | 16456       _validator: { | 
|  | 16457         type: Object, | 
|  | 16458         computed: '__computeValidator(validator)' | 
|  | 16459       } | 
|  | 16460     }, | 
|  | 16461 | 
|  | 16462     observers: [ | 
|  | 16463       '_invalidChanged(invalid)' | 
|  | 16464     ], | 
|  | 16465 | 
|  | 16466     registered: function() { | 
|  | 16467       Polymer.IronValidatableBehaviorMeta = new Polymer.IronMeta({type: 'validat
       or'}); | 
|  | 16468     }, | 
|  | 16469 | 
|  | 16470     _invalidChanged: function() { | 
|  | 16471       if (this.invalid) { | 
|  | 16472         this.setAttribute('aria-invalid', 'true'); | 
|  | 16473       } else { | 
|  | 16474         this.removeAttribute('aria-invalid'); | 
|  | 16475       } | 
|  | 16476     }, | 
|  | 16477 | 
|  | 16478     /** | 
|  | 16479      * @return {boolean} True if the validator `validator` exists. | 
|  | 16480      */ | 
|  | 16481     hasValidator: function() { | 
|  | 16482       return this._validator != null; | 
|  | 16483     }, | 
|  | 16484 | 
|  | 16485     /** | 
|  | 16486      * Returns true if the `value` is valid, and updates `invalid`. If you want | 
|  | 16487      * your element to have custom validation logic, do not override this method
       ; | 
|  | 16488      * override `_getValidity(value)` instead. | 
|  | 16489 | 
|  | 16490      * @param {Object} value The value to be validated. By default, it is passed | 
|  | 16491      * to the validator's `validate()` function, if a validator is set. | 
|  | 16492      * @return {boolean} True if `value` is valid. | 
|  | 16493      */ | 
|  | 16494     validate: function(value) { | 
|  | 16495       this.invalid = !this._getValidity(value); | 
|  | 16496       return !this.invalid; | 
|  | 16497     }, | 
|  | 16498 | 
|  | 16499     /** | 
|  | 16500      * Returns true if `value` is valid.  By default, it is passed | 
|  | 16501      * to the validator's `validate()` function, if a validator is set. You | 
|  | 16502      * should override this method if you want to implement custom validity | 
|  | 16503      * logic for your element. | 
|  | 16504      * | 
|  | 16505      * @param {Object} value The value to be validated. | 
|  | 16506      * @return {boolean} True if `value` is valid. | 
|  | 16507      */ | 
|  | 16508 | 
|  | 16509     _getValidity: function(value) { | 
|  | 16510       if (this.hasValidator()) { | 
|  | 16511         return this._validator.validate(value); | 
|  | 16512       } | 
|  | 16513       return true; | 
|  | 16514     }, | 
|  | 16515 | 
|  | 16516     __computeValidator: function() { | 
|  | 16517       return Polymer.IronValidatableBehaviorMeta && | 
|  | 16518           Polymer.IronValidatableBehaviorMeta.byKey(this.validator); | 
|  | 16519     } | 
|  | 16520   }; | 
|  | 16521 | 
|  | 16522 </script> | 
|  | 16523 <script> | 
|  | 16524   /** | 
|  | 16525   Polymer.IronFormElementBehavior enables a custom element to be included | 
|  | 16526   in an `iron-form`. | 
|  | 16527 | 
|  | 16528   @demo demo/index.html | 
|  | 16529   @polymerBehavior | 
|  | 16530   */ | 
|  | 16531   Polymer.IronFormElementBehavior = { | 
|  | 16532 | 
|  | 16533     properties: { | 
|  | 16534       /** | 
|  | 16535        * Fired when the element is added to an `iron-form`. | 
|  | 16536        * | 
|  | 16537        * @event iron-form-element-register | 
|  | 16538        */ | 
|  | 16539 | 
|  | 16540       /** | 
|  | 16541        * Fired when the element is removed from an `iron-form`. | 
|  | 16542        * | 
|  | 16543        * @event iron-form-element-unregister | 
|  | 16544        */ | 
|  | 16545 | 
|  | 16546       /** | 
|  | 16547        * The name of this element. | 
|  | 16548        */ | 
|  | 16549       name: { | 
|  | 16550         type: String | 
|  | 16551       }, | 
|  | 16552 | 
|  | 16553       /** | 
|  | 16554        * The value for this element. | 
|  | 16555        */ | 
|  | 16556       value: { | 
|  | 16557         notify: true, | 
|  | 16558         type: String | 
|  | 16559       }, | 
|  | 16560 | 
|  | 16561       /** | 
|  | 16562        * Set to true to mark the input as required. If used in a form, a | 
|  | 16563        * custom element that uses this behavior should also use | 
|  | 16564        * Polymer.IronValidatableBehavior and define a custom validation method. | 
|  | 16565        * Otherwise, a `required` element will always be considered valid. | 
|  | 16566        * It's also strongly recommended to provide a visual style for the elemen
       t | 
|  | 16567        * when its value is invalid. | 
|  | 16568        */ | 
|  | 16569       required: { | 
|  | 16570         type: Boolean, | 
|  | 16571         value: false | 
|  | 16572       }, | 
|  | 16573 | 
|  | 16574       /** | 
|  | 16575        * The form that the element is registered to. | 
|  | 16576        */ | 
|  | 16577       _parentForm: { | 
|  | 16578         type: Object | 
|  | 16579       } | 
|  | 16580     }, | 
|  | 16581 | 
|  | 16582     attached: function() { | 
|  | 16583       // Note: the iron-form that this element belongs to will set this | 
|  | 16584       // element's _parentForm property when handling this event. | 
|  | 16585       this.fire('iron-form-element-register'); | 
|  | 16586     }, | 
|  | 16587 | 
|  | 16588     detached: function() { | 
|  | 16589       if (this._parentForm) { | 
|  | 16590         this._parentForm.fire('iron-form-element-unregister', {target: this}); | 
|  | 16591       } | 
|  | 16592     } | 
|  | 16593 | 
|  | 16594   }; | 
|  | 16595 | 
|  | 16596 </script> | 
|  | 16597 <script> | 
|  | 16598 | 
|  | 16599   /** | 
|  | 16600    * Use `Polymer.IronCheckedElementBehavior` to implement a custom element | 
|  | 16601    * that has a `checked` property, which can be used for validation if the | 
|  | 16602    * element is also `required`. Element instances implementing this behavior | 
|  | 16603    * will also be registered for use in an `iron-form` element. | 
|  | 16604    * | 
|  | 16605    * @demo demo/index.html | 
|  | 16606    * @polymerBehavior Polymer.IronCheckedElementBehavior | 
|  | 16607    */ | 
|  | 16608   Polymer.IronCheckedElementBehaviorImpl = { | 
|  | 16609 | 
|  | 16610     properties: { | 
|  | 16611       /** | 
|  | 16612        * Fired when the checked state changes. | 
|  | 16613        * | 
|  | 16614        * @event iron-change | 
|  | 16615        */ | 
|  | 16616 | 
|  | 16617       /** | 
|  | 16618        * Gets or sets the state, `true` is checked and `false` is unchecked. | 
|  | 16619        */ | 
|  | 16620       checked: { | 
|  | 16621         type: Boolean, | 
|  | 16622         value: false, | 
|  | 16623         reflectToAttribute: true, | 
|  | 16624         notify: true, | 
|  | 16625         observer: '_checkedChanged' | 
|  | 16626       }, | 
|  | 16627 | 
|  | 16628       /** | 
|  | 16629        * If true, the button toggles the active state with each tap or press | 
|  | 16630        * of the spacebar. | 
|  | 16631        */ | 
|  | 16632       toggles: { | 
|  | 16633         type: Boolean, | 
|  | 16634         value: true, | 
|  | 16635         reflectToAttribute: true | 
|  | 16636       }, | 
|  | 16637 | 
|  | 16638       /* Overriden from Polymer.IronFormElementBehavior */ | 
|  | 16639       value: { | 
|  | 16640         type: String, | 
|  | 16641         value: 'on', | 
|  | 16642         observer: '_valueChanged' | 
|  | 16643       } | 
|  | 16644     }, | 
|  | 16645 | 
|  | 16646     observers: [ | 
|  | 16647       '_requiredChanged(required)' | 
|  | 16648     ], | 
|  | 16649 | 
|  | 16650     created: function() { | 
|  | 16651       // Used by `iron-form` to handle the case that an element with this behavi
       or | 
|  | 16652       // doesn't have a role of 'checkbox' or 'radio', but should still only be | 
|  | 16653       // included when the form is serialized if `this.checked === true`. | 
|  | 16654       this._hasIronCheckedElementBehavior = true; | 
|  | 16655     }, | 
|  | 16656 | 
|  | 16657     /** | 
|  | 16658      * Returns false if the element is required and not checked, and true otherw
       ise. | 
|  | 16659      * @param {*=} _value Ignored. | 
|  | 16660      * @return {boolean} true if `required` is false or if `checked` is true. | 
|  | 16661      */ | 
|  | 16662     _getValidity: function(_value) { | 
|  | 16663       return this.disabled || !this.required || this.checked; | 
|  | 16664     }, | 
|  | 16665 | 
|  | 16666     /** | 
|  | 16667      * Update the aria-required label when `required` is changed. | 
|  | 16668      */ | 
|  | 16669     _requiredChanged: function() { | 
|  | 16670       if (this.required) { | 
|  | 16671         this.setAttribute('aria-required', 'true'); | 
|  | 16672       } else { | 
|  | 16673         this.removeAttribute('aria-required'); | 
|  | 16674       } | 
|  | 16675     }, | 
|  | 16676 | 
|  | 16677     /** | 
|  | 16678      * Fire `iron-changed` when the checked state changes. | 
|  | 16679      */ | 
|  | 16680     _checkedChanged: function() { | 
|  | 16681       this.active = this.checked; | 
|  | 16682       this.fire('iron-change'); | 
|  | 16683     }, | 
|  | 16684 | 
|  | 16685     /** | 
|  | 16686      * Reset value to 'on' if it is set to `undefined`. | 
|  | 16687      */ | 
|  | 16688     _valueChanged: function() { | 
|  | 16689       if (this.value === undefined || this.value === null) { | 
|  | 16690         this.value = 'on'; | 
|  | 16691       } | 
|  | 16692     } | 
|  | 16693   }; | 
|  | 16694 | 
|  | 16695   /** @polymerBehavior Polymer.IronCheckedElementBehavior */ | 
|  | 16696   Polymer.IronCheckedElementBehavior = [ | 
|  | 16697     Polymer.IronFormElementBehavior, | 
|  | 16698     Polymer.IronValidatableBehavior, | 
|  | 16699     Polymer.IronCheckedElementBehaviorImpl | 
|  | 16700   ]; | 
|  | 16701 | 
|  | 16702 </script> | 
|  | 16703 <script> | 
|  | 16704   (function() { | 
|  | 16705     'use strict'; | 
|  | 16706 | 
|  | 16707     /** | 
|  | 16708      * Chrome uses an older version of DOM Level 3 Keyboard Events | 
|  | 16709      * | 
|  | 16710      * Most keys are labeled as text, but some are Unicode codepoints. | 
|  | 16711      * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-200712
       21/keyset.html#KeySet-Set | 
|  | 16712      */ | 
|  | 16713     var KEY_IDENTIFIER = { | 
|  | 16714       'U+0008': 'backspace', | 
|  | 16715       'U+0009': 'tab', | 
|  | 16716       'U+001B': 'esc', | 
|  | 16717       'U+0020': 'space', | 
|  | 16718       'U+007F': 'del' | 
|  | 16719     }; | 
|  | 16720 | 
|  | 16721     /** | 
|  | 16722      * Special table for KeyboardEvent.keyCode. | 
|  | 16723      * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even bett
       er | 
|  | 16724      * than that. | 
|  | 16725      * | 
|  | 16726      * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEve
       nt.keyCode#Value_of_keyCode | 
|  | 16727      */ | 
|  | 16728     var KEY_CODE = { | 
|  | 16729       8: 'backspace', | 
|  | 16730       9: 'tab', | 
|  | 16731       13: 'enter', | 
|  | 16732       27: 'esc', | 
|  | 16733       33: 'pageup', | 
|  | 16734       34: 'pagedown', | 
|  | 16735       35: 'end', | 
|  | 16736       36: 'home', | 
|  | 16737       32: 'space', | 
|  | 16738       37: 'left', | 
|  | 16739       38: 'up', | 
|  | 16740       39: 'right', | 
|  | 16741       40: 'down', | 
|  | 16742       46: 'del', | 
|  | 16743       106: '*' | 
|  | 16744     }; | 
|  | 16745 | 
|  | 16746     /** | 
|  | 16747      * MODIFIER_KEYS maps the short name for modifier keys used in a key | 
|  | 16748      * combo string to the property name that references those same keys | 
|  | 16749      * in a KeyboardEvent instance. | 
|  | 16750      */ | 
|  | 16751     var MODIFIER_KEYS = { | 
|  | 16752       'shift': 'shiftKey', | 
|  | 16753       'ctrl': 'ctrlKey', | 
|  | 16754       'alt': 'altKey', | 
|  | 16755       'meta': 'metaKey' | 
|  | 16756     }; | 
|  | 16757 | 
|  | 16758     /** | 
|  | 16759      * KeyboardEvent.key is mostly represented by printable character made by | 
|  | 16760      * the keyboard, with unprintable keys labeled nicely. | 
|  | 16761      * | 
|  | 16762      * However, on OS X, Alt+char can make a Unicode character that follows an | 
|  | 16763      * Apple-specific mapping. In this case, we fall back to .keyCode. | 
|  | 16764      */ | 
|  | 16765     var KEY_CHAR = /[a-z0-9*]/; | 
|  | 16766 | 
|  | 16767     /** | 
|  | 16768      * Matches a keyIdentifier string. | 
|  | 16769      */ | 
|  | 16770     var IDENT_CHAR = /U\+/; | 
|  | 16771 | 
|  | 16772     /** | 
|  | 16773      * Matches arrow keys in Gecko 27.0+ | 
|  | 16774      */ | 
|  | 16775     var ARROW_KEY = /^arrow/; | 
|  | 16776 | 
|  | 16777     /** | 
|  | 16778      * Matches space keys everywhere (notably including IE10's exceptional name | 
|  | 16779      * `spacebar`). | 
|  | 16780      */ | 
|  | 16781     var SPACE_KEY = /^space(bar)?/; | 
|  | 16782 | 
|  | 16783     /** | 
|  | 16784      * Matches ESC key. | 
|  | 16785      * | 
|  | 16786      * Value from: http://w3c.github.io/uievents-key/#key-Escape | 
|  | 16787      */ | 
|  | 16788     var ESC_KEY = /^escape$/; | 
|  | 16789 | 
|  | 16790     /** | 
|  | 16791      * Transforms the key. | 
|  | 16792      * @param {string} key The KeyBoardEvent.key | 
|  | 16793      * @param {Boolean} [noSpecialChars] Limits the transformation to | 
|  | 16794      * alpha-numeric characters. | 
|  | 16795      */ | 
|  | 16796     function transformKey(key, noSpecialChars) { | 
|  | 16797       var validKey = ''; | 
|  | 16798       if (key) { | 
|  | 16799         var lKey = key.toLowerCase(); | 
|  | 16800         if (lKey === ' ' || SPACE_KEY.test(lKey)) { | 
|  | 16801           validKey = 'space'; | 
|  | 16802         } else if (ESC_KEY.test(lKey)) { | 
|  | 16803           validKey = 'esc'; | 
|  | 16804         } else if (lKey.length == 1) { | 
|  | 16805           if (!noSpecialChars || KEY_CHAR.test(lKey)) { | 
|  | 16806             validKey = lKey; | 
|  | 16807           } | 
|  | 16808         } else if (ARROW_KEY.test(lKey)) { | 
|  | 16809           validKey = lKey.replace('arrow', ''); | 
|  | 16810         } else if (lKey == 'multiply') { | 
|  | 16811           // numpad '*' can map to Multiply on IE/Windows | 
|  | 16812           validKey = '*'; | 
|  | 16813         } else { | 
|  | 16814           validKey = lKey; | 
|  | 16815         } | 
|  | 16816       } | 
|  | 16817       return validKey; | 
|  | 16818     } | 
|  | 16819 | 
|  | 16820     function transformKeyIdentifier(keyIdent) { | 
|  | 16821       var validKey = ''; | 
|  | 16822       if (keyIdent) { | 
|  | 16823         if (keyIdent in KEY_IDENTIFIER) { | 
|  | 16824           validKey = KEY_IDENTIFIER[keyIdent]; | 
|  | 16825         } else if (IDENT_CHAR.test(keyIdent)) { | 
|  | 16826           keyIdent = parseInt(keyIdent.replace('U+', '0x'), 16); | 
|  | 16827           validKey = String.fromCharCode(keyIdent).toLowerCase(); | 
|  | 16828         } else { | 
|  | 16829           validKey = keyIdent.toLowerCase(); | 
|  | 16830         } | 
|  | 16831       } | 
|  | 16832       return validKey; | 
|  | 16833     } | 
|  | 16834 | 
|  | 16835     function transformKeyCode(keyCode) { | 
|  | 16836       var validKey = ''; | 
|  | 16837       if (Number(keyCode)) { | 
|  | 16838         if (keyCode >= 65 && keyCode <= 90) { | 
|  | 16839           // ascii a-z | 
|  | 16840           // lowercase is 32 offset from uppercase | 
|  | 16841           validKey = String.fromCharCode(32 + keyCode); | 
|  | 16842         } else if (keyCode >= 112 && keyCode <= 123) { | 
|  | 16843           // function keys f1-f12 | 
|  | 16844           validKey = 'f' + (keyCode - 112); | 
|  | 16845         } else if (keyCode >= 48 && keyCode <= 57) { | 
|  | 16846           // top 0-9 keys | 
|  | 16847           validKey = String(keyCode - 48); | 
|  | 16848         } else if (keyCode >= 96 && keyCode <= 105) { | 
|  | 16849           // num pad 0-9 | 
|  | 16850           validKey = String(keyCode - 96); | 
|  | 16851         } else { | 
|  | 16852           validKey = KEY_CODE[keyCode]; | 
|  | 16853         } | 
|  | 16854       } | 
|  | 16855       return validKey; | 
|  | 16856     } | 
|  | 16857 | 
|  | 16858     /** | 
|  | 16859       * Calculates the normalized key for a KeyboardEvent. | 
|  | 16860       * @param {KeyboardEvent} keyEvent | 
|  | 16861       * @param {Boolean} [noSpecialChars] Set to true to limit keyEvent.key | 
|  | 16862       * transformation to alpha-numeric chars. This is useful with key | 
|  | 16863       * combinations like shift + 2, which on FF for MacOS produces | 
|  | 16864       * keyEvent.key = @ | 
|  | 16865       * To get 2 returned, set noSpecialChars = true | 
|  | 16866       * To get @ returned, set noSpecialChars = false | 
|  | 16867      */ | 
|  | 16868     function normalizedKeyForEvent(keyEvent, noSpecialChars) { | 
|  | 16869       // Fall back from .key, to .keyIdentifier, to .keyCode, and then to | 
|  | 16870       // .detail.key to support artificial keyboard events. | 
|  | 16871       return transformKey(keyEvent.key, noSpecialChars) || | 
|  | 16872         transformKeyIdentifier(keyEvent.keyIdentifier) || | 
|  | 16873         transformKeyCode(keyEvent.keyCode) || | 
|  | 16874         transformKey(keyEvent.detail ? keyEvent.detail.key : keyEvent.detail, no
       SpecialChars) || ''; | 
|  | 16875     } | 
|  | 16876 | 
|  | 16877     function keyComboMatchesEvent(keyCombo, event) { | 
|  | 16878       // For combos with modifiers we support only alpha-numeric keys | 
|  | 16879       var keyEvent = normalizedKeyForEvent(event, keyCombo.hasModifiers); | 
|  | 16880       return keyEvent === keyCombo.key && | 
|  | 16881         (!keyCombo.hasModifiers || ( | 
|  | 16882           !!event.shiftKey === !!keyCombo.shiftKey && | 
|  | 16883           !!event.ctrlKey === !!keyCombo.ctrlKey && | 
|  | 16884           !!event.altKey === !!keyCombo.altKey && | 
|  | 16885           !!event.metaKey === !!keyCombo.metaKey) | 
|  | 16886         ); | 
|  | 16887     } | 
|  | 16888 | 
|  | 16889     function parseKeyComboString(keyComboString) { | 
|  | 16890       if (keyComboString.length === 1) { | 
|  | 16891         return { | 
|  | 16892           combo: keyComboString, | 
|  | 16893           key: keyComboString, | 
|  | 16894           event: 'keydown' | 
|  | 16895         }; | 
|  | 16896       } | 
|  | 16897       return keyComboString.split('+').reduce(function(parsedKeyCombo, keyComboP
       art) { | 
|  | 16898         var eventParts = keyComboPart.split(':'); | 
|  | 16899         var keyName = eventParts[0]; | 
|  | 16900         var event = eventParts[1]; | 
|  | 16901 | 
|  | 16902         if (keyName in MODIFIER_KEYS) { | 
|  | 16903           parsedKeyCombo[MODIFIER_KEYS[keyName]] = true; | 
|  | 16904           parsedKeyCombo.hasModifiers = true; | 
|  | 16905         } else { | 
|  | 16906           parsedKeyCombo.key = keyName; | 
|  | 16907           parsedKeyCombo.event = event || 'keydown'; | 
|  | 16908         } | 
|  | 16909 | 
|  | 16910         return parsedKeyCombo; | 
|  | 16911       }, { | 
|  | 16912         combo: keyComboString.split(':').shift() | 
|  | 16913       }); | 
|  | 16914     } | 
|  | 16915 | 
|  | 16916     function parseEventString(eventString) { | 
|  | 16917       return eventString.trim().split(' ').map(function(keyComboString) { | 
|  | 16918         return parseKeyComboString(keyComboString); | 
|  | 16919       }); | 
|  | 16920     } | 
|  | 16921 | 
|  | 16922     /** | 
|  | 16923      * `Polymer.IronA11yKeysBehavior` provides a normalized interface for proces
       sing | 
|  | 16924      * keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3
       .org/TR/wai-aria-practices/#kbd_general_binding). | 
|  | 16925      * The element takes care of browser differences with respect to Keyboard ev
       ents | 
|  | 16926      * and uses an expressive syntax to filter key presses. | 
|  | 16927      * | 
|  | 16928      * Use the `keyBindings` prototype property to express what combination of k
       eys | 
|  | 16929      * will trigger the callback. A key binding has the format | 
|  | 16930      * `"KEY+MODIFIER:EVENT": "callback"` (`"KEY": "callback"` or | 
|  | 16931      * `"KEY:EVENT": "callback"` are valid as well). Some examples: | 
|  | 16932      * | 
|  | 16933      *      keyBindings: { | 
|  | 16934      *        'space': '_onKeydown', // same as 'space:keydown' | 
|  | 16935      *        'shift+tab': '_onKeydown', | 
|  | 16936      *        'enter:keypress': '_onKeypress', | 
|  | 16937      *        'esc:keyup': '_onKeyup' | 
|  | 16938      *      } | 
|  | 16939      * | 
|  | 16940      * The callback will receive with an event containing the following informat
       ion in `event.detail`: | 
|  | 16941      * | 
|  | 16942      *      _onKeydown: function(event) { | 
|  | 16943      *        console.log(event.detail.combo); // KEY+MODIFIER, e.g. "shift+tab" | 
|  | 16944      *        console.log(event.detail.key); // KEY only, e.g. "tab" | 
|  | 16945      *        console.log(event.detail.event); // EVENT, e.g. "keydown" | 
|  | 16946      *        console.log(event.detail.keyboardEvent); // the original KeyboardE
       vent | 
|  | 16947      *      } | 
|  | 16948      * | 
|  | 16949      * Use the `keyEventTarget` attribute to set up event handlers on a specific | 
|  | 16950      * node. | 
|  | 16951      * | 
|  | 16952      * See the [demo source code](https://github.com/PolymerElements/iron-a11y-k
       eys-behavior/blob/master/demo/x-key-aware.html) | 
|  | 16953      * for an example. | 
|  | 16954      * | 
|  | 16955      * @demo demo/index.html | 
|  | 16956      * @polymerBehavior | 
|  | 16957      */ | 
|  | 16958     Polymer.IronA11yKeysBehavior = { | 
|  | 16959       properties: { | 
|  | 16960         /** | 
|  | 16961          * The EventTarget that will be firing relevant KeyboardEvents. Set it t
       o | 
|  | 16962          * `null` to disable the listeners. | 
|  | 16963          * @type {?EventTarget} | 
|  | 16964          */ | 
|  | 16965         keyEventTarget: { | 
|  | 16966           type: Object, | 
|  | 16967           value: function() { | 
|  | 16968             return this; | 
|  | 16969           } | 
|  | 16970         }, | 
|  | 16971 | 
|  | 16972         /** | 
|  | 16973          * If true, this property will cause the implementing element to | 
|  | 16974          * automatically stop propagation on any handled KeyboardEvents. | 
|  | 16975          */ | 
|  | 16976         stopKeyboardEventPropagation: { | 
|  | 16977           type: Boolean, | 
|  | 16978           value: false | 
|  | 16979         }, | 
|  | 16980 | 
|  | 16981         _boundKeyHandlers: { | 
|  | 16982           type: Array, | 
|  | 16983           value: function() { | 
|  | 16984             return []; | 
|  | 16985           } | 
|  | 16986         }, | 
|  | 16987 | 
|  | 16988         // We use this due to a limitation in IE10 where instances will have | 
|  | 16989         // own properties of everything on the "prototype". | 
|  | 16990         _imperativeKeyBindings: { | 
|  | 16991           type: Object, | 
|  | 16992           value: function() { | 
|  | 16993             return {}; | 
|  | 16994           } | 
|  | 16995         } | 
|  | 16996       }, | 
|  | 16997 | 
|  | 16998       observers: [ | 
|  | 16999         '_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)' | 
|  | 17000       ], | 
|  | 17001 | 
|  | 17002 | 
|  | 17003       /** | 
|  | 17004        * To be used to express what combination of keys  will trigger the relati
       ve | 
|  | 17005        * callback. e.g. `keyBindings: { 'esc': '_onEscPressed'}` | 
|  | 17006        * @type {Object} | 
|  | 17007        */ | 
|  | 17008       keyBindings: {}, | 
|  | 17009 | 
|  | 17010       registered: function() { | 
|  | 17011         this._prepKeyBindings(); | 
|  | 17012       }, | 
|  | 17013 | 
|  | 17014       attached: function() { | 
|  | 17015         this._listenKeyEventListeners(); | 
|  | 17016       }, | 
|  | 17017 | 
|  | 17018       detached: function() { | 
|  | 17019         this._unlistenKeyEventListeners(); | 
|  | 17020       }, | 
|  | 17021 | 
|  | 17022       /** | 
|  | 17023        * Can be used to imperatively add a key binding to the implementing | 
|  | 17024        * element. This is the imperative equivalent of declaring a keybinding | 
|  | 17025        * in the `keyBindings` prototype property. | 
|  | 17026        */ | 
|  | 17027       addOwnKeyBinding: function(eventString, handlerName) { | 
|  | 17028         this._imperativeKeyBindings[eventString] = handlerName; | 
|  | 17029         this._prepKeyBindings(); | 
|  | 17030         this._resetKeyEventListeners(); | 
|  | 17031       }, | 
|  | 17032 | 
|  | 17033       /** | 
|  | 17034        * When called, will remove all imperatively-added key bindings. | 
|  | 17035        */ | 
|  | 17036       removeOwnKeyBindings: function() { | 
|  | 17037         this._imperativeKeyBindings = {}; | 
|  | 17038         this._prepKeyBindings(); | 
|  | 17039         this._resetKeyEventListeners(); | 
|  | 17040       }, | 
|  | 17041 | 
|  | 17042       /** | 
|  | 17043        * Returns true if a keyboard event matches `eventString`. | 
|  | 17044        * | 
|  | 17045        * @param {KeyboardEvent} event | 
|  | 17046        * @param {string} eventString | 
|  | 17047        * @return {boolean} | 
|  | 17048        */ | 
|  | 17049       keyboardEventMatchesKeys: function(event, eventString) { | 
|  | 17050         var keyCombos = parseEventString(eventString); | 
|  | 17051         for (var i = 0; i < keyCombos.length; ++i) { | 
|  | 17052           if (keyComboMatchesEvent(keyCombos[i], event)) { | 
|  | 17053             return true; | 
|  | 17054           } | 
|  | 17055         } | 
|  | 17056         return false; | 
|  | 17057       }, | 
|  | 17058 | 
|  | 17059       _collectKeyBindings: function() { | 
|  | 17060         var keyBindings = this.behaviors.map(function(behavior) { | 
|  | 17061           return behavior.keyBindings; | 
|  | 17062         }); | 
|  | 17063 | 
|  | 17064         if (keyBindings.indexOf(this.keyBindings) === -1) { | 
|  | 17065           keyBindings.push(this.keyBindings); | 
|  | 17066         } | 
|  | 17067 | 
|  | 17068         return keyBindings; | 
|  | 17069       }, | 
|  | 17070 | 
|  | 17071       _prepKeyBindings: function() { | 
|  | 17072         this._keyBindings = {}; | 
|  | 17073 | 
|  | 17074         this._collectKeyBindings().forEach(function(keyBindings) { | 
|  | 17075           for (var eventString in keyBindings) { | 
|  | 17076             this._addKeyBinding(eventString, keyBindings[eventString]); | 
|  | 17077           } | 
|  | 17078         }, this); | 
|  | 17079 | 
|  | 17080         for (var eventString in this._imperativeKeyBindings) { | 
|  | 17081           this._addKeyBinding(eventString, this._imperativeKeyBindings[eventStri
       ng]); | 
|  | 17082         } | 
|  | 17083 | 
|  | 17084         // Give precedence to combos with modifiers to be checked first. | 
|  | 17085         for (var eventName in this._keyBindings) { | 
|  | 17086           this._keyBindings[eventName].sort(function (kb1, kb2) { | 
|  | 17087             var b1 = kb1[0].hasModifiers; | 
|  | 17088             var b2 = kb2[0].hasModifiers; | 
|  | 17089             return (b1 === b2) ? 0 : b1 ? -1 : 1; | 
|  | 17090           }) | 
|  | 17091         } | 
|  | 17092       }, | 
|  | 17093 | 
|  | 17094       _addKeyBinding: function(eventString, handlerName) { | 
|  | 17095         parseEventString(eventString).forEach(function(keyCombo) { | 
|  | 17096           this._keyBindings[keyCombo.event] = | 
|  | 17097             this._keyBindings[keyCombo.event] || []; | 
|  | 17098 | 
|  | 17099           this._keyBindings[keyCombo.event].push([ | 
|  | 17100             keyCombo, | 
|  | 17101             handlerName | 
|  | 17102           ]); | 
|  | 17103         }, this); | 
|  | 17104       }, | 
|  | 17105 | 
|  | 17106       _resetKeyEventListeners: function() { | 
|  | 17107         this._unlistenKeyEventListeners(); | 
|  | 17108 | 
|  | 17109         if (this.isAttached) { | 
|  | 17110           this._listenKeyEventListeners(); | 
|  | 17111         } | 
|  | 17112       }, | 
|  | 17113 | 
|  | 17114       _listenKeyEventListeners: function() { | 
|  | 17115         if (!this.keyEventTarget) { | 
|  | 17116           return; | 
|  | 17117         } | 
|  | 17118         Object.keys(this._keyBindings).forEach(function(eventName) { | 
|  | 17119           var keyBindings = this._keyBindings[eventName]; | 
|  | 17120           var boundKeyHandler = this._onKeyBindingEvent.bind(this, keyBindings); | 
|  | 17121 | 
|  | 17122           this._boundKeyHandlers.push([this.keyEventTarget, eventName, boundKeyH
       andler]); | 
|  | 17123 | 
|  | 17124           this.keyEventTarget.addEventListener(eventName, boundKeyHandler); | 
|  | 17125         }, this); | 
|  | 17126       }, | 
|  | 17127 | 
|  | 17128       _unlistenKeyEventListeners: function() { | 
|  | 17129         var keyHandlerTuple; | 
|  | 17130         var keyEventTarget; | 
|  | 17131         var eventName; | 
|  | 17132         var boundKeyHandler; | 
|  | 17133 | 
|  | 17134         while (this._boundKeyHandlers.length) { | 
|  | 17135           // My kingdom for block-scope binding and destructuring assignment.. | 
|  | 17136           keyHandlerTuple = this._boundKeyHandlers.pop(); | 
|  | 17137           keyEventTarget = keyHandlerTuple[0]; | 
|  | 17138           eventName = keyHandlerTuple[1]; | 
|  | 17139           boundKeyHandler = keyHandlerTuple[2]; | 
|  | 17140 | 
|  | 17141           keyEventTarget.removeEventListener(eventName, boundKeyHandler); | 
|  | 17142         } | 
|  | 17143       }, | 
|  | 17144 | 
|  | 17145       _onKeyBindingEvent: function(keyBindings, event) { | 
|  | 17146         if (this.stopKeyboardEventPropagation) { | 
|  | 17147           event.stopPropagation(); | 
|  | 17148         } | 
|  | 17149 | 
|  | 17150         // if event has been already prevented, don't do anything | 
|  | 17151         if (event.defaultPrevented) { | 
|  | 17152           return; | 
|  | 17153         } | 
|  | 17154 | 
|  | 17155         for (var i = 0; i < keyBindings.length; i++) { | 
|  | 17156           var keyCombo = keyBindings[i][0]; | 
|  | 17157           var handlerName = keyBindings[i][1]; | 
|  | 17158           if (keyComboMatchesEvent(keyCombo, event)) { | 
|  | 17159             this._triggerKeyHandler(keyCombo, handlerName, event); | 
|  | 17160             // exit the loop if eventDefault was prevented | 
|  | 17161             if (event.defaultPrevented) { | 
|  | 17162               return; | 
|  | 17163             } | 
|  | 17164           } | 
|  | 17165         } | 
|  | 17166       }, | 
|  | 17167 | 
|  | 17168       _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) { | 
|  | 17169         var detail = Object.create(keyCombo); | 
|  | 17170         detail.keyboardEvent = keyboardEvent; | 
|  | 17171         var event = new CustomEvent(keyCombo.event, { | 
|  | 17172           detail: detail, | 
|  | 17173           cancelable: true | 
|  | 17174         }); | 
|  | 17175         this[handlerName].call(this, event); | 
|  | 17176         if (event.defaultPrevented) { | 
|  | 17177           keyboardEvent.preventDefault(); | 
|  | 17178         } | 
|  | 17179       } | 
|  | 17180     }; | 
|  | 17181   })(); | 
|  | 17182 </script> | 
|  | 17183 <script> | 
|  | 17184 | 
|  | 17185   /** | 
|  | 17186    * @demo demo/index.html | 
|  | 17187    * @polymerBehavior | 
|  | 17188    */ | 
|  | 17189   Polymer.IronControlState = { | 
|  | 17190 | 
|  | 17191     properties: { | 
|  | 17192 | 
|  | 17193       /** | 
|  | 17194        * If true, the element currently has focus. | 
|  | 17195        */ | 
|  | 17196       focused: { | 
|  | 17197         type: Boolean, | 
|  | 17198         value: false, | 
|  | 17199         notify: true, | 
|  | 17200         readOnly: true, | 
|  | 17201         reflectToAttribute: true | 
|  | 17202       }, | 
|  | 17203 | 
|  | 17204       /** | 
|  | 17205        * If true, the user cannot interact with this element. | 
|  | 17206        */ | 
|  | 17207       disabled: { | 
|  | 17208         type: Boolean, | 
|  | 17209         value: false, | 
|  | 17210         notify: true, | 
|  | 17211         observer: '_disabledChanged', | 
|  | 17212         reflectToAttribute: true | 
|  | 17213       }, | 
|  | 17214 | 
|  | 17215       _oldTabIndex: { | 
|  | 17216         type: Number | 
|  | 17217       }, | 
|  | 17218 | 
|  | 17219       _boundFocusBlurHandler: { | 
|  | 17220         type: Function, | 
|  | 17221         value: function() { | 
|  | 17222           return this._focusBlurHandler.bind(this); | 
|  | 17223         } | 
|  | 17224       } | 
|  | 17225 | 
|  | 17226     }, | 
|  | 17227 | 
|  | 17228     observers: [ | 
|  | 17229       '_changedControlState(focused, disabled)' | 
|  | 17230     ], | 
|  | 17231 | 
|  | 17232     ready: function() { | 
|  | 17233       this.addEventListener('focus', this._boundFocusBlurHandler, true); | 
|  | 17234       this.addEventListener('blur', this._boundFocusBlurHandler, true); | 
|  | 17235     }, | 
|  | 17236 | 
|  | 17237     _focusBlurHandler: function(event) { | 
|  | 17238       // NOTE(cdata):  if we are in ShadowDOM land, `event.target` will | 
|  | 17239       // eventually become `this` due to retargeting; if we are not in | 
|  | 17240       // ShadowDOM land, `event.target` will eventually become `this` due | 
|  | 17241       // to the second conditional which fires a synthetic event (that is also | 
|  | 17242       // handled). In either case, we can disregard `event.path`. | 
|  | 17243 | 
|  | 17244       if (event.target === this) { | 
|  | 17245         this._setFocused(event.type === 'focus'); | 
|  | 17246       } else if (!this.shadowRoot) { | 
|  | 17247         var target = /** @type {Node} */(Polymer.dom(event).localTarget); | 
|  | 17248         if (!this.isLightDescendant(target)) { | 
|  | 17249           this.fire(event.type, {sourceEvent: event}, { | 
|  | 17250             node: this, | 
|  | 17251             bubbles: event.bubbles, | 
|  | 17252             cancelable: event.cancelable | 
|  | 17253           }); | 
|  | 17254         } | 
|  | 17255       } | 
|  | 17256     }, | 
|  | 17257 | 
|  | 17258     _disabledChanged: function(disabled, old) { | 
|  | 17259       this.setAttribute('aria-disabled', disabled ? 'true' : 'false'); | 
|  | 17260       this.style.pointerEvents = disabled ? 'none' : ''; | 
|  | 17261       if (disabled) { | 
|  | 17262         this._oldTabIndex = this.tabIndex; | 
|  | 17263         this._setFocused(false); | 
|  | 17264         this.tabIndex = -1; | 
|  | 17265         this.blur(); | 
|  | 17266       } else if (this._oldTabIndex !== undefined) { | 
|  | 17267         this.tabIndex = this._oldTabIndex; | 
|  | 17268       } | 
|  | 17269     }, | 
|  | 17270 | 
|  | 17271     _changedControlState: function() { | 
|  | 17272       // _controlStateChanged is abstract, follow-on behaviors may implement it | 
|  | 17273       if (this._controlStateChanged) { | 
|  | 17274         this._controlStateChanged(); | 
|  | 17275       } | 
|  | 17276     } | 
|  | 17277 | 
|  | 17278   }; | 
|  | 17279 | 
|  | 17280 </script> | 
|  | 17281 <script> | 
|  | 17282 | 
|  | 17283   /** | 
|  | 17284    * @demo demo/index.html | 
|  | 17285    * @polymerBehavior Polymer.IronButtonState | 
|  | 17286    */ | 
|  | 17287   Polymer.IronButtonStateImpl = { | 
|  | 17288 | 
|  | 17289     properties: { | 
|  | 17290 | 
|  | 17291       /** | 
|  | 17292        * If true, the user is currently holding down the button. | 
|  | 17293        */ | 
|  | 17294       pressed: { | 
|  | 17295         type: Boolean, | 
|  | 17296         readOnly: true, | 
|  | 17297         value: false, | 
|  | 17298         reflectToAttribute: true, | 
|  | 17299         observer: '_pressedChanged' | 
|  | 17300       }, | 
|  | 17301 | 
|  | 17302       /** | 
|  | 17303        * If true, the button toggles the active state with each tap or press | 
|  | 17304        * of the spacebar. | 
|  | 17305        */ | 
|  | 17306       toggles: { | 
|  | 17307         type: Boolean, | 
|  | 17308         value: false, | 
|  | 17309         reflectToAttribute: true | 
|  | 17310       }, | 
|  | 17311 | 
|  | 17312       /** | 
|  | 17313        * If true, the button is a toggle and is currently in the active state. | 
|  | 17314        */ | 
|  | 17315       active: { | 
|  | 17316         type: Boolean, | 
|  | 17317         value: false, | 
|  | 17318         notify: true, | 
|  | 17319         reflectToAttribute: true | 
|  | 17320       }, | 
|  | 17321 | 
|  | 17322       /** | 
|  | 17323        * True if the element is currently being pressed by a "pointer," which | 
|  | 17324        * is loosely defined as mouse or touch input (but specifically excluding | 
|  | 17325        * keyboard input). | 
|  | 17326        */ | 
|  | 17327       pointerDown: { | 
|  | 17328         type: Boolean, | 
|  | 17329         readOnly: true, | 
|  | 17330         value: false | 
|  | 17331       }, | 
|  | 17332 | 
|  | 17333       /** | 
|  | 17334        * True if the input device that caused the element to receive focus | 
|  | 17335        * was a keyboard. | 
|  | 17336        */ | 
|  | 17337       receivedFocusFromKeyboard: { | 
|  | 17338         type: Boolean, | 
|  | 17339         readOnly: true | 
|  | 17340       }, | 
|  | 17341 | 
|  | 17342       /** | 
|  | 17343        * The aria attribute to be set if the button is a toggle and in the | 
|  | 17344        * active state. | 
|  | 17345        */ | 
|  | 17346       ariaActiveAttribute: { | 
|  | 17347         type: String, | 
|  | 17348         value: 'aria-pressed', | 
|  | 17349         observer: '_ariaActiveAttributeChanged' | 
|  | 17350       } | 
|  | 17351     }, | 
|  | 17352 | 
|  | 17353     listeners: { | 
|  | 17354       down: '_downHandler', | 
|  | 17355       up: '_upHandler', | 
|  | 17356       tap: '_tapHandler' | 
|  | 17357     }, | 
|  | 17358 | 
|  | 17359     observers: [ | 
|  | 17360       '_detectKeyboardFocus(focused)', | 
|  | 17361       '_activeChanged(active, ariaActiveAttribute)' | 
|  | 17362     ], | 
|  | 17363 | 
|  | 17364     keyBindings: { | 
|  | 17365       'enter:keydown': '_asyncClick', | 
|  | 17366       'space:keydown': '_spaceKeyDownHandler', | 
|  | 17367       'space:keyup': '_spaceKeyUpHandler', | 
|  | 17368     }, | 
|  | 17369 | 
|  | 17370     _mouseEventRe: /^mouse/, | 
|  | 17371 | 
|  | 17372     _tapHandler: function() { | 
|  | 17373       if (this.toggles) { | 
|  | 17374        // a tap is needed to toggle the active state | 
|  | 17375         this._userActivate(!this.active); | 
|  | 17376       } else { | 
|  | 17377         this.active = false; | 
|  | 17378       } | 
|  | 17379     }, | 
|  | 17380 | 
|  | 17381     _detectKeyboardFocus: function(focused) { | 
|  | 17382       this._setReceivedFocusFromKeyboard(!this.pointerDown && focused); | 
|  | 17383     }, | 
|  | 17384 | 
|  | 17385     // to emulate native checkbox, (de-)activations from a user interaction fire | 
|  | 17386     // 'change' events | 
|  | 17387     _userActivate: function(active) { | 
|  | 17388       if (this.active !== active) { | 
|  | 17389         this.active = active; | 
|  | 17390         this.fire('change'); | 
|  | 17391       } | 
|  | 17392     }, | 
|  | 17393 | 
|  | 17394     _downHandler: function(event) { | 
|  | 17395       this._setPointerDown(true); | 
|  | 17396       this._setPressed(true); | 
|  | 17397       this._setReceivedFocusFromKeyboard(false); | 
|  | 17398     }, | 
|  | 17399 | 
|  | 17400     _upHandler: function() { | 
|  | 17401       this._setPointerDown(false); | 
|  | 17402       this._setPressed(false); | 
|  | 17403     }, | 
|  | 17404 | 
|  | 17405     /** | 
|  | 17406      * @param {!KeyboardEvent} event . | 
|  | 17407      */ | 
|  | 17408     _spaceKeyDownHandler: function(event) { | 
|  | 17409       var keyboardEvent = event.detail.keyboardEvent; | 
|  | 17410       var target = Polymer.dom(keyboardEvent).localTarget; | 
|  | 17411 | 
|  | 17412       // Ignore the event if this is coming from a focused light child, since th
       at | 
|  | 17413       // element will deal with it. | 
|  | 17414       if (this.isLightDescendant(/** @type {Node} */(target))) | 
|  | 17415         return; | 
|  | 17416 | 
|  | 17417       keyboardEvent.preventDefault(); | 
|  | 17418       keyboardEvent.stopImmediatePropagation(); | 
|  | 17419       this._setPressed(true); | 
|  | 17420     }, | 
|  | 17421 | 
|  | 17422     /** | 
|  | 17423      * @param {!KeyboardEvent} event . | 
|  | 17424      */ | 
|  | 17425     _spaceKeyUpHandler: function(event) { | 
|  | 17426       var keyboardEvent = event.detail.keyboardEvent; | 
|  | 17427       var target = Polymer.dom(keyboardEvent).localTarget; | 
|  | 17428 | 
|  | 17429       // Ignore the event if this is coming from a focused light child, since th
       at | 
|  | 17430       // element will deal with it. | 
|  | 17431       if (this.isLightDescendant(/** @type {Node} */(target))) | 
|  | 17432         return; | 
|  | 17433 | 
|  | 17434       if (this.pressed) { | 
|  | 17435         this._asyncClick(); | 
|  | 17436       } | 
|  | 17437       this._setPressed(false); | 
|  | 17438     }, | 
|  | 17439 | 
|  | 17440     // trigger click asynchronously, the asynchrony is useful to allow one | 
|  | 17441     // event handler to unwind before triggering another event | 
|  | 17442     _asyncClick: function() { | 
|  | 17443       this.async(function() { | 
|  | 17444         this.click(); | 
|  | 17445       }, 1); | 
|  | 17446     }, | 
|  | 17447 | 
|  | 17448     // any of these changes are considered a change to button state | 
|  | 17449 | 
|  | 17450     _pressedChanged: function(pressed) { | 
|  | 17451       this._changedButtonState(); | 
|  | 17452     }, | 
|  | 17453 | 
|  | 17454     _ariaActiveAttributeChanged: function(value, oldValue) { | 
|  | 17455       if (oldValue && oldValue != value && this.hasAttribute(oldValue)) { | 
|  | 17456         this.removeAttribute(oldValue); | 
|  | 17457       } | 
|  | 17458     }, | 
|  | 17459 | 
|  | 17460     _activeChanged: function(active, ariaActiveAttribute) { | 
|  | 17461       if (this.toggles) { | 
|  | 17462         this.setAttribute(this.ariaActiveAttribute, | 
|  | 17463                           active ? 'true' : 'false'); | 
|  | 17464       } else { | 
|  | 17465         this.removeAttribute(this.ariaActiveAttribute); | 
|  | 17466       } | 
|  | 17467       this._changedButtonState(); | 
|  | 17468     }, | 
|  | 17469 | 
|  | 17470     _controlStateChanged: function() { | 
|  | 17471       if (this.disabled) { | 
|  | 17472         this._setPressed(false); | 
|  | 17473       } else { | 
|  | 17474         this._changedButtonState(); | 
|  | 17475       } | 
|  | 17476     }, | 
|  | 17477 | 
|  | 17478     // provide hook for follow-on behaviors to react to button-state | 
|  | 17479 | 
|  | 17480     _changedButtonState: function() { | 
|  | 17481       if (this._buttonStateChanged) { | 
|  | 17482         this._buttonStateChanged(); // abstract | 
|  | 17483       } | 
|  | 17484     } | 
|  | 17485 | 
|  | 17486   }; | 
|  | 17487 | 
|  | 17488   /** @polymerBehavior */ | 
|  | 17489   Polymer.IronButtonState = [ | 
|  | 17490     Polymer.IronA11yKeysBehavior, | 
|  | 17491     Polymer.IronButtonStateImpl | 
|  | 17492   ]; | 
|  | 17493 | 
|  | 17494 </script> | 
|  | 17495 | 
|  | 17496 | 
|  | 17497 <dom-module id="paper-ripple" assetpath="/res/imp/bower_components/paper-ripple/
       "> | 
|  | 17498 | 
|  | 17499   <template> | 
|  | 17500     <style> | 
|  | 17501       :host { | 
|  | 17502         display: block; | 
|  | 17503         position: absolute; | 
|  | 17504         border-radius: inherit; | 
|  | 17505         overflow: hidden; | 
|  | 17506         top: 0; | 
|  | 17507         left: 0; | 
|  | 17508         right: 0; | 
|  | 17509         bottom: 0; | 
|  | 17510 | 
|  | 17511         /* See PolymerElements/paper-behaviors/issues/34. On non-Chrome browsers
       , | 
|  | 17512          * creating a node (with a position:absolute) in the middle of an event | 
|  | 17513          * handler "interrupts" that event handler (which happens when the | 
|  | 17514          * ripple is created on demand) */ | 
|  | 17515         pointer-events: none; | 
|  | 17516       } | 
|  | 17517 | 
|  | 17518       :host([animating]) { | 
|  | 17519         /* This resolves a rendering issue in Chrome (as of 40) where the | 
|  | 17520            ripple is not properly clipped by its parent (which may have | 
|  | 17521            rounded corners). See: http://jsbin.com/temexa/4 | 
|  | 17522 | 
|  | 17523            Note: We only apply this style conditionally. Otherwise, the browser | 
|  | 17524            will create a new compositing layer for every ripple element on the | 
|  | 17525            page, and that would be bad. */ | 
|  | 17526         -webkit-transform: translate(0, 0); | 
|  | 17527         transform: translate3d(0, 0, 0); | 
|  | 17528       } | 
|  | 17529 | 
|  | 17530       #background, | 
|  | 17531       #waves, | 
|  | 17532       .wave-container, | 
|  | 17533       .wave { | 
|  | 17534         pointer-events: none; | 
|  | 17535         position: absolute; | 
|  | 17536         top: 0; | 
|  | 17537         left: 0; | 
|  | 17538         width: 100%; | 
|  | 17539         height: 100%; | 
|  | 17540       } | 
|  | 17541 | 
|  | 17542       #background, | 
|  | 17543       .wave { | 
|  | 17544         opacity: 0; | 
|  | 17545       } | 
|  | 17546 | 
|  | 17547       #waves, | 
|  | 17548       .wave { | 
|  | 17549         overflow: hidden; | 
|  | 17550       } | 
|  | 17551 | 
|  | 17552       .wave-container, | 
|  | 17553       .wave { | 
|  | 17554         border-radius: 50%; | 
|  | 17555       } | 
|  | 17556 | 
|  | 17557       :host(.circle) #background, | 
|  | 17558       :host(.circle) #waves { | 
|  | 17559         border-radius: 50%; | 
|  | 17560       } | 
|  | 17561 | 
|  | 17562       :host(.circle) .wave-container { | 
|  | 17563         overflow: hidden; | 
|  | 17564       } | 
|  | 17565     </style> | 
|  | 17566 | 
|  | 17567     <div id="background"></div> | 
|  | 17568     <div id="waves"></div> | 
|  | 17569   </template> | 
|  | 17570 </dom-module> | 
|  | 17571 <script> | 
|  | 17572   (function() { | 
|  | 17573     var Utility = { | 
|  | 17574       distance: function(x1, y1, x2, y2) { | 
|  | 17575         var xDelta = (x1 - x2); | 
|  | 17576         var yDelta = (y1 - y2); | 
|  | 17577 | 
|  | 17578         return Math.sqrt(xDelta * xDelta + yDelta * yDelta); | 
|  | 17579       }, | 
|  | 17580 | 
|  | 17581       now: window.performance && window.performance.now ? | 
|  | 17582           window.performance.now.bind(window.performance) : Date.now | 
|  | 17583     }; | 
|  | 17584 | 
|  | 17585     /** | 
|  | 17586      * @param {HTMLElement} element | 
|  | 17587      * @constructor | 
|  | 17588      */ | 
|  | 17589     function ElementMetrics(element) { | 
|  | 17590       this.element = element; | 
|  | 17591       this.width = this.boundingRect.width; | 
|  | 17592       this.height = this.boundingRect.height; | 
|  | 17593 | 
|  | 17594       this.size = Math.max(this.width, this.height); | 
|  | 17595     } | 
|  | 17596 | 
|  | 17597     ElementMetrics.prototype = { | 
|  | 17598       get boundingRect () { | 
|  | 17599         return this.element.getBoundingClientRect(); | 
|  | 17600       }, | 
|  | 17601 | 
|  | 17602       furthestCornerDistanceFrom: function(x, y) { | 
|  | 17603         var topLeft = Utility.distance(x, y, 0, 0); | 
|  | 17604         var topRight = Utility.distance(x, y, this.width, 0); | 
|  | 17605         var bottomLeft = Utility.distance(x, y, 0, this.height); | 
|  | 17606         var bottomRight = Utility.distance(x, y, this.width, this.height); | 
|  | 17607 | 
|  | 17608         return Math.max(topLeft, topRight, bottomLeft, bottomRight); | 
|  | 17609       } | 
|  | 17610     }; | 
|  | 17611 | 
|  | 17612     /** | 
|  | 17613      * @param {HTMLElement} element | 
|  | 17614      * @constructor | 
|  | 17615      */ | 
|  | 17616     function Ripple(element) { | 
|  | 17617       this.element = element; | 
|  | 17618       this.color = window.getComputedStyle(element).color; | 
|  | 17619 | 
|  | 17620       this.wave = document.createElement('div'); | 
|  | 17621       this.waveContainer = document.createElement('div'); | 
|  | 17622       this.wave.style.backgroundColor = this.color; | 
|  | 17623       this.wave.classList.add('wave'); | 
|  | 17624       this.waveContainer.classList.add('wave-container'); | 
|  | 17625       Polymer.dom(this.waveContainer).appendChild(this.wave); | 
|  | 17626 | 
|  | 17627       this.resetInteractionState(); | 
|  | 17628     } | 
|  | 17629 | 
|  | 17630     Ripple.MAX_RADIUS = 300; | 
|  | 17631 | 
|  | 17632     Ripple.prototype = { | 
|  | 17633       get recenters() { | 
|  | 17634         return this.element.recenters; | 
|  | 17635       }, | 
|  | 17636 | 
|  | 17637       get center() { | 
|  | 17638         return this.element.center; | 
|  | 17639       }, | 
|  | 17640 | 
|  | 17641       get mouseDownElapsed() { | 
|  | 17642         var elapsed; | 
|  | 17643 | 
|  | 17644         if (!this.mouseDownStart) { | 
|  | 17645           return 0; | 
|  | 17646         } | 
|  | 17647 | 
|  | 17648         elapsed = Utility.now() - this.mouseDownStart; | 
|  | 17649 | 
|  | 17650         if (this.mouseUpStart) { | 
|  | 17651           elapsed -= this.mouseUpElapsed; | 
|  | 17652         } | 
|  | 17653 | 
|  | 17654         return elapsed; | 
|  | 17655       }, | 
|  | 17656 | 
|  | 17657       get mouseUpElapsed() { | 
|  | 17658         return this.mouseUpStart ? | 
|  | 17659           Utility.now () - this.mouseUpStart : 0; | 
|  | 17660       }, | 
|  | 17661 | 
|  | 17662       get mouseDownElapsedSeconds() { | 
|  | 17663         return this.mouseDownElapsed / 1000; | 
|  | 17664       }, | 
|  | 17665 | 
|  | 17666       get mouseUpElapsedSeconds() { | 
|  | 17667         return this.mouseUpElapsed / 1000; | 
|  | 17668       }, | 
|  | 17669 | 
|  | 17670       get mouseInteractionSeconds() { | 
|  | 17671         return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds; | 
|  | 17672       }, | 
|  | 17673 | 
|  | 17674       get initialOpacity() { | 
|  | 17675         return this.element.initialOpacity; | 
|  | 17676       }, | 
|  | 17677 | 
|  | 17678       get opacityDecayVelocity() { | 
|  | 17679         return this.element.opacityDecayVelocity; | 
|  | 17680       }, | 
|  | 17681 | 
|  | 17682       get radius() { | 
|  | 17683         var width2 = this.containerMetrics.width * this.containerMetrics.width; | 
|  | 17684         var height2 = this.containerMetrics.height * this.containerMetrics.heigh
       t; | 
|  | 17685         var waveRadius = Math.min( | 
|  | 17686           Math.sqrt(width2 + height2), | 
|  | 17687           Ripple.MAX_RADIUS | 
|  | 17688         ) * 1.1 + 5; | 
|  | 17689 | 
|  | 17690         var duration = 1.1 - 0.2 * (waveRadius / Ripple.MAX_RADIUS); | 
|  | 17691         var timeNow = this.mouseInteractionSeconds / duration; | 
|  | 17692         var size = waveRadius * (1 - Math.pow(80, -timeNow)); | 
|  | 17693 | 
|  | 17694         return Math.abs(size); | 
|  | 17695       }, | 
|  | 17696 | 
|  | 17697       get opacity() { | 
|  | 17698         if (!this.mouseUpStart) { | 
|  | 17699           return this.initialOpacity; | 
|  | 17700         } | 
|  | 17701 | 
|  | 17702         return Math.max( | 
|  | 17703           0, | 
|  | 17704           this.initialOpacity - this.mouseUpElapsedSeconds * this.opacityDecayVe
       locity | 
|  | 17705         ); | 
|  | 17706       }, | 
|  | 17707 | 
|  | 17708       get outerOpacity() { | 
|  | 17709         // Linear increase in background opacity, capped at the opacity | 
|  | 17710         // of the wavefront (waveOpacity). | 
|  | 17711         var outerOpacity = this.mouseUpElapsedSeconds * 0.3; | 
|  | 17712         var waveOpacity = this.opacity; | 
|  | 17713 | 
|  | 17714         return Math.max( | 
|  | 17715           0, | 
|  | 17716           Math.min(outerOpacity, waveOpacity) | 
|  | 17717         ); | 
|  | 17718       }, | 
|  | 17719 | 
|  | 17720       get isOpacityFullyDecayed() { | 
|  | 17721         return this.opacity < 0.01 && | 
|  | 17722           this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); | 
|  | 17723       }, | 
|  | 17724 | 
|  | 17725       get isRestingAtMaxRadius() { | 
|  | 17726         return this.opacity >= this.initialOpacity && | 
|  | 17727           this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); | 
|  | 17728       }, | 
|  | 17729 | 
|  | 17730       get isAnimationComplete() { | 
|  | 17731         return this.mouseUpStart ? | 
|  | 17732           this.isOpacityFullyDecayed : this.isRestingAtMaxRadius; | 
|  | 17733       }, | 
|  | 17734 | 
|  | 17735       get translationFraction() { | 
|  | 17736         return Math.min( | 
|  | 17737           1, | 
|  | 17738           this.radius / this.containerMetrics.size * 2 / Math.sqrt(2) | 
|  | 17739         ); | 
|  | 17740       }, | 
|  | 17741 | 
|  | 17742       get xNow() { | 
|  | 17743         if (this.xEnd) { | 
|  | 17744           return this.xStart + this.translationFraction * (this.xEnd - this.xSta
       rt); | 
|  | 17745         } | 
|  | 17746 | 
|  | 17747         return this.xStart; | 
|  | 17748       }, | 
|  | 17749 | 
|  | 17750       get yNow() { | 
|  | 17751         if (this.yEnd) { | 
|  | 17752           return this.yStart + this.translationFraction * (this.yEnd - this.ySta
       rt); | 
|  | 17753         } | 
|  | 17754 | 
|  | 17755         return this.yStart; | 
|  | 17756       }, | 
|  | 17757 | 
|  | 17758       get isMouseDown() { | 
|  | 17759         return this.mouseDownStart && !this.mouseUpStart; | 
|  | 17760       }, | 
|  | 17761 | 
|  | 17762       resetInteractionState: function() { | 
|  | 17763         this.maxRadius = 0; | 
|  | 17764         this.mouseDownStart = 0; | 
|  | 17765         this.mouseUpStart = 0; | 
|  | 17766 | 
|  | 17767         this.xStart = 0; | 
|  | 17768         this.yStart = 0; | 
|  | 17769         this.xEnd = 0; | 
|  | 17770         this.yEnd = 0; | 
|  | 17771         this.slideDistance = 0; | 
|  | 17772 | 
|  | 17773         this.containerMetrics = new ElementMetrics(this.element); | 
|  | 17774       }, | 
|  | 17775 | 
|  | 17776       draw: function() { | 
|  | 17777         var scale; | 
|  | 17778         var translateString; | 
|  | 17779         var dx; | 
|  | 17780         var dy; | 
|  | 17781 | 
|  | 17782         this.wave.style.opacity = this.opacity; | 
|  | 17783 | 
|  | 17784         scale = this.radius / (this.containerMetrics.size / 2); | 
|  | 17785         dx = this.xNow - (this.containerMetrics.width / 2); | 
|  | 17786         dy = this.yNow - (this.containerMetrics.height / 2); | 
|  | 17787 | 
|  | 17788 | 
|  | 17789         // 2d transform for safari because of border-radius and overflow:hidden 
       clipping bug. | 
|  | 17790         // https://bugs.webkit.org/show_bug.cgi?id=98538 | 
|  | 17791         this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' + 
       dy + 'px)'; | 
|  | 17792         this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy +
        'px, 0)'; | 
|  | 17793         this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')'; | 
|  | 17794         this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)'; | 
|  | 17795       }, | 
|  | 17796 | 
|  | 17797       /** @param {Event=} event */ | 
|  | 17798       downAction: function(event) { | 
|  | 17799         var xCenter = this.containerMetrics.width / 2; | 
|  | 17800         var yCenter = this.containerMetrics.height / 2; | 
|  | 17801 | 
|  | 17802         this.resetInteractionState(); | 
|  | 17803         this.mouseDownStart = Utility.now(); | 
|  | 17804 | 
|  | 17805         if (this.center) { | 
|  | 17806           this.xStart = xCenter; | 
|  | 17807           this.yStart = yCenter; | 
|  | 17808           this.slideDistance = Utility.distance( | 
|  | 17809             this.xStart, this.yStart, this.xEnd, this.yEnd | 
|  | 17810           ); | 
|  | 17811         } else { | 
|  | 17812           this.xStart = event ? | 
|  | 17813               event.detail.x - this.containerMetrics.boundingRect.left : | 
|  | 17814               this.containerMetrics.width / 2; | 
|  | 17815           this.yStart = event ? | 
|  | 17816               event.detail.y - this.containerMetrics.boundingRect.top : | 
|  | 17817               this.containerMetrics.height / 2; | 
|  | 17818         } | 
|  | 17819 | 
|  | 17820         if (this.recenters) { | 
|  | 17821           this.xEnd = xCenter; | 
|  | 17822           this.yEnd = yCenter; | 
|  | 17823           this.slideDistance = Utility.distance( | 
|  | 17824             this.xStart, this.yStart, this.xEnd, this.yEnd | 
|  | 17825           ); | 
|  | 17826         } | 
|  | 17827 | 
|  | 17828         this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom( | 
|  | 17829           this.xStart, | 
|  | 17830           this.yStart | 
|  | 17831         ); | 
|  | 17832 | 
|  | 17833         this.waveContainer.style.top = | 
|  | 17834           (this.containerMetrics.height - this.containerMetrics.size) / 2 + 'px'
       ; | 
|  | 17835         this.waveContainer.style.left = | 
|  | 17836           (this.containerMetrics.width - this.containerMetrics.size) / 2 + 'px'; | 
|  | 17837 | 
|  | 17838         this.waveContainer.style.width = this.containerMetrics.size + 'px'; | 
|  | 17839         this.waveContainer.style.height = this.containerMetrics.size + 'px'; | 
|  | 17840       }, | 
|  | 17841 | 
|  | 17842       /** @param {Event=} event */ | 
|  | 17843       upAction: function(event) { | 
|  | 17844         if (!this.isMouseDown) { | 
|  | 17845           return; | 
|  | 17846         } | 
|  | 17847 | 
|  | 17848         this.mouseUpStart = Utility.now(); | 
|  | 17849       }, | 
|  | 17850 | 
|  | 17851       remove: function() { | 
|  | 17852         Polymer.dom(this.waveContainer.parentNode).removeChild( | 
|  | 17853           this.waveContainer | 
|  | 17854         ); | 
|  | 17855       } | 
|  | 17856     }; | 
|  | 17857 | 
|  | 17858     Polymer({ | 
|  | 17859       is: 'paper-ripple', | 
|  | 17860 | 
|  | 17861       behaviors: [ | 
|  | 17862         Polymer.IronA11yKeysBehavior | 
|  | 17863       ], | 
|  | 17864 | 
|  | 17865       properties: { | 
|  | 17866         /** | 
|  | 17867          * The initial opacity set on the wave. | 
|  | 17868          * | 
|  | 17869          * @attribute initialOpacity | 
|  | 17870          * @type number | 
|  | 17871          * @default 0.25 | 
|  | 17872          */ | 
|  | 17873         initialOpacity: { | 
|  | 17874           type: Number, | 
|  | 17875           value: 0.25 | 
|  | 17876         }, | 
|  | 17877 | 
|  | 17878         /** | 
|  | 17879          * How fast (opacity per second) the wave fades out. | 
|  | 17880          * | 
|  | 17881          * @attribute opacityDecayVelocity | 
|  | 17882          * @type number | 
|  | 17883          * @default 0.8 | 
|  | 17884          */ | 
|  | 17885         opacityDecayVelocity: { | 
|  | 17886           type: Number, | 
|  | 17887           value: 0.8 | 
|  | 17888         }, | 
|  | 17889 | 
|  | 17890         /** | 
|  | 17891          * If true, ripples will exhibit a gravitational pull towards | 
|  | 17892          * the center of their container as they fade away. | 
|  | 17893          * | 
|  | 17894          * @attribute recenters | 
|  | 17895          * @type boolean | 
|  | 17896          * @default false | 
|  | 17897          */ | 
|  | 17898         recenters: { | 
|  | 17899           type: Boolean, | 
|  | 17900           value: false | 
|  | 17901         }, | 
|  | 17902 | 
|  | 17903         /** | 
|  | 17904          * If true, ripples will center inside its container | 
|  | 17905          * | 
|  | 17906          * @attribute recenters | 
|  | 17907          * @type boolean | 
|  | 17908          * @default false | 
|  | 17909          */ | 
|  | 17910         center: { | 
|  | 17911           type: Boolean, | 
|  | 17912           value: false | 
|  | 17913         }, | 
|  | 17914 | 
|  | 17915         /** | 
|  | 17916          * A list of the visual ripples. | 
|  | 17917          * | 
|  | 17918          * @attribute ripples | 
|  | 17919          * @type Array | 
|  | 17920          * @default [] | 
|  | 17921          */ | 
|  | 17922         ripples: { | 
|  | 17923           type: Array, | 
|  | 17924           value: function() { | 
|  | 17925             return []; | 
|  | 17926           } | 
|  | 17927         }, | 
|  | 17928 | 
|  | 17929         /** | 
|  | 17930          * True when there are visible ripples animating within the | 
|  | 17931          * element. | 
|  | 17932          */ | 
|  | 17933         animating: { | 
|  | 17934           type: Boolean, | 
|  | 17935           readOnly: true, | 
|  | 17936           reflectToAttribute: true, | 
|  | 17937           value: false | 
|  | 17938         }, | 
|  | 17939 | 
|  | 17940         /** | 
|  | 17941          * If true, the ripple will remain in the "down" state until `holdDown` | 
|  | 17942          * is set to false again. | 
|  | 17943          */ | 
|  | 17944         holdDown: { | 
|  | 17945           type: Boolean, | 
|  | 17946           value: false, | 
|  | 17947           observer: '_holdDownChanged' | 
|  | 17948         }, | 
|  | 17949 | 
|  | 17950         /** | 
|  | 17951          * If true, the ripple will not generate a ripple effect | 
|  | 17952          * via pointer interaction. | 
|  | 17953          * Calling ripple's imperative api like `simulatedRipple` will | 
|  | 17954          * still generate the ripple effect. | 
|  | 17955          */ | 
|  | 17956         noink: { | 
|  | 17957           type: Boolean, | 
|  | 17958           value: false | 
|  | 17959         }, | 
|  | 17960 | 
|  | 17961         _animating: { | 
|  | 17962           type: Boolean | 
|  | 17963         }, | 
|  | 17964 | 
|  | 17965         _boundAnimate: { | 
|  | 17966           type: Function, | 
|  | 17967           value: function() { | 
|  | 17968             return this.animate.bind(this); | 
|  | 17969           } | 
|  | 17970         } | 
|  | 17971       }, | 
|  | 17972 | 
|  | 17973       get target () { | 
|  | 17974         return this.keyEventTarget; | 
|  | 17975       }, | 
|  | 17976 | 
|  | 17977       keyBindings: { | 
|  | 17978         'enter:keydown': '_onEnterKeydown', | 
|  | 17979         'space:keydown': '_onSpaceKeydown', | 
|  | 17980         'space:keyup': '_onSpaceKeyup' | 
|  | 17981       }, | 
|  | 17982 | 
|  | 17983       attached: function() { | 
|  | 17984         // Set up a11yKeysBehavior to listen to key events on the target, | 
|  | 17985         // so that space and enter activate the ripple even if the target doesn'
       t | 
|  | 17986         // handle key events. The key handlers deal with `noink` themselves. | 
|  | 17987         if (this.parentNode.nodeType == 11) { // DOCUMENT_FRAGMENT_NODE | 
|  | 17988           this.keyEventTarget = Polymer.dom(this).getOwnerRoot().host; | 
|  | 17989         } else { | 
|  | 17990           this.keyEventTarget = this.parentNode; | 
|  | 17991         } | 
|  | 17992         var keyEventTarget = /** @type {!EventTarget} */ (this.keyEventTarget); | 
|  | 17993         this.listen(keyEventTarget, 'up', 'uiUpAction'); | 
|  | 17994         this.listen(keyEventTarget, 'down', 'uiDownAction'); | 
|  | 17995       }, | 
|  | 17996 | 
|  | 17997       detached: function() { | 
|  | 17998         this.unlisten(this.keyEventTarget, 'up', 'uiUpAction'); | 
|  | 17999         this.unlisten(this.keyEventTarget, 'down', 'uiDownAction'); | 
|  | 18000         this.keyEventTarget = null; | 
|  | 18001       }, | 
|  | 18002 | 
|  | 18003       get shouldKeepAnimating () { | 
|  | 18004         for (var index = 0; index < this.ripples.length; ++index) { | 
|  | 18005           if (!this.ripples[index].isAnimationComplete) { | 
|  | 18006             return true; | 
|  | 18007           } | 
|  | 18008         } | 
|  | 18009 | 
|  | 18010         return false; | 
|  | 18011       }, | 
|  | 18012 | 
|  | 18013       simulatedRipple: function() { | 
|  | 18014         this.downAction(null); | 
|  | 18015 | 
|  | 18016         // Please see polymer/polymer#1305 | 
|  | 18017         this.async(function() { | 
|  | 18018           this.upAction(); | 
|  | 18019         }, 1); | 
|  | 18020       }, | 
|  | 18021 | 
|  | 18022       /** | 
|  | 18023        * Provokes a ripple down effect via a UI event, | 
|  | 18024        * respecting the `noink` property. | 
|  | 18025        * @param {Event=} event | 
|  | 18026        */ | 
|  | 18027       uiDownAction: function(event) { | 
|  | 18028         if (!this.noink) { | 
|  | 18029           this.downAction(event); | 
|  | 18030         } | 
|  | 18031       }, | 
|  | 18032 | 
|  | 18033       /** | 
|  | 18034        * Provokes a ripple down effect via a UI event, | 
|  | 18035        * *not* respecting the `noink` property. | 
|  | 18036        * @param {Event=} event | 
|  | 18037        */ | 
|  | 18038       downAction: function(event) { | 
|  | 18039         if (this.holdDown && this.ripples.length > 0) { | 
|  | 18040           return; | 
|  | 18041         } | 
|  | 18042 | 
|  | 18043         var ripple = this.addRipple(); | 
|  | 18044 | 
|  | 18045         ripple.downAction(event); | 
|  | 18046 | 
|  | 18047         if (!this._animating) { | 
|  | 18048           this._animating = true; | 
|  | 18049           this.animate(); | 
|  | 18050         } | 
|  | 18051       }, | 
|  | 18052 | 
|  | 18053       /** | 
|  | 18054        * Provokes a ripple up effect via a UI event, | 
|  | 18055        * respecting the `noink` property. | 
|  | 18056        * @param {Event=} event | 
|  | 18057        */ | 
|  | 18058       uiUpAction: function(event) { | 
|  | 18059         if (!this.noink) { | 
|  | 18060           this.upAction(event); | 
|  | 18061         } | 
|  | 18062       }, | 
|  | 18063 | 
|  | 18064       /** | 
|  | 18065        * Provokes a ripple up effect via a UI event, | 
|  | 18066        * *not* respecting the `noink` property. | 
|  | 18067        * @param {Event=} event | 
|  | 18068        */ | 
|  | 18069       upAction: function(event) { | 
|  | 18070         if (this.holdDown) { | 
|  | 18071           return; | 
|  | 18072         } | 
|  | 18073 | 
|  | 18074         this.ripples.forEach(function(ripple) { | 
|  | 18075           ripple.upAction(event); | 
|  | 18076         }); | 
|  | 18077 | 
|  | 18078         this._animating = true; | 
|  | 18079         this.animate(); | 
|  | 18080       }, | 
|  | 18081 | 
|  | 18082       onAnimationComplete: function() { | 
|  | 18083         this._animating = false; | 
|  | 18084         this.$.background.style.backgroundColor = null; | 
|  | 18085         this.fire('transitionend'); | 
|  | 18086       }, | 
|  | 18087 | 
|  | 18088       addRipple: function() { | 
|  | 18089         var ripple = new Ripple(this); | 
|  | 18090 | 
|  | 18091         Polymer.dom(this.$.waves).appendChild(ripple.waveContainer); | 
|  | 18092         this.$.background.style.backgroundColor = ripple.color; | 
|  | 18093         this.ripples.push(ripple); | 
|  | 18094 | 
|  | 18095         this._setAnimating(true); | 
|  | 18096 | 
|  | 18097         return ripple; | 
|  | 18098       }, | 
|  | 18099 | 
|  | 18100       removeRipple: function(ripple) { | 
|  | 18101         var rippleIndex = this.ripples.indexOf(ripple); | 
|  | 18102 | 
|  | 18103         if (rippleIndex < 0) { | 
|  | 18104           return; | 
|  | 18105         } | 
|  | 18106 | 
|  | 18107         this.ripples.splice(rippleIndex, 1); | 
|  | 18108 | 
|  | 18109         ripple.remove(); | 
|  | 18110 | 
|  | 18111         if (!this.ripples.length) { | 
|  | 18112           this._setAnimating(false); | 
|  | 18113         } | 
|  | 18114       }, | 
|  | 18115 | 
|  | 18116       animate: function() { | 
|  | 18117         if (!this._animating) { | 
|  | 18118           return; | 
|  | 18119         } | 
|  | 18120         var index; | 
|  | 18121         var ripple; | 
|  | 18122 | 
|  | 18123         for (index = 0; index < this.ripples.length; ++index) { | 
|  | 18124           ripple = this.ripples[index]; | 
|  | 18125 | 
|  | 18126           ripple.draw(); | 
|  | 18127 | 
|  | 18128           this.$.background.style.opacity = ripple.outerOpacity; | 
|  | 18129 | 
|  | 18130           if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) { | 
|  | 18131             this.removeRipple(ripple); | 
|  | 18132           } | 
|  | 18133         } | 
|  | 18134 | 
|  | 18135         if (!this.shouldKeepAnimating && this.ripples.length === 0) { | 
|  | 18136           this.onAnimationComplete(); | 
|  | 18137         } else { | 
|  | 18138           window.requestAnimationFrame(this._boundAnimate); | 
|  | 18139         } | 
|  | 18140       }, | 
|  | 18141 | 
|  | 18142       _onEnterKeydown: function() { | 
|  | 18143         this.uiDownAction(); | 
|  | 18144         this.async(this.uiUpAction, 1); | 
|  | 18145       }, | 
|  | 18146 | 
|  | 18147       _onSpaceKeydown: function() { | 
|  | 18148         this.uiDownAction(); | 
|  | 18149       }, | 
|  | 18150 | 
|  | 18151       _onSpaceKeyup: function() { | 
|  | 18152         this.uiUpAction(); | 
|  | 18153       }, | 
|  | 18154 | 
|  | 18155       // note: holdDown does not respect noink since it can be a focus based | 
|  | 18156       // effect. | 
|  | 18157       _holdDownChanged: function(newVal, oldVal) { | 
|  | 18158         if (oldVal === undefined) { | 
|  | 18159           return; | 
|  | 18160         } | 
|  | 18161         if (newVal) { | 
|  | 18162           this.downAction(); | 
|  | 18163         } else { | 
|  | 18164           this.upAction(); | 
|  | 18165         } | 
|  | 18166       } | 
|  | 18167 | 
|  | 18168       /** | 
|  | 18169       Fired when the animation finishes. | 
|  | 18170       This is useful if you want to wait until | 
|  | 18171       the ripple animation finishes to perform some action. | 
|  | 18172 | 
|  | 18173       @event transitionend | 
|  | 18174       @param {{node: Object}} detail Contains the animated node. | 
|  | 18175       */ | 
|  | 18176     }); | 
|  | 18177   })(); | 
|  | 18178 </script> | 
|  | 18179 <script> | 
|  | 18180   /** | 
|  | 18181    * `Polymer.PaperRippleBehavior` dynamically implements a ripple | 
|  | 18182    * when the element has focus via pointer or keyboard. | 
|  | 18183    * | 
|  | 18184    * NOTE: This behavior is intended to be used in conjunction with and after | 
|  | 18185    * `Polymer.IronButtonState` and `Polymer.IronControlState`. | 
|  | 18186    * | 
|  | 18187    * @polymerBehavior Polymer.PaperRippleBehavior | 
|  | 18188    */ | 
|  | 18189   Polymer.PaperRippleBehavior = { | 
|  | 18190     properties: { | 
|  | 18191       /** | 
|  | 18192        * If true, the element will not produce a ripple effect when interacted | 
|  | 18193        * with via the pointer. | 
|  | 18194        */ | 
|  | 18195       noink: { | 
|  | 18196         type: Boolean, | 
|  | 18197         observer: '_noinkChanged' | 
|  | 18198       }, | 
|  | 18199 | 
|  | 18200       /** | 
|  | 18201        * @type {Element|undefined} | 
|  | 18202        */ | 
|  | 18203       _rippleContainer: { | 
|  | 18204         type: Object, | 
|  | 18205       } | 
|  | 18206     }, | 
|  | 18207 | 
|  | 18208     /** | 
|  | 18209      * Ensures a `<paper-ripple>` element is available when the element is | 
|  | 18210      * focused. | 
|  | 18211      */ | 
|  | 18212     _buttonStateChanged: function() { | 
|  | 18213       if (this.focused) { | 
|  | 18214         this.ensureRipple(); | 
|  | 18215       } | 
|  | 18216     }, | 
|  | 18217 | 
|  | 18218     /** | 
|  | 18219      * In addition to the functionality provided in `IronButtonState`, ensures | 
|  | 18220      * a ripple effect is created when the element is in a `pressed` state. | 
|  | 18221      */ | 
|  | 18222     _downHandler: function(event) { | 
|  | 18223       Polymer.IronButtonStateImpl._downHandler.call(this, event); | 
|  | 18224       if (this.pressed) { | 
|  | 18225         this.ensureRipple(event); | 
|  | 18226       } | 
|  | 18227     }, | 
|  | 18228 | 
|  | 18229     /** | 
|  | 18230      * Ensures this element contains a ripple effect. For startup efficiency | 
|  | 18231      * the ripple effect is dynamically on demand when needed. | 
|  | 18232      * @param {!Event=} optTriggeringEvent (optional) event that triggered the | 
|  | 18233      * ripple. | 
|  | 18234      */ | 
|  | 18235     ensureRipple: function(optTriggeringEvent) { | 
|  | 18236       if (!this.hasRipple()) { | 
|  | 18237         this._ripple = this._createRipple(); | 
|  | 18238         this._ripple.noink = this.noink; | 
|  | 18239         var rippleContainer = this._rippleContainer || this.root; | 
|  | 18240         if (rippleContainer) { | 
|  | 18241           Polymer.dom(rippleContainer).appendChild(this._ripple); | 
|  | 18242         } | 
|  | 18243         if (optTriggeringEvent) { | 
|  | 18244           // Check if the event happened inside of the ripple container | 
|  | 18245           // Fall back to host instead of the root because distributed text | 
|  | 18246           // nodes are not valid event targets | 
|  | 18247           var domContainer = Polymer.dom(this._rippleContainer || this); | 
|  | 18248           var target = Polymer.dom(optTriggeringEvent).rootTarget; | 
|  | 18249           if (domContainer.deepContains( /** @type {Node} */(target))) { | 
|  | 18250             this._ripple.uiDownAction(optTriggeringEvent); | 
|  | 18251           } | 
|  | 18252         } | 
|  | 18253       } | 
|  | 18254     }, | 
|  | 18255 | 
|  | 18256     /** | 
|  | 18257      * Returns the `<paper-ripple>` element used by this element to create | 
|  | 18258      * ripple effects. The element's ripple is created on demand, when | 
|  | 18259      * necessary, and calling this method will force the | 
|  | 18260      * ripple to be created. | 
|  | 18261      */ | 
|  | 18262     getRipple: function() { | 
|  | 18263       this.ensureRipple(); | 
|  | 18264       return this._ripple; | 
|  | 18265     }, | 
|  | 18266 | 
|  | 18267     /** | 
|  | 18268      * Returns true if this element currently contains a ripple effect. | 
|  | 18269      * @return {boolean} | 
|  | 18270      */ | 
|  | 18271     hasRipple: function() { | 
|  | 18272       return Boolean(this._ripple); | 
|  | 18273     }, | 
|  | 18274 | 
|  | 18275     /** | 
|  | 18276      * Create the element's ripple effect via creating a `<paper-ripple>`. | 
|  | 18277      * Override this method to customize the ripple element. | 
|  | 18278      * @return {!PaperRippleElement} Returns a `<paper-ripple>` element. | 
|  | 18279      */ | 
|  | 18280     _createRipple: function() { | 
|  | 18281       return /** @type {!PaperRippleElement} */ ( | 
|  | 18282           document.createElement('paper-ripple')); | 
|  | 18283     }, | 
|  | 18284 | 
|  | 18285     _noinkChanged: function(noink) { | 
|  | 18286       if (this.hasRipple()) { | 
|  | 18287         this._ripple.noink = noink; | 
|  | 18288       } | 
|  | 18289     } | 
|  | 18290   }; | 
|  | 18291 </script> | 
|  | 18292 <script> | 
|  | 18293   /** | 
|  | 18294    * `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has k
       eyboard focus. | 
|  | 18295    * | 
|  | 18296    * @polymerBehavior Polymer.PaperInkyFocusBehavior | 
|  | 18297    */ | 
|  | 18298   Polymer.PaperInkyFocusBehaviorImpl = { | 
|  | 18299     observers: [ | 
|  | 18300       '_focusedChanged(receivedFocusFromKeyboard)' | 
|  | 18301     ], | 
|  | 18302 | 
|  | 18303     _focusedChanged: function(receivedFocusFromKeyboard) { | 
|  | 18304       if (receivedFocusFromKeyboard) { | 
|  | 18305         this.ensureRipple(); | 
|  | 18306       } | 
|  | 18307       if (this.hasRipple()) { | 
|  | 18308         this._ripple.holdDown = receivedFocusFromKeyboard; | 
|  | 18309       } | 
|  | 18310     }, | 
|  | 18311 | 
|  | 18312     _createRipple: function() { | 
|  | 18313       var ripple = Polymer.PaperRippleBehavior._createRipple(); | 
|  | 18314       ripple.id = 'ink'; | 
|  | 18315       ripple.setAttribute('center', ''); | 
|  | 18316       ripple.classList.add('circle'); | 
|  | 18317       return ripple; | 
|  | 18318     } | 
|  | 18319   }; | 
|  | 18320 | 
|  | 18321   /** @polymerBehavior Polymer.PaperInkyFocusBehavior */ | 
|  | 18322   Polymer.PaperInkyFocusBehavior = [ | 
|  | 18323     Polymer.IronButtonState, | 
|  | 18324     Polymer.IronControlState, | 
|  | 18325     Polymer.PaperRippleBehavior, | 
|  | 18326     Polymer.PaperInkyFocusBehaviorImpl | 
|  | 18327   ]; | 
|  | 18328 </script> | 
|  | 18329 <script> | 
|  | 18330   /** | 
|  | 18331    * Use `Polymer.PaperCheckedElementBehavior` to implement a custom element | 
|  | 18332    * that has a `checked` property similar to `Polymer.IronCheckedElementBehavio
       r` | 
|  | 18333    * and is compatible with having a ripple effect. | 
|  | 18334    * @polymerBehavior Polymer.PaperCheckedElementBehavior | 
|  | 18335    */ | 
|  | 18336   Polymer.PaperCheckedElementBehaviorImpl = { | 
|  | 18337     /** | 
|  | 18338      * Synchronizes the element's checked state with its ripple effect. | 
|  | 18339      */ | 
|  | 18340     _checkedChanged: function() { | 
|  | 18341       Polymer.IronCheckedElementBehaviorImpl._checkedChanged.call(this); | 
|  | 18342       if (this.hasRipple()) { | 
|  | 18343         if (this.checked) { | 
|  | 18344           this._ripple.setAttribute('checked', ''); | 
|  | 18345         } else { | 
|  | 18346           this._ripple.removeAttribute('checked'); | 
|  | 18347         } | 
|  | 18348       } | 
|  | 18349     }, | 
|  | 18350 | 
|  | 18351     /** | 
|  | 18352      * Synchronizes the element's `active` and `checked` state. | 
|  | 18353      */ | 
|  | 18354     _buttonStateChanged: function() { | 
|  | 18355       Polymer.PaperRippleBehavior._buttonStateChanged.call(this); | 
|  | 18356       if (this.disabled) { | 
|  | 18357         return; | 
|  | 18358       } | 
|  | 18359       if (this.isAttached) { | 
|  | 18360         this.checked = this.active; | 
|  | 18361       } | 
|  | 18362     } | 
|  | 18363   }; | 
|  | 18364 | 
|  | 18365   /** @polymerBehavior Polymer.PaperCheckedElementBehavior */ | 
|  | 18366   Polymer.PaperCheckedElementBehavior = [ | 
|  | 18367     Polymer.PaperInkyFocusBehavior, | 
|  | 18368     Polymer.IronCheckedElementBehavior, | 
|  | 18369     Polymer.PaperCheckedElementBehaviorImpl | 
|  | 18370   ]; | 
|  | 18371 </script> | 
|  | 18372 | 
|  | 18373 | 
|  | 18374 <dom-module id="paper-checkbox" assetpath="/res/imp/bower_components/paper-check
       box/"> | 
|  | 18375   <template strip-whitespace=""> | 
|  | 18376     <style> | 
|  | 18377       :host { | 
|  | 18378         display: inline-block; | 
|  | 18379         white-space: nowrap; | 
|  | 18380         cursor: pointer; | 
|  | 18381         --calculated-paper-checkbox-size: var(--paper-checkbox-size, 18px); | 
|  | 18382         @apply(--paper-font-common-base); | 
|  | 18383         line-height: 0; | 
|  | 18384         -webkit-tap-highlight-color: transparent; | 
|  | 18385       } | 
|  | 18386 | 
|  | 18387       :host([hidden]) { | 
|  | 18388         display: none !important; | 
|  | 18389       } | 
|  | 18390 | 
|  | 18391       :host(:focus) { | 
|  | 18392         outline: none; | 
|  | 18393       } | 
|  | 18394 | 
|  | 18395       .hidden { | 
|  | 18396         display: none; | 
|  | 18397       } | 
|  | 18398 | 
|  | 18399       #checkboxContainer { | 
|  | 18400         display: inline-block; | 
|  | 18401         position: relative; | 
|  | 18402         width: var(--calculated-paper-checkbox-size); | 
|  | 18403         height: var(--calculated-paper-checkbox-size); | 
|  | 18404         min-width: var(--calculated-paper-checkbox-size); | 
|  | 18405         margin: var(--paper-checkbox-margin, initial); | 
|  | 18406         vertical-align: var(--paper-checkbox-vertical-align, middle); | 
|  | 18407         background-color: var(--paper-checkbox-unchecked-background-color, trans
       parent); | 
|  | 18408       } | 
|  | 18409 | 
|  | 18410       #ink { | 
|  | 18411         position: absolute; | 
|  | 18412 | 
|  | 18413         /* Center the ripple in the checkbox by negative offsetting it by | 
|  | 18414          * (inkWidth - rippleWidth) / 2 */ | 
|  | 18415         top: calc(0px - (2.66 * var(--calculated-paper-checkbox-size) - var(--ca
       lculated-paper-checkbox-size)) / 2); | 
|  | 18416         left: calc(0px - (2.66 * var(--calculated-paper-checkbox-size) - var(--c
       alculated-paper-checkbox-size)) / 2); | 
|  | 18417         width: calc(2.66 * var(--calculated-paper-checkbox-size)); | 
|  | 18418         height: calc(2.66 * var(--calculated-paper-checkbox-size)); | 
|  | 18419         color: var(--paper-checkbox-unchecked-ink-color, --primary-text-color); | 
|  | 18420         opacity: 0.6; | 
|  | 18421         pointer-events: none; | 
|  | 18422       } | 
|  | 18423 | 
|  | 18424       :host-context([dir="rtl"]) #ink { | 
|  | 18425         right: calc(0px - (2.66 * var(--calculated-paper-checkbox-size) - var(--
       calculated-paper-checkbox-size)) / 2); | 
|  | 18426         left: auto; | 
|  | 18427       } | 
|  | 18428 | 
|  | 18429       #ink[checked] { | 
|  | 18430         color: var(--paper-checkbox-checked-ink-color, --primary-color); | 
|  | 18431       } | 
|  | 18432 | 
|  | 18433       #checkbox { | 
|  | 18434         position: relative; | 
|  | 18435         box-sizing: border-box; | 
|  | 18436         height: 100%; | 
|  | 18437         border: solid 2px; | 
|  | 18438         border-color: var(--paper-checkbox-unchecked-color, --primary-text-color
       ); | 
|  | 18439         border-radius: 2px; | 
|  | 18440         pointer-events: none; | 
|  | 18441         -webkit-transition: background-color 140ms, border-color 140ms; | 
|  | 18442         transition: background-color 140ms, border-color 140ms; | 
|  | 18443       } | 
|  | 18444 | 
|  | 18445       /* checkbox checked animations */ | 
|  | 18446       #checkbox.checked #checkmark { | 
|  | 18447         -webkit-animation: checkmark-expand 140ms ease-out forwards; | 
|  | 18448         animation: checkmark-expand 140ms ease-out forwards; | 
|  | 18449       } | 
|  | 18450 | 
|  | 18451       @-webkit-keyframes checkmark-expand { | 
|  | 18452         0% { | 
|  | 18453           -webkit-transform: scale(0, 0) rotate(45deg); | 
|  | 18454         } | 
|  | 18455         100% { | 
|  | 18456           -webkit-transform: scale(1, 1) rotate(45deg); | 
|  | 18457         } | 
|  | 18458       } | 
|  | 18459 | 
|  | 18460       @keyframes checkmark-expand { | 
|  | 18461         0% { | 
|  | 18462           transform: scale(0, 0) rotate(45deg); | 
|  | 18463         } | 
|  | 18464         100% { | 
|  | 18465           transform: scale(1, 1) rotate(45deg); | 
|  | 18466         } | 
|  | 18467       } | 
|  | 18468 | 
|  | 18469       #checkbox.checked { | 
|  | 18470         background-color: var(--paper-checkbox-checked-color, --primary-color); | 
|  | 18471         border-color: var(--paper-checkbox-checked-color, --primary-color); | 
|  | 18472       } | 
|  | 18473 | 
|  | 18474       #checkmark { | 
|  | 18475         position: absolute; | 
|  | 18476         width: 36%; | 
|  | 18477         height: 70%; | 
|  | 18478         border-style: solid; | 
|  | 18479         border-top: none; | 
|  | 18480         border-left: none; | 
|  | 18481         border-right-width: calc(2/15 * var(--calculated-paper-checkbox-size)); | 
|  | 18482         border-bottom-width: calc(2/15 * var(--calculated-paper-checkbox-size)); | 
|  | 18483         border-color: var(--paper-checkbox-checkmark-color, white); | 
|  | 18484         -webkit-transform-origin: 97% 86%; | 
|  | 18485         transform-origin: 97% 86%; | 
|  | 18486         box-sizing: content-box; /* protect against page-level box-sizing */ | 
|  | 18487       } | 
|  | 18488 | 
|  | 18489       :host-context([dir="rtl"]) #checkmark { | 
|  | 18490         -webkit-transform-origin: 50% 14%; | 
|  | 18491         transform-origin: 50% 14%; | 
|  | 18492       } | 
|  | 18493 | 
|  | 18494       /* label */ | 
|  | 18495       #checkboxLabel { | 
|  | 18496         position: relative; | 
|  | 18497         display: inline-block; | 
|  | 18498         vertical-align: middle; | 
|  | 18499         padding-left: var(--paper-checkbox-label-spacing, 8px); | 
|  | 18500         white-space: normal; | 
|  | 18501         line-height: normal; | 
|  | 18502         color: var(--paper-checkbox-label-color, --primary-text-color); | 
|  | 18503         @apply(--paper-checkbox-label); | 
|  | 18504       } | 
|  | 18505 | 
|  | 18506       :host([checked]) #checkboxLabel { | 
|  | 18507         color: var(--paper-checkbox-label-checked-color, --paper-checkbox-label-
       color); | 
|  | 18508         @apply(--paper-checkbox-label-checked); | 
|  | 18509       } | 
|  | 18510 | 
|  | 18511       :host-context([dir="rtl"]) #checkboxLabel { | 
|  | 18512         padding-right: var(--paper-checkbox-label-spacing, 8px); | 
|  | 18513         padding-left: 0; | 
|  | 18514       } | 
|  | 18515 | 
|  | 18516       #checkboxLabel[hidden] { | 
|  | 18517         display: none; | 
|  | 18518       } | 
|  | 18519 | 
|  | 18520       /* disabled state */ | 
|  | 18521 | 
|  | 18522       :host([disabled]) #checkbox { | 
|  | 18523         opacity: 0.5; | 
|  | 18524         border-color: var(--paper-checkbox-unchecked-color, --primary-text-color
       ); | 
|  | 18525       } | 
|  | 18526 | 
|  | 18527       :host([disabled][checked]) #checkbox { | 
|  | 18528         background-color: var(--paper-checkbox-unchecked-color, --primary-text-c
       olor); | 
|  | 18529         opacity: 0.5; | 
|  | 18530       } | 
|  | 18531 | 
|  | 18532       :host([disabled]) #checkboxLabel  { | 
|  | 18533         opacity: 0.65; | 
|  | 18534       } | 
|  | 18535 | 
|  | 18536       /* invalid state */ | 
|  | 18537       #checkbox.invalid:not(.checked) { | 
|  | 18538         border-color: var(--paper-checkbox-error-color, --error-color); | 
|  | 18539       } | 
|  | 18540     </style> | 
|  | 18541 | 
|  | 18542     <div id="checkboxContainer"> | 
|  | 18543       <div id="checkbox" class$="[[_computeCheckboxClass(checked, invalid)]]"> | 
|  | 18544         <div id="checkmark" class$="[[_computeCheckmarkClass(checked)]]"></div> | 
|  | 18545       </div> | 
|  | 18546     </div> | 
|  | 18547 | 
|  | 18548     <div id="checkboxLabel"><content></content></div> | 
|  | 18549   </template> | 
|  | 18550 | 
|  | 18551   <script> | 
|  | 18552     Polymer({ | 
|  | 18553       is: 'paper-checkbox', | 
|  | 18554 | 
|  | 18555       behaviors: [ | 
|  | 18556         Polymer.PaperCheckedElementBehavior | 
|  | 18557       ], | 
|  | 18558 | 
|  | 18559       hostAttributes: { | 
|  | 18560         role: 'checkbox', | 
|  | 18561         'aria-checked': false, | 
|  | 18562         tabindex: 0 | 
|  | 18563       }, | 
|  | 18564 | 
|  | 18565       properties: { | 
|  | 18566         /** | 
|  | 18567          * Fired when the checked state changes due to user interaction. | 
|  | 18568          * | 
|  | 18569          * @event change | 
|  | 18570          */ | 
|  | 18571 | 
|  | 18572         /** | 
|  | 18573          * Fired when the checked state changes. | 
|  | 18574          * | 
|  | 18575          * @event iron-change | 
|  | 18576          */ | 
|  | 18577         ariaActiveAttribute: { | 
|  | 18578           type: String, | 
|  | 18579           value: 'aria-checked' | 
|  | 18580         } | 
|  | 18581       }, | 
|  | 18582 | 
|  | 18583       _computeCheckboxClass: function(checked, invalid) { | 
|  | 18584         var className = ''; | 
|  | 18585         if (checked) { | 
|  | 18586           className += 'checked '; | 
|  | 18587         } | 
|  | 18588         if (invalid) { | 
|  | 18589           className += 'invalid'; | 
|  | 18590         } | 
|  | 18591         return className; | 
|  | 18592       }, | 
|  | 18593 | 
|  | 18594       _computeCheckmarkClass: function(checked) { | 
|  | 18595         return checked ? '' : 'hidden'; | 
|  | 18596       }, | 
|  | 18597 | 
|  | 18598       // create ripple inside the checkboxContainer | 
|  | 18599       _createRipple: function() { | 
|  | 18600         this._rippleContainer = this.$.checkboxContainer; | 
|  | 18601         return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this); | 
|  | 18602       } | 
|  | 18603 | 
|  | 18604     }); | 
|  | 18605   </script> | 
|  | 18606 </dom-module> | 
|  | 18607 | 
|  | 18608 | 
|  | 18609 <dom-module id="paper-icon-button" assetpath="/res/imp/bower_components/paper-ic
       on-button/"> | 
|  | 18610   <template strip-whitespace=""> | 
|  | 18611     <style> | 
|  | 18612       :host { | 
|  | 18613         display: inline-block; | 
|  | 18614         position: relative; | 
|  | 18615         padding: 8px; | 
|  | 18616         outline: none; | 
|  | 18617         -webkit-user-select: none; | 
|  | 18618         -moz-user-select: none; | 
|  | 18619         -ms-user-select: none; | 
|  | 18620         user-select: none; | 
|  | 18621         cursor: pointer; | 
|  | 18622         z-index: 0; | 
|  | 18623         line-height: 1; | 
|  | 18624 | 
|  | 18625         width: 40px; | 
|  | 18626         height: 40px; | 
|  | 18627 | 
|  | 18628         /* NOTE: Both values are needed, since some phones require the value to 
       be `transparent`. */ | 
|  | 18629         -webkit-tap-highlight-color: rgba(0, 0, 0, 0); | 
|  | 18630         -webkit-tap-highlight-color: transparent; | 
|  | 18631 | 
|  | 18632         /* Because of polymer/2558, this style has lower specificity than * */ | 
|  | 18633         box-sizing: border-box !important; | 
|  | 18634 | 
|  | 18635         @apply(--paper-icon-button); | 
|  | 18636       } | 
|  | 18637 | 
|  | 18638       :host #ink { | 
|  | 18639         color: var(--paper-icon-button-ink-color, --primary-text-color); | 
|  | 18640         opacity: 0.6; | 
|  | 18641       } | 
|  | 18642 | 
|  | 18643       :host([disabled]) { | 
|  | 18644         color: var(--paper-icon-button-disabled-text, --disabled-text-color); | 
|  | 18645         pointer-events: none; | 
|  | 18646         cursor: auto; | 
|  | 18647 | 
|  | 18648         @apply(--paper-icon-button-disabled); | 
|  | 18649       } | 
|  | 18650 | 
|  | 18651       :host(:hover) { | 
|  | 18652         @apply(--paper-icon-button-hover); | 
|  | 18653       } | 
|  | 18654 | 
|  | 18655       iron-icon { | 
|  | 18656         --iron-icon-width: 100%; | 
|  | 18657         --iron-icon-height: 100%; | 
|  | 18658       } | 
|  | 18659     </style> | 
|  | 18660 | 
|  | 18661     <iron-icon id="icon" src="[[src]]" icon="[[icon]]" alt$="[[alt]]"></iron-ico
       n> | 
|  | 18662   </template> | 
|  | 18663 | 
|  | 18664   <script> | 
|  | 18665     Polymer({ | 
|  | 18666       is: 'paper-icon-button', | 
|  | 18667 | 
|  | 18668       hostAttributes: { | 
|  | 18669         role: 'button', | 
|  | 18670         tabindex: '0' | 
|  | 18671       }, | 
|  | 18672 | 
|  | 18673       behaviors: [ | 
|  | 18674         Polymer.PaperInkyFocusBehavior | 
|  | 18675       ], | 
|  | 18676 | 
|  | 18677       properties: { | 
|  | 18678         /** | 
|  | 18679          * The URL of an image for the icon. If the src property is specified, | 
|  | 18680          * the icon property should not be. | 
|  | 18681          */ | 
|  | 18682         src: { | 
|  | 18683           type: String | 
|  | 18684         }, | 
|  | 18685 | 
|  | 18686         /** | 
|  | 18687          * Specifies the icon name or index in the set of icons available in | 
|  | 18688          * the icon's icon set. If the icon property is specified, | 
|  | 18689          * the src property should not be. | 
|  | 18690          */ | 
|  | 18691         icon: { | 
|  | 18692           type: String | 
|  | 18693         }, | 
|  | 18694 | 
|  | 18695         /** | 
|  | 18696          * Specifies the alternate text for the button, for accessibility. | 
|  | 18697          */ | 
|  | 18698         alt: { | 
|  | 18699           type: String, | 
|  | 18700           observer: "_altChanged" | 
|  | 18701         } | 
|  | 18702       }, | 
|  | 18703 | 
|  | 18704       _altChanged: function(newValue, oldValue) { | 
|  | 18705         var label = this.getAttribute('aria-label'); | 
|  | 18706 | 
|  | 18707         // Don't stomp over a user-set aria-label. | 
|  | 18708         if (!label || oldValue == label) { | 
|  | 18709           this.setAttribute('aria-label', newValue); | 
|  | 18710         } | 
|  | 18711       } | 
|  | 18712     }); | 
|  | 18713   </script> | 
|  | 18714 </dom-module> | 
|  | 18715 | 
|  | 18716 | 
|  | 18717 <dom-module id="iron-a11y-announcer" assetpath="/res/imp/bower_components/iron-a
       11y-announcer/"> | 
|  | 18718   <template> | 
|  | 18719     <style> | 
|  | 18720       :host { | 
|  | 18721         display: inline-block; | 
|  | 18722         position: fixed; | 
|  | 18723         clip: rect(0px,0px,0px,0px); | 
|  | 18724       } | 
|  | 18725     </style> | 
|  | 18726     <div aria-live$="[[mode]]">[[_text]]</div> | 
|  | 18727   </template> | 
|  | 18728 | 
|  | 18729   <script> | 
|  | 18730 | 
|  | 18731     (function() { | 
|  | 18732       'use strict'; | 
|  | 18733 | 
|  | 18734       Polymer.IronA11yAnnouncer = Polymer({ | 
|  | 18735         is: 'iron-a11y-announcer', | 
|  | 18736 | 
|  | 18737         properties: { | 
|  | 18738 | 
|  | 18739           /** | 
|  | 18740            * The value of mode is used to set the `aria-live` attribute | 
|  | 18741            * for the element that will be announced. Valid values are: `off`, | 
|  | 18742            * `polite` and `assertive`. | 
|  | 18743            */ | 
|  | 18744           mode: { | 
|  | 18745             type: String, | 
|  | 18746             value: 'polite' | 
|  | 18747           }, | 
|  | 18748 | 
|  | 18749           _text: { | 
|  | 18750             type: String, | 
|  | 18751             value: '' | 
|  | 18752           } | 
|  | 18753         }, | 
|  | 18754 | 
|  | 18755         created: function() { | 
|  | 18756           if (!Polymer.IronA11yAnnouncer.instance) { | 
|  | 18757             Polymer.IronA11yAnnouncer.instance = this; | 
|  | 18758           } | 
|  | 18759 | 
|  | 18760           document.body.addEventListener('iron-announce', this._onIronAnnounce.b
       ind(this)); | 
|  | 18761         }, | 
|  | 18762 | 
|  | 18763         /** | 
|  | 18764          * Cause a text string to be announced by screen readers. | 
|  | 18765          * | 
|  | 18766          * @param {string} text The text that should be announced. | 
|  | 18767          */ | 
|  | 18768         announce: function(text) { | 
|  | 18769           this._text = ''; | 
|  | 18770           this.async(function() { | 
|  | 18771             this._text = text; | 
|  | 18772           }, 100); | 
|  | 18773         }, | 
|  | 18774 | 
|  | 18775         _onIronAnnounce: function(event) { | 
|  | 18776           if (event.detail && event.detail.text) { | 
|  | 18777             this.announce(event.detail.text); | 
|  | 18778           } | 
|  | 18779         } | 
|  | 18780       }); | 
|  | 18781 | 
|  | 18782       Polymer.IronA11yAnnouncer.instance = null; | 
|  | 18783 | 
|  | 18784       Polymer.IronA11yAnnouncer.requestAvailability = function() { | 
|  | 18785         if (!Polymer.IronA11yAnnouncer.instance) { | 
|  | 18786           Polymer.IronA11yAnnouncer.instance = document.createElement('iron-a11y
       -announcer'); | 
|  | 18787         } | 
|  | 18788 | 
|  | 18789         document.body.appendChild(Polymer.IronA11yAnnouncer.instance); | 
|  | 18790       }; | 
|  | 18791     })(); | 
|  | 18792 | 
|  | 18793   </script> | 
|  | 18794 </dom-module> | 
|  | 18795 <script> | 
|  | 18796 | 
|  | 18797 /* | 
|  | 18798 `<iron-input>` adds two-way binding and custom validators using `Polymer.IronVal
       idatorBehavior` | 
|  | 18799 to `<input>`. | 
|  | 18800 | 
|  | 18801 ### Two-way binding | 
|  | 18802 | 
|  | 18803 By default you can only get notified of changes to an `input`'s `value` due to u
       ser input: | 
|  | 18804 | 
|  | 18805     <input value="{{myValue::input}}"> | 
|  | 18806 | 
|  | 18807 `iron-input` adds the `bind-value` property that mirrors the `value` property, a
       nd can be used | 
|  | 18808 for two-way data binding. `bind-value` will notify if it is changed either by us
       er input or by script. | 
|  | 18809 | 
|  | 18810     <input is="iron-input" bind-value="{{myValue}}"> | 
|  | 18811 | 
|  | 18812 ### Custom validators | 
|  | 18813 | 
|  | 18814 You can use custom validators that implement `Polymer.IronValidatorBehavior` wit
       h `<iron-input>`. | 
|  | 18815 | 
|  | 18816     <input is="iron-input" validator="my-custom-validator"> | 
|  | 18817 | 
|  | 18818 ### Stopping invalid input | 
|  | 18819 | 
|  | 18820 It may be desirable to only allow users to enter certain characters. You can use
        the | 
|  | 18821 `prevent-invalid-input` and `allowed-pattern` attributes together to accomplish 
       this. This feature | 
|  | 18822 is separate from validation, and `allowed-pattern` does not affect how the input
        is validated. | 
|  | 18823 | 
|  | 18824     <!-- only allow characters that match [0-9] --> | 
|  | 18825     <input is="iron-input" prevent-invalid-input allowed-pattern="[0-9]"> | 
|  | 18826 | 
|  | 18827 @hero hero.svg | 
|  | 18828 @demo demo/index.html | 
|  | 18829 */ | 
|  | 18830 | 
|  | 18831   Polymer({ | 
|  | 18832 | 
|  | 18833     is: 'iron-input', | 
|  | 18834 | 
|  | 18835     extends: 'input', | 
|  | 18836 | 
|  | 18837     behaviors: [ | 
|  | 18838       Polymer.IronValidatableBehavior | 
|  | 18839     ], | 
|  | 18840 | 
|  | 18841     properties: { | 
|  | 18842 | 
|  | 18843       /** | 
|  | 18844        * Use this property instead of `value` for two-way data binding. | 
|  | 18845        */ | 
|  | 18846       bindValue: { | 
|  | 18847         observer: '_bindValueChanged', | 
|  | 18848         type: String | 
|  | 18849       }, | 
|  | 18850 | 
|  | 18851       /** | 
|  | 18852        * Set to true to prevent the user from entering invalid input. If `allowe
       dPattern` is set, | 
|  | 18853        * any character typed by the user will be matched against that pattern, a
       nd rejected if it's not a match. | 
|  | 18854        * Pasted input will have each character checked individually; if any char
       acter | 
|  | 18855        * doesn't match `allowedPattern`, the entire pasted string will be reject
       ed. | 
|  | 18856        * If `allowedPattern` is not set, it will use the `type` attribute (only 
       supported for `type=number`). | 
|  | 18857        */ | 
|  | 18858       preventInvalidInput: { | 
|  | 18859         type: Boolean | 
|  | 18860       }, | 
|  | 18861 | 
|  | 18862       /** | 
|  | 18863        * Regular expression that list the characters allowed as input. | 
|  | 18864        * This pattern represents the allowed characters for the field; as the us
       er inputs text, | 
|  | 18865        * each individual character will be checked against the pattern (rather t
       han checking | 
|  | 18866        * the entire value as a whole). The recommended format should be a list o
       f allowed characters; | 
|  | 18867        * for example, `[a-zA-Z0-9.+-!;:]` | 
|  | 18868        */ | 
|  | 18869       allowedPattern: { | 
|  | 18870         type: String, | 
|  | 18871         observer: "_allowedPatternChanged" | 
|  | 18872       }, | 
|  | 18873 | 
|  | 18874       _previousValidInput: { | 
|  | 18875         type: String, | 
|  | 18876         value: '' | 
|  | 18877       }, | 
|  | 18878 | 
|  | 18879       _patternAlreadyChecked: { | 
|  | 18880         type: Boolean, | 
|  | 18881         value: false | 
|  | 18882       } | 
|  | 18883 | 
|  | 18884     }, | 
|  | 18885 | 
|  | 18886     listeners: { | 
|  | 18887       'input': '_onInput', | 
|  | 18888       'keypress': '_onKeypress' | 
|  | 18889     }, | 
|  | 18890 | 
|  | 18891     /** @suppress {checkTypes} */ | 
|  | 18892     registered: function() { | 
|  | 18893       // Feature detect whether we need to patch dispatchEvent (i.e. on FF and I
       E). | 
|  | 18894       if (!this._canDispatchEventOnDisabled()) { | 
|  | 18895         this._origDispatchEvent = this.dispatchEvent; | 
|  | 18896         this.dispatchEvent = this._dispatchEventFirefoxIE; | 
|  | 18897       } | 
|  | 18898     }, | 
|  | 18899 | 
|  | 18900     created: function() { | 
|  | 18901       Polymer.IronA11yAnnouncer.requestAvailability(); | 
|  | 18902     }, | 
|  | 18903 | 
|  | 18904     _canDispatchEventOnDisabled: function() { | 
|  | 18905       var input = document.createElement('input'); | 
|  | 18906       var canDispatch = false; | 
|  | 18907       input.disabled = true; | 
|  | 18908 | 
|  | 18909       input.addEventListener('feature-check-dispatch-event', function() { | 
|  | 18910         canDispatch = true; | 
|  | 18911       }); | 
|  | 18912 | 
|  | 18913       try { | 
|  | 18914         input.dispatchEvent(new Event('feature-check-dispatch-event')); | 
|  | 18915       } catch(e) {} | 
|  | 18916 | 
|  | 18917       return canDispatch; | 
|  | 18918     }, | 
|  | 18919 | 
|  | 18920     _dispatchEventFirefoxIE: function() { | 
|  | 18921       // Due to Firefox bug, events fired on disabled form controls can throw | 
|  | 18922       // errors; furthermore, neither IE nor Firefox will actually dispatch | 
|  | 18923       // events from disabled form controls; as such, we toggle disable around | 
|  | 18924       // the dispatch to allow notifying properties to notify | 
|  | 18925       // See issue #47 for details | 
|  | 18926       var disabled = this.disabled; | 
|  | 18927       this.disabled = false; | 
|  | 18928       this._origDispatchEvent.apply(this, arguments); | 
|  | 18929       this.disabled = disabled; | 
|  | 18930     }, | 
|  | 18931 | 
|  | 18932     get _patternRegExp() { | 
|  | 18933       var pattern; | 
|  | 18934       if (this.allowedPattern) { | 
|  | 18935         pattern = new RegExp(this.allowedPattern); | 
|  | 18936       } else { | 
|  | 18937         switch (this.type) { | 
|  | 18938           case 'number': | 
|  | 18939             pattern = /[0-9.,e-]/; | 
|  | 18940             break; | 
|  | 18941         } | 
|  | 18942       } | 
|  | 18943       return pattern; | 
|  | 18944     }, | 
|  | 18945 | 
|  | 18946     ready: function() { | 
|  | 18947       this.bindValue = this.value; | 
|  | 18948     }, | 
|  | 18949 | 
|  | 18950     /** | 
|  | 18951      * @suppress {checkTypes} | 
|  | 18952      */ | 
|  | 18953     _bindValueChanged: function() { | 
|  | 18954       if (this.value !== this.bindValue) { | 
|  | 18955         this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue 
       === false) ? '' : this.bindValue; | 
|  | 18956       } | 
|  | 18957       // manually notify because we don't want to notify until after setting val
       ue | 
|  | 18958       this.fire('bind-value-changed', {value: this.bindValue}); | 
|  | 18959     }, | 
|  | 18960 | 
|  | 18961     _allowedPatternChanged: function() { | 
|  | 18962       // Force to prevent invalid input when an `allowed-pattern` is set | 
|  | 18963       this.preventInvalidInput = this.allowedPattern ? true : false; | 
|  | 18964     }, | 
|  | 18965 | 
|  | 18966     _onInput: function() { | 
|  | 18967       // Need to validate each of the characters pasted if they haven't | 
|  | 18968       // been validated inside `_onKeypress` already. | 
|  | 18969       if (this.preventInvalidInput && !this._patternAlreadyChecked) { | 
|  | 18970         var valid = this._checkPatternValidity(); | 
|  | 18971         if (!valid) { | 
|  | 18972           this._announceInvalidCharacter('Invalid string of characters not enter
       ed.'); | 
|  | 18973           this.value = this._previousValidInput; | 
|  | 18974         } | 
|  | 18975       } | 
|  | 18976 | 
|  | 18977       this.bindValue = this.value; | 
|  | 18978       this._previousValidInput = this.value; | 
|  | 18979       this._patternAlreadyChecked = false; | 
|  | 18980     }, | 
|  | 18981 | 
|  | 18982     _isPrintable: function(event) { | 
|  | 18983       // What a control/printable character is varies wildly based on the browse
       r. | 
|  | 18984       // - most control characters (arrows, backspace) do not send a `keypress` 
       event | 
|  | 18985       //   in Chrome, but the *do* on Firefox | 
|  | 18986       // - in Firefox, when they do send a `keypress` event, control chars have | 
|  | 18987       //   a charCode = 0, keyCode = xx (for ex. 40 for down arrow) | 
|  | 18988       // - printable characters always send a keypress event. | 
|  | 18989       // - in Firefox, printable chars always have a keyCode = 0. In Chrome, the
        keyCode | 
|  | 18990       //   always matches the charCode. | 
|  | 18991       // None of this makes any sense. | 
|  | 18992 | 
|  | 18993       // For these keys, ASCII code == browser keycode. | 
|  | 18994       var anyNonPrintable = | 
|  | 18995         (event.keyCode == 8)   ||  // backspace | 
|  | 18996         (event.keyCode == 9)   ||  // tab | 
|  | 18997         (event.keyCode == 13)  ||  // enter | 
|  | 18998         (event.keyCode == 27);     // escape | 
|  | 18999 | 
|  | 19000       // For these keys, make sure it's a browser keycode and not an ASCII code. | 
|  | 19001       var mozNonPrintable = | 
|  | 19002         (event.keyCode == 19)  ||  // pause | 
|  | 19003         (event.keyCode == 20)  ||  // caps lock | 
|  | 19004         (event.keyCode == 45)  ||  // insert | 
|  | 19005         (event.keyCode == 46)  ||  // delete | 
|  | 19006         (event.keyCode == 144) ||  // num lock | 
|  | 19007         (event.keyCode == 145) ||  // scroll lock | 
|  | 19008         (event.keyCode > 32 && event.keyCode < 41)   || // page up/down, end, ho
       me, arrows | 
|  | 19009         (event.keyCode > 111 && event.keyCode < 124); // fn keys | 
|  | 19010 | 
|  | 19011       return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable); | 
|  | 19012     }, | 
|  | 19013 | 
|  | 19014     _onKeypress: function(event) { | 
|  | 19015       if (!this.preventInvalidInput && this.type !== 'number') { | 
|  | 19016         return; | 
|  | 19017       } | 
|  | 19018       var regexp = this._patternRegExp; | 
|  | 19019       if (!regexp) { | 
|  | 19020         return; | 
|  | 19021       } | 
|  | 19022 | 
|  | 19023       // Handle special keys and backspace | 
|  | 19024       if (event.metaKey || event.ctrlKey || event.altKey) | 
|  | 19025         return; | 
|  | 19026 | 
|  | 19027       // Check the pattern either here or in `_onInput`, but not in both. | 
|  | 19028       this._patternAlreadyChecked = true; | 
|  | 19029 | 
|  | 19030       var thisChar = String.fromCharCode(event.charCode); | 
|  | 19031       if (this._isPrintable(event) && !regexp.test(thisChar)) { | 
|  | 19032         event.preventDefault(); | 
|  | 19033         this._announceInvalidCharacter('Invalid character ' + thisChar + ' not e
       ntered.'); | 
|  | 19034       } | 
|  | 19035     }, | 
|  | 19036 | 
|  | 19037     _checkPatternValidity: function() { | 
|  | 19038       var regexp = this._patternRegExp; | 
|  | 19039       if (!regexp) { | 
|  | 19040         return true; | 
|  | 19041       } | 
|  | 19042       for (var i = 0; i < this.value.length; i++) { | 
|  | 19043         if (!regexp.test(this.value[i])) { | 
|  | 19044           return false; | 
|  | 19045         } | 
|  | 19046       } | 
|  | 19047       return true; | 
|  | 19048     }, | 
|  | 19049 | 
|  | 19050     /** | 
|  | 19051      * Returns true if `value` is valid. The validator provided in `validator` w
       ill be used first, | 
|  | 19052      * then any constraints. | 
|  | 19053      * @return {boolean} True if the value is valid. | 
|  | 19054      */ | 
|  | 19055     validate: function() { | 
|  | 19056       // First, check what the browser thinks. Some inputs (like type=number) | 
|  | 19057       // behave weirdly and will set the value to "" if something invalid is | 
|  | 19058       // entered, but will set the validity correctly. | 
|  | 19059       var valid =  this.checkValidity(); | 
|  | 19060 | 
|  | 19061       // Only do extra checking if the browser thought this was valid. | 
|  | 19062       if (valid) { | 
|  | 19063         // Empty, required input is invalid | 
|  | 19064         if (this.required && this.value === '') { | 
|  | 19065           valid = false; | 
|  | 19066         } else if (this.hasValidator()) { | 
|  | 19067           valid = Polymer.IronValidatableBehavior.validate.call(this, this.value
       ); | 
|  | 19068         } | 
|  | 19069       } | 
|  | 19070 | 
|  | 19071       this.invalid = !valid; | 
|  | 19072       this.fire('iron-input-validate'); | 
|  | 19073       return valid; | 
|  | 19074     }, | 
|  | 19075 | 
|  | 19076     _announceInvalidCharacter: function(message) { | 
|  | 19077       this.fire('iron-announce', { text: message }); | 
|  | 19078     } | 
|  | 19079   }); | 
|  | 19080 | 
|  | 19081   /* | 
|  | 19082   The `iron-input-validate` event is fired whenever `validate()` is called. | 
|  | 19083   @event iron-input-validate | 
|  | 19084   */ | 
|  | 19085 | 
|  | 19086 </script> | 
|  | 19087 <script> | 
|  | 19088 | 
|  | 19089   // Generate unique, monotonically increasing IDs for labels (needed by | 
|  | 19090   // aria-labelledby) and add-ons. | 
|  | 19091   Polymer.PaperInputHelper = {}; | 
|  | 19092   Polymer.PaperInputHelper.NextLabelID = 1; | 
|  | 19093   Polymer.PaperInputHelper.NextAddonID = 1; | 
|  | 19094 | 
|  | 19095   /** | 
|  | 19096    * Use `Polymer.PaperInputBehavior` to implement inputs with `<paper-input-con
       tainer>`. This | 
|  | 19097    * behavior is implemented by `<paper-input>`. It exposes a number of properti
       es from | 
|  | 19098    * `<paper-input-container>` and `<input is="iron-input">` and they should be 
       bound in your | 
|  | 19099    * template. | 
|  | 19100    * | 
|  | 19101    * The input element can be accessed by the `inputElement` property if you nee
       d to access | 
|  | 19102    * properties or methods that are not exposed. | 
|  | 19103    * @polymerBehavior Polymer.PaperInputBehavior | 
|  | 19104    */ | 
|  | 19105   Polymer.PaperInputBehaviorImpl = { | 
|  | 19106 | 
|  | 19107     properties: { | 
|  | 19108       /** | 
|  | 19109        * Fired when the input changes due to user interaction. | 
|  | 19110        * | 
|  | 19111        * @event change | 
|  | 19112        */ | 
|  | 19113 | 
|  | 19114       /** | 
|  | 19115        * The label for this input. If you're using PaperInputBehavior to | 
|  | 19116        * implement your own paper-input-like element, bind this to | 
|  | 19117        * `<label>`'s content and `hidden` property, e.g. | 
|  | 19118        * `<label hidden$="[[!label]]">[[label]]</label>` in your `template` | 
|  | 19119        */ | 
|  | 19120       label: { | 
|  | 19121         type: String | 
|  | 19122       }, | 
|  | 19123 | 
|  | 19124       /** | 
|  | 19125        * The value for this input. If you're using PaperInputBehavior to | 
|  | 19126        * implement your own paper-input-like element, bind this to | 
|  | 19127        * the `<input is="iron-input">`'s `bindValue` | 
|  | 19128        * property, or the value property of your input that is `notify:true`. | 
|  | 19129        */ | 
|  | 19130       value: { | 
|  | 19131         notify: true, | 
|  | 19132         type: String | 
|  | 19133       }, | 
|  | 19134 | 
|  | 19135       /** | 
|  | 19136        * Set to true to disable this input. If you're using PaperInputBehavior t
       o | 
|  | 19137        * implement your own paper-input-like element, bind this to | 
|  | 19138        * both the `<paper-input-container>`'s and the input's `disabled` propert
       y. | 
|  | 19139        */ | 
|  | 19140       disabled: { | 
|  | 19141         type: Boolean, | 
|  | 19142         value: false | 
|  | 19143       }, | 
|  | 19144 | 
|  | 19145       /** | 
|  | 19146        * Returns true if the value is invalid. If you're using PaperInputBehavio
       r to | 
|  | 19147        * implement your own paper-input-like element, bind this to both the | 
|  | 19148        * `<paper-input-container>`'s and the input's `invalid` property. | 
|  | 19149        * | 
|  | 19150        * If `autoValidate` is true, the `invalid` attribute is managed automatic
       ally, | 
|  | 19151        * which can clobber attempts to manage it manually. | 
|  | 19152        */ | 
|  | 19153       invalid: { | 
|  | 19154         type: Boolean, | 
|  | 19155         value: false, | 
|  | 19156         notify: true | 
|  | 19157       }, | 
|  | 19158 | 
|  | 19159       /** | 
|  | 19160        * Set to true to prevent the user from entering invalid input. If you're | 
|  | 19161        * using PaperInputBehavior to  implement your own paper-input-like elemen
       t, | 
|  | 19162        * bind this to `<input is="iron-input">`'s `preventInvalidInput` property
       . | 
|  | 19163        */ | 
|  | 19164       preventInvalidInput: { | 
|  | 19165         type: Boolean | 
|  | 19166       }, | 
|  | 19167 | 
|  | 19168       /** | 
|  | 19169        * Set this to specify the pattern allowed by `preventInvalidInput`. If | 
|  | 19170        * you're using PaperInputBehavior to implement your own paper-input-like | 
|  | 19171        * element, bind this to the `<input is="iron-input">`'s `allowedPattern` | 
|  | 19172        * property. | 
|  | 19173        */ | 
|  | 19174       allowedPattern: { | 
|  | 19175         type: String | 
|  | 19176       }, | 
|  | 19177 | 
|  | 19178       /** | 
|  | 19179        * The type of the input. The supported types are `text`, `number` and `pa
       ssword`. | 
|  | 19180        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke element, | 
|  | 19181        * bind this to the `<input is="iron-input">`'s `type` property. | 
|  | 19182        */ | 
|  | 19183       type: { | 
|  | 19184         type: String | 
|  | 19185       }, | 
|  | 19186 | 
|  | 19187       /** | 
|  | 19188        * The datalist of the input (if any). This should match the id of an exis
       ting `<datalist>`. | 
|  | 19189        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19190        * element, bind this to the `<input is="iron-input">`'s `list` property. | 
|  | 19191        */ | 
|  | 19192       list: { | 
|  | 19193         type: String | 
|  | 19194       }, | 
|  | 19195 | 
|  | 19196       /** | 
|  | 19197        * A pattern to validate the `input` with. If you're using PaperInputBehav
       ior to | 
|  | 19198        * implement your own paper-input-like element, bind this to | 
|  | 19199        * the `<input is="iron-input">`'s `pattern` property. | 
|  | 19200        */ | 
|  | 19201       pattern: { | 
|  | 19202         type: String | 
|  | 19203       }, | 
|  | 19204 | 
|  | 19205       /** | 
|  | 19206        * Set to true to mark the input as required. If you're using PaperInputBe
       havior to | 
|  | 19207        * implement your own paper-input-like element, bind this to | 
|  | 19208        * the `<input is="iron-input">`'s `required` property. | 
|  | 19209        */ | 
|  | 19210       required: { | 
|  | 19211         type: Boolean, | 
|  | 19212         value: false | 
|  | 19213       }, | 
|  | 19214 | 
|  | 19215       /** | 
|  | 19216        * The error message to display when the input is invalid. If you're using | 
|  | 19217        * PaperInputBehavior to implement your own paper-input-like element, | 
|  | 19218        * bind this to the `<paper-input-error>`'s content, if using. | 
|  | 19219        */ | 
|  | 19220       errorMessage: { | 
|  | 19221         type: String | 
|  | 19222       }, | 
|  | 19223 | 
|  | 19224       /** | 
|  | 19225        * Set to true to show a character counter. | 
|  | 19226        */ | 
|  | 19227       charCounter: { | 
|  | 19228         type: Boolean, | 
|  | 19229         value: false | 
|  | 19230       }, | 
|  | 19231 | 
|  | 19232       /** | 
|  | 19233        * Set to true to disable the floating label. If you're using PaperInputBe
       havior to | 
|  | 19234        * implement your own paper-input-like element, bind this to | 
|  | 19235        * the `<paper-input-container>`'s `noLabelFloat` property. | 
|  | 19236        */ | 
|  | 19237       noLabelFloat: { | 
|  | 19238         type: Boolean, | 
|  | 19239         value: false | 
|  | 19240       }, | 
|  | 19241 | 
|  | 19242       /** | 
|  | 19243        * Set to true to always float the label. If you're using PaperInputBehavi
       or to | 
|  | 19244        * implement your own paper-input-like element, bind this to | 
|  | 19245        * the `<paper-input-container>`'s `alwaysFloatLabel` property. | 
|  | 19246        */ | 
|  | 19247       alwaysFloatLabel: { | 
|  | 19248         type: Boolean, | 
|  | 19249         value: false | 
|  | 19250       }, | 
|  | 19251 | 
|  | 19252       /** | 
|  | 19253        * Set to true to auto-validate the input value. If you're using PaperInpu
       tBehavior to | 
|  | 19254        * implement your own paper-input-like element, bind this to | 
|  | 19255        * the `<paper-input-container>`'s `autoValidate` property. | 
|  | 19256        */ | 
|  | 19257       autoValidate: { | 
|  | 19258         type: Boolean, | 
|  | 19259         value: false | 
|  | 19260       }, | 
|  | 19261 | 
|  | 19262       /** | 
|  | 19263        * Name of the validator to use. If you're using PaperInputBehavior to | 
|  | 19264        * implement your own paper-input-like element, bind this to | 
|  | 19265        * the `<input is="iron-input">`'s `validator` property. | 
|  | 19266        */ | 
|  | 19267       validator: { | 
|  | 19268         type: String | 
|  | 19269       }, | 
|  | 19270 | 
|  | 19271       // HTMLInputElement attributes for binding if needed | 
|  | 19272 | 
|  | 19273       /** | 
|  | 19274        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19275        * element, bind this to the `<input is="iron-input">`'s `autocomplete` pr
       operty. | 
|  | 19276        */ | 
|  | 19277       autocomplete: { | 
|  | 19278         type: String, | 
|  | 19279         value: 'off' | 
|  | 19280       }, | 
|  | 19281 | 
|  | 19282       /** | 
|  | 19283        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19284        * element, bind this to the `<input is="iron-input">`'s `autofocus` prope
       rty. | 
|  | 19285        */ | 
|  | 19286       autofocus: { | 
|  | 19287         type: Boolean, | 
|  | 19288         observer: '_autofocusChanged' | 
|  | 19289       }, | 
|  | 19290 | 
|  | 19291       /** | 
|  | 19292        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19293        * element, bind this to the `<input is="iron-input">`'s `inputmode` prope
       rty. | 
|  | 19294        */ | 
|  | 19295       inputmode: { | 
|  | 19296         type: String | 
|  | 19297       }, | 
|  | 19298 | 
|  | 19299       /** | 
|  | 19300        * The minimum length of the input value. | 
|  | 19301        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19302        * element, bind this to the `<input is="iron-input">`'s `minlength` prope
       rty. | 
|  | 19303        */ | 
|  | 19304       minlength: { | 
|  | 19305         type: Number | 
|  | 19306       }, | 
|  | 19307 | 
|  | 19308       /** | 
|  | 19309        * The maximum length of the input value. | 
|  | 19310        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19311        * element, bind this to the `<input is="iron-input">`'s `maxlength` prope
       rty. | 
|  | 19312        */ | 
|  | 19313       maxlength: { | 
|  | 19314         type: Number | 
|  | 19315       }, | 
|  | 19316 | 
|  | 19317       /** | 
|  | 19318        * The minimum (numeric or date-time) input value. | 
|  | 19319        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19320        * element, bind this to the `<input is="iron-input">`'s `min` property. | 
|  | 19321        */ | 
|  | 19322       min: { | 
|  | 19323         type: String | 
|  | 19324       }, | 
|  | 19325 | 
|  | 19326       /** | 
|  | 19327        * The maximum (numeric or date-time) input value. | 
|  | 19328        * Can be a String (e.g. `"2000-1-1"`) or a Number (e.g. `2`). | 
|  | 19329        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19330        * element, bind this to the `<input is="iron-input">`'s `max` property. | 
|  | 19331        */ | 
|  | 19332       max: { | 
|  | 19333         type: String | 
|  | 19334       }, | 
|  | 19335 | 
|  | 19336       /** | 
|  | 19337        * Limits the numeric or date-time increments. | 
|  | 19338        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19339        * element, bind this to the `<input is="iron-input">`'s `step` property. | 
|  | 19340        */ | 
|  | 19341       step: { | 
|  | 19342         type: String | 
|  | 19343       }, | 
|  | 19344 | 
|  | 19345       /** | 
|  | 19346        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19347        * element, bind this to the `<input is="iron-input">`'s `name` property. | 
|  | 19348        */ | 
|  | 19349       name: { | 
|  | 19350         type: String | 
|  | 19351       }, | 
|  | 19352 | 
|  | 19353       /** | 
|  | 19354        * A placeholder string in addition to the label. If this is set, the labe
       l will always float. | 
|  | 19355        */ | 
|  | 19356       placeholder: { | 
|  | 19357         type: String, | 
|  | 19358         // need to set a default so _computeAlwaysFloatLabel is run | 
|  | 19359         value: '' | 
|  | 19360       }, | 
|  | 19361 | 
|  | 19362       /** | 
|  | 19363        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19364        * element, bind this to the `<input is="iron-input">`'s `readonly` proper
       ty. | 
|  | 19365        */ | 
|  | 19366       readonly: { | 
|  | 19367         type: Boolean, | 
|  | 19368         value: false | 
|  | 19369       }, | 
|  | 19370 | 
|  | 19371       /** | 
|  | 19372        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19373        * element, bind this to the `<input is="iron-input">`'s `size` property. | 
|  | 19374        */ | 
|  | 19375       size: { | 
|  | 19376         type: Number | 
|  | 19377       }, | 
|  | 19378 | 
|  | 19379       // Nonstandard attributes for binding if needed | 
|  | 19380 | 
|  | 19381       /** | 
|  | 19382        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19383        * element, bind this to the `<input is="iron-input">`'s `autocapitalize` 
       property. | 
|  | 19384        */ | 
|  | 19385       autocapitalize: { | 
|  | 19386         type: String, | 
|  | 19387         value: 'none' | 
|  | 19388       }, | 
|  | 19389 | 
|  | 19390       /** | 
|  | 19391        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19392        * element, bind this to the `<input is="iron-input">`'s `autocorrect` pro
       perty. | 
|  | 19393        */ | 
|  | 19394       autocorrect: { | 
|  | 19395         type: String, | 
|  | 19396         value: 'off' | 
|  | 19397       }, | 
|  | 19398 | 
|  | 19399       /** | 
|  | 19400        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19401        * element, bind this to the `<input is="iron-input">`'s `autosave` proper
       ty, | 
|  | 19402        * used with type=search. | 
|  | 19403        */ | 
|  | 19404       autosave: { | 
|  | 19405         type: String | 
|  | 19406       }, | 
|  | 19407 | 
|  | 19408       /** | 
|  | 19409        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19410        * element, bind this to the `<input is="iron-input">`'s `results` propert
       y, | 
|  | 19411        * used with type=search. | 
|  | 19412        */ | 
|  | 19413       results: { | 
|  | 19414         type: Number | 
|  | 19415       }, | 
|  | 19416 | 
|  | 19417       /** | 
|  | 19418        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19419        * element, bind this to the `<input is="iron-input">`'s `accept` property
       , | 
|  | 19420        * used with type=file. | 
|  | 19421        */ | 
|  | 19422       accept: { | 
|  | 19423         type: String | 
|  | 19424       }, | 
|  | 19425 | 
|  | 19426       /** | 
|  | 19427        * If you're using PaperInputBehavior to implement your own paper-input-li
       ke | 
|  | 19428        * element, bind this to the`<input is="iron-input">`'s `multiple` propert
       y, | 
|  | 19429        * used with type=file. | 
|  | 19430        */ | 
|  | 19431       multiple: { | 
|  | 19432         type: Boolean | 
|  | 19433       }, | 
|  | 19434 | 
|  | 19435       _ariaDescribedBy: { | 
|  | 19436         type: String, | 
|  | 19437         value: '' | 
|  | 19438       }, | 
|  | 19439 | 
|  | 19440       _ariaLabelledBy: { | 
|  | 19441         type: String, | 
|  | 19442         value: '' | 
|  | 19443       } | 
|  | 19444 | 
|  | 19445     }, | 
|  | 19446 | 
|  | 19447     listeners: { | 
|  | 19448       'addon-attached': '_onAddonAttached', | 
|  | 19449     }, | 
|  | 19450 | 
|  | 19451     keyBindings: { | 
|  | 19452       'shift+tab:keydown': '_onShiftTabDown' | 
|  | 19453     }, | 
|  | 19454 | 
|  | 19455     hostAttributes: { | 
|  | 19456       tabindex: 0 | 
|  | 19457     }, | 
|  | 19458 | 
|  | 19459     /** | 
|  | 19460      * Returns a reference to the input element. | 
|  | 19461      */ | 
|  | 19462     get inputElement() { | 
|  | 19463       return this.$.input; | 
|  | 19464     }, | 
|  | 19465 | 
|  | 19466     /** | 
|  | 19467      * Returns a reference to the focusable element. | 
|  | 19468      */ | 
|  | 19469     get _focusableElement() { | 
|  | 19470       return this.inputElement; | 
|  | 19471     }, | 
|  | 19472 | 
|  | 19473     registered: function() { | 
|  | 19474       // These types have some default placeholder text; overlapping | 
|  | 19475       // the label on top of it looks terrible. Auto-float the label in this cas
       e. | 
|  | 19476       this._typesThatHaveText = ["date", "datetime", "datetime-local", "month", | 
|  | 19477           "time", "week", "file"]; | 
|  | 19478     }, | 
|  | 19479 | 
|  | 19480     attached: function() { | 
|  | 19481       this._updateAriaLabelledBy(); | 
|  | 19482 | 
|  | 19483       if (this.inputElement && | 
|  | 19484           this._typesThatHaveText.indexOf(this.inputElement.type) !== -1) { | 
|  | 19485         this.alwaysFloatLabel = true; | 
|  | 19486       } | 
|  | 19487     }, | 
|  | 19488 | 
|  | 19489     _appendStringWithSpace: function(str, more) { | 
|  | 19490       if (str) { | 
|  | 19491         str = str + ' ' + more; | 
|  | 19492       } else { | 
|  | 19493         str = more; | 
|  | 19494       } | 
|  | 19495       return str; | 
|  | 19496     }, | 
|  | 19497 | 
|  | 19498     _onAddonAttached: function(event) { | 
|  | 19499       var target = event.path ? event.path[0] : event.target; | 
|  | 19500       if (target.id) { | 
|  | 19501         this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedB
       y, target.id); | 
|  | 19502       } else { | 
|  | 19503         var id = 'paper-input-add-on-' + Polymer.PaperInputHelper.NextAddonID++; | 
|  | 19504         target.id = id; | 
|  | 19505         this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedB
       y, id); | 
|  | 19506       } | 
|  | 19507     }, | 
|  | 19508 | 
|  | 19509     /** | 
|  | 19510      * Validates the input element and sets an error style if needed. | 
|  | 19511      * | 
|  | 19512      * @return {boolean} | 
|  | 19513      */ | 
|  | 19514     validate: function() { | 
|  | 19515       return this.inputElement.validate(); | 
|  | 19516     }, | 
|  | 19517 | 
|  | 19518     /** | 
|  | 19519      * Forward focus to inputElement. Overriden from IronControlState. | 
|  | 19520      */ | 
|  | 19521     _focusBlurHandler: function(event) { | 
|  | 19522       Polymer.IronControlState._focusBlurHandler.call(this, event); | 
|  | 19523 | 
|  | 19524       // Forward the focus to the nested input. | 
|  | 19525       if (this.focused && !this._shiftTabPressed) | 
|  | 19526         this._focusableElement.focus(); | 
|  | 19527     }, | 
|  | 19528 | 
|  | 19529     /** | 
|  | 19530      * Handler that is called when a shift+tab keypress is detected by the menu. | 
|  | 19531      * | 
|  | 19532      * @param {CustomEvent} event A key combination event. | 
|  | 19533      */ | 
|  | 19534     _onShiftTabDown: function(event) { | 
|  | 19535       var oldTabIndex = this.getAttribute('tabindex'); | 
|  | 19536       this._shiftTabPressed = true; | 
|  | 19537       this.setAttribute('tabindex', '-1'); | 
|  | 19538       this.async(function() { | 
|  | 19539         this.setAttribute('tabindex', oldTabIndex); | 
|  | 19540         this._shiftTabPressed = false; | 
|  | 19541       }, 1); | 
|  | 19542     }, | 
|  | 19543 | 
|  | 19544     /** | 
|  | 19545      * If `autoValidate` is true, then validates the element. | 
|  | 19546      */ | 
|  | 19547     _handleAutoValidate: function() { | 
|  | 19548       if (this.autoValidate) | 
|  | 19549         this.validate(); | 
|  | 19550     }, | 
|  | 19551 | 
|  | 19552     /** | 
|  | 19553      * Restores the cursor to its original position after updating the value. | 
|  | 19554      * @param {string} newValue The value that should be saved. | 
|  | 19555      */ | 
|  | 19556     updateValueAndPreserveCaret: function(newValue) { | 
|  | 19557       // Not all elements might have selection, and even if they have the | 
|  | 19558       // right properties, accessing them might throw an exception (like for | 
|  | 19559       // <input type=number>) | 
|  | 19560       try { | 
|  | 19561         var start = this.inputElement.selectionStart; | 
|  | 19562         this.value = newValue; | 
|  | 19563 | 
|  | 19564         // The cursor automatically jumps to the end after re-setting the value, | 
|  | 19565         // so restore it to its original position. | 
|  | 19566         this.inputElement.selectionStart = start; | 
|  | 19567         this.inputElement.selectionEnd = start; | 
|  | 19568       } catch (e) { | 
|  | 19569         // Just set the value and give up on the caret. | 
|  | 19570         this.value = newValue; | 
|  | 19571       } | 
|  | 19572     }, | 
|  | 19573 | 
|  | 19574     _computeAlwaysFloatLabel: function(alwaysFloatLabel, placeholder) { | 
|  | 19575       return placeholder || alwaysFloatLabel; | 
|  | 19576     }, | 
|  | 19577 | 
|  | 19578     _updateAriaLabelledBy: function() { | 
|  | 19579       var label = Polymer.dom(this.root).querySelector('label'); | 
|  | 19580       if (!label) { | 
|  | 19581         this._ariaLabelledBy = ''; | 
|  | 19582         return; | 
|  | 19583       } | 
|  | 19584       var labelledBy; | 
|  | 19585       if (label.id) { | 
|  | 19586         labelledBy = label.id; | 
|  | 19587       } else { | 
|  | 19588         labelledBy = 'paper-input-label-' + Polymer.PaperInputHelper.NextLabelID
       ++; | 
|  | 19589         label.id = labelledBy; | 
|  | 19590       } | 
|  | 19591       this._ariaLabelledBy = labelledBy; | 
|  | 19592     }, | 
|  | 19593 | 
|  | 19594     _onChange:function(event) { | 
|  | 19595       // In the Shadow DOM, the `change` event is not leaked into the | 
|  | 19596       // ancestor tree, so we must do this manually. | 
|  | 19597       // See https://w3c.github.io/webcomponents/spec/shadow/#events-that-are-no
       t-leaked-into-ancestor-trees. | 
|  | 19598       if (this.shadowRoot) { | 
|  | 19599         this.fire(event.type, {sourceEvent: event}, { | 
|  | 19600           node: this, | 
|  | 19601           bubbles: event.bubbles, | 
|  | 19602           cancelable: event.cancelable | 
|  | 19603         }); | 
|  | 19604       } | 
|  | 19605     }, | 
|  | 19606 | 
|  | 19607     _autofocusChanged: function() { | 
|  | 19608       // Firefox doesn't respect the autofocus attribute if it's applied after | 
|  | 19609       // the page is loaded (Chrome/WebKit do respect it), preventing an | 
|  | 19610       // autofocus attribute specified in markup from taking effect when the | 
|  | 19611       // element is upgraded. As a workaround, if the autofocus property is set, | 
|  | 19612       // and the focus hasn't already been moved elsewhere, we take focus. | 
|  | 19613       if (this.autofocus && this._focusableElement) { | 
|  | 19614 | 
|  | 19615         // In IE 11, the default document.activeElement can be the page's | 
|  | 19616         // outermost html element, but there are also cases (under the | 
|  | 19617         // polyfill?) in which the activeElement is not a real HTMLElement, but | 
|  | 19618         // just a plain object. We identify the latter case as having no valid | 
|  | 19619         // activeElement. | 
|  | 19620         var activeElement = document.activeElement; | 
|  | 19621         var isActiveElementValid = activeElement instanceof HTMLElement; | 
|  | 19622 | 
|  | 19623         // Has some other element has already taken the focus? | 
|  | 19624         var isSomeElementActive = isActiveElementValid && | 
|  | 19625             activeElement !== document.body && | 
|  | 19626             activeElement !== document.documentElement; /* IE 11 */ | 
|  | 19627         if (!isSomeElementActive) { | 
|  | 19628           // No specific element has taken the focus yet, so we can take it. | 
|  | 19629           this._focusableElement.focus(); | 
|  | 19630         } | 
|  | 19631       } | 
|  | 19632     } | 
|  | 19633   } | 
|  | 19634 | 
|  | 19635   /** @polymerBehavior */ | 
|  | 19636   Polymer.PaperInputBehavior = [ | 
|  | 19637     Polymer.IronControlState, | 
|  | 19638     Polymer.IronA11yKeysBehavior, | 
|  | 19639     Polymer.PaperInputBehaviorImpl | 
|  | 19640   ]; | 
|  | 19641 </script> | 
|  | 19642 <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,
       300,300italic,400italic,500,500italic,700,700italic"> | 
|  | 19643 <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono
       :400,700"> | 
|  | 19644 <style is="custom-style"> | 
|  | 19645 | 
|  | 19646   :root { | 
|  | 19647 | 
|  | 19648     /* Shared Styles */ | 
|  | 19649     --paper-font-common-base: { | 
|  | 19650       font-family: 'Roboto', 'Noto', sans-serif; | 
|  | 19651       -webkit-font-smoothing: antialiased; | 
|  | 19652     }; | 
|  | 19653 | 
|  | 19654     --paper-font-common-code: { | 
|  | 19655       font-family: 'Roboto Mono', 'Consolas', 'Menlo', monospace; | 
|  | 19656       -webkit-font-smoothing: antialiased; | 
|  | 19657     }; | 
|  | 19658 | 
|  | 19659     --paper-font-common-expensive-kerning: { | 
|  | 19660       text-rendering: optimizeLegibility; | 
|  | 19661     }; | 
|  | 19662 | 
|  | 19663     --paper-font-common-nowrap: { | 
|  | 19664       white-space: nowrap; | 
|  | 19665       overflow: hidden; | 
|  | 19666       text-overflow: ellipsis; | 
|  | 19667     }; | 
|  | 19668 | 
|  | 19669     /* Material Font Styles */ | 
|  | 19670 | 
|  | 19671     --paper-font-display4: { | 
|  | 19672       @apply(--paper-font-common-base); | 
|  | 19673       @apply(--paper-font-common-nowrap); | 
|  | 19674 | 
|  | 19675       font-size: 112px; | 
|  | 19676       font-weight: 300; | 
|  | 19677       letter-spacing: -.044em; | 
|  | 19678       line-height: 120px; | 
|  | 19679     }; | 
|  | 19680 | 
|  | 19681     --paper-font-display3: { | 
|  | 19682       @apply(--paper-font-common-base); | 
|  | 19683       @apply(--paper-font-common-nowrap); | 
|  | 19684 | 
|  | 19685       font-size: 56px; | 
|  | 19686       font-weight: 400; | 
|  | 19687       letter-spacing: -.026em; | 
|  | 19688       line-height: 60px; | 
|  | 19689     }; | 
|  | 19690 | 
|  | 19691     --paper-font-display2: { | 
|  | 19692       @apply(--paper-font-common-base); | 
|  | 19693 | 
|  | 19694       font-size: 45px; | 
|  | 19695       font-weight: 400; | 
|  | 19696       letter-spacing: -.018em; | 
|  | 19697       line-height: 48px; | 
|  | 19698     }; | 
|  | 19699 | 
|  | 19700     --paper-font-display1: { | 
|  | 19701       @apply(--paper-font-common-base); | 
|  | 19702 | 
|  | 19703       font-size: 34px; | 
|  | 19704       font-weight: 400; | 
|  | 19705       letter-spacing: -.01em; | 
|  | 19706       line-height: 40px; | 
|  | 19707     }; | 
|  | 19708 | 
|  | 19709     --paper-font-headline: { | 
|  | 19710       @apply(--paper-font-common-base); | 
|  | 19711 | 
|  | 19712       font-size: 24px; | 
|  | 19713       font-weight: 400; | 
|  | 19714       letter-spacing: -.012em; | 
|  | 19715       line-height: 32px; | 
|  | 19716     }; | 
|  | 19717 | 
|  | 19718     --paper-font-title: { | 
|  | 19719       @apply(--paper-font-common-base); | 
|  | 19720       @apply(--paper-font-common-nowrap); | 
|  | 19721 | 
|  | 19722       font-size: 20px; | 
|  | 19723       font-weight: 500; | 
|  | 19724       line-height: 28px; | 
|  | 19725     }; | 
|  | 19726 | 
|  | 19727     --paper-font-subhead: { | 
|  | 19728       @apply(--paper-font-common-base); | 
|  | 19729 | 
|  | 19730       font-size: 16px; | 
|  | 19731       font-weight: 400; | 
|  | 19732       line-height: 24px; | 
|  | 19733     }; | 
|  | 19734 | 
|  | 19735     --paper-font-body2: { | 
|  | 19736       @apply(--paper-font-common-base); | 
|  | 19737 | 
|  | 19738       font-size: 14px; | 
|  | 19739       font-weight: 500; | 
|  | 19740       line-height: 24px; | 
|  | 19741     }; | 
|  | 19742 | 
|  | 19743     --paper-font-body1: { | 
|  | 19744       @apply(--paper-font-common-base); | 
|  | 19745 | 
|  | 19746       font-size: 14px; | 
|  | 19747       font-weight: 400; | 
|  | 19748       line-height: 20px; | 
|  | 19749     }; | 
|  | 19750 | 
|  | 19751     --paper-font-caption: { | 
|  | 19752       @apply(--paper-font-common-base); | 
|  | 19753       @apply(--paper-font-common-nowrap); | 
|  | 19754 | 
|  | 19755       font-size: 12px; | 
|  | 19756       font-weight: 400; | 
|  | 19757       letter-spacing: 0.011em; | 
|  | 19758       line-height: 20px; | 
|  | 19759     }; | 
|  | 19760 | 
|  | 19761     --paper-font-menu: { | 
|  | 19762       @apply(--paper-font-common-base); | 
|  | 19763       @apply(--paper-font-common-nowrap); | 
|  | 19764 | 
|  | 19765       font-size: 13px; | 
|  | 19766       font-weight: 500; | 
|  | 19767       line-height: 24px; | 
|  | 19768     }; | 
|  | 19769 | 
|  | 19770     --paper-font-button: { | 
|  | 19771       @apply(--paper-font-common-base); | 
|  | 19772       @apply(--paper-font-common-nowrap); | 
|  | 19773 | 
|  | 19774       font-size: 14px; | 
|  | 19775       font-weight: 500; | 
|  | 19776       letter-spacing: 0.018em; | 
|  | 19777       line-height: 24px; | 
|  | 19778       text-transform: uppercase; | 
|  | 19779     }; | 
|  | 19780 | 
|  | 19781     --paper-font-code2: { | 
|  | 19782       @apply(--paper-font-common-code); | 
|  | 19783 | 
|  | 19784       font-size: 14px; | 
|  | 19785       font-weight: 700; | 
|  | 19786       line-height: 20px; | 
|  | 19787     }; | 
|  | 19788 | 
|  | 19789     --paper-font-code1: { | 
|  | 19790       @apply(--paper-font-common-code); | 
|  | 19791 | 
|  | 19792       font-size: 14px; | 
|  | 19793       font-weight: 500; | 
|  | 19794       line-height: 20px; | 
|  | 19795     }; | 
|  | 19796 | 
|  | 19797   } | 
|  | 19798 | 
|  | 19799 </style> | 
|  | 19800 <script> | 
|  | 19801 | 
|  | 19802   /** | 
|  | 19803    * Use `Polymer.PaperInputAddonBehavior` to implement an add-on for `<paper-in
       put-container>`. A | 
|  | 19804    * add-on appears below the input, and may display information based on the in
       put value and | 
|  | 19805    * validity such as a character counter or an error message. | 
|  | 19806    * @polymerBehavior | 
|  | 19807    */ | 
|  | 19808   Polymer.PaperInputAddonBehavior = { | 
|  | 19809 | 
|  | 19810     hostAttributes: { | 
|  | 19811       'add-on': '' | 
|  | 19812     }, | 
|  | 19813 | 
|  | 19814     attached: function() { | 
|  | 19815       this.fire('addon-attached'); | 
|  | 19816     }, | 
|  | 19817 | 
|  | 19818     /** | 
|  | 19819      * The function called by `<paper-input-container>` when the input value or 
       validity changes. | 
|  | 19820      * @param {{ | 
|  | 19821      *   inputElement: (Element|undefined), | 
|  | 19822      *   value: (string|undefined), | 
|  | 19823      *   invalid: boolean | 
|  | 19824      * }} state - | 
|  | 19825      *     inputElement: The input element. | 
|  | 19826      *     value: The input value. | 
|  | 19827      *     invalid: True if the input value is invalid. | 
|  | 19828      */ | 
|  | 19829     update: function(state) { | 
|  | 19830     } | 
|  | 19831 | 
|  | 19832   }; | 
|  | 19833 | 
|  | 19834 </script> | 
|  | 19835 | 
|  | 19836 | 
|  | 19837 <dom-module id="paper-input-char-counter" assetpath="/res/imp/bower_components/p
       aper-input/"> | 
|  | 19838   <template> | 
|  | 19839     <style> | 
|  | 19840       :host { | 
|  | 19841         display: inline-block; | 
|  | 19842         float: right; | 
|  | 19843 | 
|  | 19844         @apply(--paper-font-caption); | 
|  | 19845         @apply(--paper-input-char-counter); | 
|  | 19846       } | 
|  | 19847 | 
|  | 19848       :host([hidden]) { | 
|  | 19849         display: none !important; | 
|  | 19850       } | 
|  | 19851 | 
|  | 19852       :host-context([dir="rtl"]) { | 
|  | 19853         float: left; | 
|  | 19854       } | 
|  | 19855     </style> | 
|  | 19856 | 
|  | 19857     <span>[[_charCounterStr]]</span> | 
|  | 19858   </template> | 
|  | 19859 </dom-module> | 
|  | 19860 | 
|  | 19861 <script> | 
|  | 19862   Polymer({ | 
|  | 19863     is: 'paper-input-char-counter', | 
|  | 19864 | 
|  | 19865     behaviors: [ | 
|  | 19866       Polymer.PaperInputAddonBehavior | 
|  | 19867     ], | 
|  | 19868 | 
|  | 19869     properties: { | 
|  | 19870       _charCounterStr: { | 
|  | 19871         type: String, | 
|  | 19872         value: '0' | 
|  | 19873       } | 
|  | 19874     }, | 
|  | 19875 | 
|  | 19876     /** | 
|  | 19877      * This overrides the update function in PaperInputAddonBehavior. | 
|  | 19878      * @param {{ | 
|  | 19879      *   inputElement: (Element|undefined), | 
|  | 19880      *   value: (string|undefined), | 
|  | 19881      *   invalid: boolean | 
|  | 19882      * }} state - | 
|  | 19883      *     inputElement: The input element. | 
|  | 19884      *     value: The input value. | 
|  | 19885      *     invalid: True if the input value is invalid. | 
|  | 19886      */ | 
|  | 19887     update: function(state) { | 
|  | 19888       if (!state.inputElement) { | 
|  | 19889         return; | 
|  | 19890       } | 
|  | 19891 | 
|  | 19892       state.value = state.value || ''; | 
|  | 19893 | 
|  | 19894       var counter = state.value.toString().length.toString(); | 
|  | 19895 | 
|  | 19896       if (state.inputElement.hasAttribute('maxlength')) { | 
|  | 19897         counter += '/' + state.inputElement.getAttribute('maxlength'); | 
|  | 19898       } | 
|  | 19899 | 
|  | 19900       this._charCounterStr = counter; | 
|  | 19901     } | 
|  | 19902   }); | 
|  | 19903 </script> | 
|  | 19904 | 
|  | 19905 | 
|  | 19906 <dom-module id="paper-input-container" assetpath="/res/imp/bower_components/pape
       r-input/"> | 
|  | 19907   <template> | 
|  | 19908     <style> | 
|  | 19909       :host { | 
|  | 19910         display: block; | 
|  | 19911         padding: 8px 0; | 
|  | 19912 | 
|  | 19913         @apply(--paper-input-container); | 
|  | 19914       } | 
|  | 19915 | 
|  | 19916       :host([inline]) { | 
|  | 19917         display: inline-block; | 
|  | 19918       } | 
|  | 19919 | 
|  | 19920       :host([disabled]) { | 
|  | 19921         pointer-events: none; | 
|  | 19922         opacity: 0.33; | 
|  | 19923 | 
|  | 19924         @apply(--paper-input-container-disabled); | 
|  | 19925       } | 
|  | 19926 | 
|  | 19927       :host([hidden]) { | 
|  | 19928         display: none !important; | 
|  | 19929       } | 
|  | 19930 | 
|  | 19931       .floated-label-placeholder { | 
|  | 19932         @apply(--paper-font-caption); | 
|  | 19933       } | 
|  | 19934 | 
|  | 19935       .underline { | 
|  | 19936         position: relative; | 
|  | 19937       } | 
|  | 19938 | 
|  | 19939       .focused-line { | 
|  | 19940         @apply(--layout-fit); | 
|  | 19941 | 
|  | 19942         background: var(--paper-input-container-focus-color, --primary-color); | 
|  | 19943         height: 2px; | 
|  | 19944 | 
|  | 19945         -webkit-transform-origin: center center; | 
|  | 19946         transform-origin: center center; | 
|  | 19947         -webkit-transform: scale3d(0,1,1); | 
|  | 19948         transform: scale3d(0,1,1); | 
|  | 19949 | 
|  | 19950         @apply(--paper-input-container-underline-focus); | 
|  | 19951       } | 
|  | 19952 | 
|  | 19953       .underline.is-highlighted .focused-line { | 
|  | 19954         -webkit-transform: none; | 
|  | 19955         transform: none; | 
|  | 19956         -webkit-transition: -webkit-transform 0.25s; | 
|  | 19957         transition: transform 0.25s; | 
|  | 19958 | 
|  | 19959         @apply(--paper-transition-easing); | 
|  | 19960       } | 
|  | 19961 | 
|  | 19962       .underline.is-invalid .focused-line { | 
|  | 19963         background: var(--paper-input-container-invalid-color, --error-color); | 
|  | 19964         -webkit-transform: none; | 
|  | 19965         transform: none; | 
|  | 19966         -webkit-transition: -webkit-transform 0.25s; | 
|  | 19967         transition: transform 0.25s; | 
|  | 19968 | 
|  | 19969         @apply(--paper-transition-easing); | 
|  | 19970       } | 
|  | 19971 | 
|  | 19972       .unfocused-line { | 
|  | 19973         @apply(--layout-fit); | 
|  | 19974 | 
|  | 19975         background: var(--paper-input-container-color, --secondary-text-color); | 
|  | 19976         height: 1px; | 
|  | 19977 | 
|  | 19978         @apply(--paper-input-container-underline); | 
|  | 19979       } | 
|  | 19980 | 
|  | 19981       :host([disabled]) .unfocused-line { | 
|  | 19982         border-bottom: 1px dashed; | 
|  | 19983         border-color: var(--paper-input-container-color, --secondary-text-color)
       ; | 
|  | 19984         background: transparent; | 
|  | 19985 | 
|  | 19986         @apply(--paper-input-container-underline-disabled); | 
|  | 19987       } | 
|  | 19988 | 
|  | 19989       .label-and-input-container { | 
|  | 19990         @apply(--layout-flex-auto); | 
|  | 19991         @apply(--layout-relative); | 
|  | 19992 | 
|  | 19993         width: 100%; | 
|  | 19994         max-width: 100%; | 
|  | 19995       } | 
|  | 19996 | 
|  | 19997       .input-content { | 
|  | 19998         @apply(--layout-horizontal); | 
|  | 19999         @apply(--layout-center); | 
|  | 20000 | 
|  | 20001         position: relative; | 
|  | 20002       } | 
|  | 20003 | 
|  | 20004       .input-content ::content label, | 
|  | 20005       .input-content ::content .paper-input-label { | 
|  | 20006         position: absolute; | 
|  | 20007         top: 0; | 
|  | 20008         right: 0; | 
|  | 20009         left: 0; | 
|  | 20010         width: 100%; | 
|  | 20011         font: inherit; | 
|  | 20012         color: var(--paper-input-container-color, --secondary-text-color); | 
|  | 20013         -webkit-transition: -webkit-transform 0.25s, width 0.25s; | 
|  | 20014         transition: transform 0.25s, width 0.25s; | 
|  | 20015         -webkit-transform-origin: left top; | 
|  | 20016         transform-origin: left top; | 
|  | 20017 | 
|  | 20018         @apply(--paper-font-common-nowrap); | 
|  | 20019         @apply(--paper-font-subhead); | 
|  | 20020         @apply(--paper-input-container-label); | 
|  | 20021         @apply(--paper-transition-easing); | 
|  | 20022       } | 
|  | 20023 | 
|  | 20024       .input-content.label-is-floating ::content label, | 
|  | 20025       .input-content.label-is-floating ::content .paper-input-label { | 
|  | 20026         -webkit-transform: translateY(-75%) scale(0.75); | 
|  | 20027         transform: translateY(-75%) scale(0.75); | 
|  | 20028 | 
|  | 20029         /* Since we scale to 75/100 of the size, we actually have 100/75 of the | 
|  | 20030         original space now available */ | 
|  | 20031         width: 133%; | 
|  | 20032 | 
|  | 20033         @apply(--paper-input-container-label-floating); | 
|  | 20034       } | 
|  | 20035 | 
|  | 20036       :host-context([dir="rtl"]) .input-content.label-is-floating ::content labe
       l, | 
|  | 20037       :host-context([dir="rtl"]) .input-content.label-is-floating ::content .pap
       er-input-label { | 
|  | 20038         /* TODO(noms): Figure out why leaving the width at 133% before the anima
       tion | 
|  | 20039          * actually makes | 
|  | 20040          * it wider on the right side, not left side, as you would expect in RTL
        */ | 
|  | 20041         width: 100%; | 
|  | 20042         -webkit-transform-origin: right top; | 
|  | 20043         transform-origin: right top; | 
|  | 20044       } | 
|  | 20045 | 
|  | 20046       .input-content.label-is-highlighted ::content label, | 
|  | 20047       .input-content.label-is-highlighted ::content .paper-input-label { | 
|  | 20048         color: var(--paper-input-container-focus-color, --primary-color); | 
|  | 20049 | 
|  | 20050         @apply(--paper-input-container-label-focus); | 
|  | 20051       } | 
|  | 20052 | 
|  | 20053       .input-content.is-invalid ::content label, | 
|  | 20054       .input-content.is-invalid ::content .paper-input-label { | 
|  | 20055         color: var(--paper-input-container-invalid-color, --error-color); | 
|  | 20056       } | 
|  | 20057 | 
|  | 20058       .input-content.label-is-hidden ::content label, | 
|  | 20059       .input-content.label-is-hidden ::content .paper-input-label { | 
|  | 20060         visibility: hidden; | 
|  | 20061       } | 
|  | 20062 | 
|  | 20063       .input-content ::content input, | 
|  | 20064       .input-content ::content textarea, | 
|  | 20065       .input-content ::content iron-autogrow-textarea, | 
|  | 20066       .input-content ::content .paper-input-input { | 
|  | 20067         position: relative; /* to make a stacking context */ | 
|  | 20068         outline: none; | 
|  | 20069         box-shadow: none; | 
|  | 20070         padding: 0; | 
|  | 20071         width: 100%; | 
|  | 20072         max-width: 100%; | 
|  | 20073         background: transparent; | 
|  | 20074         border: none; | 
|  | 20075         color: var(--paper-input-container-input-color, --primary-text-color); | 
|  | 20076         -webkit-appearance: none; | 
|  | 20077         text-align: inherit; | 
|  | 20078 | 
|  | 20079         @apply(--paper-font-subhead); | 
|  | 20080         @apply(--paper-input-container-input); | 
|  | 20081       } | 
|  | 20082 | 
|  | 20083       ::content [prefix] { | 
|  | 20084         @apply(--paper-font-subhead); | 
|  | 20085 | 
|  | 20086         @apply(--paper-input-prefix); | 
|  | 20087         @apply(--layout-flex-none); | 
|  | 20088       } | 
|  | 20089 | 
|  | 20090       ::content [suffix] { | 
|  | 20091         @apply(--paper-font-subhead); | 
|  | 20092 | 
|  | 20093         @apply(--paper-input-suffix); | 
|  | 20094         @apply(--layout-flex-none); | 
|  | 20095       } | 
|  | 20096 | 
|  | 20097       /* Firefox sets a min-width on the input, which can cause layout issues */ | 
|  | 20098       .input-content ::content input { | 
|  | 20099         min-width: 0; | 
|  | 20100       } | 
|  | 20101 | 
|  | 20102       .input-content ::content textarea { | 
|  | 20103         resize: none; | 
|  | 20104       } | 
|  | 20105 | 
|  | 20106       .add-on-content { | 
|  | 20107         position: relative; | 
|  | 20108       } | 
|  | 20109 | 
|  | 20110       .add-on-content.is-invalid ::content * { | 
|  | 20111         color: var(--paper-input-container-invalid-color, --error-color); | 
|  | 20112       } | 
|  | 20113 | 
|  | 20114       .add-on-content.is-highlighted ::content * { | 
|  | 20115         color: var(--paper-input-container-focus-color, --primary-color); | 
|  | 20116       } | 
|  | 20117     </style> | 
|  | 20118 | 
|  | 20119     <template is="dom-if" if="[[!noLabelFloat]]"> | 
|  | 20120       <div class="floated-label-placeholder" aria-hidden="true"> </div> | 
|  | 20121     </template> | 
|  | 20122 | 
|  | 20123     <div class$="[[_computeInputContentClass(noLabelFloat,alwaysFloatLabel,focus
       ed,invalid,_inputHasContent)]]"> | 
|  | 20124       <content select="[prefix]" id="prefix"></content> | 
|  | 20125 | 
|  | 20126       <div class="label-and-input-container" id="labelAndInputContainer"> | 
|  | 20127         <content select=":not([add-on]):not([prefix]):not([suffix])"></content> | 
|  | 20128       </div> | 
|  | 20129 | 
|  | 20130       <content select="[suffix]"></content> | 
|  | 20131     </div> | 
|  | 20132 | 
|  | 20133     <div class$="[[_computeUnderlineClass(focused,invalid)]]"> | 
|  | 20134       <div class="unfocused-line"></div> | 
|  | 20135       <div class="focused-line"></div> | 
|  | 20136     </div> | 
|  | 20137 | 
|  | 20138     <div class$="[[_computeAddOnContentClass(focused,invalid)]]"> | 
|  | 20139       <content id="addOnContent" select="[add-on]"></content> | 
|  | 20140     </div> | 
|  | 20141   </template> | 
|  | 20142 </dom-module> | 
|  | 20143 | 
|  | 20144 <script> | 
|  | 20145   Polymer({ | 
|  | 20146     is: 'paper-input-container', | 
|  | 20147 | 
|  | 20148     properties: { | 
|  | 20149       /** | 
|  | 20150        * Set to true to disable the floating label. The label disappears when th
       e input value is | 
|  | 20151        * not null. | 
|  | 20152        */ | 
|  | 20153       noLabelFloat: { | 
|  | 20154         type: Boolean, | 
|  | 20155         value: false | 
|  | 20156       }, | 
|  | 20157 | 
|  | 20158       /** | 
|  | 20159        * Set to true to always float the floating label. | 
|  | 20160        */ | 
|  | 20161       alwaysFloatLabel: { | 
|  | 20162         type: Boolean, | 
|  | 20163         value: false | 
|  | 20164       }, | 
|  | 20165 | 
|  | 20166       /** | 
|  | 20167        * The attribute to listen for value changes on. | 
|  | 20168        */ | 
|  | 20169       attrForValue: { | 
|  | 20170         type: String, | 
|  | 20171         value: 'bind-value' | 
|  | 20172       }, | 
|  | 20173 | 
|  | 20174       /** | 
|  | 20175        * Set to true to auto-validate the input value when it changes. | 
|  | 20176        */ | 
|  | 20177       autoValidate: { | 
|  | 20178         type: Boolean, | 
|  | 20179         value: false | 
|  | 20180       }, | 
|  | 20181 | 
|  | 20182       /** | 
|  | 20183        * True if the input is invalid. This property is set automatically when t
       he input value | 
|  | 20184        * changes if auto-validating, or when the `iron-input-validate` event is 
       heard from a child. | 
|  | 20185        */ | 
|  | 20186       invalid: { | 
|  | 20187         observer: '_invalidChanged', | 
|  | 20188         type: Boolean, | 
|  | 20189         value: false | 
|  | 20190       }, | 
|  | 20191 | 
|  | 20192       /** | 
|  | 20193        * True if the input has focus. | 
|  | 20194        */ | 
|  | 20195       focused: { | 
|  | 20196         readOnly: true, | 
|  | 20197         type: Boolean, | 
|  | 20198         value: false, | 
|  | 20199         notify: true | 
|  | 20200       }, | 
|  | 20201 | 
|  | 20202       _addons: { | 
|  | 20203         type: Array | 
|  | 20204         // do not set a default value here intentionally - it will be initialize
       d lazily when a | 
|  | 20205         // distributed child is attached, which may occur before configuration f
       or this element | 
|  | 20206         // in polyfill. | 
|  | 20207       }, | 
|  | 20208 | 
|  | 20209       _inputHasContent: { | 
|  | 20210         type: Boolean, | 
|  | 20211         value: false | 
|  | 20212       }, | 
|  | 20213 | 
|  | 20214       _inputSelector: { | 
|  | 20215         type: String, | 
|  | 20216         value: 'input,textarea,.paper-input-input' | 
|  | 20217       }, | 
|  | 20218 | 
|  | 20219       _boundOnFocus: { | 
|  | 20220         type: Function, | 
|  | 20221         value: function() { | 
|  | 20222           return this._onFocus.bind(this); | 
|  | 20223         } | 
|  | 20224       }, | 
|  | 20225 | 
|  | 20226       _boundOnBlur: { | 
|  | 20227         type: Function, | 
|  | 20228         value: function() { | 
|  | 20229           return this._onBlur.bind(this); | 
|  | 20230         } | 
|  | 20231       }, | 
|  | 20232 | 
|  | 20233       _boundOnInput: { | 
|  | 20234         type: Function, | 
|  | 20235         value: function() { | 
|  | 20236           return this._onInput.bind(this); | 
|  | 20237         } | 
|  | 20238       }, | 
|  | 20239 | 
|  | 20240       _boundValueChanged: { | 
|  | 20241         type: Function, | 
|  | 20242         value: function() { | 
|  | 20243           return this._onValueChanged.bind(this); | 
|  | 20244         } | 
|  | 20245       } | 
|  | 20246     }, | 
|  | 20247 | 
|  | 20248     listeners: { | 
|  | 20249       'addon-attached': '_onAddonAttached', | 
|  | 20250       'iron-input-validate': '_onIronInputValidate' | 
|  | 20251     }, | 
|  | 20252 | 
|  | 20253     get _valueChangedEvent() { | 
|  | 20254       return this.attrForValue + '-changed'; | 
|  | 20255     }, | 
|  | 20256 | 
|  | 20257     get _propertyForValue() { | 
|  | 20258       return Polymer.CaseMap.dashToCamelCase(this.attrForValue); | 
|  | 20259     }, | 
|  | 20260 | 
|  | 20261     get _inputElement() { | 
|  | 20262       return Polymer.dom(this).querySelector(this._inputSelector); | 
|  | 20263     }, | 
|  | 20264 | 
|  | 20265     get _inputElementValue() { | 
|  | 20266       return this._inputElement[this._propertyForValue] || this._inputElement.va
       lue; | 
|  | 20267     }, | 
|  | 20268 | 
|  | 20269     ready: function() { | 
|  | 20270       if (!this._addons) { | 
|  | 20271         this._addons = []; | 
|  | 20272       } | 
|  | 20273       this.addEventListener('focus', this._boundOnFocus, true); | 
|  | 20274       this.addEventListener('blur', this._boundOnBlur, true); | 
|  | 20275     }, | 
|  | 20276 | 
|  | 20277     attached: function() { | 
|  | 20278       if (this.attrForValue) { | 
|  | 20279         this._inputElement.addEventListener(this._valueChangedEvent, this._bound
       ValueChanged); | 
|  | 20280       } else { | 
|  | 20281         this.addEventListener('input', this._onInput); | 
|  | 20282       } | 
|  | 20283 | 
|  | 20284       // Only validate when attached if the input already has a value. | 
|  | 20285       if (this._inputElementValue != '') { | 
|  | 20286         this._handleValueAndAutoValidate(this._inputElement); | 
|  | 20287       } else { | 
|  | 20288         this._handleValue(this._inputElement); | 
|  | 20289       } | 
|  | 20290     }, | 
|  | 20291 | 
|  | 20292     _onAddonAttached: function(event) { | 
|  | 20293       if (!this._addons) { | 
|  | 20294         this._addons = []; | 
|  | 20295       } | 
|  | 20296       var target = event.target; | 
|  | 20297       if (this._addons.indexOf(target) === -1) { | 
|  | 20298         this._addons.push(target); | 
|  | 20299         if (this.isAttached) { | 
|  | 20300           this._handleValue(this._inputElement); | 
|  | 20301         } | 
|  | 20302       } | 
|  | 20303     }, | 
|  | 20304 | 
|  | 20305     _onFocus: function() { | 
|  | 20306       this._setFocused(true); | 
|  | 20307     }, | 
|  | 20308 | 
|  | 20309     _onBlur: function() { | 
|  | 20310       this._setFocused(false); | 
|  | 20311       this._handleValueAndAutoValidate(this._inputElement); | 
|  | 20312     }, | 
|  | 20313 | 
|  | 20314     _onInput: function(event) { | 
|  | 20315       this._handleValueAndAutoValidate(event.target); | 
|  | 20316     }, | 
|  | 20317 | 
|  | 20318     _onValueChanged: function(event) { | 
|  | 20319       this._handleValueAndAutoValidate(event.target); | 
|  | 20320     }, | 
|  | 20321 | 
|  | 20322     _handleValue: function(inputElement) { | 
|  | 20323       var value = this._inputElementValue; | 
|  | 20324 | 
|  | 20325       // type="number" hack needed because this.value is empty until it's valid | 
|  | 20326       if (value || value === 0 || (inputElement.type === 'number' && !inputEleme
       nt.checkValidity())) { | 
|  | 20327         this._inputHasContent = true; | 
|  | 20328       } else { | 
|  | 20329         this._inputHasContent = false; | 
|  | 20330       } | 
|  | 20331 | 
|  | 20332       this.updateAddons({ | 
|  | 20333         inputElement: inputElement, | 
|  | 20334         value: value, | 
|  | 20335         invalid: this.invalid | 
|  | 20336       }); | 
|  | 20337     }, | 
|  | 20338 | 
|  | 20339     _handleValueAndAutoValidate: function(inputElement) { | 
|  | 20340       if (this.autoValidate) { | 
|  | 20341         var valid; | 
|  | 20342         if (inputElement.validate) { | 
|  | 20343           valid = inputElement.validate(this._inputElementValue); | 
|  | 20344         } else { | 
|  | 20345           valid = inputElement.checkValidity(); | 
|  | 20346         } | 
|  | 20347         this.invalid = !valid; | 
|  | 20348       } | 
|  | 20349 | 
|  | 20350       // Call this last to notify the add-ons. | 
|  | 20351       this._handleValue(inputElement); | 
|  | 20352     }, | 
|  | 20353 | 
|  | 20354     _onIronInputValidate: function(event) { | 
|  | 20355       this.invalid = this._inputElement.invalid; | 
|  | 20356     }, | 
|  | 20357 | 
|  | 20358     _invalidChanged: function() { | 
|  | 20359       if (this._addons) { | 
|  | 20360         this.updateAddons({invalid: this.invalid}); | 
|  | 20361       } | 
|  | 20362     }, | 
|  | 20363 | 
|  | 20364     /** | 
|  | 20365      * Call this to update the state of add-ons. | 
|  | 20366      * @param {Object} state Add-on state. | 
|  | 20367      */ | 
|  | 20368     updateAddons: function(state) { | 
|  | 20369       for (var addon, index = 0; addon = this._addons[index]; index++) { | 
|  | 20370         addon.update(state); | 
|  | 20371       } | 
|  | 20372     }, | 
|  | 20373 | 
|  | 20374     _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused,
        invalid, _inputHasContent) { | 
|  | 20375       var cls = 'input-content'; | 
|  | 20376       if (!noLabelFloat) { | 
|  | 20377         var label = this.querySelector('label'); | 
|  | 20378 | 
|  | 20379         if (alwaysFloatLabel || _inputHasContent) { | 
|  | 20380           cls += ' label-is-floating'; | 
|  | 20381           // If the label is floating, ignore any offsets that may have been | 
|  | 20382           // applied from a prefix element. | 
|  | 20383           this.$.labelAndInputContainer.style.position = 'static'; | 
|  | 20384 | 
|  | 20385           if (invalid) { | 
|  | 20386             cls += ' is-invalid'; | 
|  | 20387           } else if (focused) { | 
|  | 20388             cls += " label-is-highlighted"; | 
|  | 20389           } | 
|  | 20390         } else { | 
|  | 20391           // When the label is not floating, it should overlap the input element
       . | 
|  | 20392           if (label) { | 
|  | 20393             this.$.labelAndInputContainer.style.position = 'relative'; | 
|  | 20394           } | 
|  | 20395         } | 
|  | 20396       } else { | 
|  | 20397         if (_inputHasContent) { | 
|  | 20398           cls += ' label-is-hidden'; | 
|  | 20399         } | 
|  | 20400       } | 
|  | 20401       return cls; | 
|  | 20402     }, | 
|  | 20403 | 
|  | 20404     _computeUnderlineClass: function(focused, invalid) { | 
|  | 20405       var cls = 'underline'; | 
|  | 20406       if (invalid) { | 
|  | 20407         cls += ' is-invalid'; | 
|  | 20408       } else if (focused) { | 
|  | 20409         cls += ' is-highlighted' | 
|  | 20410       } | 
|  | 20411       return cls; | 
|  | 20412     }, | 
|  | 20413 | 
|  | 20414     _computeAddOnContentClass: function(focused, invalid) { | 
|  | 20415       var cls = 'add-on-content'; | 
|  | 20416       if (invalid) { | 
|  | 20417         cls += ' is-invalid'; | 
|  | 20418       } else if (focused) { | 
|  | 20419         cls += ' is-highlighted' | 
|  | 20420       } | 
|  | 20421       return cls; | 
|  | 20422     } | 
|  | 20423   }); | 
|  | 20424 </script> | 
|  | 20425 | 
|  | 20426 | 
|  | 20427 <dom-module id="paper-input-error" assetpath="/res/imp/bower_components/paper-in
       put/"> | 
|  | 20428   <template> | 
|  | 20429     <style> | 
|  | 20430       :host { | 
|  | 20431         display: inline-block; | 
|  | 20432         visibility: hidden; | 
|  | 20433 | 
|  | 20434         color: var(--paper-input-container-invalid-color, --error-color); | 
|  | 20435 | 
|  | 20436         @apply(--paper-font-caption); | 
|  | 20437         @apply(--paper-input-error); | 
|  | 20438         position: absolute; | 
|  | 20439         left:0; | 
|  | 20440         right:0; | 
|  | 20441       } | 
|  | 20442 | 
|  | 20443       :host([invalid]) { | 
|  | 20444         visibility: visible; | 
|  | 20445       }; | 
|  | 20446     </style> | 
|  | 20447 | 
|  | 20448     <content></content> | 
|  | 20449   </template> | 
|  | 20450 </dom-module> | 
|  | 20451 | 
|  | 20452 <script> | 
|  | 20453   Polymer({ | 
|  | 20454     is: 'paper-input-error', | 
|  | 20455 | 
|  | 20456     behaviors: [ | 
|  | 20457       Polymer.PaperInputAddonBehavior | 
|  | 20458     ], | 
|  | 20459 | 
|  | 20460     properties: { | 
|  | 20461       /** | 
|  | 20462        * True if the error is showing. | 
|  | 20463        */ | 
|  | 20464       invalid: { | 
|  | 20465         readOnly: true, | 
|  | 20466         reflectToAttribute: true, | 
|  | 20467         type: Boolean | 
|  | 20468       } | 
|  | 20469     }, | 
|  | 20470 | 
|  | 20471     /** | 
|  | 20472      * This overrides the update function in PaperInputAddonBehavior. | 
|  | 20473      * @param {{ | 
|  | 20474      *   inputElement: (Element|undefined), | 
|  | 20475      *   value: (string|undefined), | 
|  | 20476      *   invalid: boolean | 
|  | 20477      * }} state - | 
|  | 20478      *     inputElement: The input element. | 
|  | 20479      *     value: The input value. | 
|  | 20480      *     invalid: True if the input value is invalid. | 
|  | 20481      */ | 
|  | 20482     update: function(state) { | 
|  | 20483       this._setInvalid(state.invalid); | 
|  | 20484     } | 
|  | 20485   }); | 
|  | 20486 </script> | 
|  | 20487 | 
|  | 20488 | 
|  | 20489 <dom-module id="paper-input" assetpath="/res/imp/bower_components/paper-input/"> | 
|  | 20490   <template> | 
|  | 20491     <style> | 
|  | 20492       :host { | 
|  | 20493         display: block; | 
|  | 20494       } | 
|  | 20495 | 
|  | 20496       :host([hidden]) { | 
|  | 20497         display: none !important; | 
|  | 20498       } | 
|  | 20499 | 
|  | 20500       input::-webkit-input-placeholder { | 
|  | 20501         color: var(--paper-input-container-color, --secondary-text-color); | 
|  | 20502       } | 
|  | 20503 | 
|  | 20504       input:-moz-placeholder { | 
|  | 20505         color: var(--paper-input-container-color, --secondary-text-color); | 
|  | 20506       } | 
|  | 20507 | 
|  | 20508       input::-moz-placeholder { | 
|  | 20509         color: var(--paper-input-container-color, --secondary-text-color); | 
|  | 20510       } | 
|  | 20511 | 
|  | 20512       input:-ms-input-placeholder { | 
|  | 20513         color: var(--paper-input-container-color, --secondary-text-color); | 
|  | 20514       } | 
|  | 20515     </style> | 
|  | 20516 | 
|  | 20517     <paper-input-container no-label-float="[[noLabelFloat]]" always-float-label=
       "[[_computeAlwaysFloatLabel(alwaysFloatLabel,placeholder)]]" auto-validate$="[[a
       utoValidate]]" disabled$="[[disabled]]" invalid="[[invalid]]"> | 
|  | 20518 | 
|  | 20519       <content select="[prefix]"></content> | 
|  | 20520 | 
|  | 20521       <label hidden$="[[!label]]" aria-hidden="true" for="input">[[label]]</labe
       l> | 
|  | 20522 | 
|  | 20523       <input is="iron-input" id="input" aria-labelledby$="[[_ariaLabelledBy]]" a
       ria-describedby$="[[_ariaDescribedBy]]" disabled$="[[disabled]]" title$="[[title
       ]]" bind-value="{{value}}" invalid="{{invalid}}" prevent-invalid-input="[[preven
       tInvalidInput]]" allowed-pattern="[[allowedPattern]]" validator="[[validator]]" 
       type$="[[type]]" pattern$="[[pattern]]" required$="[[required]]" autocomplete$="
       [[autocomplete]]" autofocus$="[[autofocus]]" inputmode$="[[inputmode]]" minlengt
       h$="[[minlength]]" maxlength$="[[maxlength]]" min$="[[min]]" max$="[[max]]" step
       $="[[step]]" name$="[[name]]" placeholder$="[[placeholder]]" readonly$="[[readon
       ly]]" list$="[[list]]" size$="[[size]]" autocapitalize$="[[autocapitalize]]" aut
       ocorrect$="[[autocorrect]]" on-change="_onChange" tabindex$="[[tabindex]]" autos
       ave$="[[autosave]]" results$="[[results]]" accept$="[[accept]]" multiple$="[[mul
       tiple]]"> | 
|  | 20524 | 
|  | 20525       <content select="[suffix]"></content> | 
|  | 20526 | 
|  | 20527       <template is="dom-if" if="[[errorMessage]]"> | 
|  | 20528         <paper-input-error aria-live="assertive">[[errorMessage]]</paper-input-e
       rror> | 
|  | 20529       </template> | 
|  | 20530 | 
|  | 20531       <template is="dom-if" if="[[charCounter]]"> | 
|  | 20532         <paper-input-char-counter></paper-input-char-counter> | 
|  | 20533       </template> | 
|  | 20534 | 
|  | 20535     </paper-input-container> | 
|  | 20536   </template> | 
|  | 20537 </dom-module> | 
|  | 20538 | 
|  | 20539 <script> | 
|  | 20540   Polymer({ | 
|  | 20541     is: 'paper-input', | 
|  | 20542 | 
|  | 20543     behaviors: [ | 
|  | 20544       Polymer.IronFormElementBehavior, | 
|  | 20545       Polymer.PaperInputBehavior | 
|  | 20546     ] | 
|  | 20547   }); | 
|  | 20548 </script> | 
|  | 20549 <dom-module id="bot-filters" assetpath="/res/imp/botlist/"> | 
|  | 20550   <template> | 
|  | 20551     <style is="custom-style" include="iron-flex iron-flex-alignment iron-positio
       ning"> | 
|  | 20552       :host { | 
|  | 20553         display: block; | 
|  | 20554         font-family: sans-serif; | 
|  | 20555       } | 
|  | 20556       #filter { | 
|  | 20557         margin:0 5px; | 
|  | 20558       } | 
|  | 20559 | 
|  | 20560       .container { | 
|  | 20561         min-height: 120px; | 
|  | 20562         width: 100%; | 
|  | 20563       } | 
|  | 20564 | 
|  | 20565       .item { | 
|  | 20566         border-bottom: 1px solid #EEE; | 
|  | 20567         max-width: 250px; | 
|  | 20568         min-height: 1.0em; | 
|  | 20569         min-width: 100px; | 
|  | 20570         padding: 0.1em 0.2em; | 
|  | 20571         line-height: 1.5em; | 
|  | 20572       } | 
|  | 20573 | 
|  | 20574       .header { | 
|  | 20575         height: 2em; | 
|  | 20576         padding: .25em; | 
|  | 20577         line-height: 2em; | 
|  | 20578       } | 
|  | 20579 | 
|  | 20580       .selector { | 
|  | 20581         border: 1px solid black; | 
|  | 20582         margin: 0 5px; | 
|  | 20583         max-height: 200px; | 
|  | 20584         min-height: 130px; | 
|  | 20585         min-width: 200px; | 
|  | 20586         overflow-y: auto; | 
|  | 20587         overflow-x: hidden; | 
|  | 20588       } | 
|  | 20589 | 
|  | 20590       .selectable { | 
|  | 20591         cursor: pointer; | 
|  | 20592       } | 
|  | 20593 | 
|  | 20594       .selectable:hover { | 
|  | 20595         /* See https://sites.google.com/a/google.com/skia-infrastructure/design-
       docs/general-design-guidance */ | 
|  | 20596         background-color: #A6CEE3; | 
|  | 20597       } | 
|  | 20598 | 
|  | 20599       .iron-selected { | 
|  | 20600         /* See https://sites.google.com/a/google.com/skia-infrastructure/design-
       docs/general-design-guidance */ | 
|  | 20601         background-color: #1F78B4; | 
|  | 20602         color: white; | 
|  | 20603       } | 
|  | 20604 | 
|  | 20605       .icons { | 
|  | 20606         cursor:pointer; | 
|  | 20607         height:20px; | 
|  | 20608         margin:2px; | 
|  | 20609         width:20px; | 
|  | 20610         flex-shrink: 0; | 
|  | 20611       } | 
|  | 20612 | 
|  | 20613       .side-by-side { | 
|  | 20614         display: inline-block; | 
|  | 20615         vertical-align: top; | 
|  | 20616       } | 
|  | 20617 | 
|  | 20618       .bold { | 
|  | 20619         font-weight: bold; | 
|  | 20620       } | 
|  | 20621 | 
|  | 20622       paper-checkbox { | 
|  | 20623         max-height: 2em; | 
|  | 20624         margin: 2px; | 
|  | 20625         /* See https://sites.google.com/a/google.com/skia-infrastructure/design-
       docs/general-design-guidance */ | 
|  | 20626         --paper-checkbox-checked-color: black; | 
|  | 20627         --paper-checkbox-checked-ink-color: black; | 
|  | 20628         --paper-checkbox-unchecked-color: black; | 
|  | 20629         --paper-checkbox-unchecked-ink-color: black; | 
|  | 20630         --paper-checkbox-label-color: black; | 
|  | 20631       } | 
|  | 20632     </style> | 
|  | 20633 | 
|  | 20634     <div class="container horizontal layout"> | 
|  | 20635 | 
|  | 20636 | 
|  | 20637       <div class="narrow-down-selector"> | 
|  | 20638         <div> | 
|  | 20639           <paper-input id="filter" label="Search columns and filters" placeholde
       r="gpu nvidia" value="{{_query}}"></paper-input> | 
|  | 20640         </div> | 
|  | 20641 | 
|  | 20642         <div class="selector side-by-side"> | 
|  | 20643           <iron-selector attr-for-selected="label" selected="{{_primarySelected}
       }"> | 
|  | 20644             <template is="dom-repeat" items="[[_primaryItems]]" as="item"> | 
|  | 20645               <div class="selectable item horizontal layout" label="[[item]]"> | 
|  | 20646 | 
|  | 20647                 <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(ite
       m,_query)]]</span>[[_afterBold(item,_query)]]</span> | 
|  | 20648                 <span class="flex"></span> | 
|  | 20649                 <paper-checkbox noink="" disabled$="[[_cantToggleColumn(item)]]"
        checked="[[_columnState(item,columns.*)]]" on-change="_toggleColumn"> | 
|  | 20650                 </paper-checkbox> | 
|  | 20651               </div> | 
|  | 20652             </template> | 
|  | 20653           </iron-selector> | 
|  | 20654         </div> | 
|  | 20655 | 
|  | 20656         <div class="selector side-by-side"> | 
|  | 20657           <template is="dom-repeat" id="secondaryList" items="[[_secondaryItems]
       ]" as="item"> | 
|  | 20658             <div class="item horizontal layout" label="[[item]]"> | 
|  | 20659 | 
|  | 20660               <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(item,
       _query)]]</span>[[_afterBold(item,_query)]]</span> | 
|  | 20661               <span class="flex"></span> | 
|  | 20662               <iron-icon class="icons" icon="icons:arrow-forward" hidden="[[_can
       tAddFilter(_primarySelected,item,_filters.*)]]" on-tap="_addFilter"> | 
|  | 20663               </iron-icon> | 
|  | 20664             </div> | 
|  | 20665           </template> | 
|  | 20666         </div> | 
|  | 20667 | 
|  | 20668         <div class="selector side-by-side"> | 
|  | 20669           <template is="dom-repeat" items="[[_filters]]" as="fil"> | 
|  | 20670             <div class="item horizontal layout" label="[[fil]]"> | 
|  | 20671               <span>[[fil]]</span> | 
|  | 20672               <span class="flex"></span> | 
|  | 20673               <iron-icon class="icons" icon="icons:remove-circle-outline" hidden
       ="[[_cantRemoveFilter(fil,_filters.*)]]" on-tap="_removeFilter"> | 
|  | 20674               </iron-icon> | 
|  | 20675             </div> | 
|  | 20676           </template> | 
|  | 20677         </div> | 
|  | 20678 | 
|  | 20679         <paper-checkbox checked="{{verbose}}">Verbose Entries</paper-checkbox> | 
|  | 20680       </div> | 
|  | 20681 | 
|  | 20682     </div> | 
|  | 20683 | 
|  | 20684   </template> | 
|  | 20685   <script> | 
|  | 20686   (function(){ | 
|  | 20687     var FILTER_SEP = " | "; | 
|  | 20688     // filterMap is a map of primary -> function.  The function returns a | 
|  | 20689     // boolean "does the bot (first arg) match the second argument".  These | 
|  | 20690     // functions will have "this" be the botlist, and will have access to all | 
|  | 20691     // functions defined in bot-list and bot-list-shared. | 
|  | 20692     var filterMap = { | 
|  | 20693       cores: function(bot, cores){ | 
|  | 20694         var o = this._cores(bot); | 
|  | 20695         return o.indexOf(cores) !== -1; | 
|  | 20696       }, | 
|  | 20697       cpu: function(bot, cpu){ | 
|  | 20698         var o = this._dimension(bot, "cpu") || ["none"]; | 
|  | 20699         return o.indexOf(cpu) !== -1; | 
|  | 20700       }, | 
|  | 20701       devices: function(bot, device){ | 
|  | 20702         if (device === "none") { | 
|  | 20703           return this._devices(bot).length === 0; | 
|  | 20704         } | 
|  | 20705         // extract the deviceType, if it is not "unknown". | 
|  | 20706         device = this._unalias(device); | 
|  | 20707         var found = false; | 
|  | 20708         this._devices(bot).forEach(function(d) { | 
|  | 20709           if (this._deviceType(d) === device) { | 
|  | 20710             found = true; | 
|  | 20711           } | 
|  | 20712         }.bind(this)); | 
|  | 20713         return found; | 
|  | 20714       }, | 
|  | 20715       gpu: function(bot, gpu){ | 
|  | 20716         var o = this._dimension(bot, "gpu") || ["none"]; | 
|  | 20717         return o.indexOf(this._unalias(gpu)) !== -1; | 
|  | 20718       }, | 
|  | 20719       id: function(bot, id) { | 
|  | 20720         return bot.bot_id === id; | 
|  | 20721       }, | 
|  | 20722       os: function(bot, os){ | 
|  | 20723         var o = this._dimension(bot, "os") || ["Unknown"]; | 
|  | 20724         return o.indexOf(os) !== -1; | 
|  | 20725       }, | 
|  | 20726       pool: function(bot, pool){ | 
|  | 20727         var o = this._dimension(bot, "pool") || ["Unknown"]; | 
|  | 20728         return o.indexOf(pool) !== -1; | 
|  | 20729       }, | 
|  | 20730       status: function(bot, status){ | 
|  | 20731         if (status === "quarantined") { | 
|  | 20732           return bot.quarantined; | 
|  | 20733         } else if (status === "dead") { | 
|  | 20734           return bot.is_dead; | 
|  | 20735         } else { | 
|  | 20736           // Status must be "available". | 
|  | 20737           return !bot.quarantined && !bot.is_dead; | 
|  | 20738         } | 
|  | 20739       }, | 
|  | 20740       task: function(bot, task) { | 
|  | 20741         if (task === "idle") { | 
|  | 20742           return this._taskId(bot) === "idle"; | 
|  | 20743         } | 
|  | 20744         // Task must be "busy". | 
|  | 20745         return this._taskId(bot) !== "idle"; | 
|  | 20746       } | 
|  | 20747     }; | 
|  | 20748 | 
|  | 20749     // Given a space separated list of queries, matchPartCaseInsensitive | 
|  | 20750     // returns an object of any query that matches a part of str, case | 
|  | 20751     // insensitive.  The object has an idx (index) and the part that matched. | 
|  | 20752     var matchPartCaseInsensitive = function(str, queries) { | 
|  | 20753       if (!queries) { | 
|  | 20754         return { | 
|  | 20755           idx: 0, | 
|  | 20756           part: "", | 
|  | 20757         }; | 
|  | 20758       } | 
|  | 20759       if (!str) { | 
|  | 20760         return { | 
|  | 20761           idx: -1, | 
|  | 20762         }; | 
|  | 20763       } | 
|  | 20764       queries = queries.trim().toLocaleLowerCase(); | 
|  | 20765       str = str.toLocaleLowerCase(); | 
|  | 20766       var xq = queries.split(" "); | 
|  | 20767       for (var i = 0; i < xq.length; i++) { | 
|  | 20768         var idx = str.indexOf(xq[i]); | 
|  | 20769         if (idx !== -1) { | 
|  | 20770           return { | 
|  | 20771             idx: idx, | 
|  | 20772             part: xq[i], | 
|  | 20773           }; | 
|  | 20774         } | 
|  | 20775       } | 
|  | 20776       return { | 
|  | 20777         idx: -1, | 
|  | 20778       }; | 
|  | 20779     }; | 
|  | 20780 | 
|  | 20781     Polymer({ | 
|  | 20782       is: "bot-filters", | 
|  | 20783       properties: { | 
|  | 20784         // input | 
|  | 20785         primary_map: { | 
|  | 20786           type: Object, | 
|  | 20787         }, | 
|  | 20788         primary_arr: { | 
|  | 20789           type: Array, | 
|  | 20790         }, | 
|  | 20791 | 
|  | 20792         // output | 
|  | 20793         columns: { | 
|  | 20794           type: Array, | 
|  | 20795           value: function() { | 
|  | 20796             // TODO(kjlubick) back these up to URL params and load them from | 
|  | 20797             // there on reload. | 
|  | 20798             return ["id","os","task","status"]; | 
|  | 20799           }, | 
|  | 20800           notify: true, | 
|  | 20801         }, | 
|  | 20802         filter: { | 
|  | 20803           type: Object, | 
|  | 20804           computed: "_makeFilter(_filters.*)", | 
|  | 20805           notify: true, | 
|  | 20806         }, | 
|  | 20807         verbose: { | 
|  | 20808           type: Boolean, | 
|  | 20809           value: false, | 
|  | 20810           notify: true, | 
|  | 20811         }, | 
|  | 20812 | 
|  | 20813         // private | 
|  | 20814         _filters: { | 
|  | 20815           type:Array, | 
|  | 20816           value: function() { | 
|  | 20817             return []; | 
|  | 20818           } | 
|  | 20819         }, | 
|  | 20820         _primaryItems: { | 
|  | 20821           type: Array, | 
|  | 20822           computed: "_primary(_query, primary_map, primary_arr, columns.*)", | 
|  | 20823         }, | 
|  | 20824         _primarySelected: { | 
|  | 20825           type: String, | 
|  | 20826           value: "", | 
|  | 20827         }, | 
|  | 20828         // query is treated as a space separated list. | 
|  | 20829         _query: { | 
|  | 20830           type:String, | 
|  | 20831           value: "", | 
|  | 20832         }, | 
|  | 20833         _secondaryItems: { | 
|  | 20834           type: Array, | 
|  | 20835           computed: "_secondary(_primarySelected, _query, primary_map)", | 
|  | 20836         }, | 
|  | 20837 | 
|  | 20838       }, | 
|  | 20839 | 
|  | 20840       _addFilter: function(e) { | 
|  | 20841         // e.model.foo is a way to get access to the "foo" inside a dom-repeat | 
|  | 20842         // that had the event (in our case, a tap) acted upon it.  This name, | 
|  | 20843         // "foo", is set by the dom-repeat above 'as="foo"' | 
|  | 20844         var filterItem = e.model.item; | 
|  | 20845         if (this._cantAddFilter(this._primarySelected, filterItem)) { | 
|  | 20846           return; | 
|  | 20847         } | 
|  | 20848         var filter = this._primarySelected + FILTER_SEP + filterItem; | 
|  | 20849         this.push("_filters", filter); | 
|  | 20850       }, | 
|  | 20851 | 
|  | 20852       _removeFilter: function(e){ | 
|  | 20853         var filter = e.model.fil; | 
|  | 20854         if (this._cantRemoveFilter(filter)){ | 
|  | 20855           return; | 
|  | 20856         } | 
|  | 20857         var idx = this._filters.indexOf(filter); | 
|  | 20858         if (idx !== -1) { | 
|  | 20859           this.splice("_filters", idx, 1); | 
|  | 20860         } | 
|  | 20861       }, | 
|  | 20862 | 
|  | 20863       _cantAddFilter: function(primarySelected, filterItem) { | 
|  | 20864         // Check that everything is selected and this filter isn't already in | 
|  | 20865         // the array. | 
|  | 20866         if (!primarySelected || !filterItem) { | 
|  | 20867           return true; | 
|  | 20868         } | 
|  | 20869         var filter = primarySelected + FILTER_SEP + filterItem; | 
|  | 20870         return this._filters.indexOf(filter) !== -1; | 
|  | 20871       }, | 
|  | 20872 | 
|  | 20873       _cantRemoveFilter: function(filter) { | 
|  | 20874         return !filter || this._filters.indexOf(filter) === -1; | 
|  | 20875       }, | 
|  | 20876 | 
|  | 20877       _toggleColumn: function(e) { | 
|  | 20878         var col = e.model.item; | 
|  | 20879 | 
|  | 20880         if (this._cantToggleColumn(col)) { | 
|  | 20881           return; | 
|  | 20882         } | 
|  | 20883         if (this._columnState(col)) { | 
|  | 20884           var idx = this.columns.indexOf(col); | 
|  | 20885           if (idx !== -1) { | 
|  | 20886             this.splice("columns", idx, 1); | 
|  | 20887           } | 
|  | 20888           return; | 
|  | 20889         } | 
|  | 20890         this.push("columns", col); | 
|  | 20891       }, | 
|  | 20892 | 
|  | 20893       _cantToggleColumn: function(col) { | 
|  | 20894         // Don't allow the id column to be removed, as the bot list is basically | 
|  | 20895         // meaningless without it. | 
|  | 20896         return !col || col === "id" ; | 
|  | 20897       }, | 
|  | 20898 | 
|  | 20899       _columnState: function(col) { | 
|  | 20900         if (!col) { | 
|  | 20901           return false; | 
|  | 20902         } | 
|  | 20903         return this.columns.indexOf(col) !== -1; | 
|  | 20904       }, | 
|  | 20905 | 
|  | 20906       _makeFilter: function() { | 
|  | 20907         // The filters belonging to the same primary key will be or'd together. | 
|  | 20908         // Those groups will be and'd together. | 
|  | 20909         // filterGroups will be a map of primary (i.e. column) -> array of | 
|  | 20910         // options that should be filtered to. | 
|  | 20911         // e.g. "os" -> ["Windows", "Linux"] | 
|  | 20912         // Since they will be or'd together, order doesn't matter. | 
|  | 20913         var filterGroups = {}; | 
|  | 20914         this._filters.forEach(function(filterString){ | 
|  | 20915           var idx = filterString.indexOf(FILTER_SEP); | 
|  | 20916           var primary = filterString.slice(0, idx); | 
|  | 20917           var param = filterString.slice(idx + FILTER_SEP.length); | 
|  | 20918           var arr = filterGroups[primary] || []; | 
|  | 20919           arr.push(param); | 
|  | 20920           filterGroups[primary] = arr; | 
|  | 20921         }); | 
|  | 20922         return { | 
|  | 20923           filter: function(bot){ | 
|  | 20924             var retVal = true; | 
|  | 20925             // Look up all the primary keys we are filter by, then look up how | 
|  | 20926             // to filter (in filterMap) and apply the filter for each filter | 
|  | 20927             // option. | 
|  | 20928             for (primary in filterGroups){ | 
|  | 20929               var params = filterGroups[primary]; | 
|  | 20930               var filter = filterMap[primary]; | 
|  | 20931               var groupResult = false; | 
|  | 20932               if (filter) { | 
|  | 20933                 params.forEach(function(param){ | 
|  | 20934                   groupResult = groupResult || filter.bind(this)(bot,param); | 
|  | 20935                 }.bind(this)); | 
|  | 20936               } | 
|  | 20937               retVal = retVal && groupResult; | 
|  | 20938             } | 
|  | 20939             return retVal; | 
|  | 20940           } | 
|  | 20941         } | 
|  | 20942       }, | 
|  | 20943 | 
|  | 20944       _primary: function(query, primary_map, primary_arr) { | 
|  | 20945         // If the user has typed in a query, only show those primary keys that | 
|  | 20946         // partially match the query or that have secondary values which | 
|  | 20947         // partially match. | 
|  | 20948         var arr = this.primary_arr.filter(function(s){ | 
|  | 20949           if (matchPartCaseInsensitive(s, query).idx !== -1) { | 
|  | 20950             return true; | 
|  | 20951           } | 
|  | 20952           var opts = primary_map[s]; | 
|  | 20953           for (var i = 0; i < opts.length; i++) { | 
|  | 20954             if (matchPartCaseInsensitive(opts[i], query).idx !== -1) { | 
|  | 20955               return true; | 
|  | 20956             } | 
|  | 20957           } | 
|  | 20958           return false; | 
|  | 20959         }); | 
|  | 20960         // Update the selected to be the current one (if it is still with being | 
|  | 20961         // shown) or the first match.  This saves the user from having to click | 
|  | 20962         // the first result before seeing results. | 
|  | 20963         if (query && arr.length > 0 && | 
|  | 20964             arr.indexOf(this._primarySelected) === -1) { | 
|  | 20965           this.set("_primarySelected", arr[0]); | 
|  | 20966         } | 
|  | 20967         return arr; | 
|  | 20968       }, | 
|  | 20969 | 
|  | 20970       _secondary: function(primarySelected, query, primary_map) { | 
|  | 20971         // Changing the secondary list doesn't always trigger a reorder of the | 
|  | 20972         // secondary elements.  So, we request it be done asynchronously. | 
|  | 20973         requestAnimationFrame(function(){ | 
|  | 20974           this.$.secondaryList.render(); | 
|  | 20975         }.bind(this)); | 
|  | 20976 | 
|  | 20977         // Only show secondary options when a primary option has been selected. | 
|  | 20978         // If the user has typed in a query, show all secondary elements if | 
|  | 20979         // their primary element matches.  If it doesn't match the primary | 
|  | 20980         // element, only show those secondary elements that do. | 
|  | 20981         if (!primarySelected) { | 
|  | 20982           return []; | 
|  | 20983         } | 
|  | 20984         if (matchPartCaseInsensitive(primarySelected, query).idx !== -1) { | 
|  | 20985           // Sort the secondaries alphabetically, but prioritize query matches. | 
|  | 20986           return primary_map[primarySelected].sort(function(a, b){ | 
|  | 20987             var aMatch = matchPartCaseInsensitive(a, query).idx !== -1; | 
|  | 20988             var bMatch = matchPartCaseInsensitive(b, query).idx !== -1; | 
|  | 20989             if (aMatch === bMatch) { | 
|  | 20990               return swarming.naturalCompare(a,b); | 
|  | 20991             } | 
|  | 20992             // true == 1 and false == 0.  So, put the one that matches first. | 
|  | 20993             return bMatch - aMatch; | 
|  | 20994           }); | 
|  | 20995         } | 
|  | 20996         // Otherwise, filter out those that do not match. | 
|  | 20997         return primary_map[primarySelected].filter(function(s) { | 
|  | 20998           return matchPartCaseInsensitive(s, query).idx !== -1; | 
|  | 20999         }); | 
|  | 21000       }, | 
|  | 21001 | 
|  | 21002       // These three methods (_beforeBold, _bold, _afterBold) bold the first | 
|  | 21003       // instance of the filter query, making it easier to see why elements | 
|  | 21004       // show up. | 
|  | 21005       _beforeBold: function(item, query) { | 
|  | 21006         var match = matchPartCaseInsensitive(item, query); | 
|  | 21007         if (match.idx === -1) { | 
|  | 21008           return item; | 
|  | 21009         } | 
|  | 21010         return item.substring(0, match.idx); | 
|  | 21011       }, | 
|  | 21012 | 
|  | 21013       _bold: function(item, query) { | 
|  | 21014         var match = matchPartCaseInsensitive(item, query); | 
|  | 21015         if (match.idx === -1) { | 
|  | 21016           return ""; | 
|  | 21017         } | 
|  | 21018         return item.substring(match.idx, match.idx + match.part.length); | 
|  | 21019       }, | 
|  | 21020 | 
|  | 21021       _afterBold: function(item, query) { | 
|  | 21022         var match = matchPartCaseInsensitive(item, query); | 
|  | 21023         if (match.idx === -1) { | 
|  | 21024           return ""; | 
|  | 21025         } | 
|  | 21026         return item.substring(match.idx + match.part.length); | 
|  | 21027       }, | 
|  | 21028 | 
|  | 21029     }); | 
|  | 21030   })(); | 
|  | 21031   </script> | 
|  | 21032 </dom-module><script> | 
|  | 21033 | 
|  | 21034   window.SwarmingBehaviors = window.SwarmingBehaviors || {}; | 
|  | 21035   (function(){ | 
|  | 21036     var ANDROID_ALIASES = { | 
|  | 21037       "bullhead": "Nexus 5X", | 
|  | 21038       "flo": "Nexus 7", | 
|  | 21039       "hammerhead": "Nexus 5", | 
|  | 21040       "mako": "Nexus 4", | 
|  | 21041       "shamu": "Nexus 6", | 
|  | 21042     }; | 
|  | 21043     // Taken from http://developer.android.com/reference/android/os/BatteryManag
       er.html | 
|  | 21044     var BATTERY_HEALTH_UNKNOWN = 1; | 
|  | 21045     var BATTERY_HEALTH_GOOD = 2; | 
|  | 21046     var BATTERY_STATUS_CHARGING = 2; | 
|  | 21047 | 
|  | 21048     var UNAUTHENTICATED = "unauthenticated"; | 
|  | 21049     var AVAILABLE = "available"; | 
|  | 21050 | 
|  | 21051     var GPU_ALIASES = { | 
|  | 21052       "1002": "AMD", | 
|  | 21053       "1002:6779": "AMD Radeon HD 6450/7450/8450", | 
|  | 21054       "1002:6821": "AMD Radeon HD 8870M", | 
|  | 21055       "102b":      "Matrox", | 
|  | 21056       "102b:0522": "Matrox MGA G200e", | 
|  | 21057       "102b:0532": "Matrox MGA G200eW", | 
|  | 21058       "102b:0534": "Matrox G200eR2", | 
|  | 21059       "10de":      "NVIDIA", | 
|  | 21060       "10de:08aa": "NVIDIA GeForce 320M", | 
|  | 21061       "10de:0fe9": "NVIDIA GeForce GT 750M Mac Edition", | 
|  | 21062       "10de:104a": "NVIDIA GeForce GT 610", | 
|  | 21063       "10de:11c0": "NVIDIA GeForce GTX 660", | 
|  | 21064       "10de:1244": "NVIDIA GeForce GTX 550 Ti", | 
|  | 21065       "10de:1401": "NVIDIA GeForce GTX 960", | 
|  | 21066       "8086":      "Intel", | 
|  | 21067       "8086:041a": "Intel Xeon Integrated", | 
|  | 21068       "8086:0a2e": "Intel Haswell Integrated", | 
|  | 21069       "8086:0d26": "Intel Crystal Well Integrated", | 
|  | 21070     } | 
|  | 21071 | 
|  | 21072     // For consistency, all aliases are displayed like: | 
|  | 21073     // Nexus 5X (bullhead) | 
|  | 21074     // This regex matches a string like "ALIAS (ORIG)", with ORIG as group 1. | 
|  | 21075     var ALIAS_REGEXP = /.+ \((.*)\)/; | 
|  | 21076 | 
|  | 21077     // This behavior wraps up all the shared bot-list functionality. | 
|  | 21078     SwarmingBehaviors.BotListBehavior = { | 
|  | 21079 | 
|  | 21080       _androidAlias: function(device) { | 
|  | 21081         if (device.notReady) { | 
|  | 21082           return UNAUTHENTICATED.toUpperCase(); | 
|  | 21083         } | 
|  | 21084         var t = this._deviceType(device); | 
|  | 21085         var a = ANDROID_ALIASES[t]; | 
|  | 21086         if (!a) { | 
|  | 21087           return "UNKNOWN"; | 
|  | 21088         } | 
|  | 21089         return a; | 
|  | 21090       }, | 
|  | 21091 | 
|  | 21092       // _applyAlias is the consistent way to modify a string to show its alias. | 
|  | 21093       _applyAlias: function(orig, alias) { | 
|  | 21094         return alias +" ("+orig+")"; | 
|  | 21095       }, | 
|  | 21096 | 
|  | 21097       _cores: function(bot) { | 
|  | 21098         // For whatever reason, sometimes cores are in dimensions and sometimes | 
|  | 21099         // they are in state, but never both. | 
|  | 21100         var c = (bot && bot.state && bot.state.cores); | 
|  | 21101         if (c && c.length > 0) { | 
|  | 21102           return c; | 
|  | 21103         } | 
|  | 21104         c = this._dimension(bot, "cores") || ["Unknown"]; | 
|  | 21105         return c; | 
|  | 21106       }, | 
|  | 21107 | 
|  | 21108       _devices: function(bot) { | 
|  | 21109         var devices = []; | 
|  | 21110         var d = (bot && bot.state && bot.state.devices) || {}; | 
|  | 21111         // state.devices is like {Serial:Object}, so we need to keep the serial | 
|  | 21112         for (key in d) { | 
|  | 21113           var o = d[key]; | 
|  | 21114           o.serial = key; | 
|  | 21115           o.okay = (o.state === AVAILABLE); | 
|  | 21116           devices.push(o); | 
|  | 21117         } | 
|  | 21118         return devices; | 
|  | 21119       }, | 
|  | 21120 | 
|  | 21121       // _deviceType returns the codename of a given Android device. | 
|  | 21122       _deviceType: function(device) { | 
|  | 21123         if (!device || !device.build) { | 
|  | 21124           return "unknown"; | 
|  | 21125         } | 
|  | 21126         var t = device.build["build.product"] || device.build["product.board"] |
       | | 
|  | 21127                 device.build["product.device"] || "unknown"; | 
|  | 21128         return t.toLowerCase(); | 
|  | 21129       }, | 
|  | 21130 | 
|  | 21131       // _dimension returns the given dimension of a bot. If it is defined, it | 
|  | 21132       // is typically an array of strings. | 
|  | 21133       _dimension: function(bot, dim) { | 
|  | 21134         if (!bot || !bot.dimensions || !dim) { | 
|  | 21135           return undefined; | 
|  | 21136         } | 
|  | 21137         for (var i = 0; i < bot.dimensions.length; i++) { | 
|  | 21138           if (bot.dimensions[i].key === dim) { | 
|  | 21139             return bot.dimensions[i].value; | 
|  | 21140           } | 
|  | 21141         } | 
|  | 21142         return undefined; | 
|  | 21143       }, | 
|  | 21144 | 
|  | 21145       _gpuAlias: function(gpu) { | 
|  | 21146         var a = GPU_ALIASES[gpu]; | 
|  | 21147         if (!a) { | 
|  | 21148           return "UNKNOWN"; | 
|  | 21149         } | 
|  | 21150         return a; | 
|  | 21151       }, | 
|  | 21152 | 
|  | 21153       _not: function(a) { | 
|  | 21154         return a; | 
|  | 21155       }, | 
|  | 21156 | 
|  | 21157       _taskId: function(bot) { | 
|  | 21158         if (bot && bot.task_id) { | 
|  | 21159           return bot.task_id; | 
|  | 21160         } | 
|  | 21161         return "idle"; | 
|  | 21162       }, | 
|  | 21163 | 
|  | 21164       // _unalias will return the base dimension/state with its alias removed | 
|  | 21165       // if it had one.  This is handy for sorting and filtering. | 
|  | 21166       _unalias: function(str) { | 
|  | 21167         var match = ALIAS_REGEXP.exec(str); | 
|  | 21168         if (match) { | 
|  | 21169           return match[1]; | 
|  | 21170         } | 
|  | 21171         return str; | 
|  | 21172       }, | 
|  | 21173     } | 
|  | 21174   })() | 
|  | 21175 </script> | 
|  | 21176 <dom-module id="bot-list-data" assetpath="/res/imp/botlist/"> | 
|  | 21177   <template> | 
|  | 21178     <iron-ajax id="request" url="/_ah/api/swarming/v1/bots/list" headers="[[auth
       _headers]]" handle-as="json" last-response="{{_data}}" loading="{{busy}}"> | 
|  | 21179     </iron-ajax> | 
|  | 21180   </template> | 
|  | 21181   <script> | 
|  | 21182   (function(){ | 
|  | 21183     // TODO(kjlubick): Add more of these as well as things from state | 
|  | 21184     // i.e. disk space remaining. | 
|  | 21185     var DIMENSIONS = ["cores", "cpu", "id", "os", "pool"]; | 
|  | 21186      // "gpu" and "devices" are added separately because we need to | 
|  | 21187      // deal with aliases. | 
|  | 21188     var BOT_PROPERTIES = ["gpu", "devices", "task", "status"]; | 
|  | 21189     Polymer({ | 
|  | 21190       is: 'bot-list-data', | 
|  | 21191       properties: { | 
|  | 21192         // inputs | 
|  | 21193         auth_headers: { | 
|  | 21194           type: Object, | 
|  | 21195           observer: "signIn", | 
|  | 21196         }, | 
|  | 21197 | 
|  | 21198         //outputs | 
|  | 21199         bots: { | 
|  | 21200           type: Array, | 
|  | 21201           computed: "_bots(_data)", | 
|  | 21202           notify: true, | 
|  | 21203         }, | 
|  | 21204         busy: { | 
|  | 21205           type: Boolean, | 
|  | 21206           notify: true, | 
|  | 21207         }, | 
|  | 21208         primary_map: { | 
|  | 21209           type:Object, | 
|  | 21210           computed: "_primaryMap(bots)", | 
|  | 21211           notify: true, | 
|  | 21212         }, | 
|  | 21213         primary_arr: { | 
|  | 21214           type:Array, | 
|  | 21215           value: function() { | 
|  | 21216             return DIMENSIONS.concat(BOT_PROPERTIES); | 
|  | 21217           }, | 
|  | 21218           notify: true, | 
|  | 21219         }, | 
|  | 21220 | 
|  | 21221         // private | 
|  | 21222         _data: { | 
|  | 21223           type: Object, | 
|  | 21224         }, | 
|  | 21225       }, | 
|  | 21226       behaviors: [SwarmingBehaviors.BotListBehavior], | 
|  | 21227 | 
|  | 21228       signIn: function(){ | 
|  | 21229         this.$.request.generateRequest(); | 
|  | 21230       }, | 
|  | 21231 | 
|  | 21232       _bots: function(){ | 
|  | 21233         if (!this._data || !this._data.items) { | 
|  | 21234           return []; | 
|  | 21235         } | 
|  | 21236         this._data.items.forEach(function(o){ | 
|  | 21237           o.state = JSON.parse(o.state); | 
|  | 21238         }); | 
|  | 21239         return this._data.items; | 
|  | 21240       }, | 
|  | 21241 | 
|  | 21242       _primaryMap: function(bots){ | 
|  | 21243         // map will keep track of dimensions that we have seen at least once. | 
|  | 21244         // This will then basically get turned into an array to be used for | 
|  | 21245         // filtering. | 
|  | 21246         var map = {}; | 
|  | 21247         DIMENSIONS.forEach(function(p){ | 
|  | 21248           map[p] = {}; | 
|  | 21249         }); | 
|  | 21250         map["devices"] = {}; | 
|  | 21251         map["gpu"] = {}; | 
|  | 21252         bots.forEach(function(b){ | 
|  | 21253           DIMENSIONS.forEach(function(d){ | 
|  | 21254             var dims = this._dimension(b, d) || []; | 
|  | 21255             dims.forEach(function(e){ | 
|  | 21256               map[d][e] = true; | 
|  | 21257             }); | 
|  | 21258           }.bind(this)); | 
|  | 21259 | 
|  | 21260           // Add Android devices and their aliases | 
|  | 21261           this._devices(b).forEach(function(d){ | 
|  | 21262             var dt = this._deviceType(d); | 
|  | 21263             var alias = this._androidAlias(d); | 
|  | 21264             if (dt !== "unknown") { | 
|  | 21265               dt = this._applyAlias(dt,alias); | 
|  | 21266             } | 
|  | 21267             map["devices"][dt] = true; | 
|  | 21268           }.bind(this)); | 
|  | 21269           map["devices"]["none"] = true; | 
|  | 21270 | 
|  | 21271           // Add GPUs and their aliases | 
|  | 21272           var gpus = this._dimension(b, "gpu") || []; | 
|  | 21273           gpus.forEach(function(g){ | 
|  | 21274             var alias = this._gpuAlias(g); | 
|  | 21275             if (alias !== "UNKNOWN") { | 
|  | 21276               map["gpu"][this._applyAlias(g, alias)] = true; | 
|  | 21277             } else { | 
|  | 21278               map["gpu"][g] = true; | 
|  | 21279             } | 
|  | 21280 | 
|  | 21281           }.bind(this)); | 
|  | 21282         }.bind(this)); | 
|  | 21283 | 
|  | 21284         // Turn the Map<Object,Map<Boolean>> into a Map<Object,Array<String>> | 
|  | 21285         // with all of the secondary elements sorted appropriately. | 
|  | 21286         var pMap = {}; | 
|  | 21287         for (key in map){ | 
|  | 21288           pMap[key] = Object.keys(map[key]).sort(swarming.naturalCompare); | 
|  | 21289         } | 
|  | 21290 | 
|  | 21291         // Create custom filter options | 
|  | 21292         pMap["task"] = ["busy", "idle"]; | 
|  | 21293         pMap["status"] = ["available", "dead", "quarantined"]; | 
|  | 21294         return pMap; | 
|  | 21295       }, | 
|  | 21296 | 
|  | 21297     }); | 
|  | 21298   })(); | 
|  | 21299   </script> | 
|  | 21300 </dom-module><dom-module id="bot-list" assetpath="/res/imp/botlist/"> | 
|  | 21301   <template> | 
|  | 21302     <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-
       style"> | 
|  | 21303       bot-filters { | 
|  | 21304         margin-bottom: 5px; | 
|  | 21305       } | 
|  | 21306       .bot { | 
|  | 21307         margin:5px; | 
|  | 21308         max-width:400px; | 
|  | 21309         min-height:100px; | 
|  | 21310         min-width:300px; | 
|  | 21311       } | 
|  | 21312       table { | 
|  | 21313         border-collapse: collapse; | 
|  | 21314         margin-left: 5px; | 
|  | 21315       } | 
|  | 21316       td, th { | 
|  | 21317         border: 1px solid #DDD; | 
|  | 21318         padding: 5px; | 
|  | 21319       } | 
|  | 21320 | 
|  | 21321       .quarantined, .bad-device { | 
|  | 21322         background-color: #ffdddd; | 
|  | 21323       } | 
|  | 21324       .dead { | 
|  | 21325         background-color: #cccccc; | 
|  | 21326       } | 
|  | 21327 | 
|  | 21328       th { | 
|  | 21329         position: relative; | 
|  | 21330       } | 
|  | 21331       sort-toggle { | 
|  | 21332         position: absolute; | 
|  | 21333         right: 0; | 
|  | 21334         top: 0.4em; | 
|  | 21335       } | 
|  | 21336       .bot-list th > span { | 
|  | 21337         /* Leave space for sort-toggle*/ | 
|  | 21338         padding-right: 30px; | 
|  | 21339       } | 
|  | 21340     </style> | 
|  | 21341 | 
|  | 21342     <swarming-app auth_headers="{{auth_headers}}" busy="[[busy]]" name="Swarming
        Bot List"> | 
|  | 21343 | 
|  | 21344       <bot-filters primary_map="[[primary_map]]" primary_arr="[[primary_arr]]" c
       olumns="{{columns}}" filter="{{filter}}" verbose="{{verbose}}"> | 
|  | 21345       </bot-filters> | 
|  | 21346 | 
|  | 21347       <bot-list-data auth_headers="[[auth_headers]]" bots="{{bots}}" busy="{{bus
       y}}" primary_map="{{primary_map}}" primary_arr="{{primary_arr}}"> | 
|  | 21348       </bot-list-data> | 
|  | 21349 | 
|  | 21350       <table class="bot-list"> | 
|  | 21351         <thead on-sort_change="sortChange"> | 
|  | 21352 | 
|  | 21353           <tr><th> | 
|  | 21354             <span>Bot Id</span> | 
|  | 21355             <sort-toggle name="id" current="[[sort]]"> | 
|  | 21356             </sort-toggle> | 
|  | 21357           </th> | 
|  | 21358 | 
|  | 21359           <th hidden$="[[_hide('task', columns.*)]]"> | 
|  | 21360             <span>Current Task</span> | 
|  | 21361             <sort-toggle name="task" current="[[sort]]"> | 
|  | 21362             </sort-toggle> | 
|  | 21363           </th> | 
|  | 21364 | 
|  | 21365           <template is="dom-repeat" items="[[plain_columns]]" as="c"> | 
|  | 21366             <th hidden$="[[_hide(c)]]"> | 
|  | 21367               <span>[[_header(c)]]</span> | 
|  | 21368               <sort-toggle name="[[c]]" current="[[sort]]"> | 
|  | 21369               </sort-toggle> | 
|  | 21370             </th> | 
|  | 21371           </template> | 
|  | 21372         </tr></thead> | 
|  | 21373         <tbody> | 
|  | 21374           <template id="bot_table" is="dom-repeat" items="[[bots]]" as="bot" ini
       tial-count="50" filter="_filterBotTable"> | 
|  | 21375 | 
|  | 21376             <tr class$="[[_botClass(bot)]]"> | 
|  | 21377               <td> | 
|  | 21378                 <a class="center" href$="[[_botLink(bot.bot_id)]]" target="_blan
       k"> | 
|  | 21379                    [[bot.bot_id]] | 
|  | 21380                 </a> | 
|  | 21381               </td> | 
|  | 21382               <td hidden$="[[_hide('task', columns.*)]]"> | 
|  | 21383                 <a href$="[[_taskLink(bot)]]">[[_taskId(bot)]]</a> | 
|  | 21384               </td> | 
|  | 21385 | 
|  | 21386               <template is="dom-repeat" items="[[plain_columns]]" as="c"> | 
|  | 21387                 <td hidden$="[[_hide(c)]]"> | 
|  | 21388                   [[_column(c, bot, verbose)]] | 
|  | 21389                 </td> | 
|  | 21390               </template> | 
|  | 21391 | 
|  | 21392             </tr> | 
|  | 21393             <template is="dom-repeat" items="[[_devices(bot)]]" as="device"> | 
|  | 21394               <tr hidden$="[[_hide('devices', columns.*)]]" class$="[[_deviceCla
       ss(device)]]"> | 
|  | 21395                 <td></td> | 
|  | 21396                 <td hidden$="[[_hide('task', columns.*)]]"></td> | 
|  | 21397                 <template is="dom-repeat" items="[[plain_columns]]" as="c"> | 
|  | 21398                   <td hidden$="[[_hide(c)]]"> | 
|  | 21399                     [[_deviceColumn(c, device, verbose)]] | 
|  | 21400                   </td> | 
|  | 21401                 </template> | 
|  | 21402               </tr> | 
|  | 21403             </template> | 
|  | 21404           </template> | 
|  | 21405         </tbody> | 
|  | 21406       </table> | 
|  | 21407 | 
|  | 21408     </swarming-app> | 
|  | 21409 | 
|  | 21410   </template> | 
|  | 21411   <script> | 
|  | 21412   (function(){ | 
|  | 21413     var special_columns = ["id", "task"]; | 
|  | 21414 | 
|  | 21415     var headerMap = { | 
|  | 21416       // "id" and "task" are special, so they don't go here and have their | 
|  | 21417       // headers hard-coded below. | 
|  | 21418       "cores": "Cores", | 
|  | 21419       "cpu": "CPU", | 
|  | 21420       "devices": "Devices", | 
|  | 21421       "gpu": "GPU", | 
|  | 21422       "os": "OS", | 
|  | 21423       "pool": "Pool", | 
|  | 21424       "status": "Status", | 
|  | 21425     }; | 
|  | 21426 | 
|  | 21427     // This maps column name to a function that will return the content for a | 
|  | 21428     // given bot. These functions are bound to this element, and have access | 
|  | 21429     // to all functions defined here and in bot-list-shared. | 
|  | 21430     var columnMap = { | 
|  | 21431       cores: function(bot){ | 
|  | 21432         var cores =  this._cores(bot); | 
|  | 21433         if (this.verbose){ | 
|  | 21434           return cores.join(" | "); | 
|  | 21435         } | 
|  | 21436         return cores[0]; | 
|  | 21437       }, | 
|  | 21438       cpu: function(bot){ | 
|  | 21439         var cpus = this._dimension(bot, 'cpu') || ['Unknown']; | 
|  | 21440         if (this.verbose){ | 
|  | 21441           return cpus.join(" | "); | 
|  | 21442         } | 
|  | 21443         return cpus[0]; | 
|  | 21444       }, | 
|  | 21445       devices: function(bot){ | 
|  | 21446         return this._devices(bot).length + " devices attached"; | 
|  | 21447       }, | 
|  | 21448       gpu: function(bot){ | 
|  | 21449         var gpus = this._dimension(bot, 'gpu') | 
|  | 21450         if (!gpus) { | 
|  | 21451           return "none"; | 
|  | 21452         } | 
|  | 21453         var verbose = [] | 
|  | 21454         var named = []; | 
|  | 21455         // non-verbose mode has only the top level GPU info "e.g. NVidia" | 
|  | 21456         // which is found by looking for gpu ids w/o a colon. | 
|  | 21457         gpus.forEach(function(g){ | 
|  | 21458           var alias = this._gpuAlias(g); | 
|  | 21459           if (alias === "UNKNOWN") { | 
|  | 21460             verbose.push(g); | 
|  | 21461             if (g.indexOf(":") === -1) { | 
|  | 21462               named.push(g); | 
|  | 21463             } | 
|  | 21464             return; | 
|  | 21465           } | 
|  | 21466           verbose.push(this._applyAlias(g, alias)); | 
|  | 21467           if (g.indexOf(":") === -1) { | 
|  | 21468             named.push(this._applyAlias(g, alias)); | 
|  | 21469           } | 
|  | 21470         }.bind(this)) | 
|  | 21471         if (this.verbose) { | 
|  | 21472           return verbose.join(" | "); | 
|  | 21473         } | 
|  | 21474         return named.join(" | "); | 
|  | 21475       }, | 
|  | 21476       id: function(bot) { | 
|  | 21477         return bot.bot_id; | 
|  | 21478       }, | 
|  | 21479       os: function(bot) { | 
|  | 21480         var os = this._dimension(bot, 'os') || ['Unknown']; | 
|  | 21481         if (this.verbose){ | 
|  | 21482           return os.join(" | "); | 
|  | 21483         } | 
|  | 21484         return os[0]; | 
|  | 21485       }, | 
|  | 21486       pool: function(bot) { | 
|  | 21487         var pool = this._dimension(bot, 'pool') || ['Unknown']; | 
|  | 21488         return pool.join(" | "); | 
|  | 21489       }, | 
|  | 21490       status: function(bot) { | 
|  | 21491         // If a bot is both dead and quarantined, show the deadness over the | 
|  | 21492         // quarentinedness. | 
|  | 21493         if (bot.is_dead) { | 
|  | 21494           return "Dead: " + bot.is_dead; | 
|  | 21495         } | 
|  | 21496         if (bot.quarantined) { | 
|  | 21497           return "Quarantined: " + bot.quarantined; | 
|  | 21498         } | 
|  | 21499         return "Alive"; | 
|  | 21500       }, | 
|  | 21501       task: function(bot){ | 
|  | 21502         return this._taskId(bot); | 
|  | 21503       }, | 
|  | 21504     }; | 
|  | 21505 | 
|  | 21506     Polymer({ | 
|  | 21507       is: 'bot-list', | 
|  | 21508       behaviors: [SwarmingBehaviors.BotListBehavior], | 
|  | 21509 | 
|  | 21510       properties: { | 
|  | 21511 | 
|  | 21512         columns: { | 
|  | 21513           type: Array, | 
|  | 21514         }, | 
|  | 21515         // Should have a property "filter" which is a function. | 
|  | 21516         filter: { | 
|  | 21517           type: Object, | 
|  | 21518         }, | 
|  | 21519 | 
|  | 21520         plain_columns: { | 
|  | 21521           type: Array, | 
|  | 21522           computed: "_stripSpecial(columns.*)", | 
|  | 21523         }, | 
|  | 21524 | 
|  | 21525         // sort is an Object {name:String, direction:String}. | 
|  | 21526         sort: { | 
|  | 21527           type: Object, | 
|  | 21528         }, | 
|  | 21529 | 
|  | 21530         verbose: { | 
|  | 21531           type: Boolean, | 
|  | 21532         } | 
|  | 21533       }, | 
|  | 21534 | 
|  | 21535       observers: [ | 
|  | 21536         '_reRender(filter.*)', | 
|  | 21537         '_checkSorts(columns.*)' | 
|  | 21538       ], | 
|  | 21539 | 
|  | 21540       _botClass: function(bot) { | 
|  | 21541         if (bot.is_dead) { | 
|  | 21542           return "dead"; | 
|  | 21543         } | 
|  | 21544         if (bot.quarantined) { | 
|  | 21545           return "quarantined"; | 
|  | 21546         } | 
|  | 21547         return ""; | 
|  | 21548       }, | 
|  | 21549 | 
|  | 21550       _botLink: function(id) { | 
|  | 21551         // TODO(kjlubick) Make this point to /newui/ when appropriate. | 
|  | 21552         return "/restricted/bot/"+id; | 
|  | 21553       }, | 
|  | 21554 | 
|  | 21555       // _checkSorts makes sure that if a column has been removed, the related | 
|  | 21556       // sort is also removed. | 
|  | 21557       _checkSorts: function() { | 
|  | 21558         if (!this.sort) { | 
|  | 21559           return; | 
|  | 21560         } | 
|  | 21561         this._reRender(); | 
|  | 21562       }, | 
|  | 21563 | 
|  | 21564       _column: function(col, bot) { | 
|  | 21565         return columnMap[col].bind(this)(bot); | 
|  | 21566       }, | 
|  | 21567 | 
|  | 21568       _deviceColumn: function(col, device) { | 
|  | 21569         if (col === "devices") { | 
|  | 21570           var str = this._androidAlias(device); | 
|  | 21571           if (device.okay) { | 
|  | 21572             str = this._applyAlias(this._deviceType(device), str); | 
|  | 21573           } | 
|  | 21574           str += " S/N:"; | 
|  | 21575           str += device.serial; | 
|  | 21576           return str; | 
|  | 21577         } | 
|  | 21578         if (col === "status") { | 
|  | 21579           return device.state; | 
|  | 21580         } | 
|  | 21581         return ""; | 
|  | 21582       }, | 
|  | 21583 | 
|  | 21584       _deviceClass: function(device) { | 
|  | 21585         if (!device.okay) { | 
|  | 21586           return "bad-device"; | 
|  | 21587         } | 
|  | 21588         return ""; | 
|  | 21589       }, | 
|  | 21590 | 
|  | 21591       _filterBotTable: function(bot) { | 
|  | 21592         if (!this.filter || !this.filter.filter) { | 
|  | 21593           return true; | 
|  | 21594         } | 
|  | 21595         return this.filter.filter.bind(this)(bot); | 
|  | 21596       }, | 
|  | 21597 | 
|  | 21598       _header: function(col){ | 
|  | 21599         return headerMap[col]; | 
|  | 21600       }, | 
|  | 21601 | 
|  | 21602       _hide: function(col) { | 
|  | 21603         return this.columns.indexOf(col) === -1; | 
|  | 21604       }, | 
|  | 21605 | 
|  | 21606       _reRender: function(filter, sort) { | 
|  | 21607         this.$.bot_table.render(); | 
|  | 21608       }, | 
|  | 21609 | 
|  | 21610       _sortBotTable: function(botA, botB) { | 
|  | 21611         if (!this.sort) { | 
|  | 21612           return 0; | 
|  | 21613         } | 
|  | 21614         var dir = 1; | 
|  | 21615         if (this.sort.direction === "desc") { | 
|  | 21616           dir = -1; | 
|  | 21617         } | 
|  | 21618         var botACol = this._column(this.sort.name, botA); | 
|  | 21619         var botBCol = this._column(this.sort.name, botB); | 
|  | 21620 | 
|  | 21621         return dir * swarming.naturalCompare(botACol, botBCol); | 
|  | 21622       }, | 
|  | 21623 | 
|  | 21624       sortChange: function(e) { | 
|  | 21625         // The event we get from sort-toggle tells us the name of what needs | 
|  | 21626         // to be sorting and how to sort it. | 
|  | 21627         if (!(e && e.detail && e.detail.name)) { | 
|  | 21628           return; | 
|  | 21629         } | 
|  | 21630         this.set("sort", e.detail); | 
|  | 21631         swarming.stableSort(this.bots, this._sortBotTable.bind(this)); | 
|  | 21632         this._reRender(); | 
|  | 21633       }, | 
|  | 21634 | 
|  | 21635       // _stripSpecial removes the special columns and sorts the remaining | 
|  | 21636       // columns so they always appear in the same order, regardless of | 
|  | 21637       // the order they are added. | 
|  | 21638       _stripSpecial: function(){ | 
|  | 21639         return this.columns.filter(function(c){ | 
|  | 21640           return special_columns.indexOf(c) === -1; | 
|  | 21641         }).sort(); | 
|  | 21642       }, | 
|  | 21643 | 
|  | 21644       _taskLink: function(data) { | 
|  | 21645         if (data && data.task_id) { | 
|  | 21646           return "/user/task/" + data.task_id; | 
|  | 21647         } | 
|  | 21648         return undefined; | 
|  | 21649       } | 
|  | 21650 | 
|  | 21651     }); | 
|  | 21652   })(); | 
|  | 21653   </script> | 
| 14650 </dom-module></div></body></html> | 21654 </dom-module></div></body></html> | 
| OLD | NEW | 
|---|