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

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

Issue 2182693002: Add new botlist for swarming (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@app-wrapper
Patch Set: Adjust font and layout a bit more Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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">&nbsp;</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>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698