| OLD | NEW |
| 1 <!DOCTYPE html><html><head><!-- | 1 <!DOCTYPE html><html><head><!-- |
| 2 @license | 2 @license |
| 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. | 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also | 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --><!-- | 9 --><!-- |
| 10 @license | 10 @license |
| (...skipping 12213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12224 * | 12224 * |
| 12225 * @method getScrollState | 12225 * @method getScrollState |
| 12226 * @return {Object} | 12226 * @return {Object} |
| 12227 */ | 12227 */ |
| 12228 getScrollState: function() { | 12228 getScrollState: function() { |
| 12229 return { progress: this._progress }; | 12229 return { progress: this._progress }; |
| 12230 } | 12230 } |
| 12231 }); | 12231 }); |
| 12232 </script> | 12232 </script> |
| 12233 </dom-module> | 12233 </dom-module> |
| 12234 |
| 12235 <dom-module id="iron-flex" assetpath="/res/imp/bower_components/iron-flex-layout
/"> |
| 12236 <template> |
| 12237 <style> |
| 12238 .layout.horizontal, |
| 12239 .layout.vertical { |
| 12240 display: -ms-flexbox; |
| 12241 display: -webkit-flex; |
| 12242 display: flex; |
| 12243 } |
| 12244 |
| 12245 .layout.inline { |
| 12246 display: -ms-inline-flexbox; |
| 12247 display: -webkit-inline-flex; |
| 12248 display: inline-flex; |
| 12249 } |
| 12250 |
| 12251 .layout.horizontal { |
| 12252 -ms-flex-direction: row; |
| 12253 -webkit-flex-direction: row; |
| 12254 flex-direction: row; |
| 12255 } |
| 12256 |
| 12257 .layout.vertical { |
| 12258 -ms-flex-direction: column; |
| 12259 -webkit-flex-direction: column; |
| 12260 flex-direction: column; |
| 12261 } |
| 12262 |
| 12263 .layout.wrap { |
| 12264 -ms-flex-wrap: wrap; |
| 12265 -webkit-flex-wrap: wrap; |
| 12266 flex-wrap: wrap; |
| 12267 } |
| 12268 |
| 12269 .layout.center, |
| 12270 .layout.center-center { |
| 12271 -ms-flex-align: center; |
| 12272 -webkit-align-items: center; |
| 12273 align-items: center; |
| 12274 } |
| 12275 |
| 12276 .layout.center-justified, |
| 12277 .layout.center-center { |
| 12278 -ms-flex-pack: center; |
| 12279 -webkit-justify-content: center; |
| 12280 justify-content: center; |
| 12281 } |
| 12282 |
| 12283 .flex { |
| 12284 -ms-flex: 1 1 0.000000001px; |
| 12285 -webkit-flex: 1; |
| 12286 flex: 1; |
| 12287 -webkit-flex-basis: 0.000000001px; |
| 12288 flex-basis: 0.000000001px; |
| 12289 } |
| 12290 |
| 12291 .flex-auto { |
| 12292 -ms-flex: 1 1 auto; |
| 12293 -webkit-flex: 1 1 auto; |
| 12294 flex: 1 1 auto; |
| 12295 } |
| 12296 |
| 12297 .flex-none { |
| 12298 -ms-flex: none; |
| 12299 -webkit-flex: none; |
| 12300 flex: none; |
| 12301 } |
| 12302 </style> |
| 12303 </template> |
| 12304 </dom-module> |
| 12305 |
| 12306 |
| 12307 <dom-module id="iron-flex-reverse" assetpath="/res/imp/bower_components/iron-fle
x-layout/"> |
| 12308 <template> |
| 12309 <style> |
| 12310 .layout.horizontal-reverse, |
| 12311 .layout.vertical-reverse { |
| 12312 display: -ms-flexbox; |
| 12313 display: -webkit-flex; |
| 12314 display: flex; |
| 12315 } |
| 12316 |
| 12317 .layout.horizontal-reverse { |
| 12318 -ms-flex-direction: row-reverse; |
| 12319 -webkit-flex-direction: row-reverse; |
| 12320 flex-direction: row-reverse; |
| 12321 } |
| 12322 |
| 12323 .layout.vertical-reverse { |
| 12324 -ms-flex-direction: column-reverse; |
| 12325 -webkit-flex-direction: column-reverse; |
| 12326 flex-direction: column-reverse; |
| 12327 } |
| 12328 |
| 12329 .layout.wrap-reverse { |
| 12330 -ms-flex-wrap: wrap-reverse; |
| 12331 -webkit-flex-wrap: wrap-reverse; |
| 12332 flex-wrap: wrap-reverse; |
| 12333 } |
| 12334 </style> |
| 12335 </template> |
| 12336 </dom-module> |
| 12337 |
| 12338 |
| 12339 <dom-module id="iron-flex-alignment" assetpath="/res/imp/bower_components/iron-f
lex-layout/"> |
| 12340 <template> |
| 12341 <style> |
| 12342 /** |
| 12343 * Alignment in cross axis. |
| 12344 */ |
| 12345 .layout.start { |
| 12346 -ms-flex-align: start; |
| 12347 -webkit-align-items: flex-start; |
| 12348 align-items: flex-start; |
| 12349 } |
| 12350 |
| 12351 .layout.center, |
| 12352 .layout.center-center { |
| 12353 -ms-flex-align: center; |
| 12354 -webkit-align-items: center; |
| 12355 align-items: center; |
| 12356 } |
| 12357 |
| 12358 .layout.end { |
| 12359 -ms-flex-align: end; |
| 12360 -webkit-align-items: flex-end; |
| 12361 align-items: flex-end; |
| 12362 } |
| 12363 |
| 12364 .layout.baseline { |
| 12365 -ms-flex-align: baseline; |
| 12366 -webkit-align-items: baseline; |
| 12367 align-items: baseline; |
| 12368 } |
| 12369 |
| 12370 /** |
| 12371 * Alignment in main axis. |
| 12372 */ |
| 12373 .layout.start-justified { |
| 12374 -ms-flex-pack: start; |
| 12375 -webkit-justify-content: flex-start; |
| 12376 justify-content: flex-start; |
| 12377 } |
| 12378 |
| 12379 .layout.center-justified, |
| 12380 .layout.center-center { |
| 12381 -ms-flex-pack: center; |
| 12382 -webkit-justify-content: center; |
| 12383 justify-content: center; |
| 12384 } |
| 12385 |
| 12386 .layout.end-justified { |
| 12387 -ms-flex-pack: end; |
| 12388 -webkit-justify-content: flex-end; |
| 12389 justify-content: flex-end; |
| 12390 } |
| 12391 |
| 12392 .layout.around-justified { |
| 12393 -ms-flex-pack: distribute; |
| 12394 -webkit-justify-content: space-around; |
| 12395 justify-content: space-around; |
| 12396 } |
| 12397 |
| 12398 .layout.justified { |
| 12399 -ms-flex-pack: justify; |
| 12400 -webkit-justify-content: space-between; |
| 12401 justify-content: space-between; |
| 12402 } |
| 12403 |
| 12404 /** |
| 12405 * Self alignment. |
| 12406 */ |
| 12407 .self-start { |
| 12408 -ms-align-self: flex-start; |
| 12409 -webkit-align-self: flex-start; |
| 12410 align-self: flex-start; |
| 12411 } |
| 12412 |
| 12413 .self-center { |
| 12414 -ms-align-self: center; |
| 12415 -webkit-align-self: center; |
| 12416 align-self: center; |
| 12417 } |
| 12418 |
| 12419 .self-end { |
| 12420 -ms-align-self: flex-end; |
| 12421 -webkit-align-self: flex-end; |
| 12422 align-self: flex-end; |
| 12423 } |
| 12424 |
| 12425 .self-stretch { |
| 12426 -ms-align-self: stretch; |
| 12427 -webkit-align-self: stretch; |
| 12428 align-self: stretch; |
| 12429 } |
| 12430 |
| 12431 .self-baseline { |
| 12432 -ms-align-self: baseline; |
| 12433 -webkit-align-self: baseline; |
| 12434 align-self: baseline; |
| 12435 }; |
| 12436 |
| 12437 /** |
| 12438 * multi-line alignment in main axis. |
| 12439 */ |
| 12440 .layout.start-aligned { |
| 12441 -ms-flex-line-pack: start; /* IE10 */ |
| 12442 -ms-align-content: flex-start; |
| 12443 -webkit-align-content: flex-start; |
| 12444 align-content: flex-start; |
| 12445 } |
| 12446 |
| 12447 .layout.end-aligned { |
| 12448 -ms-flex-line-pack: end; /* IE10 */ |
| 12449 -ms-align-content: flex-end; |
| 12450 -webkit-align-content: flex-end; |
| 12451 align-content: flex-end; |
| 12452 } |
| 12453 |
| 12454 .layout.center-aligned { |
| 12455 -ms-flex-line-pack: center; /* IE10 */ |
| 12456 -ms-align-content: center; |
| 12457 -webkit-align-content: center; |
| 12458 align-content: center; |
| 12459 } |
| 12460 |
| 12461 .layout.between-aligned { |
| 12462 -ms-flex-line-pack: justify; /* IE10 */ |
| 12463 -ms-align-content: space-between; |
| 12464 -webkit-align-content: space-between; |
| 12465 align-content: space-between; |
| 12466 } |
| 12467 |
| 12468 .layout.around-aligned { |
| 12469 -ms-flex-line-pack: distribute; /* IE10 */ |
| 12470 -ms-align-content: space-around; |
| 12471 -webkit-align-content: space-around; |
| 12472 align-content: space-around; |
| 12473 } |
| 12474 </style> |
| 12475 </template> |
| 12476 </dom-module> |
| 12477 |
| 12478 <dom-module id="iron-flex-factors" assetpath="/res/imp/bower_components/iron-fle
x-layout/"> |
| 12479 <template> |
| 12480 <style> |
| 12481 .flex, |
| 12482 .flex-1 { |
| 12483 -ms-flex: 1 1 0.000000001px; |
| 12484 -webkit-flex: 1; |
| 12485 flex: 1; |
| 12486 -webkit-flex-basis: 0.000000001px; |
| 12487 flex-basis: 0.000000001px; |
| 12488 } |
| 12489 |
| 12490 .flex-2 { |
| 12491 -ms-flex: 2; |
| 12492 -webkit-flex: 2; |
| 12493 flex: 2; |
| 12494 } |
| 12495 |
| 12496 .flex-3 { |
| 12497 -ms-flex: 3; |
| 12498 -webkit-flex: 3; |
| 12499 flex: 3; |
| 12500 } |
| 12501 |
| 12502 .flex-4 { |
| 12503 -ms-flex: 4; |
| 12504 -webkit-flex: 4; |
| 12505 flex: 4; |
| 12506 } |
| 12507 |
| 12508 .flex-5 { |
| 12509 -ms-flex: 5; |
| 12510 -webkit-flex: 5; |
| 12511 flex: 5; |
| 12512 } |
| 12513 |
| 12514 .flex-6 { |
| 12515 -ms-flex: 6; |
| 12516 -webkit-flex: 6; |
| 12517 flex: 6; |
| 12518 } |
| 12519 |
| 12520 .flex-7 { |
| 12521 -ms-flex: 7; |
| 12522 -webkit-flex: 7; |
| 12523 flex: 7; |
| 12524 } |
| 12525 |
| 12526 .flex-8 { |
| 12527 -ms-flex: 8; |
| 12528 -webkit-flex: 8; |
| 12529 flex: 8; |
| 12530 } |
| 12531 |
| 12532 .flex-9 { |
| 12533 -ms-flex: 9; |
| 12534 -webkit-flex: 9; |
| 12535 flex: 9; |
| 12536 } |
| 12537 |
| 12538 .flex-10 { |
| 12539 -ms-flex: 10; |
| 12540 -webkit-flex: 10; |
| 12541 flex: 10; |
| 12542 } |
| 12543 |
| 12544 .flex-11 { |
| 12545 -ms-flex: 11; |
| 12546 -webkit-flex: 11; |
| 12547 flex: 11; |
| 12548 } |
| 12549 |
| 12550 .flex-12 { |
| 12551 -ms-flex: 12; |
| 12552 -webkit-flex: 12; |
| 12553 flex: 12; |
| 12554 } |
| 12555 </style> |
| 12556 </template> |
| 12557 </dom-module> |
| 12558 |
| 12559 |
| 12560 <dom-module id="iron-positioning" assetpath="/res/imp/bower_components/iron-flex
-layout/"> |
| 12561 <template> |
| 12562 <style> |
| 12563 .block { |
| 12564 display: block; |
| 12565 } |
| 12566 |
| 12567 /* IE 10 support for HTML5 hidden attr */ |
| 12568 [hidden] { |
| 12569 display: none !important; |
| 12570 } |
| 12571 |
| 12572 .invisible { |
| 12573 visibility: hidden !important; |
| 12574 } |
| 12575 |
| 12576 .relative { |
| 12577 position: relative; |
| 12578 } |
| 12579 |
| 12580 .fit { |
| 12581 position: absolute; |
| 12582 top: 0; |
| 12583 right: 0; |
| 12584 bottom: 0; |
| 12585 left: 0; |
| 12586 } |
| 12587 |
| 12588 body.fullbleed { |
| 12589 margin: 0; |
| 12590 height: 100vh; |
| 12591 } |
| 12592 |
| 12593 .scroll { |
| 12594 -webkit-overflow-scrolling: touch; |
| 12595 overflow: auto; |
| 12596 } |
| 12597 |
| 12598 /* fixed position */ |
| 12599 .fixed-bottom, |
| 12600 .fixed-left, |
| 12601 .fixed-right, |
| 12602 .fixed-top { |
| 12603 position: fixed; |
| 12604 } |
| 12605 |
| 12606 .fixed-top { |
| 12607 top: 0; |
| 12608 left: 0; |
| 12609 right: 0; |
| 12610 } |
| 12611 |
| 12612 .fixed-right { |
| 12613 top: 0; |
| 12614 right: 0; |
| 12615 bottom: 0; |
| 12616 } |
| 12617 |
| 12618 .fixed-bottom { |
| 12619 right: 0; |
| 12620 bottom: 0; |
| 12621 left: 0; |
| 12622 } |
| 12623 |
| 12624 .fixed-left { |
| 12625 top: 0; |
| 12626 bottom: 0; |
| 12627 left: 0; |
| 12628 } |
| 12629 </style> |
| 12630 </template> |
| 12631 </dom-module> |
| 12234 <style is="custom-style"> | 12632 <style is="custom-style"> |
| 12235 | 12633 |
| 12236 :root { | 12634 :root { |
| 12237 | 12635 |
| 12238 /* Material Design color palette for Google products */ | 12636 /* Material Design color palette for Google products */ |
| 12239 | 12637 |
| 12240 --google-red-100: #f4c7c3; | 12638 --google-red-100: #f4c7c3; |
| 12241 --google-red-300: #e67c73; | 12639 --google-red-300: #e67c73; |
| 12242 --google-red-500: #db4437; | 12640 --google-red-500: #db4437; |
| 12243 --google-red-700: #c53929; | 12641 --google-red-700: #c53929; |
| (...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12975 <script> | 13373 <script> |
| 12976 Polymer({ | 13374 Polymer({ |
| 12977 is: 'paper-spinner-lite', | 13375 is: 'paper-spinner-lite', |
| 12978 | 13376 |
| 12979 behaviors: [ | 13377 behaviors: [ |
| 12980 Polymer.PaperSpinnerBehavior | 13378 Polymer.PaperSpinnerBehavior |
| 12981 ] | 13379 ] |
| 12982 }); | 13380 }); |
| 12983 </script> | 13381 </script> |
| 12984 </dom-module> | 13382 </dom-module> |
| 12985 | |
| 12986 <dom-module id="iron-flex" assetpath="/res/imp/bower_components/iron-flex-layout
/"> | |
| 12987 <template> | |
| 12988 <style> | |
| 12989 .layout.horizontal, | |
| 12990 .layout.vertical { | |
| 12991 display: -ms-flexbox; | |
| 12992 display: -webkit-flex; | |
| 12993 display: flex; | |
| 12994 } | |
| 12995 | |
| 12996 .layout.inline { | |
| 12997 display: -ms-inline-flexbox; | |
| 12998 display: -webkit-inline-flex; | |
| 12999 display: inline-flex; | |
| 13000 } | |
| 13001 | |
| 13002 .layout.horizontal { | |
| 13003 -ms-flex-direction: row; | |
| 13004 -webkit-flex-direction: row; | |
| 13005 flex-direction: row; | |
| 13006 } | |
| 13007 | |
| 13008 .layout.vertical { | |
| 13009 -ms-flex-direction: column; | |
| 13010 -webkit-flex-direction: column; | |
| 13011 flex-direction: column; | |
| 13012 } | |
| 13013 | |
| 13014 .layout.wrap { | |
| 13015 -ms-flex-wrap: wrap; | |
| 13016 -webkit-flex-wrap: wrap; | |
| 13017 flex-wrap: wrap; | |
| 13018 } | |
| 13019 | |
| 13020 .layout.center, | |
| 13021 .layout.center-center { | |
| 13022 -ms-flex-align: center; | |
| 13023 -webkit-align-items: center; | |
| 13024 align-items: center; | |
| 13025 } | |
| 13026 | |
| 13027 .layout.center-justified, | |
| 13028 .layout.center-center { | |
| 13029 -ms-flex-pack: center; | |
| 13030 -webkit-justify-content: center; | |
| 13031 justify-content: center; | |
| 13032 } | |
| 13033 | |
| 13034 .flex { | |
| 13035 -ms-flex: 1 1 0.000000001px; | |
| 13036 -webkit-flex: 1; | |
| 13037 flex: 1; | |
| 13038 -webkit-flex-basis: 0.000000001px; | |
| 13039 flex-basis: 0.000000001px; | |
| 13040 } | |
| 13041 | |
| 13042 .flex-auto { | |
| 13043 -ms-flex: 1 1 auto; | |
| 13044 -webkit-flex: 1 1 auto; | |
| 13045 flex: 1 1 auto; | |
| 13046 } | |
| 13047 | |
| 13048 .flex-none { | |
| 13049 -ms-flex: none; | |
| 13050 -webkit-flex: none; | |
| 13051 flex: none; | |
| 13052 } | |
| 13053 </style> | |
| 13054 </template> | |
| 13055 </dom-module> | |
| 13056 | |
| 13057 | |
| 13058 <dom-module id="iron-flex-reverse" assetpath="/res/imp/bower_components/iron-fle
x-layout/"> | |
| 13059 <template> | |
| 13060 <style> | |
| 13061 .layout.horizontal-reverse, | |
| 13062 .layout.vertical-reverse { | |
| 13063 display: -ms-flexbox; | |
| 13064 display: -webkit-flex; | |
| 13065 display: flex; | |
| 13066 } | |
| 13067 | |
| 13068 .layout.horizontal-reverse { | |
| 13069 -ms-flex-direction: row-reverse; | |
| 13070 -webkit-flex-direction: row-reverse; | |
| 13071 flex-direction: row-reverse; | |
| 13072 } | |
| 13073 | |
| 13074 .layout.vertical-reverse { | |
| 13075 -ms-flex-direction: column-reverse; | |
| 13076 -webkit-flex-direction: column-reverse; | |
| 13077 flex-direction: column-reverse; | |
| 13078 } | |
| 13079 | |
| 13080 .layout.wrap-reverse { | |
| 13081 -ms-flex-wrap: wrap-reverse; | |
| 13082 -webkit-flex-wrap: wrap-reverse; | |
| 13083 flex-wrap: wrap-reverse; | |
| 13084 } | |
| 13085 </style> | |
| 13086 </template> | |
| 13087 </dom-module> | |
| 13088 | |
| 13089 | |
| 13090 <dom-module id="iron-flex-alignment" assetpath="/res/imp/bower_components/iron-f
lex-layout/"> | |
| 13091 <template> | |
| 13092 <style> | |
| 13093 /** | |
| 13094 * Alignment in cross axis. | |
| 13095 */ | |
| 13096 .layout.start { | |
| 13097 -ms-flex-align: start; | |
| 13098 -webkit-align-items: flex-start; | |
| 13099 align-items: flex-start; | |
| 13100 } | |
| 13101 | |
| 13102 .layout.center, | |
| 13103 .layout.center-center { | |
| 13104 -ms-flex-align: center; | |
| 13105 -webkit-align-items: center; | |
| 13106 align-items: center; | |
| 13107 } | |
| 13108 | |
| 13109 .layout.end { | |
| 13110 -ms-flex-align: end; | |
| 13111 -webkit-align-items: flex-end; | |
| 13112 align-items: flex-end; | |
| 13113 } | |
| 13114 | |
| 13115 .layout.baseline { | |
| 13116 -ms-flex-align: baseline; | |
| 13117 -webkit-align-items: baseline; | |
| 13118 align-items: baseline; | |
| 13119 } | |
| 13120 | |
| 13121 /** | |
| 13122 * Alignment in main axis. | |
| 13123 */ | |
| 13124 .layout.start-justified { | |
| 13125 -ms-flex-pack: start; | |
| 13126 -webkit-justify-content: flex-start; | |
| 13127 justify-content: flex-start; | |
| 13128 } | |
| 13129 | |
| 13130 .layout.center-justified, | |
| 13131 .layout.center-center { | |
| 13132 -ms-flex-pack: center; | |
| 13133 -webkit-justify-content: center; | |
| 13134 justify-content: center; | |
| 13135 } | |
| 13136 | |
| 13137 .layout.end-justified { | |
| 13138 -ms-flex-pack: end; | |
| 13139 -webkit-justify-content: flex-end; | |
| 13140 justify-content: flex-end; | |
| 13141 } | |
| 13142 | |
| 13143 .layout.around-justified { | |
| 13144 -ms-flex-pack: distribute; | |
| 13145 -webkit-justify-content: space-around; | |
| 13146 justify-content: space-around; | |
| 13147 } | |
| 13148 | |
| 13149 .layout.justified { | |
| 13150 -ms-flex-pack: justify; | |
| 13151 -webkit-justify-content: space-between; | |
| 13152 justify-content: space-between; | |
| 13153 } | |
| 13154 | |
| 13155 /** | |
| 13156 * Self alignment. | |
| 13157 */ | |
| 13158 .self-start { | |
| 13159 -ms-align-self: flex-start; | |
| 13160 -webkit-align-self: flex-start; | |
| 13161 align-self: flex-start; | |
| 13162 } | |
| 13163 | |
| 13164 .self-center { | |
| 13165 -ms-align-self: center; | |
| 13166 -webkit-align-self: center; | |
| 13167 align-self: center; | |
| 13168 } | |
| 13169 | |
| 13170 .self-end { | |
| 13171 -ms-align-self: flex-end; | |
| 13172 -webkit-align-self: flex-end; | |
| 13173 align-self: flex-end; | |
| 13174 } | |
| 13175 | |
| 13176 .self-stretch { | |
| 13177 -ms-align-self: stretch; | |
| 13178 -webkit-align-self: stretch; | |
| 13179 align-self: stretch; | |
| 13180 } | |
| 13181 | |
| 13182 .self-baseline { | |
| 13183 -ms-align-self: baseline; | |
| 13184 -webkit-align-self: baseline; | |
| 13185 align-self: baseline; | |
| 13186 }; | |
| 13187 | |
| 13188 /** | |
| 13189 * multi-line alignment in main axis. | |
| 13190 */ | |
| 13191 .layout.start-aligned { | |
| 13192 -ms-flex-line-pack: start; /* IE10 */ | |
| 13193 -ms-align-content: flex-start; | |
| 13194 -webkit-align-content: flex-start; | |
| 13195 align-content: flex-start; | |
| 13196 } | |
| 13197 | |
| 13198 .layout.end-aligned { | |
| 13199 -ms-flex-line-pack: end; /* IE10 */ | |
| 13200 -ms-align-content: flex-end; | |
| 13201 -webkit-align-content: flex-end; | |
| 13202 align-content: flex-end; | |
| 13203 } | |
| 13204 | |
| 13205 .layout.center-aligned { | |
| 13206 -ms-flex-line-pack: center; /* IE10 */ | |
| 13207 -ms-align-content: center; | |
| 13208 -webkit-align-content: center; | |
| 13209 align-content: center; | |
| 13210 } | |
| 13211 | |
| 13212 .layout.between-aligned { | |
| 13213 -ms-flex-line-pack: justify; /* IE10 */ | |
| 13214 -ms-align-content: space-between; | |
| 13215 -webkit-align-content: space-between; | |
| 13216 align-content: space-between; | |
| 13217 } | |
| 13218 | |
| 13219 .layout.around-aligned { | |
| 13220 -ms-flex-line-pack: distribute; /* IE10 */ | |
| 13221 -ms-align-content: space-around; | |
| 13222 -webkit-align-content: space-around; | |
| 13223 align-content: space-around; | |
| 13224 } | |
| 13225 </style> | |
| 13226 </template> | |
| 13227 </dom-module> | |
| 13228 | |
| 13229 <dom-module id="iron-flex-factors" assetpath="/res/imp/bower_components/iron-fle
x-layout/"> | |
| 13230 <template> | |
| 13231 <style> | |
| 13232 .flex, | |
| 13233 .flex-1 { | |
| 13234 -ms-flex: 1 1 0.000000001px; | |
| 13235 -webkit-flex: 1; | |
| 13236 flex: 1; | |
| 13237 -webkit-flex-basis: 0.000000001px; | |
| 13238 flex-basis: 0.000000001px; | |
| 13239 } | |
| 13240 | |
| 13241 .flex-2 { | |
| 13242 -ms-flex: 2; | |
| 13243 -webkit-flex: 2; | |
| 13244 flex: 2; | |
| 13245 } | |
| 13246 | |
| 13247 .flex-3 { | |
| 13248 -ms-flex: 3; | |
| 13249 -webkit-flex: 3; | |
| 13250 flex: 3; | |
| 13251 } | |
| 13252 | |
| 13253 .flex-4 { | |
| 13254 -ms-flex: 4; | |
| 13255 -webkit-flex: 4; | |
| 13256 flex: 4; | |
| 13257 } | |
| 13258 | |
| 13259 .flex-5 { | |
| 13260 -ms-flex: 5; | |
| 13261 -webkit-flex: 5; | |
| 13262 flex: 5; | |
| 13263 } | |
| 13264 | |
| 13265 .flex-6 { | |
| 13266 -ms-flex: 6; | |
| 13267 -webkit-flex: 6; | |
| 13268 flex: 6; | |
| 13269 } | |
| 13270 | |
| 13271 .flex-7 { | |
| 13272 -ms-flex: 7; | |
| 13273 -webkit-flex: 7; | |
| 13274 flex: 7; | |
| 13275 } | |
| 13276 | |
| 13277 .flex-8 { | |
| 13278 -ms-flex: 8; | |
| 13279 -webkit-flex: 8; | |
| 13280 flex: 8; | |
| 13281 } | |
| 13282 | |
| 13283 .flex-9 { | |
| 13284 -ms-flex: 9; | |
| 13285 -webkit-flex: 9; | |
| 13286 flex: 9; | |
| 13287 } | |
| 13288 | |
| 13289 .flex-10 { | |
| 13290 -ms-flex: 10; | |
| 13291 -webkit-flex: 10; | |
| 13292 flex: 10; | |
| 13293 } | |
| 13294 | |
| 13295 .flex-11 { | |
| 13296 -ms-flex: 11; | |
| 13297 -webkit-flex: 11; | |
| 13298 flex: 11; | |
| 13299 } | |
| 13300 | |
| 13301 .flex-12 { | |
| 13302 -ms-flex: 12; | |
| 13303 -webkit-flex: 12; | |
| 13304 flex: 12; | |
| 13305 } | |
| 13306 </style> | |
| 13307 </template> | |
| 13308 </dom-module> | |
| 13309 | |
| 13310 | |
| 13311 <dom-module id="iron-positioning" assetpath="/res/imp/bower_components/iron-flex
-layout/"> | |
| 13312 <template> | |
| 13313 <style> | |
| 13314 .block { | |
| 13315 display: block; | |
| 13316 } | |
| 13317 | |
| 13318 /* IE 10 support for HTML5 hidden attr */ | |
| 13319 [hidden] { | |
| 13320 display: none !important; | |
| 13321 } | |
| 13322 | |
| 13323 .invisible { | |
| 13324 visibility: hidden !important; | |
| 13325 } | |
| 13326 | |
| 13327 .relative { | |
| 13328 position: relative; | |
| 13329 } | |
| 13330 | |
| 13331 .fit { | |
| 13332 position: absolute; | |
| 13333 top: 0; | |
| 13334 right: 0; | |
| 13335 bottom: 0; | |
| 13336 left: 0; | |
| 13337 } | |
| 13338 | |
| 13339 body.fullbleed { | |
| 13340 margin: 0; | |
| 13341 height: 100vh; | |
| 13342 } | |
| 13343 | |
| 13344 .scroll { | |
| 13345 -webkit-overflow-scrolling: touch; | |
| 13346 overflow: auto; | |
| 13347 } | |
| 13348 | |
| 13349 /* fixed position */ | |
| 13350 .fixed-bottom, | |
| 13351 .fixed-left, | |
| 13352 .fixed-right, | |
| 13353 .fixed-top { | |
| 13354 position: fixed; | |
| 13355 } | |
| 13356 | |
| 13357 .fixed-top { | |
| 13358 top: 0; | |
| 13359 left: 0; | |
| 13360 right: 0; | |
| 13361 } | |
| 13362 | |
| 13363 .fixed-right { | |
| 13364 top: 0; | |
| 13365 right: 0; | |
| 13366 bottom: 0; | |
| 13367 } | |
| 13368 | |
| 13369 .fixed-bottom { | |
| 13370 right: 0; | |
| 13371 bottom: 0; | |
| 13372 left: 0; | |
| 13373 } | |
| 13374 | |
| 13375 .fixed-left { | |
| 13376 top: 0; | |
| 13377 bottom: 0; | |
| 13378 left: 0; | |
| 13379 } | |
| 13380 </style> | |
| 13381 </template> | |
| 13382 </dom-module> | |
| 13383 <script> | 13383 <script> |
| 13384 (function() { | 13384 (function() { |
| 13385 "use strict"; | 13385 "use strict"; |
| 13386 /** | 13386 /** |
| 13387 `Polymer.IronJsonpLibraryBehavior` loads a jsonp library. | 13387 `Polymer.IronJsonpLibraryBehavior` loads a jsonp library. |
| 13388 Multiple components can request same library, only one copy will load. | 13388 Multiple components can request same library, only one copy will load. |
| 13389 | 13389 |
| 13390 Some libraries require a specific global function be defined. | 13390 Some libraries require a specific global function be defined. |
| 13391 If this is the case, specify the `callbackName` property. | 13391 If this is the case, specify the `callbackName` property. |
| 13392 | 13392 |
| (...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14540 <style include="iron-flex"> | 14540 <style include="iron-flex"> |
| 14541 :host { | 14541 :host { |
| 14542 position: absolute; | 14542 position: absolute; |
| 14543 top: 0; | 14543 top: 0; |
| 14544 bottom: 0; | 14544 bottom: 0; |
| 14545 left: 0; | 14545 left: 0; |
| 14546 right: 0; | 14546 right: 0; |
| 14547 } | 14547 } |
| 14548 | 14548 |
| 14549 app-toolbar { | 14549 app-toolbar { |
| 14550 background-color: #4285f4; | 14550 background-color: #1F78B4; |
| 14551 color: #fff; | 14551 color: #fff; |
| 14552 } | 14552 } |
| 14553 | 14553 |
| 14554 app-toolbar a { | 14554 app-toolbar a { |
| 14555 color: #fff; | 14555 color: #fff; |
| 14556 } | 14556 } |
| 14557 .left { | 14557 .left { |
| 14558 margin-right:15px; | 14558 margin-right:15px; |
| 14559 } | 14559 } |
| 14560 .right { | 14560 .right { |
| 14561 margin-left:15px; | 14561 margin-left:15px; |
| 14562 } | 14562 } |
| 14563 .main-content { | 14563 .main-content { |
| 14564 padding: 3px; | 14564 padding: 3px; |
| 14565 } | 14565 } |
| 14566 | 14566 |
| 14567 .main-content a { |
| 14568 color: #1F78B4; |
| 14569 } |
| 14570 |
| 14567 paper-spinner-lite { | 14571 paper-spinner-lite { |
| 14568 --paper-spinner-color: var(--google-yellow-500); | 14572 --paper-spinner-color: var(--google-yellow-500); |
| 14569 } | 14573 } |
| 14570 </style> | 14574 </style> |
| 14571 <app-header-layout> | 14575 <app-header-layout> |
| 14572 <app-header fixed=""> | 14576 <app-header fixed=""> |
| 14573 <app-toolbar> | 14577 <app-toolbar> |
| 14574 <div class="title left">[[name]]</div> | 14578 <div class="title left">[[name]]</div> |
| 14575 <paper-spinner-lite class="left" active="[[busy]]"></paper-spinner-lit
e> | 14579 <paper-spinner-lite class="left" active="[[busy]]"></paper-spinner-lit
e> |
| 14576 | 14580 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 14599 busy: { | 14603 busy: { |
| 14600 type: Boolean, | 14604 type: Boolean, |
| 14601 }, | 14605 }, |
| 14602 name: { | 14606 name: { |
| 14603 type: String, | 14607 type: String, |
| 14604 }, | 14608 }, |
| 14605 }, | 14609 }, |
| 14606 | 14610 |
| 14607 }); | 14611 }); |
| 14608 </script> | 14612 </script> |
| 14613 </dom-module> |
| 14614 |
| 14615 <dom-module id="swarming-app-style" assetpath="/res/imp/common/"> |
| 14616 <style> |
| 14617 * { |
| 14618 font-family: sans-serif; |
| 14619 } |
| 14620 /* Only style anchor tags that are actually linking somewhere.*/ |
| 14621 a[href] { |
| 14622 color: #1F78B4; |
| 14623 } |
| 14624 </style> |
| 14609 </dom-module><dom-module id="swarming-index" assetpath="/res/imp/index/"> | 14625 </dom-module><dom-module id="swarming-index" assetpath="/res/imp/index/"> |
| 14610 <template> | 14626 <template> |
| 14611 <style> | 14627 <style include="swarming-app-style"> |
| 14612 :host { | 14628 |
| 14613 display: block; | |
| 14614 } | |
| 14615 </style> | 14629 </style> |
| 14616 | 14630 |
| 14617 <swarming-app auth_headers="{{auth_headers}}" name="Swarming" busy="[[busy]]
"> | 14631 <swarming-app auth_headers="{{auth_headers}}" name="Swarming" busy="[[busy]]
"> |
| 14618 | 14632 |
| 14619 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers=
"[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{
{busy}}"> | 14633 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers=
"[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{
{busy}}"> |
| 14620 </iron-ajax> | 14634 </iron-ajax> |
| 14621 | 14635 |
| 14622 <h1>HELLO WORLD</h1> | 14636 <h1>HELLO WORLD</h1> |
| 14623 | 14637 |
| 14624 <div>Server Version: [[serverDetails.server_version]]</div> | 14638 <div>Server Version: [[serverDetails.server_version]]</div> |
| (...skipping 15 matching lines...) Expand all Loading... |
| 14640 type: String, | 14654 type: String, |
| 14641 } | 14655 } |
| 14642 }, | 14656 }, |
| 14643 | 14657 |
| 14644 signIn: function(){ | 14658 signIn: function(){ |
| 14645 this.$.request.generateRequest(); | 14659 this.$.request.generateRequest(); |
| 14646 }, | 14660 }, |
| 14647 | 14661 |
| 14648 }); | 14662 }); |
| 14649 </script> | 14663 </script> |
| 14664 </dom-module> |
| 14665 |
| 14666 <script> |
| 14667 |
| 14668 (function() { |
| 14669 |
| 14670 // monostate data |
| 14671 var metaDatas = {}; |
| 14672 var metaArrays = {}; |
| 14673 var singleton = null; |
| 14674 |
| 14675 Polymer.IronMeta = Polymer({ |
| 14676 |
| 14677 is: 'iron-meta', |
| 14678 |
| 14679 properties: { |
| 14680 |
| 14681 /** |
| 14682 * The type of meta-data. All meta-data of the same type is stored |
| 14683 * together. |
| 14684 */ |
| 14685 type: { |
| 14686 type: String, |
| 14687 value: 'default', |
| 14688 observer: '_typeChanged' |
| 14689 }, |
| 14690 |
| 14691 /** |
| 14692 * The key used to store `value` under the `type` namespace. |
| 14693 */ |
| 14694 key: { |
| 14695 type: String, |
| 14696 observer: '_keyChanged' |
| 14697 }, |
| 14698 |
| 14699 /** |
| 14700 * The meta-data to store or retrieve. |
| 14701 */ |
| 14702 value: { |
| 14703 type: Object, |
| 14704 notify: true, |
| 14705 observer: '_valueChanged' |
| 14706 }, |
| 14707 |
| 14708 /** |
| 14709 * If true, `value` is set to the iron-meta instance itself. |
| 14710 */ |
| 14711 self: { |
| 14712 type: Boolean, |
| 14713 observer: '_selfChanged' |
| 14714 }, |
| 14715 |
| 14716 /** |
| 14717 * Array of all meta-data values for the given type. |
| 14718 */ |
| 14719 list: { |
| 14720 type: Array, |
| 14721 notify: true |
| 14722 } |
| 14723 |
| 14724 }, |
| 14725 |
| 14726 hostAttributes: { |
| 14727 hidden: true |
| 14728 }, |
| 14729 |
| 14730 /** |
| 14731 * Only runs if someone invokes the factory/constructor directly |
| 14732 * e.g. `new Polymer.IronMeta()` |
| 14733 * |
| 14734 * @param {{type: (string|undefined), key: (string|undefined), value}=} co
nfig |
| 14735 */ |
| 14736 factoryImpl: function(config) { |
| 14737 if (config) { |
| 14738 for (var n in config) { |
| 14739 switch(n) { |
| 14740 case 'type': |
| 14741 case 'key': |
| 14742 case 'value': |
| 14743 this[n] = config[n]; |
| 14744 break; |
| 14745 } |
| 14746 } |
| 14747 } |
| 14748 }, |
| 14749 |
| 14750 created: function() { |
| 14751 // TODO(sjmiles): good for debugging? |
| 14752 this._metaDatas = metaDatas; |
| 14753 this._metaArrays = metaArrays; |
| 14754 }, |
| 14755 |
| 14756 _keyChanged: function(key, old) { |
| 14757 this._resetRegistration(old); |
| 14758 }, |
| 14759 |
| 14760 _valueChanged: function(value) { |
| 14761 this._resetRegistration(this.key); |
| 14762 }, |
| 14763 |
| 14764 _selfChanged: function(self) { |
| 14765 if (self) { |
| 14766 this.value = this; |
| 14767 } |
| 14768 }, |
| 14769 |
| 14770 _typeChanged: function(type) { |
| 14771 this._unregisterKey(this.key); |
| 14772 if (!metaDatas[type]) { |
| 14773 metaDatas[type] = {}; |
| 14774 } |
| 14775 this._metaData = metaDatas[type]; |
| 14776 if (!metaArrays[type]) { |
| 14777 metaArrays[type] = []; |
| 14778 } |
| 14779 this.list = metaArrays[type]; |
| 14780 this._registerKeyValue(this.key, this.value); |
| 14781 }, |
| 14782 |
| 14783 /** |
| 14784 * Retrieves meta data value by key. |
| 14785 * |
| 14786 * @method byKey |
| 14787 * @param {string} key The key of the meta-data to be returned. |
| 14788 * @return {*} |
| 14789 */ |
| 14790 byKey: function(key) { |
| 14791 return this._metaData && this._metaData[key]; |
| 14792 }, |
| 14793 |
| 14794 _resetRegistration: function(oldKey) { |
| 14795 this._unregisterKey(oldKey); |
| 14796 this._registerKeyValue(this.key, this.value); |
| 14797 }, |
| 14798 |
| 14799 _unregisterKey: function(key) { |
| 14800 this._unregister(key, this._metaData, this.list); |
| 14801 }, |
| 14802 |
| 14803 _registerKeyValue: function(key, value) { |
| 14804 this._register(key, value, this._metaData, this.list); |
| 14805 }, |
| 14806 |
| 14807 _register: function(key, value, data, list) { |
| 14808 if (key && data && value !== undefined) { |
| 14809 data[key] = value; |
| 14810 list.push(value); |
| 14811 } |
| 14812 }, |
| 14813 |
| 14814 _unregister: function(key, data, list) { |
| 14815 if (key && data) { |
| 14816 if (key in data) { |
| 14817 var value = data[key]; |
| 14818 delete data[key]; |
| 14819 this.arrayDelete(list, value); |
| 14820 } |
| 14821 } |
| 14822 } |
| 14823 |
| 14824 }); |
| 14825 |
| 14826 Polymer.IronMeta.getIronMeta = function getIronMeta() { |
| 14827 if (singleton === null) { |
| 14828 singleton = new Polymer.IronMeta(); |
| 14829 } |
| 14830 return singleton; |
| 14831 }; |
| 14832 |
| 14833 /** |
| 14834 `iron-meta-query` can be used to access infomation stored in `iron-meta`. |
| 14835 |
| 14836 Examples: |
| 14837 |
| 14838 If I create an instance like this: |
| 14839 |
| 14840 <iron-meta key="info" value="foo/bar"></iron-meta> |
| 14841 |
| 14842 Note that value="foo/bar" is the metadata I've defined. I could define more |
| 14843 attributes or use child nodes to define additional metadata. |
| 14844 |
| 14845 Now I can access that element (and it's metadata) from any `iron-meta-query`
instance: |
| 14846 |
| 14847 var value = new Polymer.IronMetaQuery({key: 'info'}).value; |
| 14848 |
| 14849 @group Polymer Iron Elements |
| 14850 @element iron-meta-query |
| 14851 */ |
| 14852 Polymer.IronMetaQuery = Polymer({ |
| 14853 |
| 14854 is: 'iron-meta-query', |
| 14855 |
| 14856 properties: { |
| 14857 |
| 14858 /** |
| 14859 * The type of meta-data. All meta-data of the same type is stored |
| 14860 * together. |
| 14861 */ |
| 14862 type: { |
| 14863 type: String, |
| 14864 value: 'default', |
| 14865 observer: '_typeChanged' |
| 14866 }, |
| 14867 |
| 14868 /** |
| 14869 * Specifies a key to use for retrieving `value` from the `type` |
| 14870 * namespace. |
| 14871 */ |
| 14872 key: { |
| 14873 type: String, |
| 14874 observer: '_keyChanged' |
| 14875 }, |
| 14876 |
| 14877 /** |
| 14878 * The meta-data to store or retrieve. |
| 14879 */ |
| 14880 value: { |
| 14881 type: Object, |
| 14882 notify: true, |
| 14883 readOnly: true |
| 14884 }, |
| 14885 |
| 14886 /** |
| 14887 * Array of all meta-data values for the given type. |
| 14888 */ |
| 14889 list: { |
| 14890 type: Array, |
| 14891 notify: true |
| 14892 } |
| 14893 |
| 14894 }, |
| 14895 |
| 14896 /** |
| 14897 * Actually a factory method, not a true constructor. Only runs if |
| 14898 * someone invokes it directly (via `new Polymer.IronMeta()`); |
| 14899 * |
| 14900 * @param {{type: (string|undefined), key: (string|undefined)}=} config |
| 14901 */ |
| 14902 factoryImpl: function(config) { |
| 14903 if (config) { |
| 14904 for (var n in config) { |
| 14905 switch(n) { |
| 14906 case 'type': |
| 14907 case 'key': |
| 14908 this[n] = config[n]; |
| 14909 break; |
| 14910 } |
| 14911 } |
| 14912 } |
| 14913 }, |
| 14914 |
| 14915 created: function() { |
| 14916 // TODO(sjmiles): good for debugging? |
| 14917 this._metaDatas = metaDatas; |
| 14918 this._metaArrays = metaArrays; |
| 14919 }, |
| 14920 |
| 14921 _keyChanged: function(key) { |
| 14922 this._setValue(this._metaData && this._metaData[key]); |
| 14923 }, |
| 14924 |
| 14925 _typeChanged: function(type) { |
| 14926 this._metaData = metaDatas[type]; |
| 14927 this.list = metaArrays[type]; |
| 14928 if (this.key) { |
| 14929 this._keyChanged(this.key); |
| 14930 } |
| 14931 }, |
| 14932 |
| 14933 /** |
| 14934 * Retrieves meta data value by key. |
| 14935 * @param {string} key The key of the meta-data to be returned. |
| 14936 * @return {*} |
| 14937 */ |
| 14938 byKey: function(key) { |
| 14939 return this._metaData && this._metaData[key]; |
| 14940 } |
| 14941 |
| 14942 }); |
| 14943 |
| 14944 })(); |
| 14945 </script> |
| 14946 |
| 14947 |
| 14948 <dom-module id="iron-icon" assetpath="/res/imp/bower_components/iron-icon/"> |
| 14949 <template> |
| 14950 <style> |
| 14951 :host { |
| 14952 @apply(--layout-inline); |
| 14953 @apply(--layout-center-center); |
| 14954 position: relative; |
| 14955 |
| 14956 vertical-align: middle; |
| 14957 |
| 14958 fill: var(--iron-icon-fill-color, currentcolor); |
| 14959 stroke: var(--iron-icon-stroke-color, none); |
| 14960 |
| 14961 width: var(--iron-icon-width, 24px); |
| 14962 height: var(--iron-icon-height, 24px); |
| 14963 } |
| 14964 </style> |
| 14965 </template> |
| 14966 |
| 14967 <script> |
| 14968 |
| 14969 Polymer({ |
| 14970 |
| 14971 is: 'iron-icon', |
| 14972 |
| 14973 properties: { |
| 14974 |
| 14975 /** |
| 14976 * The name of the icon to use. The name should be of the form: |
| 14977 * `iconset_name:icon_name`. |
| 14978 */ |
| 14979 icon: { |
| 14980 type: String, |
| 14981 observer: '_iconChanged' |
| 14982 }, |
| 14983 |
| 14984 /** |
| 14985 * The name of the theme to used, if one is specified by the |
| 14986 * iconset. |
| 14987 */ |
| 14988 theme: { |
| 14989 type: String, |
| 14990 observer: '_updateIcon' |
| 14991 }, |
| 14992 |
| 14993 /** |
| 14994 * If using iron-icon without an iconset, you can set the src to be |
| 14995 * the URL of an individual icon image file. Note that this will take |
| 14996 * precedence over a given icon attribute. |
| 14997 */ |
| 14998 src: { |
| 14999 type: String, |
| 15000 observer: '_srcChanged' |
| 15001 }, |
| 15002 |
| 15003 /** |
| 15004 * @type {!Polymer.IronMeta} |
| 15005 */ |
| 15006 _meta: { |
| 15007 value: Polymer.Base.create('iron-meta', {type: 'iconset'}), |
| 15008 observer: '_updateIcon' |
| 15009 } |
| 15010 |
| 15011 }, |
| 15012 |
| 15013 _DEFAULT_ICONSET: 'icons', |
| 15014 |
| 15015 _iconChanged: function(icon) { |
| 15016 var parts = (icon || '').split(':'); |
| 15017 this._iconName = parts.pop(); |
| 15018 this._iconsetName = parts.pop() || this._DEFAULT_ICONSET; |
| 15019 this._updateIcon(); |
| 15020 }, |
| 15021 |
| 15022 _srcChanged: function(src) { |
| 15023 this._updateIcon(); |
| 15024 }, |
| 15025 |
| 15026 _usesIconset: function() { |
| 15027 return this.icon || !this.src; |
| 15028 }, |
| 15029 |
| 15030 /** @suppress {visibility} */ |
| 15031 _updateIcon: function() { |
| 15032 if (this._usesIconset()) { |
| 15033 if (this._img && this._img.parentNode) { |
| 15034 Polymer.dom(this.root).removeChild(this._img); |
| 15035 } |
| 15036 if (this._iconName === "") { |
| 15037 if (this._iconset) { |
| 15038 this._iconset.removeIcon(this); |
| 15039 } |
| 15040 } else if (this._iconsetName && this._meta) { |
| 15041 this._iconset = /** @type {?Polymer.Iconset} */ ( |
| 15042 this._meta.byKey(this._iconsetName)); |
| 15043 if (this._iconset) { |
| 15044 this._iconset.applyIcon(this, this._iconName, this.theme); |
| 15045 this.unlisten(window, 'iron-iconset-added', '_updateIcon'); |
| 15046 } else { |
| 15047 this.listen(window, 'iron-iconset-added', '_updateIcon'); |
| 15048 } |
| 15049 } |
| 15050 } else { |
| 15051 if (this._iconset) { |
| 15052 this._iconset.removeIcon(this); |
| 15053 } |
| 15054 if (!this._img) { |
| 15055 this._img = document.createElement('img'); |
| 15056 this._img.style.width = '100%'; |
| 15057 this._img.style.height = '100%'; |
| 15058 this._img.draggable = false; |
| 15059 } |
| 15060 this._img.src = this.src; |
| 15061 Polymer.dom(this.root).appendChild(this._img); |
| 15062 } |
| 15063 } |
| 15064 |
| 15065 }); |
| 15066 |
| 15067 </script> |
| 15068 |
| 15069 </dom-module> |
| 15070 <script> |
| 15071 /** |
| 15072 * The `iron-iconset-svg` element allows users to define their own icon sets |
| 15073 * that contain svg icons. The svg icon elements should be children of the |
| 15074 * `iron-iconset-svg` element. Multiple icons should be given distinct id's. |
| 15075 * |
| 15076 * Using svg elements to create icons has a few advantages over traditional |
| 15077 * bitmap graphics like jpg or png. Icons that use svg are vector based so |
| 15078 * they are resolution independent and should look good on any device. They |
| 15079 * are stylable via css. Icons can be themed, colorized, and even animated. |
| 15080 * |
| 15081 * Example: |
| 15082 * |
| 15083 * <iron-iconset-svg name="my-svg-icons" size="24"> |
| 15084 * <svg> |
| 15085 * <defs> |
| 15086 * <g id="shape"> |
| 15087 * <rect x="12" y="0" width="12" height="24" /> |
| 15088 * <circle cx="12" cy="12" r="12" /> |
| 15089 * </g> |
| 15090 * </defs> |
| 15091 * </svg> |
| 15092 * </iron-iconset-svg> |
| 15093 * |
| 15094 * This will automatically register the icon set "my-svg-icons" to the iconset |
| 15095 * database. To use these icons from within another element, make a |
| 15096 * `iron-iconset` element and call the `byId` method |
| 15097 * to retrieve a given iconset. To apply a particular icon inside an |
| 15098 * element use the `applyIcon` method. For example: |
| 15099 * |
| 15100 * iconset.applyIcon(iconNode, 'car'); |
| 15101 * |
| 15102 * @element iron-iconset-svg |
| 15103 * @demo demo/index.html |
| 15104 * @implements {Polymer.Iconset} |
| 15105 */ |
| 15106 Polymer({ |
| 15107 is: 'iron-iconset-svg', |
| 15108 |
| 15109 properties: { |
| 15110 |
| 15111 /** |
| 15112 * The name of the iconset. |
| 15113 */ |
| 15114 name: { |
| 15115 type: String, |
| 15116 observer: '_nameChanged' |
| 15117 }, |
| 15118 |
| 15119 /** |
| 15120 * The size of an individual icon. Note that icons must be square. |
| 15121 */ |
| 15122 size: { |
| 15123 type: Number, |
| 15124 value: 24 |
| 15125 } |
| 15126 |
| 15127 }, |
| 15128 |
| 15129 attached: function() { |
| 15130 this.style.display = 'none'; |
| 15131 }, |
| 15132 |
| 15133 /** |
| 15134 * Construct an array of all icon names in this iconset. |
| 15135 * |
| 15136 * @return {!Array} Array of icon names. |
| 15137 */ |
| 15138 getIconNames: function() { |
| 15139 this._icons = this._createIconMap(); |
| 15140 return Object.keys(this._icons).map(function(n) { |
| 15141 return this.name + ':' + n; |
| 15142 }, this); |
| 15143 }, |
| 15144 |
| 15145 /** |
| 15146 * Applies an icon to the given element. |
| 15147 * |
| 15148 * An svg icon is prepended to the element's shadowRoot if it exists, |
| 15149 * otherwise to the element itself. |
| 15150 * |
| 15151 * @method applyIcon |
| 15152 * @param {Element} element Element to which the icon is applied. |
| 15153 * @param {string} iconName Name of the icon to apply. |
| 15154 * @return {?Element} The svg element which renders the icon. |
| 15155 */ |
| 15156 applyIcon: function(element, iconName) { |
| 15157 // insert svg element into shadow root, if it exists |
| 15158 element = element.root || element; |
| 15159 // Remove old svg element |
| 15160 this.removeIcon(element); |
| 15161 // install new svg element |
| 15162 var svg = this._cloneIcon(iconName); |
| 15163 if (svg) { |
| 15164 var pde = Polymer.dom(element); |
| 15165 pde.insertBefore(svg, pde.childNodes[0]); |
| 15166 return element._svgIcon = svg; |
| 15167 } |
| 15168 return null; |
| 15169 }, |
| 15170 |
| 15171 /** |
| 15172 * Remove an icon from the given element by undoing the changes effected |
| 15173 * by `applyIcon`. |
| 15174 * |
| 15175 * @param {Element} element The element from which the icon is removed. |
| 15176 */ |
| 15177 removeIcon: function(element) { |
| 15178 // Remove old svg element |
| 15179 if (element._svgIcon) { |
| 15180 Polymer.dom(element).removeChild(element._svgIcon); |
| 15181 element._svgIcon = null; |
| 15182 } |
| 15183 }, |
| 15184 |
| 15185 /** |
| 15186 * |
| 15187 * When name is changed, register iconset metadata |
| 15188 * |
| 15189 */ |
| 15190 _nameChanged: function() { |
| 15191 new Polymer.IronMeta({type: 'iconset', key: this.name, value: this}); |
| 15192 this.async(function() { |
| 15193 this.fire('iron-iconset-added', this, {node: window}); |
| 15194 }); |
| 15195 }, |
| 15196 |
| 15197 /** |
| 15198 * Create a map of child SVG elements by id. |
| 15199 * |
| 15200 * @return {!Object} Map of id's to SVG elements. |
| 15201 */ |
| 15202 _createIconMap: function() { |
| 15203 // Objects chained to Object.prototype (`{}`) have members. Specifically, |
| 15204 // on FF there is a `watch` method that confuses the icon map, so we |
| 15205 // need to use a null-based object here. |
| 15206 var icons = Object.create(null); |
| 15207 Polymer.dom(this).querySelectorAll('[id]') |
| 15208 .forEach(function(icon) { |
| 15209 icons[icon.id] = icon; |
| 15210 }); |
| 15211 return icons; |
| 15212 }, |
| 15213 |
| 15214 /** |
| 15215 * Produce installable clone of the SVG element matching `id` in this |
| 15216 * iconset, or `undefined` if there is no matching element. |
| 15217 * |
| 15218 * @return {Element} Returns an installable clone of the SVG element |
| 15219 * matching `id`. |
| 15220 */ |
| 15221 _cloneIcon: function(id) { |
| 15222 // create the icon map on-demand, since the iconset itself has no discrete |
| 15223 // signal to know when it's children are fully parsed |
| 15224 this._icons = this._icons || this._createIconMap(); |
| 15225 return this._prepareSvgClone(this._icons[id], this.size); |
| 15226 }, |
| 15227 |
| 15228 /** |
| 15229 * @param {Element} sourceSvg |
| 15230 * @param {number} size |
| 15231 * @return {Element} |
| 15232 */ |
| 15233 _prepareSvgClone: function(sourceSvg, size) { |
| 15234 if (sourceSvg) { |
| 15235 var content = sourceSvg.cloneNode(true), |
| 15236 svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), |
| 15237 viewBox = content.getAttribute('viewBox') || '0 0 ' + size + ' ' + s
ize; |
| 15238 svg.setAttribute('viewBox', viewBox); |
| 15239 svg.setAttribute('preserveAspectRatio', 'xMidYMid meet'); |
| 15240 // TODO(dfreedm): `pointer-events: none` works around https://crbug.com/
370136 |
| 15241 // TODO(sjmiles): inline style may not be ideal, but avoids requiring a
shadow-root |
| 15242 svg.style.cssText = 'pointer-events: none; display: block; width: 100%;
height: 100%;'; |
| 15243 svg.appendChild(content).removeAttribute('id'); |
| 15244 return svg; |
| 15245 } |
| 15246 return null; |
| 15247 } |
| 15248 |
| 15249 }); |
| 15250 </script> |
| 15251 <iron-iconset-svg name="icons" size="24"> |
| 15252 <svg><defs> |
| 15253 <g id="3d-rotation"><path d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 1
9.16 5.71 24 12 24l.66-.03-3.81-3.81-1.33 1.32zm.89-6.52c-.19 0-.37-.03-.52-.08-
.16-.06-.29-.13-.4-.24-.11-.1-.2-.22-.26-.37-.06-.14-.09-.3-.09-.47h-1.3c0 .36.0
7.68.21.95.14.27.33.5.56.69.24.18.51.32.82.41.3.1.62.15.96.15.37 0 .72-.05 1.03-
.15.32-.1.6-.25.83-.44s.42-.43.55-.72c.13-.29.2-.61.2-.97 0-.19-.02-.38-.07-.56-
.05-.18-.12-.35-.23-.51-.1-.16-.24-.3-.4-.43-.17-.13-.37-.23-.61-.31.2-.09.37-.2
.52-.33.15-.13.27-.27.37-.42.1-.15.17-.3.22-.46.05-.16.07-.32.07-.48 0-.36-.06-.
68-.18-.96-.12-.28-.29-.51-.51-.69-.2-.19-.47-.33-.77-.43C9.1 8.05 8.76 8 8.39 8
c-.36 0-.69.05-1 .16-.3.11-.57.26-.79.45-.21.19-.38.41-.51.67-.12.26-.18.54-.18.
85h1.3c0-.17.03-.32.09-.45s.14-.25.25-.34c.11-.09.23-.17.38-.22.15-.05.3-.08.48-
.08.4 0 .7.1.89.31.19.2.29.49.29.86 0 .18-.03.34-.08.49-.05.15-.14.27-.25.37-.11
.1-.25.18-.41.24-.16.06-.36.09-.58.09H7.5v1.03h.77c.22 0 .42.02.6.07s.33.13.45.2
3c.12.11.22.24.29.4.07.16.1.35.1.57 0 .41-.12.72-.35.93-.23.23-.55.33-.95.33zm8.
55-5.92c-.32-.33-.7-.59-1.14-.77-.43-.18-.92-.27-1.46-.27H12v8h2.3c.55 0 1.06-.0
9 1.51-.27.45-.18.84-.43 1.16-.76.32-.33.57-.73.74-1.19.17-.47.26-.99.26-1.57v-.
4c0-.58-.09-1.1-.26-1.57-.18-.47-.43-.87-.75-1.2zm-.39 3.16c0 .42-.05.79-.14 1.1
3-.1.33-.24.62-.43.85-.19.23-.43.41-.71.53-.29.12-.62.18-.99.18h-.91V9.12h.97c.7
2 0 1.27.23 1.64.69.38.46.57 1.12.57 1.99v.4zM12 0l-.66.03 3.81 3.81 1.33-1.33c3
.27 1.55 5.61 4.72 5.96 8.48h1.5C23.44 4.84 18.29 0 12 0z"></path></g> |
| 15254 <g id="accessibility"><path d="M12 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2z
m9 7h-6v13h-2v-6h-2v6H9V9H3V7h18v2z"></path></g> |
| 15255 <g id="accessible"><circle cx="12" cy="4" r="2"></circle><path d="M19 13v-2c-1.5
4.02-3.09-.75-4.07-1.83l-1.29-1.43c-.17-.19-.38-.34-.61-.45-.01 0-.01-.01-.02-.0
1H13c-.35-.2-.75-.3-1.19-.26C10.76 7.11 10 8.04 10 9.09V15c0 1.1.9 2 2 2h5v5h2v-
5.5c0-1.1-.9-2-2-2h-3v-3.45c1.29 1.07 3.25 1.94 5 1.95zm-6.17 5c-.41 1.16-1.52 2
-2.83 2-1.66 0-3-1.34-3-3 0-1.31.84-2.41 2-2.83V12.1c-2.28.46-4 2.48-4 4.9 0 2.7
6 2.24 5 5 5 2.42 0 4.44-1.72 4.9-4h-2.07z"></path></g> |
| 15256 <g id="account-balance"><path d="M4 10v7h3v-7H4zm6 0v7h3v-7h-3zM2 22h19v-3H2v3zm
14-12v7h3v-7h-3zm-4.5-9L2 6v2h19V6l-9.5-5z"></path></g> |
| 15257 <g id="account-balance-wallet"><path d="M21 18v1c0 1.1-.9 2-2 2H5c-1.11 0-2-.9-2
-2V5c0-1.1.89-2 2-2h14c1.1 0 2 .9 2 2v1h-9c-1.11 0-2 .9-2 2v8c0 1.1.89 2 2 2h9zm
-9-2h10V8H12v8zm4-2.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67
1.5-1.5 1.5z"></path></g> |
| 15258 <g id="account-box"><path d="M3 5v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9
-2-2-2H5c-1.11 0-2 .9-2 2zm12 4c0 1.66-1.34 3-3 3s-3-1.34-3-3 1.34-3 3-3 3 1.34
3 3zm-9 8c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6v-1z"></path></g> |
| 15259 <g id="account-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 1
0-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14
.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.
94-3.5 3.22-6 3.22z"></path></g> |
| 15260 <g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g> |
| 15261 <g id="add-alert"><path d="M10.01 21.01c0 1.1.89 1.99 1.99 1.99s1.99-.89 1.99-1.
99h-3.98zm8.87-4.19V11c0-3.25-2.25-5.97-5.29-6.69v-.72C13.59 2.71 12.88 2 12 2s-
1.59.71-1.59 1.59v.72C7.37 5.03 5.12 7.75 5.12 11v5.82L3 18.94V20h18v-1.06l-2.12
-2.12zM16 13.01h-3v3h-2v-3H8V11h3V8h2v3h3v2.01z"></path></g> |
| 15262 <g id="add-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.
9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"></path></g> |
| 15263 <g id="add-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10
S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"></path></g> |
| 15264 <g id="add-circle-outline"><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.48
2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8
s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"></path></g> |
| 15265 <g id="add-shopping-cart"><path d="M11 9h2V6h3V4h-3V1h-2v3H8v2h3v3zm-4 9c-1.1 0-
1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zm10 0c-1.1 0-1.99.9-1.99 2s.89 2 1.9
9 2 2-.9 2-2-.9-2-2-2zm-9.83-3.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3
.86-7.01L19.42 4h-.01l-1.1 2-2.76 5H8.53l-.13-.27L6.16 6l-.95-2-.94-2H1v2h2l3.6
7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.13 0-.25-.11-.25
-.25z"></path></g> |
| 15266 <g id="alarm"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L
6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12
4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.
13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"></path></g> |
| 15267 <g id="alarm-add"><path d="M7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM22 5.
72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97
0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-
7 7zm1-11h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"></path></g> |
| 15268 <g id="alarm-off"><path d="M12 6c3.87 0 7 3.13 7 7 0 .84-.16 1.65-.43 2.4l1.52 1
.52c.58-1.19.91-2.51.91-3.92 0-4.97-4.03-9-9-9-1.41 0-2.73.33-3.92.91L9.6 6.43C1
0.35 6.16 11.16 6 12 6zm10-.28l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM2.92 2.29L1
.65 3.57 2.98 4.9l-1.11.93 1.42 1.42 1.11-.94.8.8C3.83 8.69 3 10.75 3 13c0 4.97
4.02 9 9 9 2.25 0 4.31-.83 5.89-2.2l2.2 2.2 1.27-1.27L3.89 3.27l-.97-.98zm13.55
16.1C15.26 19.39 13.7 20 12 20c-3.87 0-7-3.13-7-7 0-1.7.61-3.26 1.61-4.47l9.86 9
.86zM8.02 3.28L6.6 1.86l-.86.71 1.42 1.42.86-.71z"></path></g> |
| 15269 <g id="alarm-on"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.
39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97
0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7
7zm-1.46-5.47L8.41 12.4l-1.06 1.06 3.18 3.18 6-6-1.06-1.06-4.93 4.95z"></path><
/g> |
| 15270 <g id="all-out"><path d="M16.21 4.16l4 4v-4zm4 12l-4 4h4zm-12 4l-4-4v4zm-4-12l4-
4h-4zm12.95-.95c-2.73-2.73-7.17-2.73-9.9 0s-2.73 7.17 0 9.9 7.17 2.73 9.9 0 2.73
-7.16 0-9.9zm-1.1 8.8c-2.13 2.13-5.57 2.13-7.7 0s-2.13-5.57 0-7.7 5.57-2.13 7.7
0 2.13 5.57 0 7.7z"></path></g> |
| 15271 <g id="android"><path d="M6 18c0 .55.45 1 1 1h1v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67
1.5-1.5V19h2v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h1c.55 0 1-.45 1-1V8H6v
10zM3.5 8C2.67 8 2 8.67 2 9.5v7c0 .83.67 1.5 1.5 1.5S5 17.33 5 16.5v-7C5 8.67 4.
33 8 3.5 8zm17 0c-.83 0-1.5.67-1.5 1.5v7c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-7
c0-.83-.67-1.5-1.5-1.5zm-4.97-5.84l1.3-1.3c.2-.2.2-.51 0-.71-.2-.2-.51-.2-.71 0l
-1.48 1.48C13.85 1.23 12.95 1 12 1c-.96 0-1.86.23-2.66.63L7.85.15c-.2-.2-.51-.2-
.71 0-.2.2-.2.51 0 .71l1.31 1.31C6.97 3.26 6 5.01 6 7h12c0-1.99-.97-3.75-2.47-4.
84zM10 5H9V4h1v1zm5 0h-1V4h1v1z"></path></g> |
| 15272 <g id="announcement"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.
9 2-2V4c0-1.1-.9-2-2-2zm-7 9h-2V5h2v6zm0 4h-2v-2h2v2z"></path></g> |
| 15273 <g id="apps"><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4z
m6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"></p
ath></g> |
| 15274 <g id="archive"><path d="M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0
-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9
2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81
-1h12l.94 1H5.12z"></path></g> |
| 15275 <g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 1
3H20v-2z"></path></g> |
| 15276 <g id="arrow-downward"><path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59
L4 12l8 8 8-8z"></path></g> |
| 15277 <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g> |
| 15278 <g id="arrow-drop-down-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 1
0-4.48 10-10S17.52 2 12 2zm0 12l-4-4h8l-4 4z"></path></g> |
| 15279 <g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"></path></g> |
| 15280 <g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12
20l8-8z"></path></g> |
| 15281 <g id="arrow-upward"><path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l
-8-8-8 8z"></path></g> |
| 15282 <g id="aspect-ratio"><path d="M19 12h-2v3h-3v2h5v-5zM7 9h3V7H5v5h2V9zm14-6H3c-1.
1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99
h18v14.02z"></path></g> |
| 15283 <g id="assessment"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-
.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"></path></
g> |
| 15284 <g id="assignment"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82
2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.
55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4
H7V7h10v2z"></path></g> |
| 15285 <g id="assignment-ind"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-
2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7
0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 4c1.66 0 3 1.34 3 3s-1.34 3
-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1.4c0-2 4-3.1 6-3.1s6 1.1 6 3.1V19z"></path>
</g> |
| 15286 <g id="assignment-late"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84
-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-
6 15h-2v-2h2v2zm0-4h-2V8h2v6zm-1-9c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1
1z"></path></g> |
| 15287 <g id="assignment-return"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.
84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z
m-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm4 12h-4v3l-5-5 5-5v3h4v4z"
></path></g> |
| 15288 <g id="assignment-returned"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.
4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-
2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 15l-5-5h3V9h4v4h3l-5 5
z"></path></g> |
| 15289 <g id="assignment-turned-in"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2
.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2
-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm-2 14l-4-4 1.41-1.41L10
14.17l6.59-6.59L18 9l-8 8z"></path></g> |
| 15290 <g id="attachment"><path d="M2 12.5C2 9.46 4.46 7 7.5 7H18c2.21 0 4 1.79 4 4s-1.
79 4-4 4H9.5C8.12 15 7 13.88 7 12.5S8.12 10 9.5 10H17v2H9.41c-.55 0-.55 1 0 1H18
c1.1 0 2-.9 2-2s-.9-2-2-2H7.5C5.57 9 4 10.57 4 12.5S5.57 16 7.5 16H17v2H7.5C4.46
18 2 15.54 2 12.5z"></path></g> |
| 15291 <g id="autorenew"><path d="M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1
.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c
.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.4
6-3.03-1.24-4.26z"></path></g> |
| 15292 <g id="backspace"><path d="M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.11c.36.53.
9.89 1.59.89h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.4
1 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z
"></path></g> |
| 15293 <g id="backup"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.3
5 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05
-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"></path></g> |
| 15294 <g id="block"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.5
2 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4
13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0
4.42-3.58 8-8 8z"></path></g> |
| 15295 <g id="book"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2
V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"></path></g> |
| 15296 <g id="bookmark"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2
-2-2z"></path></g> |
| 15297 <g id="bookmark-border"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1
.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"></path></g> |
| 15298 <g id="bug-report"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.
59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62
1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.0
4.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.
09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v
2z"></path></g> |
| 15299 <g id="build"><path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9
6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1
.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z"></path></g> |
| 15300 <g id="cached"><path d="M19 8l-4 4h3c0 3.31-2.69 6-6 6-1.01 0-1.97-.25-2.8-.7l-1
.46 1.46C8.97 19.54 10.43 20 12 20c4.42 0 8-3.58 8-8h3l-4-4zM6 12c0-3.31 2.69-6
6-6 1.01 0 1.97.25 2.8.7l1.46-1.46C15.03 4.46 13.57 4 12 4c-4.42 0-8 3.58-8 8H1l
4 4 4-4H6z"></path></g> |
| 15301 <g id="camera-enhance"><path d="M9 3L7.17 5H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h1
6c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2h-3.17L15 3H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5
-5 5 2.24 5 5-2.24 5-5 5zm0-1l1.25-2.75L16 13l-2.75-1.25L12 9l-1.25 2.75L8 13l2.
75 1.25z"></path></g> |
| 15302 <g id="cancel"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.
53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 1
0.59 15.59 7 17 8.41 13.41 12 17 15.59z"></path></g> |
| 15303 <g id="card-giftcard"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3
-1.05 0-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c
0 .35.07.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2
-2V8c0-1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c
.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7
10.83 8.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"></path></g> |
| 15304 <g id="card-membership"><path d="M20 2H4c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h4v
5l4-2 4 2v-5h4c1.11 0 2-.89 2-2V4c0-1.11-.89-2-2-2zm0 13H4v-2h16v2zm0-5H4V4h16v6
z"></path></g> |
| 15305 <g id="card-travel"><path d="M20 6h-3V4c0-1.11-.89-2-2-2H9c-1.11 0-2 .89-2 2v2H4
c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zM9
4h6v2H9V4zm11 15H4v-2h16v2zm0-5H4V8h3v2h2V8h6v2h2V8h3v6z"></path></g> |
| 15306 <g id="change-history"><path d="M12 7.77L18.39 18H5.61L12 7.77M12 4L2 20h20L12 4
z"></path></g> |
| 15307 <g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path
></g> |
| 15308 <g id="check-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0
2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z">
</path></g> |
| 15309 <g id="check-box-outline-blank"><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v1
4c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path></g> |
| 15310 <g id="check-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-
10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path></g> |
| 15311 <g id="chevron-left"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"></p
ath></g> |
| 15312 <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"><
/path></g> |
| 15313 <g id="chrome-reader-mode"><path d="M13 12h7v1.5h-7zm0-2.5h7V11h-7zm0 5h7V16h-7z
M21 4H3c-1.1 0-2 .9-2 2v13c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 1
5h-9V6h9v13z"></path></g> |
| 15314 <g id="class"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-
2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"></path></g> |
| 15315 <g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59
6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g> |
| 15316 <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59
6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g> |
| 15317 <g id="cloud"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35
8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-
4.78-4.65-4.96z"></path></g> |
| 15318 <g id="cloud-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-
10S17.52 2 12 2zm4.5 14H8c-1.66 0-3-1.34-3-3s1.34-3 3-3l.14.01C8.58 8.28 10.13 7
12 7c2.21 0 4 1.79 4 4h.5c1.38 0 2.5 1.12 2.5 2.5S17.88 16 16.5 16z"></path></g
> |
| 15319 <g id="cloud-done"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64
5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-
2.05-4.78-4.65-4.96zM10 17l-3.5-3.5 1.41-1.41L10 14.17 15.18 9l1.41 1.41L10 17z"
></path></g> |
| 15320 <g id="cloud-download"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6
5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2
.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"></path></g> |
| 15321 <g id="cloud-off"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4c-1.48 0-2.85.43-
4.01 1.17l1.46 1.46C10.21 6.23 11.08 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0
3 1.34 3 3 0 1.13-.64 2.11-1.56 2.62l1.45 1.45C23.16 18.16 24 16.68 24 15c0-2.6
4-2.05-4.78-4.65-4.96zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14c0 3.31 2.69 6 6 6
h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h1
.73z"></path></g> |
| 15322 <g id="cloud-queue"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.6
4 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64
-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h.71C7.37 7.69 9.48 6
12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3s-1.34 3-3 3z"></path></g> |
| 15323 <g id="cloud-upload"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.
64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.6
4-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"></path></g> |
| 15324 <g id="code"><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4
.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"></path></g> |
| 15325 <g id="compare-arrows"><path d="M9.01 14H2v2h7.01v3L13 15l-3.99-4v3zm5.98-1v-3H2
2V8h-7.01V5L11 9l3.99 4z"></path></g> |
| 15326 <g id="content-copy"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-
2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"><
/path></g> |
| 15327 <g id="content-cut"><path d="M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4
S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59
14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7
7h3v-1L9.64 7.64zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm0 12c-1.1 0
-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.
22.5.5-.22.5-.5.5zM19 3l-6 6 2 2 7-7V3z"></path></g> |
| 15328 <g id="content-paste"><path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.8
2 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c
.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"></path>
</g> |
| 15329 <g id="copyright"><path d="M10.08 10.86c.05-.33.16-.62.3-.87s.34-.46.59-.62c.24-
.15.54-.22.91-.23.23.01.44.05.63.13.2.09.38.21.52.36s.25.33.34.53.13.42.14.64h1.
79c-.02-.47-.11-.9-.28-1.29s-.4-.73-.7-1.01-.66-.5-1.08-.66-.88-.23-1.39-.23c-.6
5 0-1.22.11-1.7.34s-.88.53-1.2.92-.56.84-.71 1.36S8 11.29 8 11.87v.27c0 .58.08 1
.12.23 1.64s.39.97.71 1.35.72.69 1.2.91 1.05.34 1.7.34c.47 0 .91-.08 1.32-.23s.7
7-.36 1.08-.63.56-.58.74-.94.29-.74.3-1.15h-1.79c-.01.21-.06.4-.15.58s-.21.33-.3
6.46-.32.23-.52.3c-.19.07-.39.09-.6.1-.36-.01-.66-.08-.89-.23-.25-.16-.45-.37-.5
9-.62s-.25-.55-.3-.88-.08-.67-.08-1v-.27c0-.35.03-.68.08-1.01zM12 2C6.48 2 2 6.4
8 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8
8-8 8 3.59 8 8-3.59 8-8 8z"></path></g> |
| 15330 <g id="create"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.
04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.
75 1.83-1.83z"></path></g> |
| 15331 <g id="create-new-folder"><path d="M20 6h-8l-2-2H4c-1.11 0-1.99.89-1.99 2L2 18c0
1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-1 8h-3v3h-2v-3h-3v-2h3V9
h2v3h3v2z"></path></g> |
| 15332 <g id="credit-card"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2
h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"></path>
</g> |
| 15333 <g id="dashboard"><path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6
h8V3h-8z"></path></g> |
| 15334 <g id="date-range"><path d="M9 11H7v2h2v-2zm4 0h-2v2h2v-2zm4 0h-2v2h2v-2zm2-7h-1
V2h-2v2H8V2H6v2H5c-1.11 0-1.99.9-1.99 2L3 20c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c
0-1.1-.9-2-2-2zm0 16H5V9h14v11z"></path></g> |
| 15335 <g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-
1-1h-5l-1 1H5v2h14V4z"></path></g> |
| 15336 <g id="description"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2
H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"></p
ath></g> |
| 15337 <g id="dns"><path d="M20 13H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1
-1v-6c0-.55-.45-1-1-1zM7 19c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM20 3H4c-
.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zM7 9c-1.1
0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"></path></g> |
| 15338 <g id="done"><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"></path
></g> |
| 15339 <g id="done-all"><path d="M18 7l-1.41-1.41-6.34 6.34 1.41 1.41L18 7zm4.24-1.41L1
1.66 16.17 7.48 12l-1.41 1.41L11.66 19l12-12-1.42-1.41zM.41 13.41L6 19l1.41-1.41
L1.83 12 .41 13.41z"></path></g> |
| 15340 <g id="donut-large"><path d="M11 5.08V2c-5 .5-9 4.81-9 10s4 9.5 9 10v-3.08c-3-.4
8-6-3.4-6-6.92s3-6.44 6-6.92zM18.97 11H22c-.47-5-4-8.53-9-9v3.08C16 5.51 18.54 8
18.97 11zM13 18.92V22c5-.47 8.53-4 9-9h-3.03c-.43 3-2.97 5.49-5.97 5.92z"></pat
h></g> |
| 15341 <g id="donut-small"><path d="M11 9.16V2c-5 .5-9 4.79-9 10s4 9.5 9 10v-7.16c-1-.4
1-2-1.52-2-2.84s1-2.43 2-2.84zM14.86 11H22c-.48-4.75-4-8.53-9-9v7.16c1 .3 1.52.9
8 1.86 1.84zM13 14.84V22c5-.47 8.52-4.25 9-9h-7.14c-.34.86-.86 1.54-1.86 1.84z">
</path></g> |
| 15342 <g id="drafts"><path d="M21.99 8c0-.72-.37-1.35-.94-1.7L12 1 2.95 6.3C2.38 6.65
2 7.28 2 8v10c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2l-.01-10zM12 13L3.74 7.84 12 3l8.26
4.84L12 13z"></path></g> |
| 15343 <g id="eject"><path d="M5 17h14v2H5zm7-12L5.33 15h13.34z"></path></g> |
| 15344 <g id="error"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.5
2 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></g> |
| 15345 <g id="error-outline"><path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2
12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58
-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g> |
| 15346 <g id="event"><path d="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L
3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z"
></path></g> |
| 15347 <g id="event-seat"><path d="M4 18v3h3v-3h10v3h3v-6H4zm15-8h3v3h-3zM2 10h3v3H2zm1
5 3H7V5c0-1.1.9-2 2-2h6c1.1 0 2 .9 2 2v8z"></path></g> |
| 15348 <g id="exit-to-app"><path d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2
h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14
c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path></g> |
| 15349 <g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"></p
ath></g> |
| 15350 <g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"></pat
h></g> |
| 15351 <g id="explore"><path d="M12 10.9c-.61 0-1.1.49-1.1 1.1s.49 1.1 1.1 1.1c.61 0 1.
1-.49 1.1-1.1s-.49-1.1-1.1-1.1zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10
-10S17.52 2 12 2zm2.19 12.19L6 18l3.81-8.19L18 6l-3.81 8.19z"></path></g> |
| 15352 <g id="extension"><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 1
0.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.2
1 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.2
1 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"
></path></g> |
| 15353 <g id="face"><path d="M9 11.75c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.25 1.25-
.56 1.25-1.25-.56-1.25-1.25-1.25zm6 0c-.69 0-1.25.56-1.25 1.25s.56 1.25 1.25 1.2
5 1.25-.56 1.25-1.25-.56-1.25-1.25-1.25zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 1
0-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8 0-.29.02-.58.05-.86 2.36-1.05
4.23-2.98 5.21-5.37C11.07 8.33 14.05 10 17.42 10c.78 0 1.53-.09 2.25-.26.21.71.
33 1.47.33 2.26 0 4.41-3.59 8-8 8z"></path></g> |
| 15354 <g id="favorite"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.
42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22
8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"></path></g> |
| 15355 <g id="favorite-border"><path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.2
4 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6
15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24
4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96
5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"></path></g> |
| 15356 <g id="feedback"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-
2V4c0-1.1-.9-2-2-2zm-7 12h-2v-2h2v2zm0-4h-2V6h2v4z"></path></g> |
| 15357 <g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path
></g> |
| 15358 <g id="file-upload"><path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"></path></g> |
| 15359 <g id="filter-list"><path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"></p
ath></g> |
| 15360 <g id="find-in-page"><path d="M20 19.59V8l-6-6H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1
.89 2 1.99 2H18c.45 0 .85-.15 1.19-.4l-4.43-4.43c-.8.52-1.74.83-2.76.83-2.76 0-5
-2.24-5-5s2.24-5 5-5 5 2.24 5 5c0 1.02-.31 1.96-.83 2.75L20 19.59zM9 13c0 1.66 1
.34 3 3 3s3-1.34 3-3-1.34-3-3-3-3 1.34-3 3z"></path></g> |
| 15361 <g id="find-replace"><path d="M11 6c1.38 0 2.63.56 3.54 1.46L12 10h6V4l-2.05 2.0
5C14.68 4.78 12.93 4 11 4c-3.53 0-6.43 2.61-6.92 6H6.1c.46-2.28 2.48-4 4.9-4zm5.
64 9.14c.66-.9 1.12-1.97 1.28-3.14H15.9c-.46 2.28-2.48 4-4.9 4-1.38 0-2.63-.56-3
.54-1.46L10 12H4v6l2.05-2.05C7.32 17.22 9.07 18 11 18c1.55 0 2.98-.51 4.14-1.36L
20 21.49 21.49 20l-4.85-4.86z"></path></g> |
| 15362 <g id="fingerprint"><path d="M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3
12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.8
2 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.
44.28zM3.5 9.72c-.1 0-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4 2.25-2.5 3.75
-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25.16.22.11.54-.12.7-
.23.16-.54.11-.7-.12-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36
.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21zm6.25 12.07c-.13 0-.26-.05-.35-.15-.87-
.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s
5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39-2.
57 0-4.66 1.97-4.66 4.39 0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2
.19.51 0 .71-.11.1-.24.15-.37.15zm7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.
38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54
.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1
.07.12-1.21.12zM14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-
1.39-2.17-3.24-2.17-5.22 0-1.62 1.38-2.94 3.08-2.94 1.7 0 3.08 1.32 3.08 2.94 0
1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44
1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64
-.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96 0-1.2.23-2.29.68-3.24 1.33-2.7
9 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-
1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87
4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38z"></path><
/g> |
| 15363 <g id="flag"><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"></path></g> |
| 15364 <g id="flight-land"><path d="M2.5 19h19v2h-19zm7.18-5.73l4.35 1.16 5.31 1.42c.8.
21 1.62-.26 1.84-1.06.21-.8-.26-1.62-1.06-1.84l-5.31-1.42-2.76-9.02L10.12 2v8.28
L5.15 8.95l-.93-2.32-1.45-.39v5.17l1.6.43 5.31 1.43z"></path></g> |
| 15365 <g id="flight-takeoff"><path d="M2.5 19h19v2h-19zm19.57-9.36c-.21-.8-1.04-1.28-1
.84-1.06L14.92 10l-6.9-6.43-1.93.51 4.14 7.17-4.97 1.33-1.97-1.54-1.45.39 1.82 3
.16.77 1.33 1.6-.43 5.31-1.42 4.35-1.16L21 11.49c.81-.23 1.28-1.05 1.07-1.85z"><
/path></g> |
| 15366 <g id="flip-to-back"><path d="M9 7H7v2h2V7zm0 4H7v2h2v-2zm0-8c-1.11 0-2 .9-2 2h2
V3zm4 12h-2v2h2v-2zm6-12v2h2c0-1.1-.9-2-2-2zm-6 0h-2v2h2V3zM9 17v-2H7c0 1.1.89 2
2 2zm10-4h2v-2h-2v2zm0-4h2V7h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zM5 7H3v12c0 1.1.89 2
2 2h12v-2H5V7zm10-2h2V3h-2v2zm0 12h2v-2h-2v2z"></path></g> |
| 15367 <g id="flip-to-front"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm2 4v-2H3c0 1.1.89 2
2 2zM3 9h2V7H3v2zm12 12h2v-2h-2v2zm4-18H9c-1.11 0-2 .9-2 2v10c0 1.1.89 2 2 2h10
c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12H9V5h10v10zm-8 6h2v-2h-2v2zm-4 0h2v-2H7v2z
"></path></g> |
| 15368 <g id="folder"><path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0
2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"></path></g> |
| 15369 <g id="folder-open"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2
2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"></path></g> |
| 15370 <g id="folder-shared"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9
2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-5 3c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-
2 .9-2 2-2zm4 8h-8v-1c0-1.33 2.67-2 4-2s4 .67 4 2v1z"></path></g> |
| 15371 <g id="font-download"><path d="M9.93 13.5h4.14L12 7.98zM20 2H4c-1.1 0-2 .9-2 2v1
6c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-4.05 16.5l-1.14-3H9.17l-1.1
2 3H5.96l5.11-13h1.86l5.11 13h-2.09z"></path></g> |
| 15372 <g id="forward"><path d="M12 8V4l8 8-8 8v-4H4V8z"></path></g> |
| 15373 <g id="fullscreen"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-
5h-2v3zM14 5v2h3v3h2V5h-5z"></path></g> |
| 15374 <g id="fullscreen-exit"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h
3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"></path></g> |
| 15375 <g id="gavel"><path d="M1 21h12v2H1zM5.245 8.07l2.83-2.827 14.14 14.142-2.828 2.
828zM12.317 1l5.657 5.656-2.83 2.83-5.654-5.66zM3.825 9.485l5.657 5.657-2.828 2.
828-5.657-5.657z"></path></g> |
| 15376 <g id="gesture"><path d="M4.59 6.89c.7-.71 1.4-1.35 1.71-1.22.5.2 0 1.03-.3 1.52
-.25.42-2.86 3.89-2.86 6.31 0 1.28.48 2.34 1.34 2.98.75.56 1.74.73 2.64.46 1.07-
.31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-
3.78.64-5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1H
21v-2.5h-2.47c-.15-1.65-1.09-4.2-4.03-4.2-2.25 0-4.18 1.91-4.94 2.84-.58.73-2.06
2.48-2.29 2.72-.25.3-.68.84-1.11.84-.45 0-.72-.83-.36-1.92.35-1.09 1.4-2.86 1.8
5-3.52.78-1.14 1.3-1.92 1.3-3.28C8.95 3.69 7.31 3 6.44 3 5.12 3 3.97 4 3.72 4.25
c-.36.36-.66.66-.88.93l1.75 1.71zm9.29 11.66c-.31 0-.74-.26-.74-.72 0-.6.73-2.2
2.87-2.76-.3 2.69-1.43 3.48-2.13 3.48z"></path></g> |
| 15377 <g id="get-app"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path></g> |
| 15378 <g id="gif"><path d="M11.5 9H13v6h-1.5zM9 9H6c-.6 0-1 .5-1 1v4c0 .5.4 1 1 1h3c.6
0 1-.5 1-1v-2H8.5v1.5h-2v-3H10V10c0-.5-.4-1-1-1zm10 1.5V9h-4.5v6H16v-2h2v-1.5h-
2v-1z"></path></g> |
| 15379 <g id="grade"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19
8.63 2 9.24l5.46 4.73L5.82 21z"></path></g> |
| 15380 <g id="group-work"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10
S17.52 2 12 2zM8 17.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5
-1.12 2.5-2.5 2.5zM9.5 8c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5-1.12 2.5-2.5 2
.5S9.5 9.38 9.5 8zm6.5 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.
5 2.5-1.12 2.5-2.5 2.5z"></path></g> |
| 15381 <g id="help"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52
2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.
45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2
.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"></path></g> |
| 15382 <g id="help-outline"><path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10
10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-
3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-
2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"></path></g> |
| 15383 <g id="highlight-off"><path d="M14.59 8L12 10.59 9.41 8 8 9.41 10.59 12 8 14.59
9.41 16 12 13.41 14.59 16 16 14.59 13.41 12 16 9.41 14.59 8zM12 2C6.47 2 2 6.47
2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-
8 8 3.59 8 8-3.59 8-8 8z"></path></g> |
| 15384 <g id="history"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.8
7 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19
.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2
.08V8H12z"></path></g> |
| 15385 <g id="home"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path></g> |
| 15386 <g id="hourglass-empty"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.
99h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6zm10 14.5V20H8v-3.5l4-4 4 4zm-4-5l-4-4V4
h8v3.5l-4 4z"></path></g> |
| 15387 <g id="hourglass-full"><path d="M6 2v6h.01L6 8.01 10 12l-4 4 .01.01H6V22h12v-5.9
9h-.01L18 16l-4-4 4-3.99-.01-.01H18V2H6z"></path></g> |
| 15388 <g id="http"><path d="M4.5 11h-2V9H1v6h1.5v-2.5h2V15H6V9H4.5v2zm2.5-.5h1.5V15H10
v-4.5h1.5V9H7v1.5zm5.5 0H14V15h1.5v-4.5H17V9h-4.5v1.5zm9-1.5H18v6h1.5v-2h2c.8 0
1.5-.7 1.5-1.5v-1c0-.8-.7-1.5-1.5-1.5zm0 2.5h-2v-1h2v1z"></path></g> |
| 15389 <g id="https"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2
2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9
-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.
1 3.1v2z"></path></g> |
| 15390 <g id="important-devices"><path d="M23 11.01L18 11c-.55 0-1 .45-1 1v9c0 .55.45 1
1 1h5c.55 0 1-.45 1-1v-9c0-.55-.45-.99-1-.99zM23 20h-5v-7h5v7zM20 2H2C.89 2 0 2
.89 0 4v12c0 1.1.89 2 2 2h7v2H7v2h8v-2h-2v-2h2v-2H2V4h18v5h2V4c0-1.11-.9-2-2-2zm
-8.03 7L11 6l-.97 3H7l2.47 1.76-.94 2.91 2.47-1.8 2.47 1.8-.94-2.91L15 9h-3.03z"
></path></g> |
| 15391 <g id="inbox"><path d="M19 3H4.99c-1.11 0-1.98.89-1.98 2L3 19c0 1.1.88 2 1.99 2H
19c1.1 0 2-.9 2-2V5c0-1.11-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3H4.99V
5H19v10z"></path></g> |
| 15392 <g id="indeterminate-check-box"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2
2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10H7v-2h10v2z"></path></g> |
| 15393 <g id="info"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52
2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"></path></g> |
| 15394 <g id="info-outline"><path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10
10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-
3.59 8-8 8zM11 9h2V7h-2v2z"></path></g> |
| 15395 <g id="input"><path d="M21 3.01H3c-1.1 0-2 .9-2 2V9h2V4.99h18v14.03H3V15H1v4.01c
0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98v-14c0-1.11-.9-2-2-2zM11 16l4-4-4-4v3H1
v2h10v3z"></path></g> |
| 15396 <g id="invert-colors"><path d="M17.66 7.93L12 2.27 6.34 7.93c-3.12 3.12-3.12 8.1
9 0 11.31C7.9 20.8 9.95 21.58 12 21.58c2.05 0 4.1-.78 5.66-2.34 3.12-3.12 3.12-8
.19 0-11.31zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3
.11 1.76-4.24L12 5.1v14.49z"></path></g> |
| 15397 <g id="label"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9
3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"></p
ath></g> |
| 15398 <g id="label-outline"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.
01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.
16zM16 17H5V7h11l3.55 5L16 17z"></path></g> |
| 15399 <g id="language"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 2
2 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63
3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.
76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-
.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.
37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8
.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96z
M14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16
2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.4
9 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64
.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"></path></g> |
| 15400 <g id="launch"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1
.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"></pa
th></g> |
| 15401 <g id="lightbulb-outline"><path d="M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1
zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45
1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.
3l-.85-.6C7.8 12.16 7 10.63 7 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15
4.1z"></path></g> |
| 15402 <g id="line-style"><path d="M3 16h5v-2H3v2zm6.5 0h5v-2h-5v2zm6.5 0h5v-2h-5v2zM3
20h2v-2H3v2zm4 0h2v-2H7v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zM3 12h8v-
2H3v2zm10 0h8v-2h-8v2zM3 4v4h18V4H3z"></path></g> |
| 15403 <g id="line-weight"><path d="M3 17h18v-2H3v2zm0 3h18v-1H3v1zm0-7h18v-3H3v3zm0-9v
4h18V4H3z"></path></g> |
| 15404 <g id="link"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2
.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0
3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"></pat
h></g> |
| 15405 <g id="list"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm
0 4h14v-2H7v2zM7 7v2h14V7H7z"></path></g> |
| 15406 <g id="lock"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2
2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-
2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1
3.1v2z"></path></g> |
| 15407 <g id="lock-open"><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-
9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39
3.1 3.1v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2
zm0 12H6V10h12v10z"></path></g> |
| 15408 <g id="lock-outline"><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z
m6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1
.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM8.9 6c0-1.71 1.39-3.1 3.1-3.1s3.1 1.39 3.1 3.1v
2H8.9V6zM18 20H6V10h12v10z"></path></g> |
| 15409 <g id="loyalty"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9
-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7
c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67
4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7zm11.77 8.27L13 19.54l-4.27-4.27C8.28 14.81 8 1
4.19 8 13.5c0-1.38 1.12-2.5 2.5-2.5.69 0 1.32.28 1.77.74l.73.72.73-.73c.45-.45 1
.08-.73 1.77-.73 1.38 0 2.5 1.12 2.5 2.5 0 .69-.28 1.32-.73 1.77z"></path></g> |
| 15410 <g id="mail"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2
-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"></path></g> |
| 15411 <g id="markunread"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1
.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"></path></g> |
| 15412 <g id="markunread-mailbox"><path d="M20 6H10v6H8V4h6V0H6v6H4c-1.1 0-2 .9-2 2v12c
0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2z"></path></g> |
| 15413 <g id="menu"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></g> |
| 15414 <g id="more-horiz"><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12
0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.
9 2-2-.9-2-2-2z"></path></g> |
| 15415 <g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2
c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2
-2-.9-2-2-2z"></path></g> |
| 15416 <g id="motorcycle"><path d="M19.44 9.03L15.41 5H11v2h3.59l2 2H5c-2.8 0-5 2.2-5 5
s2.2 5 5 5c2.46 0 4.45-1.69 4.9-4h1.65l2.77-2.77c-.21.54-.32 1.14-.32 1.77 0 2.8
2.2 5 5 5s5-2.2 5-5c0-2.65-1.97-4.77-4.56-4.97zM7.82 15C7.4 16.15 6.28 17 5 17c
-1.63 0-3-1.37-3-3s1.37-3 3-3c1.28 0 2.4.85 2.82 2H5v2h2.82zM19 17c-1.66 0-3-1.3
4-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z"></path></g> |
| 15417 <g id="move-to-inbox"><path d="M19 3H4.99c-1.11 0-1.98.9-1.98 2L3 19c0 1.1.88 2
1.99 2H19c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12h-4c0 1.66-1.35 3-3 3s-3-1.34-3-3
H4.99V5H19v10zm-3-5h-2V7h-4v3H8l4 4 4-4z"></path></g> |
| 15418 <g id="next-week"><path d="M20 7h-4V5c0-.55-.22-1.05-.59-1.41C15.05 3.22 14.55 3
14 3h-4c-1.1 0-2 .9-2 2v2H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V
9c0-1.1-.9-2-2-2zM10 5h4v2h-4V5zm1 13.5l-1-1 3-3-3-3 1-1 4 4-4 4z"></path></g> |
| 15419 <g id="note-add"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18
c1.1 0 2-.9 2-2V8l-6-6zm2 14h-3v3h-2v-3H8v-2h3v-3h2v3h3v2zm-3-7V3.5L18.5 9H13z">
</path></g> |
| 15420 <g id="offline-pin"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17
.5 2 12 2zm5 16H7v-2h10v2zm-6.7-4L7 10.7l1.4-1.4 1.9 1.9 5.3-5.3L17 7.3 10.3 14z
"></path></g> |
| 15421 <g id="opacity"><path d="M17.66 8L12 2.35 6.34 8C4.78 9.56 4 11.64 4 13.64s.78 4
.11 2.34 5.67 3.61 2.35 5.66 2.35 4.1-.79 5.66-2.35S20 15.64 20 13.64 19.22 9.56
17.66 8zM6 14c.01-2 .62-3.27 1.76-4.4L12 5.27l4.24 4.38C17.38 10.77 17.99 12 18
14H6z"></path></g> |
| 15422 <g id="open-in-browser"><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2
H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z">
</path></g> |
| 15423 <g id="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2
h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
></path></g> |
| 15424 <g id="open-with"><path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm
14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"></path></g> |
| 15425 <g id="pageview"><path d="M11.5 9C10.12 9 9 10.12 9 11.5s1.12 2.5 2.5 2.5 2.5-1.
12 2.5-2.5S12.88 9 11.5 9zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9
2-2V6c0-1.1-.9-2-2-2zm-3.21 14.21l-2.91-2.91c-.69.44-1.51.7-2.39.7C9.01 16 7 13
.99 7 11.5S9.01 7 11.5 7 16 9.01 16 11.5c0 .88-.26 1.69-.7 2.39l2.91 2.9-1.42 1.
42z"></path></g> |
| 15426 <g id="pan-tool"><path d="M23 5.5V20c0 2.2-1.8 4-4 4h-7.3c-1.08 0-2.1-.43-2.85-1
.19L1 14.83s1.26-1.23 1.3-1.25c.22-.19.49-.29.79-.29.22 0 .42.06.6.16.04.01 4.31
2.46 4.31 2.46V4c0-.83.67-1.5 1.5-1.5S11 3.17 11 4v7h1V1.5c0-.83.67-1.5 1.5-1.5
S15 .67 15 1.5V11h1V2.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V11h1V5.5c0-.83.67-1.
5 1.5-1.5s1.5.67 1.5 1.5z"></path></g> |
| 15427 <g id="payment"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c
1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"></path></g> |
| 15428 <g id="perm-camera-mic"><path d="M20 5h-3.17L15 3H9L7.17 5H4c-1.1 0-2 .9-2 2v12c
0 1.1.9 2 2 2h7v-2.09c-2.83-.48-5-2.94-5-5.91h2c0 2.21 1.79 4 4 4s4-1.79 4-4h2c0
2.97-2.17 5.43-5 5.91V21h7c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-6 8c0 1.1-.9 2-2 2
s-2-.9-2-2V9c0-1.1.9-2 2-2s2 .9 2 2v4z"></path></g> |
| 15429 <g id="perm-contact-calendar"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-2 .9-2
2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 3c1.66 0 3 1.34 3 3s-
1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1z"></pa
th></g> |
| 15430 <g id="perm-data-setting"><path d="M18.99 11.5c.34 0 .67.03 1 .07L20 0 0 20h11.5
6c-.04-.33-.07-.66-.07-1 0-4.14 3.36-7.5 7.5-7.5zm3.71 7.99c.02-.16.04-.32.04-.4
9 0-.17-.01-.33-.04-.49l1.06-.83c.09-.08.12-.21.06-.32l-1-1.73c-.06-.11-.19-.15-
.31-.11l-1.24.5c-.26-.2-.54-.37-.85-.49l-.19-1.32c-.01-.12-.12-.21-.24-.21h-2c-.
12 0-.23.09-.25.21l-.19 1.32c-.3.13-.59.29-.85.49l-1.24-.5c-.11-.04-.24 0-.31.11
l-1 1.73c-.06.11-.04.24.06.32l1.06.83c-.02.16-.03.32-.03.49 0 .17.01.33.03.49l-1
.06.83c-.09.08-.12.21-.06.32l1 1.73c.06.11.19.15.31.11l1.24-.5c.26.2.54.37.85.49
l.19 1.32c.02.12.12.21.25.21h2c.12 0 .23-.09.25-.21l.19-1.32c.3-.13.59-.29.84-.4
9l1.25.5c.11.04.24 0 .31-.11l1-1.73c.06-.11.03-.24-.06-.32l-1.07-.83zm-3.71 1.01
c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path>
</g> |
| 15431 <g id="perm-device-information"><path d="M13 7h-2v2h2V7zm0 4h-2v6h2v-6zm4-9.99L7
1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17
19H7V5h10v14z"></path></g> |
| 15432 <g id="perm-identity"><path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.
9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2
.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-
8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z"></path></g> |
| 15433 <g id="perm-media"><path d="M2 6H0v5h.01L0 20c0 1.1.9 2 2 2h18v-2H2V6zm20-2h-8l-
2-2H6c-1.1 0-1.99.9-1.99 2L4 16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2
zM7 15l4.5-6 3.5 4.51 2.5-3.01L21 15H7z"></path></g> |
| 15434 <g id="perm-phone-msg"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.0
3-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2-2.21c.28-.27.36-.66.25-1.0
1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 1
7 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM12 3v10l3-3h6V3h-9z"></path></g> |
| 15435 <g id="perm-scan-wifi"><path d="M12 3C6.95 3 3.15 4.85 0 7.23L12 22 24 7.25C20.8
5 4.87 17.05 3 12 3zm1 13h-2v-6h2v6zm-2-8V6h2v2h-2z"></path></g> |
| 15436 <g id="pets"><circle cx="4.5" cy="9.5" r="2.5"></circle><circle cx="9" cy="5.5"
r="2.5"></circle><circle cx="15" cy="5.5" r="2.5"></circle><circle cx="19.5" cy=
"9.5" r="2.5"></circle><path d="M17.34 14.86c-.87-1.02-1.6-1.89-2.48-2.91-.46-.5
4-1.05-1.08-1.75-1.32-.11-.04-.22-.07-.33-.09-.25-.04-.52-.04-.78-.04s-.53 0-.79
.05c-.11.02-.22.05-.33.09-.7.24-1.28.78-1.75 1.32-.87 1.02-1.6 1.89-2.48 2.91-1.
31 1.31-2.92 2.76-2.62 4.79.29 1.02 1.02 2.03 2.33 2.32.73.15 3.06-.44 5.54-.44h
.18c2.48 0 4.81.58 5.54.44 1.31-.29 2.04-1.31 2.33-2.32.31-2.04-1.3-3.49-2.61-4.
8z"></path></g> |
| 15437 <g id="picture-in-picture"><path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1
.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03
z"></path></g> |
| 15438 <g id="picture-in-picture-alt"><path d="M19 11h-8v6h8v-6zm4 8V4.98C23 3.88 22.1
3 21 3H3c-1.1 0-2 .88-2 1.98V19c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zm-2 .02H3V4.97h1
8v14.05z"></path></g> |
| 15439 <g id="play-for-work"><path d="M11 5v5.59H7.5l4.5 4.5 4.5-4.5H13V5h-2zm-5 9c0 3.
31 2.69 6 6 6s6-2.69 6-6h-2c0 2.21-1.79 4-4 4s-4-1.79-4-4H6z"></path></g> |
| 15440 <g id="polymer"><path d="M19 4h-4L7.11 16.63 4.5 12 9 4H5L.5 12 5 20h4l7.89-12.6
3L19.5 12 15 20h4l4.5-8z"></path></g> |
| 15441 <g id="power-settings-new"><path d="M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99
7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17
5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6
.83z"></path></g> |
| 15442 <g id="pregnant-woman"><path d="M9 4c0-1.11.89-2 2-2s2 .89 2 2-.89 2-2 2-2-.89-2
-2zm7 9c-.01-1.34-.83-2.51-2-3 0-1.66-1.34-3-3-3s-3 1.34-3 3v7h2v5h3v-5h3v-4z"><
/path></g> |
| 15443 <g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3
-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6
v4h12V3z"></path></g> |
| 15444 <g id="query-builder"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52
22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8
8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"></path></g> |
| 15445 <g id="question-answer"><path d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.4
5-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"><
/path></g> |
| 15446 <g id="radio-button-checked"><path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24
5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2
zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g> |
| 15447 <g id="radio-button-unchecked"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 1
0-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-
8 8z"></path></g> |
| 15448 <g id="receipt"><path d="M18 17H6v-2h12v2zm0-4H6v-2h12v2zm0-4H6V7h12v2zM3 22l1.5
-1.5L6 22l1.5-1.5L9 22l1.5-1.5L12 22l1.5-1.5L15 22l1.5-1.5L18 22l1.5-1.5L21 22V2
l-1.5 1.5L18 2l-1.5 1.5L15 2l-1.5 1.5L12 2l-1.5 1.5L9 2 7.5 3.5 6 2 4.5 3.5 3 2v
20z"></path></g> |
| 15449 <g id="record-voice-over"><circle cx="9" cy="9" r="4"></circle><path d="M9 15c-2
.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4zm7.76-9.64l-1.68 1.69c.84 1.18.84 2.7
1 0 3.89l1.68 1.69c2.02-2.02 2.02-5.07 0-7.27zM20.07 2l-1.63 1.63c2.77 3.02 2.77
7.56 0 10.74L20.07 16c3.9-3.89 3.91-9.95 0-14z"></path></g> |
| 15450 <g id="redeem"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3-1.05 0
-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 .35.0
7.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-
1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c.55 0 1
.45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8
.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"></path></g> |
| 15451 <g id="redo"><path d="M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.9
6 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6
3.6z"></path></g> |
| 15452 <g id="refresh"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.9
9 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6
-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"></path></g> |
| 15453 <g id="remove"><path d="M19 13H5v-2h14v2z"></path></g> |
| 15454 <g id="remove-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10
-10S17.52 2 12 2zm5 11H7v-2h10v2z"></path></g> |
| 15455 <g id="remove-circle-outline"><path d="M7 11v2h10v-2H7zm5-9C6.48 2 2 6.48 2 12s4
.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.
59 8 8-3.59 8-8 8z"></path></g> |
| 15456 <g id="reorder"><path d="M3 15h18v-2H3v2zm0 4h18v-2H3v2zm0-8h18V9H3v2zm0-6v2h18V
5H3z"></path></g> |
| 15457 <g id="reply"><path d="M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"
></path></g> |
| 15458 <g id="reply-all"><path d="M7 8V5l-7 7 7 7v-3l-4-4 4-4zm6 1V5l-7 7 7 7v-4.1c5 0
8.5 1.6 11 5.1-1-5-4-10-11-11z"></path></g> |
| 15459 <g id="report"><path d="M15.73 3H8.27L3 8.27v7.46L8.27 21h7.46L21 15.73V8.27L15.
73 3zM12 17.3c-.72 0-1.3-.58-1.3-1.3 0-.72.58-1.3 1.3-1.3.72 0 1.3.58 1.3 1.3 0
.72-.58 1.3-1.3 1.3zm1-4.3h-2V7h2v6z"></path></g> |
| 15460 <g id="report-problem"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v
4z"></path></g> |
| 15461 <g id="restore"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.8
7 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19
.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2
.08V8H12z"></path></g> |
| 15462 <g id="room"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.8
7-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1
.12 2.5-2.5 2.5z"></path></g> |
| 15463 <g id="rounded-corner"><path d="M19 19h2v2h-2v-2zm0-2h2v-2h-2v2zM3 13h2v-2H3v2zm
0 4h2v-2H3v2zm0-8h2V7H3v2zm0-4h2V3H3v2zm4 0h2V3H7v2zm8 16h2v-2h-2v2zm-4 0h2v-2h-
2v2zm4 0h2v-2h-2v2zm-8 0h2v-2H7v2zm-4 0h2v-2H3v2zM21 8c0-2.76-2.24-5-5-5h-5v2h5c
1.65 0 3 1.35 3 3v5h2V8z"></path></g> |
| 15464 <g id="rowing"><path d="M8.5 14.5L4 19l1.5 1.5L9 17h2l-2.5-2.5zM15 1c-1.1 0-2 .9
-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 20.01L18 24l-2.99-3.01V19.5l-7.1-7.09c-.31.05
-.61.07-.91.07v-2.16c1.66.03 3.61-.87 4.67-2.04l1.4-1.55c.19-.21.43-.38.69-.5.29
-.14.62-.23.96-.23h.03C15.99 6.01 17 7.02 17 8.26v5.75c0 .84-.35 1.61-.92 2.16l-
3.58-3.58v-2.27c-.63.52-1.43 1.02-2.29 1.39L16.5 18H18l3 3.01z"></path></g> |
| 15465 <g id="save"><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2
-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h1
0v4z"></path></g> |
| 15466 <g id="schedule"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 2
2 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.
58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z"></path></g> |
| 15467 <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.
91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.7
9l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.
5 11.99 14 9.5 14z"></path></g> |
| 15468 <g id="select-all"><path d="M3 5h2V3c-1.1 0-2 .9-2 2zm0 8h2v-2H3v2zm4 8h2v-2H7v2
zM3 9h2V7H3v2zm10-6h-2v2h2V3zm6 0v2h2c0-1.1-.9-2-2-2zM5 21v-2H3c0 1.1.9 2 2 2zm-
2-4h2v-2H3v2zM9 3H7v2h2V3zm2 18h2v-2h-2v2zm8-8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v
2zm0-12h2V7h-2v2zm0 8h2v-2h-2v2zm-4 4h2v-2h-2v2zm0-16h2V3h-2v2zM7 17h10V7H7v10zm
2-8h6v6H9V9z"></path></g> |
| 15469 <g id="send"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"></path></g> |
| 15470 <g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.
11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.
08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2
.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49
.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.1
2.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42
.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.4
9 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3
.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g> |
| 15471 <g id="settings-applications"><path d="M12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-
.9-2-2-2zm7-7H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.8
9-2-2-2zm-1.75 9c0 .23-.02.46-.05.68l1.48 1.16c.13.11.17.3.08.45l-1.4 2.42c-.09.
15-.27.21-.43.15l-1.74-.7c-.36.28-.76.51-1.18.69l-.26 1.85c-.03.17-.18.3-.35.3h-
2.8c-.17 0-.32-.13-.35-.29l-.26-1.85c-.43-.18-.82-.41-1.18-.69l-1.74.7c-.16.06-.
34 0-.43-.15l-1.4-2.42c-.09-.15-.05-.34.08-.45l1.48-1.16c-.03-.23-.05-.46-.05-.6
9 0-.23.02-.46.05-.68l-1.48-1.16c-.13-.11-.17-.3-.08-.45l1.4-2.42c.09-.15.27-.21
.43-.15l1.74.7c.36-.28.76-.51 1.18-.69l.26-1.85c.03-.17.18-.3.35-.3h2.8c.17 0 .3
2.13.35.29l.26 1.85c.43.18.82.41 1.18.69l1.74-.7c.16-.06.34 0 .43.15l1.4 2.42c.0
9.15.05.34-.08.45l-1.48 1.16c.03.23.05.46.05.69z"></path></g> |
| 15472 <g id="settings-backup-restore"><path d="M14 12c0-1.1-.9-2-2-2s-2 .9-2 2 .9 2 2
2 2-.9 2-2zm-2-9c-4.97 0-9 4.03-9 9H0l4 4 4-4H5c0-3.87 3.13-7 7-7s7 3.13 7 7-3.1
3 7-7 7c-1.51 0-2.91-.49-4.06-1.3l-1.42 1.44C8.04 20.3 9.94 21 12 21c4.97 0 9-4.
03 9-9s-4.03-9-9-9z"></path></g> |
| 15473 <g id="settings-bluetooth"><path d="M11 24h2v-2h-2v2zm-4 0h2v-2H7v2zm8 0h2v-2h-2
v2zm2.71-18.29L12 0h-1v7.59L6.41 3 5 4.41 10.59 10 5 15.59 6.41 17 11 12.41V20h1
l5.71-5.71-4.3-4.29 4.3-4.29zM13 3.83l1.88 1.88L13 7.59V3.83zm1.88 10.46L13 16.1
7v-3.76l1.88 1.88z"></path></g> |
| 15474 <g id="settings-brightness"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18
c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02zM8 16h2.5l1.5 1.5 1.5-
1.5H16v-2.5l1.5-1.5-1.5-1.5V8h-2.5L12 6.5 10.5 8H8v2.5L6.5 12 8 13.5V16zm4-7c1.6
6 0 3 1.34 3 3s-1.34 3-3 3V9z"></path></g> |
| 15475 <g id="settings-cell"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zM16
.01L8 0C6.9 0 6 .9 6 2v16c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V2c0-1.1-.9-1.99-2-1.99z
M16 16H8V4h8v12z"></path></g> |
| 15476 <g id="settings-ethernet"><path d="M7.77 6.76L6.23 5.48.82 12l5.41 6.52 1.54-1.2
8L3.42 12l4.35-5.24zM7 13h2v-2H7v2zm10-2h-2v2h2v-2zm-6 2h2v-2h-2v2zm6.77-7.52l-1
.54 1.28L20.58 12l-4.35 5.24 1.54 1.28L23.18 12l-5.41-6.52z"></path></g> |
| 15477 <g id="settings-input-antenna"><path d="M12 5c-3.87 0-7 3.13-7 7h2c0-2.76 2.24-5
5-5s5 2.24 5 5h2c0-3.87-3.13-7-7-7zm1 9.29c.88-.39 1.5-1.26 1.5-2.29 0-1.38-1.1
2-2.5-2.5-2.5S9.5 10.62 9.5 12c0 1.02.62 1.9 1.5 2.29v3.3L7.59 21 9 22.41l3-3 3
3L16.41 21 13 17.59v-3.3zM12 1C5.93 1 1 5.93 1 12h2c0-4.97 4.03-9 9-9s9 4.03 9 9
h2c0-6.07-4.93-11-11-11z"></path></g> |
| 15478 <g id="settings-input-component"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h
6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0
c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1
-1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4
14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"></path></g> |
| 15479 <g id="settings-input-composite"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h
6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0
c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1
-1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4
14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"></path></g> |
| 15480 <g id="settings-input-hdmi"><path d="M18 7V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v3H
5v6l3 6v3h8v-3l3-6V7h-1zM8 4h8v3h-2V5h-1v2h-2V5h-1v2H8V4z"></path></g> |
| 15481 <g id="settings-input-svideo"><path d="M8 11.5c0-.83-.67-1.5-1.5-1.5S5 10.67 5 1
1.5 5.67 13 6.5 13 8 12.33 8 11.5zm7-5c0-.83-.67-1.5-1.5-1.5h-3C9.67 5 9 5.67 9
6.5S9.67 8 10.5 8h3c.83 0 1.5-.67 1.5-1.5zM8.5 15c-.83 0-1.5.67-1.5 1.5S7.67 18
8.5 18s1.5-.67 1.5-1.5S9.33 15 8.5 15zM12 1C5.93 1 1 5.93 1 12s4.93 11 11 11 11-
4.93 11-11S18.07 1 12 1zm0 20c-4.96 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9
9zm5.5-11c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z
m-2 5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"></
path></g> |
| 15482 <g id="settings-overscan"><path d="M12.01 5.5L10 8h4l-1.99-2.5zM18 10v4l2.5-1.99
L18 10zM6 10l-2.5 2.01L6 14v-4zm8 6h-4l2.01 2.5L14 16zm7-13H3c-1.1 0-2 .9-2 2v14
c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"></p
ath></g> |
| 15483 <g id="settings-phone"><path d="M13 9h-2v2h2V9zm4 0h-2v2h2V9zm3 6.5c-1.25 0-2.45
-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2
-2.21c.28-.27.36-.66.25-1.01C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1
.45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 9v2h2V9h-2
z"></path></g> |
| 15484 <g id="settings-power"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm2-22h-2v10h2V2zm3
.56 2.44l-1.45 1.45C16.84 6.94 18 8.83 18 11c0 3.31-2.69 6-6 6s-6-2.69-6-6c0-2.1
7 1.16-4.06 2.88-5.12L7.44 4.44C5.36 5.88 4 8.28 4 11c0 4.42 3.58 8 8 8s8-3.58 8
-8c0-2.72-1.36-5.12-3.44-6.56zM15 24h2v-2h-2v2z"></path></g> |
| 15485 <g id="settings-remote"><path d="M15 9H9c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h6c.5
5 0 1-.45 1-1V10c0-.55-.45-1-1-1zm-3 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2
2zM7.05 6.05l1.41 1.41C9.37 6.56 10.62 6 12 6s2.63.56 3.54 1.46l1.41-1.41C15.68
4.78 13.93 4 12 4s-3.68.78-4.95 2.05zM12 0C8.96 0 6.21 1.23 4.22 3.22l1.41 1.41C
7.26 3.01 9.51 2 12 2s4.74 1.01 6.36 2.64l1.41-1.41C17.79 1.23 15.04 0 12 0z"></
path></g> |
| 15486 <g id="settings-voice"><path d="M7 24h2v-2H7v2zm5-11c1.66 0 2.99-1.34 2.99-3L15
4c0-1.66-1.34-3-3-3S9 2.34 9 4v6c0 1.66 1.34 3 3 3zm-1 11h2v-2h-2v2zm4 0h2v-2h-2
v2zm4-14h-1.7c0 3-2.54 5.1-5.3 5.1S6.7 13 6.7 10H5c0 3.41 2.72 6.23 6 6.72V20h2v
-3.28c3.28-.49 6-3.31 6-6.72z"></path></g> |
| 15487 <g id="shop"><path d="M16 6V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H2v13c0 1.1
1.89 2 2 2h16c1.11 0 2-.89 2-2V6h-6zm-6-2h4v2h-4V4zM9 18V9l7.5 4L9 18z"></path><
/g> |
| 15488 <g id="shop-two"><path d="M3 9H1v11c0 1.11.89 2 2 2h14c1.11 0 2-.89 2-2H3V9zm15-
4V3c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H5v11c0 1.11.89 2 2 2h14c1.11 0 2-.89
2-2V5h-5zm-6-2h4v2h-4V3zm0 12V8l5.5 3-5.5 4z"></path></g> |
| 15489 <g id="shopping-basket"><path d="M17.21 9l-4.38-6.56c-.19-.28-.51-.42-.83-.42-.3
2 0-.64.14-.83.43L6.79 9H2c-.55 0-1 .45-1 1 0 .09.01.18.04.27l2.54 9.27c.23.84 1
1.46 1.92 1.46h13c.92 0 1.69-.62 1.93-1.46l2.54-9.27L23 10c0-.55-.45-1-1-1h-4.7
9zM9 9l3-4.4L15 9H9zm3 8c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"></path></g
> |
| 15490 <g id="shopping-cart"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.
9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.
42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49
c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2
s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"></path></g> |
| 15491 <g id="sort"><path d="M3 18h6v-2H3v2zM3 6v2h18V6H3zm0 7h12v-2H3v2z"></path></g> |
| 15492 <g id="speaker-notes"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-
.9 2-2V4c0-1.1-.9-2-2-2zM8 14H6v-2h2v2zm0-3H6V9h2v2zm0-3H6V6h2v2zm7 6h-5v-2h5v2z
m3-3h-8V9h8v2zm0-3h-8V6h8v2z"></path></g> |
| 15493 <g id="spellcheck"><path d="M12.45 16h2.09L9.43 3H7.57L2.46 16h2.09l1.12-3h5.64l
1.14 3zm-6.02-5L8.5 5.48 10.57 11H6.43zm15.16.59l-8.09 8.09L9.83 16l-1.41 1.41 5
.09 5.09L23 13l-1.41-1.41z"></path></g> |
| 15494 <g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19
8.63 2 9.24l5.46 4.73L5.82 21z"></path></g> |
| 15495 <g id="star-border"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L
5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.8
8 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"></path></g> |
| 15496 <g id="star-half"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.
82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4V6.1l1.71 4.04 4.38.38-3.32 2
.88 1 4.28L12 15.4z"></path></g> |
| 15497 <g id="stars"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 1
7.52 22 12S17.52 2 11.99 2zm4.24 16L12 15.45 7.77 18l1.12-4.81-3.73-3.23 4.92-.4
2L12 5l1.92 4.53 4.92.42-3.73 3.23L16.23 18z"></path></g> |
| 15498 <g id="store"><path d="M20 4H4v2h16V4zm1 10v-2l-1-5H4l-1 5v2h1v6h10v-6h4v6h2v-6h
1zm-9 4H6v-4h6v4z"></path></g> |
| 15499 <g id="subdirectory-arrow-left"><path d="M11 9l1.42 1.42L8.83 14H18V4h2v12H8.83l
3.59 3.58L11 21l-6-6 6-6z"></path></g> |
| 15500 <g id="subdirectory-arrow-right"><path d="M19 15l-6 6-1.42-1.42L15.17 16H4V4h2v1
0h9.17l-3.59-3.58L13 9l6 6z"></path></g> |
| 15501 <g id="subject"><path d="M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h1
6V5H4z"></path></g> |
| 15502 <g id="supervisor-account"><path d="M16.5 12c1.38 0 2.49-1.12 2.49-2.5S17.88 7 1
6.5 7C15.12 7 14 8.12 14 9.5s1.12 2.5 2.5 2.5zM9 11c1.66 0 2.99-1.34 2.99-3S10.6
6 5 9 5C7.34 5 6 6.34 6 8s1.34 3 3 3zm7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c
0-1.83-3.67-2.75-5.5-2.75zM9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.
37-3.47C10.5 13.1 9.66 13 9 13z"></path></g> |
| 15503 <g id="swap-horiz"><path d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v
3H10v2h7.01v3L21 9z"></path></g> |
| 15504 <g id="swap-vert"><path d="M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3zM9 3L5 6.99h3
V14h2V6.99h3L9 3z"></path></g> |
| 15505 <g id="swap-vertical-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-
4.48 10-10S17.52 2 12 2zM6.5 9L10 5.5 13.5 9H11v4H9V9H6.5zm11 6L14 18.5 10.5 15H
13v-4h2v4h2.5z"></path></g> |
| 15506 <g id="system-update-alt"><path d="M12 16.5l4-4h-3v-9h-2v9H8l4 4zm9-13h-6v1.99h6
v14.03H3V5.49h6V3.5H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2v-14c0-1
.1-.9-2-2-2z"></path></g> |
| 15507 <g id="tab"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V
5c0-1.1-.9-2-2-2zm0 16H3V5h10v4h8v10z"></path></g> |
| 15508 <g id="tab-unselected"><path d="M1 9h2V7H1v2zm0 4h2v-2H1v2zm0-8h2V3c-1.1 0-2 .9-
2 2zm8 16h2v-2H9v2zm-8-4h2v-2H1v2zm2 4v-2H1c0 1.1.9 2 2 2zM21 3h-8v6h10V5c0-1.1-
.9-2-2-2zm0 14h2v-2h-2v2zM9 5h2V3H9v2zM5 21h2v-2H5v2zM5 5h2V3H5v2zm16 16c1.1 0 2
-.9 2-2h-2v2zm0-8h2v-2h-2v2zm-8 8h2v-2h-2v2zm4 0h2v-2h-2v2z"></path></g> |
| 15509 <g id="text-format"><path d="M5 17v2h14v-2H5zm4.5-4.2h5l.9 2.2h2.1L12.75 4h-1.5L
6.5 15h2.1l.9-2.2zM12 5.98L13.87 11h-3.74L12 5.98z"></path></g> |
| 15510 <g id="theaters"><path d="M18 3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3h-2zM8
17H6v-2h2v2zm0-4H6v-2h2v2zm0-4H6V7h2v2zm10 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V7h
2v2z"></path></g> |
| 15511 <g id="thumb-down"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.
14.47-.14.73v1.91l.01.01L1 14c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44
1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"
></path></g> |
| 15512 <g id="thumb-up"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03
-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2
2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-1.91l-.01-.01L23
10z"></path></g> |
| 15513 <g id="thumbs-up-down"><path d="M12 6c0-.55-.45-1-1-1H5.82l.66-3.18.02-.23c0-.31
-.13-.59-.33-.8L5.38 0 .44 4.94C.17 5.21 0 5.59 0 6v6.5c0 .83.67 1.5 1.5 1.5h6.7
5c.62 0 1.15-.38 1.38-.91l2.26-5.29c.07-.17.11-.36.11-.55V6zm10.5 4h-6.75c-.62 0
-1.15.38-1.38.91l-2.26 5.29c-.07.17-.11.36-.11.55V18c0 .55.45 1 1 1h5.18l-.66 3.
18-.02.24c0 .31.13.59.33.8l.79.78 4.94-4.94c.27-.27.44-.65.44-1.06v-6.5c0-.83-.6
7-1.5-1.5-1.5z"></path></g> |
| 15514 <g id="timeline"><path d="M23 8c0 1.1-.9 2-2 2-.18 0-.35-.02-.51-.07l-3.56 3.55c
.05.16.07.34.07.52 0 1.1-.9 2-2 2s-2-.9-2-2c0-.18.02-.36.07-.52l-2.55-2.55c-.16.
05-.34.07-.52.07s-.36-.02-.52-.07l-4.55 4.56c.05.16.07.33.07.51 0 1.1-.9 2-2 2s-
2-.9-2-2 .9-2 2-2c.18 0 .35.02.51.07l4.56-4.55C8.02 9.36 8 9.18 8 9c0-1.1.9-2 2-
2s2 .9 2 2c0 .18-.02.36-.07.52l2.55 2.55c.16-.05.34-.07.52-.07s.36.02.52.07l3.55
-3.56C19.02 8.35 19 8.18 19 8c0-1.1.9-2 2-2s2 .9 2 2z"></path></g> |
| 15515 <g id="toc"><path d="M3 9h14V7H3v2zm0 4h14v-2H3v2zm0 4h14v-2H3v2zm16 0h2v-2h-2v2
zm0-10v2h2V7h-2zm0 6h2v-2h-2v2z"></path></g> |
| 15516 <g id="today"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.
1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"></pa
th></g> |
| 15517 <g id="toll"><path d="M15 4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8z
m0 14c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zM3 12c0-2.61 1.67-4.83
4-5.65V4.26C3.55 5.15 1 8.27 1 12s2.55 6.85 6 7.74v-2.09c-2.33-.82-4-3.04-4-5.6
5z"></path></g> |
| 15518 <g id="touch-app"><path d="M9 11.24V7.5C9 6.12 10.12 5 11.5 5S14 6.12 14 7.5v3.7
4c1.21-.81 2-2.18 2-3.74C16 5.01 13.99 3 11.5 3S7 5.01 7 7.5c0 1.56.79 2.93 2 3.
74zm9.84 4.63l-4.54-2.26c-.17-.07-.35-.11-.54-.11H13v-6c0-.83-.67-1.5-1.5-1.5S10
6.67 10 7.5v10.74l-3.43-.72c-.08-.01-.15-.03-.24-.03-.31 0-.59.13-.79.33l-.79.8
4.94 4.94c.27.27.65.44 1.06.44h6.79c.75 0 1.33-.55 1.44-1.28l.75-5.27c.01-.07.0
2-.14.02-.2 0-.62-.38-1.16-.91-1.38z"></path></g> |
| 15519 <g id="track-changes"><path d="M19.07 4.93l-1.41 1.41C19.1 7.79 20 9.79 20 12c0
4.42-3.58 8-8 8s-8-3.58-8-8c0-4.08 3.05-7.44 7-7.93v2.02C8.16 6.57 6 9.03 6 12c0
3.31 2.69 6 6 6s6-2.69 6-6c0-1.66-.67-3.16-1.76-4.24l-1.41 1.41C15.55 9.9 16 10
.9 16 12c0 2.21-1.79 4-4 4s-4-1.79-4-4c0-1.86 1.28-3.41 3-3.86v2.14c-.6.35-1 .98
-1 1.72 0 1.1.9 2 2 2s2-.9 2-2c0-.74-.4-1.38-1-1.72V2h-1C6.48 2 2 6.48 2 12s4.48
10 10 10 10-4.48 10-10c0-2.76-1.12-5.26-2.93-7.07z"></path></g> |
| 15520 <g id="translate"><path d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.
71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9
.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04
zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.
24z"></path></g> |
| 15521 <g id="trending-down"><path d="M16 18l2.29-2.29-4.88-4.88-4 4L2 7.41 3.41 6l6 6
4-4 6.3 6.29L22 12v6z"></path></g> |
| 15522 <g id="trending-flat"><path d="M22 12l-4-4v3H3v2h15v3z"></path></g> |
| 15523 <g id="trending-up"><path d="M16 6l2.29 2.29-4.88 4.88-4-4L2 16.59 3.41 18l6-6 4
4 6.3-6.29L22 12V6z"></path></g> |
| 15524 <g id="turned-in"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-
2-2-2z"></path></g> |
| 15525 <g id="turned-in-not"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1
-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"></path></g> |
| 15526 <g id="unarchive"><path d="M20.55 5.22l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47
0-.88.21-1.15.55L3.46 5.22C3.17 5.57 3 6.01 3 6.5V19c0 1.1.89 2 2 2h14c1.1 0 2-
.9 2-2V6.5c0-.49-.17-.93-.45-1.28zM12 9.5l5.5 5.5H14v2h-4v-2H6.5L12 9.5zM5.12 5l
.82-1h12l.93 1H5.12z"></path></g> |
| 15527 <g id="undo"><path d="M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.
16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.
5 8z"></path></g> |
| 15528 <g id="unfold-less"><path d="M7.41 18.59L8.83 20 12 16.83 15.17 20l1.41-1.41L12
14l-4.59 4.59zm9.18-13.18L15.17 4 12 7.17 8.83 4 7.41 5.41 12 10l4.59-4.59z"></p
ath></g> |
| 15529 <g id="unfold-more"><path d="M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12
5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z"></path></g
> |
| 15530 <g id="update"><path d="M21 10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-.1-2.7
3 2.71-2.73 7.08 0 9.79 2.73 2.71 7.15 2.71 9.88 0C18.32 15.65 19 14.08 19 12.1h
2c0 1.98-.88 4.55-2.64 6.29-3.51 3.48-9.21 3.48-12.72 0-3.5-3.47-3.53-9.11-.02-1
2.58 3.51-3.47 9.14-3.47 12.65 0L21 3v7.12zM12.5 8v4.25l3.5 2.08-.72 1.21L11 13V
8h1.5z"></path></g> |
| 15531 <g id="verified-user"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.
45 9-12V5l-9-4zm-2 16l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"></path></g> |
| 15532 <g id="view-agenda"><path d="M20 13H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0
1-.45 1-1v-6c0-.55-.45-1-1-1zm0-10H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0
1-.45 1-1V4c0-.55-.45-1-1-1z"></path></g> |
| 15533 <g id="view-array"><path d="M4 18h3V5H4v13zM18 5v13h3V5h-3zM8 18h9V5H8v13z"></pa
th></g> |
| 15534 <g id="view-carousel"><path d="M7 19h10V4H7v15zm-5-2h4V6H2v11zM18 6v11h4V6h-4z">
</path></g> |
| 15535 <g id="view-column"><path d="M10 18h5V5h-5v13zm-6 0h5V5H4v13zM16 5v13h5V5h-5z"><
/path></g> |
| 15536 <g id="view-day"><path d="M2 21h19v-3H2v3zM20 8H3c-.55 0-1 .45-1 1v6c0 .55.45 1
1 1h17c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1zM2 3v3h19V3H2z"></path></g> |
| 15537 <g id="view-headline"><path d="M4 15h16v-2H4v2zm0 4h16v-2H4v2zm0-8h16V9H4v2zm0-6
v2h16V5H4z"></path></g> |
| 15538 <g id="view-list"><path d="M4 14h4v-4H4v4zm0 5h4v-4H4v4zM4 9h4V5H4v4zm5 5h12v-4H
9v4zm0 5h12v-4H9v4zM9 5v4h12V5H9z"></path></g> |
| 15539 <g id="view-module"><path d="M4 11h5V5H4v6zm0 7h5v-6H4v6zm6 0h5v-6h-5v6zm6 0h5v-
6h-5v6zm-6-7h5V5h-5v6zm6-6v6h5V5h-5z"></path></g> |
| 15540 <g id="view-quilt"><path d="M10 18h5v-6h-5v6zm-6 0h5V5H4v13zm12 0h5v-6h-5v6zM10
5v6h11V5H10z"></path></g> |
| 15541 <g id="view-stream"><path d="M4 18h17v-6H4v6zM4 5v6h17V5H4z"></path></g> |
| 15542 <g id="view-week"><path d="M6 5H3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.
45 1-1V6c0-.55-.45-1-1-1zm14 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.
45 1-1V6c0-.55-.45-1-1-1zm-7 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.
45 1-1V6c0-.55-.45-1-1-1z"></path></g> |
| 15543 <g id="visibility"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s
9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5
2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"><
/path></g> |
| 15544 <g id="visibility-off"><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l
2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98
.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02
1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.
27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .4
4-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-
2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"></path></g> |
| 15545 <g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></p
ath></g> |
| 15546 <g id="watch-later"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17
.5 2 12 2zm4.2 14.2L11 13V7h1.5v5.2l4.5 2.7-.8 1.3z"></path></g> |
| 15547 <g id="weekend"><path d="M21 10c-1.1 0-2 .9-2 2v3H5v-3c0-1.1-.9-2-2-2s-2 .9-2 2v
5c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2v-5c0-1.1-.9-2-2-2zm-3-5H6c-1.1 0-2 .9-2 2v2.15
c1.16.41 2 1.51 2 2.82V14h12v-2.03c0-1.3.84-2.4 2-2.82V7c0-1.1-.9-2-2-2z"></path
></g> |
| 15548 <g id="work"><path d="M20 6h-4V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H4c-1.11
0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-
6 0h-4V4h4v2z"></path></g> |
| 15549 <g id="youtube-searched-for"><path d="M17.01 14h-.8l-.27-.27c.98-1.14 1.57-2.61
1.57-4.23 0-3.59-2.91-6.5-6.5-6.5s-6.5 3-6.5 6.5H2l3.84 4 4.16-4H6.51C6.51 7 8.5
3 5 11.01 5s4.5 2.01 4.5 4.5c0 2.48-2.02 4.5-4.5 4.5-.65 0-1.26-.14-1.82-.38L7.7
1 15.1c.97.57 2.09.9 3.3.9 1.61 0 3.08-.59 4.22-1.57l.27.27v.79l5.01 4.99L22 19l
-4.99-5z"></path></g> |
| 15550 <g id="zoom-in"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5
.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.
79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9
.5 11.99 14 9.5 14zm2.5-4h-2v2H9v-2H7V9h2V7h1v2h2v1z"></path></g> |
| 15551 <g id="zoom-out"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16
5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v
.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14
9.5 11.99 14 9.5 14zM7 9h5v1H7z"></path></g> |
| 15552 </defs></svg> |
| 15553 </iron-iconset-svg> |
| 15554 <dom-module id="sort-toggle" assetpath="/res/imp/common/"> |
| 15555 <template> |
| 15556 <style> |
| 15557 :host { |
| 15558 display: inline-block; |
| 15559 position: relative; |
| 15560 min-width: 20px; |
| 15561 min-height: 16px; |
| 15562 vertical-align: middle; |
| 15563 } |
| 15564 iron-icon { |
| 15565 position: absolute; |
| 15566 left: 0; |
| 15567 cursor: pointer; |
| 15568 } |
| 15569 .hidden { |
| 15570 visibility: hidden; |
| 15571 } |
| 15572 </style> |
| 15573 |
| 15574 <span on-click="toggle"> |
| 15575 <iron-icon style="top:0" class$="[[_hidden(direction,'asc')]]" icon="icons
:arrow-drop-down"> |
| 15576 </iron-icon> |
| 15577 <iron-icon style="bottom:0" class$="[[_hidden(direction,'desc')]]" icon="i
cons:arrow-drop-up"> |
| 15578 </iron-icon> |
| 15579 </span> |
| 15580 |
| 15581 </template> |
| 15582 <script> |
| 15583 Polymer({ |
| 15584 is: "sort-toggle", |
| 15585 properties: { |
| 15586 current: { |
| 15587 type: Object, |
| 15588 observer: "_resetSort", |
| 15589 }, |
| 15590 name: { |
| 15591 type: String, |
| 15592 observer: "_resetSort", |
| 15593 }, |
| 15594 |
| 15595 direction: { |
| 15596 type: String, |
| 15597 value: "", |
| 15598 notify: true, |
| 15599 }, |
| 15600 }, |
| 15601 |
| 15602 toggle: function() { |
| 15603 if (this.direction === "asc") { |
| 15604 this.set("direction", "desc"); |
| 15605 } else { |
| 15606 this.set("direction", "asc"); |
| 15607 } |
| 15608 this.fire("sort_change", {direction: this.direction, name: this.name}); |
| 15609 }, |
| 15610 |
| 15611 _hidden: function(num, compare) { |
| 15612 if (num === compare) { |
| 15613 return "hidden"; |
| 15614 } |
| 15615 return ""; |
| 15616 }, |
| 15617 |
| 15618 _resetSort: function() { |
| 15619 // Because of how Polymer inserts and moves elements around, we need to |
| 15620 // update the direction value if the name changes so the ascending sort |
| 15621 // by "os" doesn't become the ascending sort by "gpu" if a column gets |
| 15622 // added before "os", for example. Additionally, this makes sure that |
| 15623 // only one sort-toggle is active at a given time. |
| 15624 if (this.current && this.current.name === this.name) { |
| 15625 this.set("direction", this.current.direction); |
| 15626 } else { |
| 15627 this.set("direction", ""); |
| 15628 } |
| 15629 |
| 15630 }, |
| 15631 }); |
| 15632 </script> |
| 15633 </dom-module><script> |
| 15634 |
| 15635 /** |
| 15636 * @param {!Function} selectCallback |
| 15637 * @constructor |
| 15638 */ |
| 15639 Polymer.IronSelection = function(selectCallback) { |
| 15640 this.selection = []; |
| 15641 this.selectCallback = selectCallback; |
| 15642 }; |
| 15643 |
| 15644 Polymer.IronSelection.prototype = { |
| 15645 |
| 15646 /** |
| 15647 * Retrieves the selected item(s). |
| 15648 * |
| 15649 * @method get |
| 15650 * @returns Returns the selected item(s). If the multi property is true, |
| 15651 * `get` will return an array, otherwise it will return |
| 15652 * the selected item or undefined if there is no selection. |
| 15653 */ |
| 15654 get: function() { |
| 15655 return this.multi ? this.selection.slice() : this.selection[0]; |
| 15656 }, |
| 15657 |
| 15658 /** |
| 15659 * Clears all the selection except the ones indicated. |
| 15660 * |
| 15661 * @method clear |
| 15662 * @param {Array} excludes items to be excluded. |
| 15663 */ |
| 15664 clear: function(excludes) { |
| 15665 this.selection.slice().forEach(function(item) { |
| 15666 if (!excludes || excludes.indexOf(item) < 0) { |
| 15667 this.setItemSelected(item, false); |
| 15668 } |
| 15669 }, this); |
| 15670 }, |
| 15671 |
| 15672 /** |
| 15673 * Indicates if a given item is selected. |
| 15674 * |
| 15675 * @method isSelected |
| 15676 * @param {*} item The item whose selection state should be checked. |
| 15677 * @returns Returns true if `item` is selected. |
| 15678 */ |
| 15679 isSelected: function(item) { |
| 15680 return this.selection.indexOf(item) >= 0; |
| 15681 }, |
| 15682 |
| 15683 /** |
| 15684 * Sets the selection state for a given item to either selected or deselecte
d. |
| 15685 * |
| 15686 * @method setItemSelected |
| 15687 * @param {*} item The item to select. |
| 15688 * @param {boolean} isSelected True for selected, false for deselected. |
| 15689 */ |
| 15690 setItemSelected: function(item, isSelected) { |
| 15691 if (item != null) { |
| 15692 if (isSelected !== this.isSelected(item)) { |
| 15693 // proceed to update selection only if requested state differs from cu
rrent |
| 15694 if (isSelected) { |
| 15695 this.selection.push(item); |
| 15696 } else { |
| 15697 var i = this.selection.indexOf(item); |
| 15698 if (i >= 0) { |
| 15699 this.selection.splice(i, 1); |
| 15700 } |
| 15701 } |
| 15702 if (this.selectCallback) { |
| 15703 this.selectCallback(item, isSelected); |
| 15704 } |
| 15705 } |
| 15706 } |
| 15707 }, |
| 15708 |
| 15709 /** |
| 15710 * Sets the selection state for a given item. If the `multi` property |
| 15711 * is true, then the selected state of `item` will be toggled; otherwise |
| 15712 * the `item` will be selected. |
| 15713 * |
| 15714 * @method select |
| 15715 * @param {*} item The item to select. |
| 15716 */ |
| 15717 select: function(item) { |
| 15718 if (this.multi) { |
| 15719 this.toggle(item); |
| 15720 } else if (this.get() !== item) { |
| 15721 this.setItemSelected(this.get(), false); |
| 15722 this.setItemSelected(item, true); |
| 15723 } |
| 15724 }, |
| 15725 |
| 15726 /** |
| 15727 * Toggles the selection state for `item`. |
| 15728 * |
| 15729 * @method toggle |
| 15730 * @param {*} item The item to toggle. |
| 15731 */ |
| 15732 toggle: function(item) { |
| 15733 this.setItemSelected(item, !this.isSelected(item)); |
| 15734 } |
| 15735 |
| 15736 }; |
| 15737 |
| 15738 </script> |
| 15739 <script> |
| 15740 |
| 15741 /** @polymerBehavior */ |
| 15742 Polymer.IronSelectableBehavior = { |
| 15743 |
| 15744 /** |
| 15745 * Fired when iron-selector is activated (selected or deselected). |
| 15746 * It is fired before the selected items are changed. |
| 15747 * Cancel the event to abort selection. |
| 15748 * |
| 15749 * @event iron-activate |
| 15750 */ |
| 15751 |
| 15752 /** |
| 15753 * Fired when an item is selected |
| 15754 * |
| 15755 * @event iron-select |
| 15756 */ |
| 15757 |
| 15758 /** |
| 15759 * Fired when an item is deselected |
| 15760 * |
| 15761 * @event iron-deselect |
| 15762 */ |
| 15763 |
| 15764 /** |
| 15765 * Fired when the list of selectable items changes (e.g., items are |
| 15766 * added or removed). The detail of the event is a mutation record that |
| 15767 * describes what changed. |
| 15768 * |
| 15769 * @event iron-items-changed |
| 15770 */ |
| 15771 |
| 15772 properties: { |
| 15773 |
| 15774 /** |
| 15775 * If you want to use an attribute value or property of an element for |
| 15776 * `selected` instead of the index, set this to the name of the attribute |
| 15777 * or property. Hyphenated values are converted to camel case when used to |
| 15778 * look up the property of a selectable element. Camel cased values are |
| 15779 * *not* converted to hyphenated values for attribute lookup. It's |
| 15780 * recommended that you provide the hyphenated form of the name so that |
| 15781 * selection works in both cases. (Use `attr-or-property-name` instead of |
| 15782 * `attrOrPropertyName`.) |
| 15783 */ |
| 15784 attrForSelected: { |
| 15785 type: String, |
| 15786 value: null |
| 15787 }, |
| 15788 |
| 15789 /** |
| 15790 * Gets or sets the selected element. The default is to use the index of t
he item. |
| 15791 * @type {string|number} |
| 15792 */ |
| 15793 selected: { |
| 15794 type: String, |
| 15795 notify: true |
| 15796 }, |
| 15797 |
| 15798 /** |
| 15799 * Returns the currently selected item. |
| 15800 * |
| 15801 * @type {?Object} |
| 15802 */ |
| 15803 selectedItem: { |
| 15804 type: Object, |
| 15805 readOnly: true, |
| 15806 notify: true |
| 15807 }, |
| 15808 |
| 15809 /** |
| 15810 * The event that fires from items when they are selected. Selectable |
| 15811 * will listen for this event from items and update the selection state. |
| 15812 * Set to empty string to listen to no events. |
| 15813 */ |
| 15814 activateEvent: { |
| 15815 type: String, |
| 15816 value: 'tap', |
| 15817 observer: '_activateEventChanged' |
| 15818 }, |
| 15819 |
| 15820 /** |
| 15821 * This is a CSS selector string. If this is set, only items that match t
he CSS selector |
| 15822 * are selectable. |
| 15823 */ |
| 15824 selectable: String, |
| 15825 |
| 15826 /** |
| 15827 * The class to set on elements when selected. |
| 15828 */ |
| 15829 selectedClass: { |
| 15830 type: String, |
| 15831 value: 'iron-selected' |
| 15832 }, |
| 15833 |
| 15834 /** |
| 15835 * The attribute to set on elements when selected. |
| 15836 */ |
| 15837 selectedAttribute: { |
| 15838 type: String, |
| 15839 value: null |
| 15840 }, |
| 15841 |
| 15842 /** |
| 15843 * Default fallback if the selection based on selected with `attrForSelect
ed` |
| 15844 * is not found. |
| 15845 */ |
| 15846 fallbackSelection: { |
| 15847 type: String, |
| 15848 value: null |
| 15849 }, |
| 15850 |
| 15851 /** |
| 15852 * The list of items from which a selection can be made. |
| 15853 */ |
| 15854 items: { |
| 15855 type: Array, |
| 15856 readOnly: true, |
| 15857 notify: true, |
| 15858 value: function() { |
| 15859 return []; |
| 15860 } |
| 15861 }, |
| 15862 |
| 15863 /** |
| 15864 * The set of excluded elements where the key is the `localName` |
| 15865 * of the element that will be ignored from the item list. |
| 15866 * |
| 15867 * @default {template: 1} |
| 15868 */ |
| 15869 _excludedLocalNames: { |
| 15870 type: Object, |
| 15871 value: function() { |
| 15872 return { |
| 15873 'template': 1 |
| 15874 }; |
| 15875 } |
| 15876 } |
| 15877 }, |
| 15878 |
| 15879 observers: [ |
| 15880 '_updateAttrForSelected(attrForSelected)', |
| 15881 '_updateSelected(selected)', |
| 15882 '_checkFallback(fallbackSelection)' |
| 15883 ], |
| 15884 |
| 15885 created: function() { |
| 15886 this._bindFilterItem = this._filterItem.bind(this); |
| 15887 this._selection = new Polymer.IronSelection(this._applySelection.bind(this
)); |
| 15888 }, |
| 15889 |
| 15890 attached: function() { |
| 15891 this._observer = this._observeItems(this); |
| 15892 this._updateItems(); |
| 15893 if (!this._shouldUpdateSelection) { |
| 15894 this._updateSelected(); |
| 15895 } |
| 15896 this._addListener(this.activateEvent); |
| 15897 }, |
| 15898 |
| 15899 detached: function() { |
| 15900 if (this._observer) { |
| 15901 Polymer.dom(this).unobserveNodes(this._observer); |
| 15902 } |
| 15903 this._removeListener(this.activateEvent); |
| 15904 }, |
| 15905 |
| 15906 /** |
| 15907 * Returns the index of the given item. |
| 15908 * |
| 15909 * @method indexOf |
| 15910 * @param {Object} item |
| 15911 * @returns Returns the index of the item |
| 15912 */ |
| 15913 indexOf: function(item) { |
| 15914 return this.items.indexOf(item); |
| 15915 }, |
| 15916 |
| 15917 /** |
| 15918 * Selects the given value. |
| 15919 * |
| 15920 * @method select |
| 15921 * @param {string|number} value the value to select. |
| 15922 */ |
| 15923 select: function(value) { |
| 15924 this.selected = value; |
| 15925 }, |
| 15926 |
| 15927 /** |
| 15928 * Selects the previous item. |
| 15929 * |
| 15930 * @method selectPrevious |
| 15931 */ |
| 15932 selectPrevious: function() { |
| 15933 var length = this.items.length; |
| 15934 var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % len
gth; |
| 15935 this.selected = this._indexToValue(index); |
| 15936 }, |
| 15937 |
| 15938 /** |
| 15939 * Selects the next item. |
| 15940 * |
| 15941 * @method selectNext |
| 15942 */ |
| 15943 selectNext: function() { |
| 15944 var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.l
ength; |
| 15945 this.selected = this._indexToValue(index); |
| 15946 }, |
| 15947 |
| 15948 /** |
| 15949 * Selects the item at the given index. |
| 15950 * |
| 15951 * @method selectIndex |
| 15952 */ |
| 15953 selectIndex: function(index) { |
| 15954 this.select(this._indexToValue(index)); |
| 15955 }, |
| 15956 |
| 15957 /** |
| 15958 * Force a synchronous update of the `items` property. |
| 15959 * |
| 15960 * NOTE: Consider listening for the `iron-items-changed` event to respond to |
| 15961 * updates to the set of selectable items after updates to the DOM list and |
| 15962 * selection state have been made. |
| 15963 * |
| 15964 * WARNING: If you are using this method, you should probably consider an |
| 15965 * alternate approach. Synchronously querying for items is potentially |
| 15966 * slow for many use cases. The `items` property will update asynchronously |
| 15967 * on its own to reflect selectable items in the DOM. |
| 15968 */ |
| 15969 forceSynchronousItemUpdate: function() { |
| 15970 this._updateItems(); |
| 15971 }, |
| 15972 |
| 15973 get _shouldUpdateSelection() { |
| 15974 return this.selected != null; |
| 15975 }, |
| 15976 |
| 15977 _checkFallback: function() { |
| 15978 if (this._shouldUpdateSelection) { |
| 15979 this._updateSelected(); |
| 15980 } |
| 15981 }, |
| 15982 |
| 15983 _addListener: function(eventName) { |
| 15984 this.listen(this, eventName, '_activateHandler'); |
| 15985 }, |
| 15986 |
| 15987 _removeListener: function(eventName) { |
| 15988 this.unlisten(this, eventName, '_activateHandler'); |
| 15989 }, |
| 15990 |
| 15991 _activateEventChanged: function(eventName, old) { |
| 15992 this._removeListener(old); |
| 15993 this._addListener(eventName); |
| 15994 }, |
| 15995 |
| 15996 _updateItems: function() { |
| 15997 var nodes = Polymer.dom(this).queryDistributedElements(this.selectable ||
'*'); |
| 15998 nodes = Array.prototype.filter.call(nodes, this._bindFilterItem); |
| 15999 this._setItems(nodes); |
| 16000 }, |
| 16001 |
| 16002 _updateAttrForSelected: function() { |
| 16003 if (this._shouldUpdateSelection) { |
| 16004 this.selected = this._indexToValue(this.indexOf(this.selectedItem)); |
| 16005 } |
| 16006 }, |
| 16007 |
| 16008 _updateSelected: function() { |
| 16009 this._selectSelected(this.selected); |
| 16010 }, |
| 16011 |
| 16012 _selectSelected: function(selected) { |
| 16013 this._selection.select(this._valueToItem(this.selected)); |
| 16014 // Check for items, since this array is populated only when attached |
| 16015 // Since Number(0) is falsy, explicitly check for undefined |
| 16016 if (this.fallbackSelection && this.items.length && (this._selection.get()
=== undefined)) { |
| 16017 this.selected = this.fallbackSelection; |
| 16018 } |
| 16019 }, |
| 16020 |
| 16021 _filterItem: function(node) { |
| 16022 return !this._excludedLocalNames[node.localName]; |
| 16023 }, |
| 16024 |
| 16025 _valueToItem: function(value) { |
| 16026 return (value == null) ? null : this.items[this._valueToIndex(value)]; |
| 16027 }, |
| 16028 |
| 16029 _valueToIndex: function(value) { |
| 16030 if (this.attrForSelected) { |
| 16031 for (var i = 0, item; item = this.items[i]; i++) { |
| 16032 if (this._valueForItem(item) == value) { |
| 16033 return i; |
| 16034 } |
| 16035 } |
| 16036 } else { |
| 16037 return Number(value); |
| 16038 } |
| 16039 }, |
| 16040 |
| 16041 _indexToValue: function(index) { |
| 16042 if (this.attrForSelected) { |
| 16043 var item = this.items[index]; |
| 16044 if (item) { |
| 16045 return this._valueForItem(item); |
| 16046 } |
| 16047 } else { |
| 16048 return index; |
| 16049 } |
| 16050 }, |
| 16051 |
| 16052 _valueForItem: function(item) { |
| 16053 var propValue = item[Polymer.CaseMap.dashToCamelCase(this.attrForSelected)
]; |
| 16054 return propValue != undefined ? propValue : item.getAttribute(this.attrFor
Selected); |
| 16055 }, |
| 16056 |
| 16057 _applySelection: function(item, isSelected) { |
| 16058 if (this.selectedClass) { |
| 16059 this.toggleClass(this.selectedClass, isSelected, item); |
| 16060 } |
| 16061 if (this.selectedAttribute) { |
| 16062 this.toggleAttribute(this.selectedAttribute, isSelected, item); |
| 16063 } |
| 16064 this._selectionChange(); |
| 16065 this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item}); |
| 16066 }, |
| 16067 |
| 16068 _selectionChange: function() { |
| 16069 this._setSelectedItem(this._selection.get()); |
| 16070 }, |
| 16071 |
| 16072 // observe items change under the given node. |
| 16073 _observeItems: function(node) { |
| 16074 return Polymer.dom(node).observeNodes(function(mutation) { |
| 16075 this._updateItems(); |
| 16076 |
| 16077 if (this._shouldUpdateSelection) { |
| 16078 this._updateSelected(); |
| 16079 } |
| 16080 |
| 16081 // Let other interested parties know about the change so that |
| 16082 // we don't have to recreate mutation observers everywhere. |
| 16083 this.fire('iron-items-changed', mutation, { |
| 16084 bubbles: false, |
| 16085 cancelable: false |
| 16086 }); |
| 16087 }); |
| 16088 }, |
| 16089 |
| 16090 _activateHandler: function(e) { |
| 16091 var t = e.target; |
| 16092 var items = this.items; |
| 16093 while (t && t != this) { |
| 16094 var i = items.indexOf(t); |
| 16095 if (i >= 0) { |
| 16096 var value = this._indexToValue(i); |
| 16097 this._itemActivate(value, t); |
| 16098 return; |
| 16099 } |
| 16100 t = t.parentNode; |
| 16101 } |
| 16102 }, |
| 16103 |
| 16104 _itemActivate: function(value, item) { |
| 16105 if (!this.fire('iron-activate', |
| 16106 {selected: value, item: item}, {cancelable: true}).defaultPrevented) { |
| 16107 this.select(value); |
| 16108 } |
| 16109 } |
| 16110 |
| 16111 }; |
| 16112 |
| 16113 </script> |
| 16114 <script> |
| 16115 /** @polymerBehavior Polymer.IronMultiSelectableBehavior */ |
| 16116 Polymer.IronMultiSelectableBehaviorImpl = { |
| 16117 properties: { |
| 16118 |
| 16119 /** |
| 16120 * If true, multiple selections are allowed. |
| 16121 */ |
| 16122 multi: { |
| 16123 type: Boolean, |
| 16124 value: false, |
| 16125 observer: 'multiChanged' |
| 16126 }, |
| 16127 |
| 16128 /** |
| 16129 * Gets or sets the selected elements. This is used instead of `selected`
when `multi` |
| 16130 * is true. |
| 16131 */ |
| 16132 selectedValues: { |
| 16133 type: Array, |
| 16134 notify: true |
| 16135 }, |
| 16136 |
| 16137 /** |
| 16138 * Returns an array of currently selected items. |
| 16139 */ |
| 16140 selectedItems: { |
| 16141 type: Array, |
| 16142 readOnly: true, |
| 16143 notify: true |
| 16144 }, |
| 16145 |
| 16146 }, |
| 16147 |
| 16148 observers: [ |
| 16149 '_updateSelected(selectedValues.splices)' |
| 16150 ], |
| 16151 |
| 16152 /** |
| 16153 * Selects the given value. If the `multi` property is true, then the select
ed state of the |
| 16154 * `value` will be toggled; otherwise the `value` will be selected. |
| 16155 * |
| 16156 * @method select |
| 16157 * @param {string|number} value the value to select. |
| 16158 */ |
| 16159 select: function(value) { |
| 16160 if (this.multi) { |
| 16161 if (this.selectedValues) { |
| 16162 this._toggleSelected(value); |
| 16163 } else { |
| 16164 this.selectedValues = [value]; |
| 16165 } |
| 16166 } else { |
| 16167 this.selected = value; |
| 16168 } |
| 16169 }, |
| 16170 |
| 16171 multiChanged: function(multi) { |
| 16172 this._selection.multi = multi; |
| 16173 }, |
| 16174 |
| 16175 get _shouldUpdateSelection() { |
| 16176 return this.selected != null || |
| 16177 (this.selectedValues != null && this.selectedValues.length); |
| 16178 }, |
| 16179 |
| 16180 _updateAttrForSelected: function() { |
| 16181 if (!this.multi) { |
| 16182 Polymer.IronSelectableBehavior._updateAttrForSelected.apply(this); |
| 16183 } else if (this._shouldUpdateSelection) { |
| 16184 this.selectedValues = this.selectedItems.map(function(selectedItem) { |
| 16185 return this._indexToValue(this.indexOf(selectedItem)); |
| 16186 }, this).filter(function(unfilteredValue) { |
| 16187 return unfilteredValue != null; |
| 16188 }, this); |
| 16189 } |
| 16190 }, |
| 16191 |
| 16192 _updateSelected: function() { |
| 16193 if (this.multi) { |
| 16194 this._selectMulti(this.selectedValues); |
| 16195 } else { |
| 16196 this._selectSelected(this.selected); |
| 16197 } |
| 16198 }, |
| 16199 |
| 16200 _selectMulti: function(values) { |
| 16201 if (values) { |
| 16202 var selectedItems = this._valuesToItems(values); |
| 16203 // clear all but the current selected items |
| 16204 this._selection.clear(selectedItems); |
| 16205 // select only those not selected yet |
| 16206 for (var i = 0; i < selectedItems.length; i++) { |
| 16207 this._selection.setItemSelected(selectedItems[i], true); |
| 16208 } |
| 16209 // Check for items, since this array is populated only when attached |
| 16210 if (this.fallbackSelection && this.items.length && !this._selection.get(
).length) { |
| 16211 var fallback = this._valueToItem(this.fallbackSelection); |
| 16212 if (fallback) { |
| 16213 this.selectedValues = [this.fallbackSelection]; |
| 16214 } |
| 16215 } |
| 16216 } else { |
| 16217 this._selection.clear(); |
| 16218 } |
| 16219 }, |
| 16220 |
| 16221 _selectionChange: function() { |
| 16222 var s = this._selection.get(); |
| 16223 if (this.multi) { |
| 16224 this._setSelectedItems(s); |
| 16225 } else { |
| 16226 this._setSelectedItems([s]); |
| 16227 this._setSelectedItem(s); |
| 16228 } |
| 16229 }, |
| 16230 |
| 16231 _toggleSelected: function(value) { |
| 16232 var i = this.selectedValues.indexOf(value); |
| 16233 var unselected = i < 0; |
| 16234 if (unselected) { |
| 16235 this.push('selectedValues',value); |
| 16236 } else { |
| 16237 this.splice('selectedValues',i,1); |
| 16238 } |
| 16239 }, |
| 16240 |
| 16241 _valuesToItems: function(values) { |
| 16242 return (values == null) ? null : values.map(function(value) { |
| 16243 return this._valueToItem(value); |
| 16244 }, this); |
| 16245 } |
| 16246 }; |
| 16247 |
| 16248 /** @polymerBehavior */ |
| 16249 Polymer.IronMultiSelectableBehavior = [ |
| 16250 Polymer.IronSelectableBehavior, |
| 16251 Polymer.IronMultiSelectableBehaviorImpl |
| 16252 ]; |
| 16253 |
| 16254 </script> |
| 16255 <script> |
| 16256 /** |
| 16257 `iron-selector` is an element which can be used to manage a list of elements |
| 16258 that can be selected. Tapping on the item will make the item selected. The `
selected` indicates |
| 16259 which item is being selected. The default is to use the index of the item. |
| 16260 |
| 16261 Example: |
| 16262 |
| 16263 <iron-selector selected="0"> |
| 16264 <div>Item 1</div> |
| 16265 <div>Item 2</div> |
| 16266 <div>Item 3</div> |
| 16267 </iron-selector> |
| 16268 |
| 16269 If you want to use the attribute value of an element for `selected` instead of
the index, |
| 16270 set `attrForSelected` to the name of the attribute. For example, if you want
to select item by |
| 16271 `name`, set `attrForSelected` to `name`. |
| 16272 |
| 16273 Example: |
| 16274 |
| 16275 <iron-selector attr-for-selected="name" selected="foo"> |
| 16276 <div name="foo">Foo</div> |
| 16277 <div name="bar">Bar</div> |
| 16278 <div name="zot">Zot</div> |
| 16279 </iron-selector> |
| 16280 |
| 16281 You can specify a default fallback with `fallbackSelection` in case the `selec
ted` attribute does |
| 16282 not match the `attrForSelected` attribute of any elements. |
| 16283 |
| 16284 Example: |
| 16285 |
| 16286 <iron-selector attr-for-selected="name" selected="non-existing" |
| 16287 fallback-selection="default"> |
| 16288 <div name="foo">Foo</div> |
| 16289 <div name="bar">Bar</div> |
| 16290 <div name="default">Default</div> |
| 16291 </iron-selector> |
| 16292 |
| 16293 Note: When the selector is multi, the selection will set to `fallbackSelection
` iff |
| 16294 the number of matching elements is zero. |
| 16295 |
| 16296 `iron-selector` is not styled. Use the `iron-selected` CSS class to style the
selected element. |
| 16297 |
| 16298 Example: |
| 16299 |
| 16300 <style> |
| 16301 .iron-selected { |
| 16302 background: #eee; |
| 16303 } |
| 16304 </style> |
| 16305 |
| 16306 ... |
| 16307 |
| 16308 <iron-selector selected="0"> |
| 16309 <div>Item 1</div> |
| 16310 <div>Item 2</div> |
| 16311 <div>Item 3</div> |
| 16312 </iron-selector> |
| 16313 |
| 16314 @demo demo/index.html |
| 16315 */ |
| 16316 |
| 16317 Polymer({ |
| 16318 |
| 16319 is: 'iron-selector', |
| 16320 |
| 16321 behaviors: [ |
| 16322 Polymer.IronMultiSelectableBehavior |
| 16323 ] |
| 16324 |
| 16325 }); |
| 16326 |
| 16327 </script> |
| 16328 |
| 16329 |
| 16330 <style is="custom-style"> |
| 16331 |
| 16332 :root { |
| 16333 /* |
| 16334 * You can use these generic variables in your elements for easy theming. |
| 16335 * For example, if all your elements use `--primary-text-color` as its main |
| 16336 * color, then switching from a light to a dark theme is just a matter of |
| 16337 * changing the value of `--primary-text-color` in your application. |
| 16338 */ |
| 16339 --primary-text-color: var(--light-theme-text-color); |
| 16340 --primary-background-color: var(--light-theme-background-color); |
| 16341 --secondary-text-color: var(--light-theme-secondary-color); |
| 16342 --disabled-text-color: var(--light-theme-disabled-color); |
| 16343 --divider-color: var(--light-theme-divider-color); |
| 16344 --error-color: var(--paper-deep-orange-a700); |
| 16345 |
| 16346 /* |
| 16347 * Primary and accent colors. Also see color.html for more colors. |
| 16348 */ |
| 16349 --primary-color: var(--paper-indigo-500); |
| 16350 --light-primary-color: var(--paper-indigo-100); |
| 16351 --dark-primary-color: var(--paper-indigo-700); |
| 16352 |
| 16353 --accent-color: var(--paper-pink-a200); |
| 16354 --light-accent-color: var(--paper-pink-a100); |
| 16355 --dark-accent-color: var(--paper-pink-a400); |
| 16356 |
| 16357 |
| 16358 /* |
| 16359 * Material Design Light background theme |
| 16360 */ |
| 16361 --light-theme-background-color: #ffffff; |
| 16362 --light-theme-base-color: #000000; |
| 16363 --light-theme-text-color: var(--paper-grey-900); |
| 16364 --light-theme-secondary-color: #737373; /* for secondary text and icons */ |
| 16365 --light-theme-disabled-color: #9b9b9b; /* disabled/hint text */ |
| 16366 --light-theme-divider-color: #dbdbdb; |
| 16367 |
| 16368 /* |
| 16369 * Material Design Dark background theme |
| 16370 */ |
| 16371 --dark-theme-background-color: var(--paper-grey-900); |
| 16372 --dark-theme-base-color: #ffffff; |
| 16373 --dark-theme-text-color: #ffffff; |
| 16374 --dark-theme-secondary-color: #bcbcbc; /* for secondary text and icons */ |
| 16375 --dark-theme-disabled-color: #646464; /* disabled/hint text */ |
| 16376 --dark-theme-divider-color: #3c3c3c; |
| 16377 |
| 16378 /* |
| 16379 * Deprecated values because of their confusing names. |
| 16380 */ |
| 16381 --text-primary-color: var(--dark-theme-text-color); |
| 16382 --default-primary-color: var(--primary-color); |
| 16383 |
| 16384 } |
| 16385 |
| 16386 </style> |
| 16387 <script> |
| 16388 /** |
| 16389 * Singleton IronMeta instance. |
| 16390 */ |
| 16391 Polymer.IronValidatableBehaviorMeta = null; |
| 16392 |
| 16393 /** |
| 16394 * `Use Polymer.IronValidatableBehavior` to implement an element that validate
s user input. |
| 16395 * Use the related `Polymer.IronValidatorBehavior` to add custom validation lo
gic to an iron-input. |
| 16396 * |
| 16397 * By default, an `<iron-form>` element validates its fields when the user pre
sses the submit button. |
| 16398 * To validate a form imperatively, call the form's `validate()` method, which
in turn will |
| 16399 * call `validate()` on all its children. By using `Polymer.IronValidatableBeh
avior`, your |
| 16400 * custom element will get a public `validate()`, which |
| 16401 * will return the validity of the element, and a corresponding `invalid` attr
ibute, |
| 16402 * which can be used for styling. |
| 16403 * |
| 16404 * To implement the custom validation logic of your element, you must override |
| 16405 * the protected `_getValidity()` method of this behaviour, rather than `valid
ate()`. |
| 16406 * See [this](https://github.com/PolymerElements/iron-form/blob/master/demo/si
mple-element.html) |
| 16407 * for an example. |
| 16408 * |
| 16409 * ### Accessibility |
| 16410 * |
| 16411 * Changing the `invalid` property, either manually or by calling `validate()`
will update the |
| 16412 * `aria-invalid` attribute. |
| 16413 * |
| 16414 * @demo demo/index.html |
| 16415 * @polymerBehavior |
| 16416 */ |
| 16417 Polymer.IronValidatableBehavior = { |
| 16418 |
| 16419 properties: { |
| 16420 |
| 16421 /** |
| 16422 * Name of the validator to use. |
| 16423 */ |
| 16424 validator: { |
| 16425 type: String |
| 16426 }, |
| 16427 |
| 16428 /** |
| 16429 * True if the last call to `validate` is invalid. |
| 16430 */ |
| 16431 invalid: { |
| 16432 notify: true, |
| 16433 reflectToAttribute: true, |
| 16434 type: Boolean, |
| 16435 value: false |
| 16436 }, |
| 16437 |
| 16438 /** |
| 16439 * This property is deprecated and should not be used. Use the global |
| 16440 * validator meta singleton, `Polymer.IronValidatableBehaviorMeta` instead
. |
| 16441 */ |
| 16442 _validatorMeta: { |
| 16443 type: Object |
| 16444 }, |
| 16445 |
| 16446 /** |
| 16447 * Namespace for this validator. This property is deprecated and should |
| 16448 * not be used. For all intents and purposes, please consider it a |
| 16449 * read-only, config-time property. |
| 16450 */ |
| 16451 validatorType: { |
| 16452 type: String, |
| 16453 value: 'validator' |
| 16454 }, |
| 16455 |
| 16456 _validator: { |
| 16457 type: Object, |
| 16458 computed: '__computeValidator(validator)' |
| 16459 } |
| 16460 }, |
| 16461 |
| 16462 observers: [ |
| 16463 '_invalidChanged(invalid)' |
| 16464 ], |
| 16465 |
| 16466 registered: function() { |
| 16467 Polymer.IronValidatableBehaviorMeta = new Polymer.IronMeta({type: 'validat
or'}); |
| 16468 }, |
| 16469 |
| 16470 _invalidChanged: function() { |
| 16471 if (this.invalid) { |
| 16472 this.setAttribute('aria-invalid', 'true'); |
| 16473 } else { |
| 16474 this.removeAttribute('aria-invalid'); |
| 16475 } |
| 16476 }, |
| 16477 |
| 16478 /** |
| 16479 * @return {boolean} True if the validator `validator` exists. |
| 16480 */ |
| 16481 hasValidator: function() { |
| 16482 return this._validator != null; |
| 16483 }, |
| 16484 |
| 16485 /** |
| 16486 * Returns true if the `value` is valid, and updates `invalid`. If you want |
| 16487 * your element to have custom validation logic, do not override this method
; |
| 16488 * override `_getValidity(value)` instead. |
| 16489 |
| 16490 * @param {Object} value The value to be validated. By default, it is passed |
| 16491 * to the validator's `validate()` function, if a validator is set. |
| 16492 * @return {boolean} True if `value` is valid. |
| 16493 */ |
| 16494 validate: function(value) { |
| 16495 this.invalid = !this._getValidity(value); |
| 16496 return !this.invalid; |
| 16497 }, |
| 16498 |
| 16499 /** |
| 16500 * Returns true if `value` is valid. By default, it is passed |
| 16501 * to the validator's `validate()` function, if a validator is set. You |
| 16502 * should override this method if you want to implement custom validity |
| 16503 * logic for your element. |
| 16504 * |
| 16505 * @param {Object} value The value to be validated. |
| 16506 * @return {boolean} True if `value` is valid. |
| 16507 */ |
| 16508 |
| 16509 _getValidity: function(value) { |
| 16510 if (this.hasValidator()) { |
| 16511 return this._validator.validate(value); |
| 16512 } |
| 16513 return true; |
| 16514 }, |
| 16515 |
| 16516 __computeValidator: function() { |
| 16517 return Polymer.IronValidatableBehaviorMeta && |
| 16518 Polymer.IronValidatableBehaviorMeta.byKey(this.validator); |
| 16519 } |
| 16520 }; |
| 16521 |
| 16522 </script> |
| 16523 <script> |
| 16524 /** |
| 16525 Polymer.IronFormElementBehavior enables a custom element to be included |
| 16526 in an `iron-form`. |
| 16527 |
| 16528 @demo demo/index.html |
| 16529 @polymerBehavior |
| 16530 */ |
| 16531 Polymer.IronFormElementBehavior = { |
| 16532 |
| 16533 properties: { |
| 16534 /** |
| 16535 * Fired when the element is added to an `iron-form`. |
| 16536 * |
| 16537 * @event iron-form-element-register |
| 16538 */ |
| 16539 |
| 16540 /** |
| 16541 * Fired when the element is removed from an `iron-form`. |
| 16542 * |
| 16543 * @event iron-form-element-unregister |
| 16544 */ |
| 16545 |
| 16546 /** |
| 16547 * The name of this element. |
| 16548 */ |
| 16549 name: { |
| 16550 type: String |
| 16551 }, |
| 16552 |
| 16553 /** |
| 16554 * The value for this element. |
| 16555 */ |
| 16556 value: { |
| 16557 notify: true, |
| 16558 type: String |
| 16559 }, |
| 16560 |
| 16561 /** |
| 16562 * Set to true to mark the input as required. If used in a form, a |
| 16563 * custom element that uses this behavior should also use |
| 16564 * Polymer.IronValidatableBehavior and define a custom validation method. |
| 16565 * Otherwise, a `required` element will always be considered valid. |
| 16566 * It's also strongly recommended to provide a visual style for the elemen
t |
| 16567 * when its value is invalid. |
| 16568 */ |
| 16569 required: { |
| 16570 type: Boolean, |
| 16571 value: false |
| 16572 }, |
| 16573 |
| 16574 /** |
| 16575 * The form that the element is registered to. |
| 16576 */ |
| 16577 _parentForm: { |
| 16578 type: Object |
| 16579 } |
| 16580 }, |
| 16581 |
| 16582 attached: function() { |
| 16583 // Note: the iron-form that this element belongs to will set this |
| 16584 // element's _parentForm property when handling this event. |
| 16585 this.fire('iron-form-element-register'); |
| 16586 }, |
| 16587 |
| 16588 detached: function() { |
| 16589 if (this._parentForm) { |
| 16590 this._parentForm.fire('iron-form-element-unregister', {target: this}); |
| 16591 } |
| 16592 } |
| 16593 |
| 16594 }; |
| 16595 |
| 16596 </script> |
| 16597 <script> |
| 16598 |
| 16599 /** |
| 16600 * Use `Polymer.IronCheckedElementBehavior` to implement a custom element |
| 16601 * that has a `checked` property, which can be used for validation if the |
| 16602 * element is also `required`. Element instances implementing this behavior |
| 16603 * will also be registered for use in an `iron-form` element. |
| 16604 * |
| 16605 * @demo demo/index.html |
| 16606 * @polymerBehavior Polymer.IronCheckedElementBehavior |
| 16607 */ |
| 16608 Polymer.IronCheckedElementBehaviorImpl = { |
| 16609 |
| 16610 properties: { |
| 16611 /** |
| 16612 * Fired when the checked state changes. |
| 16613 * |
| 16614 * @event iron-change |
| 16615 */ |
| 16616 |
| 16617 /** |
| 16618 * Gets or sets the state, `true` is checked and `false` is unchecked. |
| 16619 */ |
| 16620 checked: { |
| 16621 type: Boolean, |
| 16622 value: false, |
| 16623 reflectToAttribute: true, |
| 16624 notify: true, |
| 16625 observer: '_checkedChanged' |
| 16626 }, |
| 16627 |
| 16628 /** |
| 16629 * If true, the button toggles the active state with each tap or press |
| 16630 * of the spacebar. |
| 16631 */ |
| 16632 toggles: { |
| 16633 type: Boolean, |
| 16634 value: true, |
| 16635 reflectToAttribute: true |
| 16636 }, |
| 16637 |
| 16638 /* Overriden from Polymer.IronFormElementBehavior */ |
| 16639 value: { |
| 16640 type: String, |
| 16641 value: 'on', |
| 16642 observer: '_valueChanged' |
| 16643 } |
| 16644 }, |
| 16645 |
| 16646 observers: [ |
| 16647 '_requiredChanged(required)' |
| 16648 ], |
| 16649 |
| 16650 created: function() { |
| 16651 // Used by `iron-form` to handle the case that an element with this behavi
or |
| 16652 // doesn't have a role of 'checkbox' or 'radio', but should still only be |
| 16653 // included when the form is serialized if `this.checked === true`. |
| 16654 this._hasIronCheckedElementBehavior = true; |
| 16655 }, |
| 16656 |
| 16657 /** |
| 16658 * Returns false if the element is required and not checked, and true otherw
ise. |
| 16659 * @param {*=} _value Ignored. |
| 16660 * @return {boolean} true if `required` is false or if `checked` is true. |
| 16661 */ |
| 16662 _getValidity: function(_value) { |
| 16663 return this.disabled || !this.required || this.checked; |
| 16664 }, |
| 16665 |
| 16666 /** |
| 16667 * Update the aria-required label when `required` is changed. |
| 16668 */ |
| 16669 _requiredChanged: function() { |
| 16670 if (this.required) { |
| 16671 this.setAttribute('aria-required', 'true'); |
| 16672 } else { |
| 16673 this.removeAttribute('aria-required'); |
| 16674 } |
| 16675 }, |
| 16676 |
| 16677 /** |
| 16678 * Fire `iron-changed` when the checked state changes. |
| 16679 */ |
| 16680 _checkedChanged: function() { |
| 16681 this.active = this.checked; |
| 16682 this.fire('iron-change'); |
| 16683 }, |
| 16684 |
| 16685 /** |
| 16686 * Reset value to 'on' if it is set to `undefined`. |
| 16687 */ |
| 16688 _valueChanged: function() { |
| 16689 if (this.value === undefined || this.value === null) { |
| 16690 this.value = 'on'; |
| 16691 } |
| 16692 } |
| 16693 }; |
| 16694 |
| 16695 /** @polymerBehavior Polymer.IronCheckedElementBehavior */ |
| 16696 Polymer.IronCheckedElementBehavior = [ |
| 16697 Polymer.IronFormElementBehavior, |
| 16698 Polymer.IronValidatableBehavior, |
| 16699 Polymer.IronCheckedElementBehaviorImpl |
| 16700 ]; |
| 16701 |
| 16702 </script> |
| 16703 <script> |
| 16704 (function() { |
| 16705 'use strict'; |
| 16706 |
| 16707 /** |
| 16708 * Chrome uses an older version of DOM Level 3 Keyboard Events |
| 16709 * |
| 16710 * Most keys are labeled as text, but some are Unicode codepoints. |
| 16711 * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-200712
21/keyset.html#KeySet-Set |
| 16712 */ |
| 16713 var KEY_IDENTIFIER = { |
| 16714 'U+0008': 'backspace', |
| 16715 'U+0009': 'tab', |
| 16716 'U+001B': 'esc', |
| 16717 'U+0020': 'space', |
| 16718 'U+007F': 'del' |
| 16719 }; |
| 16720 |
| 16721 /** |
| 16722 * Special table for KeyboardEvent.keyCode. |
| 16723 * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even bett
er |
| 16724 * than that. |
| 16725 * |
| 16726 * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEve
nt.keyCode#Value_of_keyCode |
| 16727 */ |
| 16728 var KEY_CODE = { |
| 16729 8: 'backspace', |
| 16730 9: 'tab', |
| 16731 13: 'enter', |
| 16732 27: 'esc', |
| 16733 33: 'pageup', |
| 16734 34: 'pagedown', |
| 16735 35: 'end', |
| 16736 36: 'home', |
| 16737 32: 'space', |
| 16738 37: 'left', |
| 16739 38: 'up', |
| 16740 39: 'right', |
| 16741 40: 'down', |
| 16742 46: 'del', |
| 16743 106: '*' |
| 16744 }; |
| 16745 |
| 16746 /** |
| 16747 * MODIFIER_KEYS maps the short name for modifier keys used in a key |
| 16748 * combo string to the property name that references those same keys |
| 16749 * in a KeyboardEvent instance. |
| 16750 */ |
| 16751 var MODIFIER_KEYS = { |
| 16752 'shift': 'shiftKey', |
| 16753 'ctrl': 'ctrlKey', |
| 16754 'alt': 'altKey', |
| 16755 'meta': 'metaKey' |
| 16756 }; |
| 16757 |
| 16758 /** |
| 16759 * KeyboardEvent.key is mostly represented by printable character made by |
| 16760 * the keyboard, with unprintable keys labeled nicely. |
| 16761 * |
| 16762 * However, on OS X, Alt+char can make a Unicode character that follows an |
| 16763 * Apple-specific mapping. In this case, we fall back to .keyCode. |
| 16764 */ |
| 16765 var KEY_CHAR = /[a-z0-9*]/; |
| 16766 |
| 16767 /** |
| 16768 * Matches a keyIdentifier string. |
| 16769 */ |
| 16770 var IDENT_CHAR = /U\+/; |
| 16771 |
| 16772 /** |
| 16773 * Matches arrow keys in Gecko 27.0+ |
| 16774 */ |
| 16775 var ARROW_KEY = /^arrow/; |
| 16776 |
| 16777 /** |
| 16778 * Matches space keys everywhere (notably including IE10's exceptional name |
| 16779 * `spacebar`). |
| 16780 */ |
| 16781 var SPACE_KEY = /^space(bar)?/; |
| 16782 |
| 16783 /** |
| 16784 * Matches ESC key. |
| 16785 * |
| 16786 * Value from: http://w3c.github.io/uievents-key/#key-Escape |
| 16787 */ |
| 16788 var ESC_KEY = /^escape$/; |
| 16789 |
| 16790 /** |
| 16791 * Transforms the key. |
| 16792 * @param {string} key The KeyBoardEvent.key |
| 16793 * @param {Boolean} [noSpecialChars] Limits the transformation to |
| 16794 * alpha-numeric characters. |
| 16795 */ |
| 16796 function transformKey(key, noSpecialChars) { |
| 16797 var validKey = ''; |
| 16798 if (key) { |
| 16799 var lKey = key.toLowerCase(); |
| 16800 if (lKey === ' ' || SPACE_KEY.test(lKey)) { |
| 16801 validKey = 'space'; |
| 16802 } else if (ESC_KEY.test(lKey)) { |
| 16803 validKey = 'esc'; |
| 16804 } else if (lKey.length == 1) { |
| 16805 if (!noSpecialChars || KEY_CHAR.test(lKey)) { |
| 16806 validKey = lKey; |
| 16807 } |
| 16808 } else if (ARROW_KEY.test(lKey)) { |
| 16809 validKey = lKey.replace('arrow', ''); |
| 16810 } else if (lKey == 'multiply') { |
| 16811 // numpad '*' can map to Multiply on IE/Windows |
| 16812 validKey = '*'; |
| 16813 } else { |
| 16814 validKey = lKey; |
| 16815 } |
| 16816 } |
| 16817 return validKey; |
| 16818 } |
| 16819 |
| 16820 function transformKeyIdentifier(keyIdent) { |
| 16821 var validKey = ''; |
| 16822 if (keyIdent) { |
| 16823 if (keyIdent in KEY_IDENTIFIER) { |
| 16824 validKey = KEY_IDENTIFIER[keyIdent]; |
| 16825 } else if (IDENT_CHAR.test(keyIdent)) { |
| 16826 keyIdent = parseInt(keyIdent.replace('U+', '0x'), 16); |
| 16827 validKey = String.fromCharCode(keyIdent).toLowerCase(); |
| 16828 } else { |
| 16829 validKey = keyIdent.toLowerCase(); |
| 16830 } |
| 16831 } |
| 16832 return validKey; |
| 16833 } |
| 16834 |
| 16835 function transformKeyCode(keyCode) { |
| 16836 var validKey = ''; |
| 16837 if (Number(keyCode)) { |
| 16838 if (keyCode >= 65 && keyCode <= 90) { |
| 16839 // ascii a-z |
| 16840 // lowercase is 32 offset from uppercase |
| 16841 validKey = String.fromCharCode(32 + keyCode); |
| 16842 } else if (keyCode >= 112 && keyCode <= 123) { |
| 16843 // function keys f1-f12 |
| 16844 validKey = 'f' + (keyCode - 112); |
| 16845 } else if (keyCode >= 48 && keyCode <= 57) { |
| 16846 // top 0-9 keys |
| 16847 validKey = String(keyCode - 48); |
| 16848 } else if (keyCode >= 96 && keyCode <= 105) { |
| 16849 // num pad 0-9 |
| 16850 validKey = String(keyCode - 96); |
| 16851 } else { |
| 16852 validKey = KEY_CODE[keyCode]; |
| 16853 } |
| 16854 } |
| 16855 return validKey; |
| 16856 } |
| 16857 |
| 16858 /** |
| 16859 * Calculates the normalized key for a KeyboardEvent. |
| 16860 * @param {KeyboardEvent} keyEvent |
| 16861 * @param {Boolean} [noSpecialChars] Set to true to limit keyEvent.key |
| 16862 * transformation to alpha-numeric chars. This is useful with key |
| 16863 * combinations like shift + 2, which on FF for MacOS produces |
| 16864 * keyEvent.key = @ |
| 16865 * To get 2 returned, set noSpecialChars = true |
| 16866 * To get @ returned, set noSpecialChars = false |
| 16867 */ |
| 16868 function normalizedKeyForEvent(keyEvent, noSpecialChars) { |
| 16869 // Fall back from .key, to .keyIdentifier, to .keyCode, and then to |
| 16870 // .detail.key to support artificial keyboard events. |
| 16871 return transformKey(keyEvent.key, noSpecialChars) || |
| 16872 transformKeyIdentifier(keyEvent.keyIdentifier) || |
| 16873 transformKeyCode(keyEvent.keyCode) || |
| 16874 transformKey(keyEvent.detail ? keyEvent.detail.key : keyEvent.detail, no
SpecialChars) || ''; |
| 16875 } |
| 16876 |
| 16877 function keyComboMatchesEvent(keyCombo, event) { |
| 16878 // For combos with modifiers we support only alpha-numeric keys |
| 16879 var keyEvent = normalizedKeyForEvent(event, keyCombo.hasModifiers); |
| 16880 return keyEvent === keyCombo.key && |
| 16881 (!keyCombo.hasModifiers || ( |
| 16882 !!event.shiftKey === !!keyCombo.shiftKey && |
| 16883 !!event.ctrlKey === !!keyCombo.ctrlKey && |
| 16884 !!event.altKey === !!keyCombo.altKey && |
| 16885 !!event.metaKey === !!keyCombo.metaKey) |
| 16886 ); |
| 16887 } |
| 16888 |
| 16889 function parseKeyComboString(keyComboString) { |
| 16890 if (keyComboString.length === 1) { |
| 16891 return { |
| 16892 combo: keyComboString, |
| 16893 key: keyComboString, |
| 16894 event: 'keydown' |
| 16895 }; |
| 16896 } |
| 16897 return keyComboString.split('+').reduce(function(parsedKeyCombo, keyComboP
art) { |
| 16898 var eventParts = keyComboPart.split(':'); |
| 16899 var keyName = eventParts[0]; |
| 16900 var event = eventParts[1]; |
| 16901 |
| 16902 if (keyName in MODIFIER_KEYS) { |
| 16903 parsedKeyCombo[MODIFIER_KEYS[keyName]] = true; |
| 16904 parsedKeyCombo.hasModifiers = true; |
| 16905 } else { |
| 16906 parsedKeyCombo.key = keyName; |
| 16907 parsedKeyCombo.event = event || 'keydown'; |
| 16908 } |
| 16909 |
| 16910 return parsedKeyCombo; |
| 16911 }, { |
| 16912 combo: keyComboString.split(':').shift() |
| 16913 }); |
| 16914 } |
| 16915 |
| 16916 function parseEventString(eventString) { |
| 16917 return eventString.trim().split(' ').map(function(keyComboString) { |
| 16918 return parseKeyComboString(keyComboString); |
| 16919 }); |
| 16920 } |
| 16921 |
| 16922 /** |
| 16923 * `Polymer.IronA11yKeysBehavior` provides a normalized interface for proces
sing |
| 16924 * keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3
.org/TR/wai-aria-practices/#kbd_general_binding). |
| 16925 * The element takes care of browser differences with respect to Keyboard ev
ents |
| 16926 * and uses an expressive syntax to filter key presses. |
| 16927 * |
| 16928 * Use the `keyBindings` prototype property to express what combination of k
eys |
| 16929 * will trigger the callback. A key binding has the format |
| 16930 * `"KEY+MODIFIER:EVENT": "callback"` (`"KEY": "callback"` or |
| 16931 * `"KEY:EVENT": "callback"` are valid as well). Some examples: |
| 16932 * |
| 16933 * keyBindings: { |
| 16934 * 'space': '_onKeydown', // same as 'space:keydown' |
| 16935 * 'shift+tab': '_onKeydown', |
| 16936 * 'enter:keypress': '_onKeypress', |
| 16937 * 'esc:keyup': '_onKeyup' |
| 16938 * } |
| 16939 * |
| 16940 * The callback will receive with an event containing the following informat
ion in `event.detail`: |
| 16941 * |
| 16942 * _onKeydown: function(event) { |
| 16943 * console.log(event.detail.combo); // KEY+MODIFIER, e.g. "shift+tab" |
| 16944 * console.log(event.detail.key); // KEY only, e.g. "tab" |
| 16945 * console.log(event.detail.event); // EVENT, e.g. "keydown" |
| 16946 * console.log(event.detail.keyboardEvent); // the original KeyboardE
vent |
| 16947 * } |
| 16948 * |
| 16949 * Use the `keyEventTarget` attribute to set up event handlers on a specific |
| 16950 * node. |
| 16951 * |
| 16952 * See the [demo source code](https://github.com/PolymerElements/iron-a11y-k
eys-behavior/blob/master/demo/x-key-aware.html) |
| 16953 * for an example. |
| 16954 * |
| 16955 * @demo demo/index.html |
| 16956 * @polymerBehavior |
| 16957 */ |
| 16958 Polymer.IronA11yKeysBehavior = { |
| 16959 properties: { |
| 16960 /** |
| 16961 * The EventTarget that will be firing relevant KeyboardEvents. Set it t
o |
| 16962 * `null` to disable the listeners. |
| 16963 * @type {?EventTarget} |
| 16964 */ |
| 16965 keyEventTarget: { |
| 16966 type: Object, |
| 16967 value: function() { |
| 16968 return this; |
| 16969 } |
| 16970 }, |
| 16971 |
| 16972 /** |
| 16973 * If true, this property will cause the implementing element to |
| 16974 * automatically stop propagation on any handled KeyboardEvents. |
| 16975 */ |
| 16976 stopKeyboardEventPropagation: { |
| 16977 type: Boolean, |
| 16978 value: false |
| 16979 }, |
| 16980 |
| 16981 _boundKeyHandlers: { |
| 16982 type: Array, |
| 16983 value: function() { |
| 16984 return []; |
| 16985 } |
| 16986 }, |
| 16987 |
| 16988 // We use this due to a limitation in IE10 where instances will have |
| 16989 // own properties of everything on the "prototype". |
| 16990 _imperativeKeyBindings: { |
| 16991 type: Object, |
| 16992 value: function() { |
| 16993 return {}; |
| 16994 } |
| 16995 } |
| 16996 }, |
| 16997 |
| 16998 observers: [ |
| 16999 '_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)' |
| 17000 ], |
| 17001 |
| 17002 |
| 17003 /** |
| 17004 * To be used to express what combination of keys will trigger the relati
ve |
| 17005 * callback. e.g. `keyBindings: { 'esc': '_onEscPressed'}` |
| 17006 * @type {Object} |
| 17007 */ |
| 17008 keyBindings: {}, |
| 17009 |
| 17010 registered: function() { |
| 17011 this._prepKeyBindings(); |
| 17012 }, |
| 17013 |
| 17014 attached: function() { |
| 17015 this._listenKeyEventListeners(); |
| 17016 }, |
| 17017 |
| 17018 detached: function() { |
| 17019 this._unlistenKeyEventListeners(); |
| 17020 }, |
| 17021 |
| 17022 /** |
| 17023 * Can be used to imperatively add a key binding to the implementing |
| 17024 * element. This is the imperative equivalent of declaring a keybinding |
| 17025 * in the `keyBindings` prototype property. |
| 17026 */ |
| 17027 addOwnKeyBinding: function(eventString, handlerName) { |
| 17028 this._imperativeKeyBindings[eventString] = handlerName; |
| 17029 this._prepKeyBindings(); |
| 17030 this._resetKeyEventListeners(); |
| 17031 }, |
| 17032 |
| 17033 /** |
| 17034 * When called, will remove all imperatively-added key bindings. |
| 17035 */ |
| 17036 removeOwnKeyBindings: function() { |
| 17037 this._imperativeKeyBindings = {}; |
| 17038 this._prepKeyBindings(); |
| 17039 this._resetKeyEventListeners(); |
| 17040 }, |
| 17041 |
| 17042 /** |
| 17043 * Returns true if a keyboard event matches `eventString`. |
| 17044 * |
| 17045 * @param {KeyboardEvent} event |
| 17046 * @param {string} eventString |
| 17047 * @return {boolean} |
| 17048 */ |
| 17049 keyboardEventMatchesKeys: function(event, eventString) { |
| 17050 var keyCombos = parseEventString(eventString); |
| 17051 for (var i = 0; i < keyCombos.length; ++i) { |
| 17052 if (keyComboMatchesEvent(keyCombos[i], event)) { |
| 17053 return true; |
| 17054 } |
| 17055 } |
| 17056 return false; |
| 17057 }, |
| 17058 |
| 17059 _collectKeyBindings: function() { |
| 17060 var keyBindings = this.behaviors.map(function(behavior) { |
| 17061 return behavior.keyBindings; |
| 17062 }); |
| 17063 |
| 17064 if (keyBindings.indexOf(this.keyBindings) === -1) { |
| 17065 keyBindings.push(this.keyBindings); |
| 17066 } |
| 17067 |
| 17068 return keyBindings; |
| 17069 }, |
| 17070 |
| 17071 _prepKeyBindings: function() { |
| 17072 this._keyBindings = {}; |
| 17073 |
| 17074 this._collectKeyBindings().forEach(function(keyBindings) { |
| 17075 for (var eventString in keyBindings) { |
| 17076 this._addKeyBinding(eventString, keyBindings[eventString]); |
| 17077 } |
| 17078 }, this); |
| 17079 |
| 17080 for (var eventString in this._imperativeKeyBindings) { |
| 17081 this._addKeyBinding(eventString, this._imperativeKeyBindings[eventStri
ng]); |
| 17082 } |
| 17083 |
| 17084 // Give precedence to combos with modifiers to be checked first. |
| 17085 for (var eventName in this._keyBindings) { |
| 17086 this._keyBindings[eventName].sort(function (kb1, kb2) { |
| 17087 var b1 = kb1[0].hasModifiers; |
| 17088 var b2 = kb2[0].hasModifiers; |
| 17089 return (b1 === b2) ? 0 : b1 ? -1 : 1; |
| 17090 }) |
| 17091 } |
| 17092 }, |
| 17093 |
| 17094 _addKeyBinding: function(eventString, handlerName) { |
| 17095 parseEventString(eventString).forEach(function(keyCombo) { |
| 17096 this._keyBindings[keyCombo.event] = |
| 17097 this._keyBindings[keyCombo.event] || []; |
| 17098 |
| 17099 this._keyBindings[keyCombo.event].push([ |
| 17100 keyCombo, |
| 17101 handlerName |
| 17102 ]); |
| 17103 }, this); |
| 17104 }, |
| 17105 |
| 17106 _resetKeyEventListeners: function() { |
| 17107 this._unlistenKeyEventListeners(); |
| 17108 |
| 17109 if (this.isAttached) { |
| 17110 this._listenKeyEventListeners(); |
| 17111 } |
| 17112 }, |
| 17113 |
| 17114 _listenKeyEventListeners: function() { |
| 17115 if (!this.keyEventTarget) { |
| 17116 return; |
| 17117 } |
| 17118 Object.keys(this._keyBindings).forEach(function(eventName) { |
| 17119 var keyBindings = this._keyBindings[eventName]; |
| 17120 var boundKeyHandler = this._onKeyBindingEvent.bind(this, keyBindings); |
| 17121 |
| 17122 this._boundKeyHandlers.push([this.keyEventTarget, eventName, boundKeyH
andler]); |
| 17123 |
| 17124 this.keyEventTarget.addEventListener(eventName, boundKeyHandler); |
| 17125 }, this); |
| 17126 }, |
| 17127 |
| 17128 _unlistenKeyEventListeners: function() { |
| 17129 var keyHandlerTuple; |
| 17130 var keyEventTarget; |
| 17131 var eventName; |
| 17132 var boundKeyHandler; |
| 17133 |
| 17134 while (this._boundKeyHandlers.length) { |
| 17135 // My kingdom for block-scope binding and destructuring assignment.. |
| 17136 keyHandlerTuple = this._boundKeyHandlers.pop(); |
| 17137 keyEventTarget = keyHandlerTuple[0]; |
| 17138 eventName = keyHandlerTuple[1]; |
| 17139 boundKeyHandler = keyHandlerTuple[2]; |
| 17140 |
| 17141 keyEventTarget.removeEventListener(eventName, boundKeyHandler); |
| 17142 } |
| 17143 }, |
| 17144 |
| 17145 _onKeyBindingEvent: function(keyBindings, event) { |
| 17146 if (this.stopKeyboardEventPropagation) { |
| 17147 event.stopPropagation(); |
| 17148 } |
| 17149 |
| 17150 // if event has been already prevented, don't do anything |
| 17151 if (event.defaultPrevented) { |
| 17152 return; |
| 17153 } |
| 17154 |
| 17155 for (var i = 0; i < keyBindings.length; i++) { |
| 17156 var keyCombo = keyBindings[i][0]; |
| 17157 var handlerName = keyBindings[i][1]; |
| 17158 if (keyComboMatchesEvent(keyCombo, event)) { |
| 17159 this._triggerKeyHandler(keyCombo, handlerName, event); |
| 17160 // exit the loop if eventDefault was prevented |
| 17161 if (event.defaultPrevented) { |
| 17162 return; |
| 17163 } |
| 17164 } |
| 17165 } |
| 17166 }, |
| 17167 |
| 17168 _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) { |
| 17169 var detail = Object.create(keyCombo); |
| 17170 detail.keyboardEvent = keyboardEvent; |
| 17171 var event = new CustomEvent(keyCombo.event, { |
| 17172 detail: detail, |
| 17173 cancelable: true |
| 17174 }); |
| 17175 this[handlerName].call(this, event); |
| 17176 if (event.defaultPrevented) { |
| 17177 keyboardEvent.preventDefault(); |
| 17178 } |
| 17179 } |
| 17180 }; |
| 17181 })(); |
| 17182 </script> |
| 17183 <script> |
| 17184 |
| 17185 /** |
| 17186 * @demo demo/index.html |
| 17187 * @polymerBehavior |
| 17188 */ |
| 17189 Polymer.IronControlState = { |
| 17190 |
| 17191 properties: { |
| 17192 |
| 17193 /** |
| 17194 * If true, the element currently has focus. |
| 17195 */ |
| 17196 focused: { |
| 17197 type: Boolean, |
| 17198 value: false, |
| 17199 notify: true, |
| 17200 readOnly: true, |
| 17201 reflectToAttribute: true |
| 17202 }, |
| 17203 |
| 17204 /** |
| 17205 * If true, the user cannot interact with this element. |
| 17206 */ |
| 17207 disabled: { |
| 17208 type: Boolean, |
| 17209 value: false, |
| 17210 notify: true, |
| 17211 observer: '_disabledChanged', |
| 17212 reflectToAttribute: true |
| 17213 }, |
| 17214 |
| 17215 _oldTabIndex: { |
| 17216 type: Number |
| 17217 }, |
| 17218 |
| 17219 _boundFocusBlurHandler: { |
| 17220 type: Function, |
| 17221 value: function() { |
| 17222 return this._focusBlurHandler.bind(this); |
| 17223 } |
| 17224 } |
| 17225 |
| 17226 }, |
| 17227 |
| 17228 observers: [ |
| 17229 '_changedControlState(focused, disabled)' |
| 17230 ], |
| 17231 |
| 17232 ready: function() { |
| 17233 this.addEventListener('focus', this._boundFocusBlurHandler, true); |
| 17234 this.addEventListener('blur', this._boundFocusBlurHandler, true); |
| 17235 }, |
| 17236 |
| 17237 _focusBlurHandler: function(event) { |
| 17238 // NOTE(cdata): if we are in ShadowDOM land, `event.target` will |
| 17239 // eventually become `this` due to retargeting; if we are not in |
| 17240 // ShadowDOM land, `event.target` will eventually become `this` due |
| 17241 // to the second conditional which fires a synthetic event (that is also |
| 17242 // handled). In either case, we can disregard `event.path`. |
| 17243 |
| 17244 if (event.target === this) { |
| 17245 this._setFocused(event.type === 'focus'); |
| 17246 } else if (!this.shadowRoot) { |
| 17247 var target = /** @type {Node} */(Polymer.dom(event).localTarget); |
| 17248 if (!this.isLightDescendant(target)) { |
| 17249 this.fire(event.type, {sourceEvent: event}, { |
| 17250 node: this, |
| 17251 bubbles: event.bubbles, |
| 17252 cancelable: event.cancelable |
| 17253 }); |
| 17254 } |
| 17255 } |
| 17256 }, |
| 17257 |
| 17258 _disabledChanged: function(disabled, old) { |
| 17259 this.setAttribute('aria-disabled', disabled ? 'true' : 'false'); |
| 17260 this.style.pointerEvents = disabled ? 'none' : ''; |
| 17261 if (disabled) { |
| 17262 this._oldTabIndex = this.tabIndex; |
| 17263 this._setFocused(false); |
| 17264 this.tabIndex = -1; |
| 17265 this.blur(); |
| 17266 } else if (this._oldTabIndex !== undefined) { |
| 17267 this.tabIndex = this._oldTabIndex; |
| 17268 } |
| 17269 }, |
| 17270 |
| 17271 _changedControlState: function() { |
| 17272 // _controlStateChanged is abstract, follow-on behaviors may implement it |
| 17273 if (this._controlStateChanged) { |
| 17274 this._controlStateChanged(); |
| 17275 } |
| 17276 } |
| 17277 |
| 17278 }; |
| 17279 |
| 17280 </script> |
| 17281 <script> |
| 17282 |
| 17283 /** |
| 17284 * @demo demo/index.html |
| 17285 * @polymerBehavior Polymer.IronButtonState |
| 17286 */ |
| 17287 Polymer.IronButtonStateImpl = { |
| 17288 |
| 17289 properties: { |
| 17290 |
| 17291 /** |
| 17292 * If true, the user is currently holding down the button. |
| 17293 */ |
| 17294 pressed: { |
| 17295 type: Boolean, |
| 17296 readOnly: true, |
| 17297 value: false, |
| 17298 reflectToAttribute: true, |
| 17299 observer: '_pressedChanged' |
| 17300 }, |
| 17301 |
| 17302 /** |
| 17303 * If true, the button toggles the active state with each tap or press |
| 17304 * of the spacebar. |
| 17305 */ |
| 17306 toggles: { |
| 17307 type: Boolean, |
| 17308 value: false, |
| 17309 reflectToAttribute: true |
| 17310 }, |
| 17311 |
| 17312 /** |
| 17313 * If true, the button is a toggle and is currently in the active state. |
| 17314 */ |
| 17315 active: { |
| 17316 type: Boolean, |
| 17317 value: false, |
| 17318 notify: true, |
| 17319 reflectToAttribute: true |
| 17320 }, |
| 17321 |
| 17322 /** |
| 17323 * True if the element is currently being pressed by a "pointer," which |
| 17324 * is loosely defined as mouse or touch input (but specifically excluding |
| 17325 * keyboard input). |
| 17326 */ |
| 17327 pointerDown: { |
| 17328 type: Boolean, |
| 17329 readOnly: true, |
| 17330 value: false |
| 17331 }, |
| 17332 |
| 17333 /** |
| 17334 * True if the input device that caused the element to receive focus |
| 17335 * was a keyboard. |
| 17336 */ |
| 17337 receivedFocusFromKeyboard: { |
| 17338 type: Boolean, |
| 17339 readOnly: true |
| 17340 }, |
| 17341 |
| 17342 /** |
| 17343 * The aria attribute to be set if the button is a toggle and in the |
| 17344 * active state. |
| 17345 */ |
| 17346 ariaActiveAttribute: { |
| 17347 type: String, |
| 17348 value: 'aria-pressed', |
| 17349 observer: '_ariaActiveAttributeChanged' |
| 17350 } |
| 17351 }, |
| 17352 |
| 17353 listeners: { |
| 17354 down: '_downHandler', |
| 17355 up: '_upHandler', |
| 17356 tap: '_tapHandler' |
| 17357 }, |
| 17358 |
| 17359 observers: [ |
| 17360 '_detectKeyboardFocus(focused)', |
| 17361 '_activeChanged(active, ariaActiveAttribute)' |
| 17362 ], |
| 17363 |
| 17364 keyBindings: { |
| 17365 'enter:keydown': '_asyncClick', |
| 17366 'space:keydown': '_spaceKeyDownHandler', |
| 17367 'space:keyup': '_spaceKeyUpHandler', |
| 17368 }, |
| 17369 |
| 17370 _mouseEventRe: /^mouse/, |
| 17371 |
| 17372 _tapHandler: function() { |
| 17373 if (this.toggles) { |
| 17374 // a tap is needed to toggle the active state |
| 17375 this._userActivate(!this.active); |
| 17376 } else { |
| 17377 this.active = false; |
| 17378 } |
| 17379 }, |
| 17380 |
| 17381 _detectKeyboardFocus: function(focused) { |
| 17382 this._setReceivedFocusFromKeyboard(!this.pointerDown && focused); |
| 17383 }, |
| 17384 |
| 17385 // to emulate native checkbox, (de-)activations from a user interaction fire |
| 17386 // 'change' events |
| 17387 _userActivate: function(active) { |
| 17388 if (this.active !== active) { |
| 17389 this.active = active; |
| 17390 this.fire('change'); |
| 17391 } |
| 17392 }, |
| 17393 |
| 17394 _downHandler: function(event) { |
| 17395 this._setPointerDown(true); |
| 17396 this._setPressed(true); |
| 17397 this._setReceivedFocusFromKeyboard(false); |
| 17398 }, |
| 17399 |
| 17400 _upHandler: function() { |
| 17401 this._setPointerDown(false); |
| 17402 this._setPressed(false); |
| 17403 }, |
| 17404 |
| 17405 /** |
| 17406 * @param {!KeyboardEvent} event . |
| 17407 */ |
| 17408 _spaceKeyDownHandler: function(event) { |
| 17409 var keyboardEvent = event.detail.keyboardEvent; |
| 17410 var target = Polymer.dom(keyboardEvent).localTarget; |
| 17411 |
| 17412 // Ignore the event if this is coming from a focused light child, since th
at |
| 17413 // element will deal with it. |
| 17414 if (this.isLightDescendant(/** @type {Node} */(target))) |
| 17415 return; |
| 17416 |
| 17417 keyboardEvent.preventDefault(); |
| 17418 keyboardEvent.stopImmediatePropagation(); |
| 17419 this._setPressed(true); |
| 17420 }, |
| 17421 |
| 17422 /** |
| 17423 * @param {!KeyboardEvent} event . |
| 17424 */ |
| 17425 _spaceKeyUpHandler: function(event) { |
| 17426 var keyboardEvent = event.detail.keyboardEvent; |
| 17427 var target = Polymer.dom(keyboardEvent).localTarget; |
| 17428 |
| 17429 // Ignore the event if this is coming from a focused light child, since th
at |
| 17430 // element will deal with it. |
| 17431 if (this.isLightDescendant(/** @type {Node} */(target))) |
| 17432 return; |
| 17433 |
| 17434 if (this.pressed) { |
| 17435 this._asyncClick(); |
| 17436 } |
| 17437 this._setPressed(false); |
| 17438 }, |
| 17439 |
| 17440 // trigger click asynchronously, the asynchrony is useful to allow one |
| 17441 // event handler to unwind before triggering another event |
| 17442 _asyncClick: function() { |
| 17443 this.async(function() { |
| 17444 this.click(); |
| 17445 }, 1); |
| 17446 }, |
| 17447 |
| 17448 // any of these changes are considered a change to button state |
| 17449 |
| 17450 _pressedChanged: function(pressed) { |
| 17451 this._changedButtonState(); |
| 17452 }, |
| 17453 |
| 17454 _ariaActiveAttributeChanged: function(value, oldValue) { |
| 17455 if (oldValue && oldValue != value && this.hasAttribute(oldValue)) { |
| 17456 this.removeAttribute(oldValue); |
| 17457 } |
| 17458 }, |
| 17459 |
| 17460 _activeChanged: function(active, ariaActiveAttribute) { |
| 17461 if (this.toggles) { |
| 17462 this.setAttribute(this.ariaActiveAttribute, |
| 17463 active ? 'true' : 'false'); |
| 17464 } else { |
| 17465 this.removeAttribute(this.ariaActiveAttribute); |
| 17466 } |
| 17467 this._changedButtonState(); |
| 17468 }, |
| 17469 |
| 17470 _controlStateChanged: function() { |
| 17471 if (this.disabled) { |
| 17472 this._setPressed(false); |
| 17473 } else { |
| 17474 this._changedButtonState(); |
| 17475 } |
| 17476 }, |
| 17477 |
| 17478 // provide hook for follow-on behaviors to react to button-state |
| 17479 |
| 17480 _changedButtonState: function() { |
| 17481 if (this._buttonStateChanged) { |
| 17482 this._buttonStateChanged(); // abstract |
| 17483 } |
| 17484 } |
| 17485 |
| 17486 }; |
| 17487 |
| 17488 /** @polymerBehavior */ |
| 17489 Polymer.IronButtonState = [ |
| 17490 Polymer.IronA11yKeysBehavior, |
| 17491 Polymer.IronButtonStateImpl |
| 17492 ]; |
| 17493 |
| 17494 </script> |
| 17495 |
| 17496 |
| 17497 <dom-module id="paper-ripple" assetpath="/res/imp/bower_components/paper-ripple/
"> |
| 17498 |
| 17499 <template> |
| 17500 <style> |
| 17501 :host { |
| 17502 display: block; |
| 17503 position: absolute; |
| 17504 border-radius: inherit; |
| 17505 overflow: hidden; |
| 17506 top: 0; |
| 17507 left: 0; |
| 17508 right: 0; |
| 17509 bottom: 0; |
| 17510 |
| 17511 /* See PolymerElements/paper-behaviors/issues/34. On non-Chrome browsers
, |
| 17512 * creating a node (with a position:absolute) in the middle of an event |
| 17513 * handler "interrupts" that event handler (which happens when the |
| 17514 * ripple is created on demand) */ |
| 17515 pointer-events: none; |
| 17516 } |
| 17517 |
| 17518 :host([animating]) { |
| 17519 /* This resolves a rendering issue in Chrome (as of 40) where the |
| 17520 ripple is not properly clipped by its parent (which may have |
| 17521 rounded corners). See: http://jsbin.com/temexa/4 |
| 17522 |
| 17523 Note: We only apply this style conditionally. Otherwise, the browser |
| 17524 will create a new compositing layer for every ripple element on the |
| 17525 page, and that would be bad. */ |
| 17526 -webkit-transform: translate(0, 0); |
| 17527 transform: translate3d(0, 0, 0); |
| 17528 } |
| 17529 |
| 17530 #background, |
| 17531 #waves, |
| 17532 .wave-container, |
| 17533 .wave { |
| 17534 pointer-events: none; |
| 17535 position: absolute; |
| 17536 top: 0; |
| 17537 left: 0; |
| 17538 width: 100%; |
| 17539 height: 100%; |
| 17540 } |
| 17541 |
| 17542 #background, |
| 17543 .wave { |
| 17544 opacity: 0; |
| 17545 } |
| 17546 |
| 17547 #waves, |
| 17548 .wave { |
| 17549 overflow: hidden; |
| 17550 } |
| 17551 |
| 17552 .wave-container, |
| 17553 .wave { |
| 17554 border-radius: 50%; |
| 17555 } |
| 17556 |
| 17557 :host(.circle) #background, |
| 17558 :host(.circle) #waves { |
| 17559 border-radius: 50%; |
| 17560 } |
| 17561 |
| 17562 :host(.circle) .wave-container { |
| 17563 overflow: hidden; |
| 17564 } |
| 17565 </style> |
| 17566 |
| 17567 <div id="background"></div> |
| 17568 <div id="waves"></div> |
| 17569 </template> |
| 17570 </dom-module> |
| 17571 <script> |
| 17572 (function() { |
| 17573 var Utility = { |
| 17574 distance: function(x1, y1, x2, y2) { |
| 17575 var xDelta = (x1 - x2); |
| 17576 var yDelta = (y1 - y2); |
| 17577 |
| 17578 return Math.sqrt(xDelta * xDelta + yDelta * yDelta); |
| 17579 }, |
| 17580 |
| 17581 now: window.performance && window.performance.now ? |
| 17582 window.performance.now.bind(window.performance) : Date.now |
| 17583 }; |
| 17584 |
| 17585 /** |
| 17586 * @param {HTMLElement} element |
| 17587 * @constructor |
| 17588 */ |
| 17589 function ElementMetrics(element) { |
| 17590 this.element = element; |
| 17591 this.width = this.boundingRect.width; |
| 17592 this.height = this.boundingRect.height; |
| 17593 |
| 17594 this.size = Math.max(this.width, this.height); |
| 17595 } |
| 17596 |
| 17597 ElementMetrics.prototype = { |
| 17598 get boundingRect () { |
| 17599 return this.element.getBoundingClientRect(); |
| 17600 }, |
| 17601 |
| 17602 furthestCornerDistanceFrom: function(x, y) { |
| 17603 var topLeft = Utility.distance(x, y, 0, 0); |
| 17604 var topRight = Utility.distance(x, y, this.width, 0); |
| 17605 var bottomLeft = Utility.distance(x, y, 0, this.height); |
| 17606 var bottomRight = Utility.distance(x, y, this.width, this.height); |
| 17607 |
| 17608 return Math.max(topLeft, topRight, bottomLeft, bottomRight); |
| 17609 } |
| 17610 }; |
| 17611 |
| 17612 /** |
| 17613 * @param {HTMLElement} element |
| 17614 * @constructor |
| 17615 */ |
| 17616 function Ripple(element) { |
| 17617 this.element = element; |
| 17618 this.color = window.getComputedStyle(element).color; |
| 17619 |
| 17620 this.wave = document.createElement('div'); |
| 17621 this.waveContainer = document.createElement('div'); |
| 17622 this.wave.style.backgroundColor = this.color; |
| 17623 this.wave.classList.add('wave'); |
| 17624 this.waveContainer.classList.add('wave-container'); |
| 17625 Polymer.dom(this.waveContainer).appendChild(this.wave); |
| 17626 |
| 17627 this.resetInteractionState(); |
| 17628 } |
| 17629 |
| 17630 Ripple.MAX_RADIUS = 300; |
| 17631 |
| 17632 Ripple.prototype = { |
| 17633 get recenters() { |
| 17634 return this.element.recenters; |
| 17635 }, |
| 17636 |
| 17637 get center() { |
| 17638 return this.element.center; |
| 17639 }, |
| 17640 |
| 17641 get mouseDownElapsed() { |
| 17642 var elapsed; |
| 17643 |
| 17644 if (!this.mouseDownStart) { |
| 17645 return 0; |
| 17646 } |
| 17647 |
| 17648 elapsed = Utility.now() - this.mouseDownStart; |
| 17649 |
| 17650 if (this.mouseUpStart) { |
| 17651 elapsed -= this.mouseUpElapsed; |
| 17652 } |
| 17653 |
| 17654 return elapsed; |
| 17655 }, |
| 17656 |
| 17657 get mouseUpElapsed() { |
| 17658 return this.mouseUpStart ? |
| 17659 Utility.now () - this.mouseUpStart : 0; |
| 17660 }, |
| 17661 |
| 17662 get mouseDownElapsedSeconds() { |
| 17663 return this.mouseDownElapsed / 1000; |
| 17664 }, |
| 17665 |
| 17666 get mouseUpElapsedSeconds() { |
| 17667 return this.mouseUpElapsed / 1000; |
| 17668 }, |
| 17669 |
| 17670 get mouseInteractionSeconds() { |
| 17671 return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds; |
| 17672 }, |
| 17673 |
| 17674 get initialOpacity() { |
| 17675 return this.element.initialOpacity; |
| 17676 }, |
| 17677 |
| 17678 get opacityDecayVelocity() { |
| 17679 return this.element.opacityDecayVelocity; |
| 17680 }, |
| 17681 |
| 17682 get radius() { |
| 17683 var width2 = this.containerMetrics.width * this.containerMetrics.width; |
| 17684 var height2 = this.containerMetrics.height * this.containerMetrics.heigh
t; |
| 17685 var waveRadius = Math.min( |
| 17686 Math.sqrt(width2 + height2), |
| 17687 Ripple.MAX_RADIUS |
| 17688 ) * 1.1 + 5; |
| 17689 |
| 17690 var duration = 1.1 - 0.2 * (waveRadius / Ripple.MAX_RADIUS); |
| 17691 var timeNow = this.mouseInteractionSeconds / duration; |
| 17692 var size = waveRadius * (1 - Math.pow(80, -timeNow)); |
| 17693 |
| 17694 return Math.abs(size); |
| 17695 }, |
| 17696 |
| 17697 get opacity() { |
| 17698 if (!this.mouseUpStart) { |
| 17699 return this.initialOpacity; |
| 17700 } |
| 17701 |
| 17702 return Math.max( |
| 17703 0, |
| 17704 this.initialOpacity - this.mouseUpElapsedSeconds * this.opacityDecayVe
locity |
| 17705 ); |
| 17706 }, |
| 17707 |
| 17708 get outerOpacity() { |
| 17709 // Linear increase in background opacity, capped at the opacity |
| 17710 // of the wavefront (waveOpacity). |
| 17711 var outerOpacity = this.mouseUpElapsedSeconds * 0.3; |
| 17712 var waveOpacity = this.opacity; |
| 17713 |
| 17714 return Math.max( |
| 17715 0, |
| 17716 Math.min(outerOpacity, waveOpacity) |
| 17717 ); |
| 17718 }, |
| 17719 |
| 17720 get isOpacityFullyDecayed() { |
| 17721 return this.opacity < 0.01 && |
| 17722 this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); |
| 17723 }, |
| 17724 |
| 17725 get isRestingAtMaxRadius() { |
| 17726 return this.opacity >= this.initialOpacity && |
| 17727 this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); |
| 17728 }, |
| 17729 |
| 17730 get isAnimationComplete() { |
| 17731 return this.mouseUpStart ? |
| 17732 this.isOpacityFullyDecayed : this.isRestingAtMaxRadius; |
| 17733 }, |
| 17734 |
| 17735 get translationFraction() { |
| 17736 return Math.min( |
| 17737 1, |
| 17738 this.radius / this.containerMetrics.size * 2 / Math.sqrt(2) |
| 17739 ); |
| 17740 }, |
| 17741 |
| 17742 get xNow() { |
| 17743 if (this.xEnd) { |
| 17744 return this.xStart + this.translationFraction * (this.xEnd - this.xSta
rt); |
| 17745 } |
| 17746 |
| 17747 return this.xStart; |
| 17748 }, |
| 17749 |
| 17750 get yNow() { |
| 17751 if (this.yEnd) { |
| 17752 return this.yStart + this.translationFraction * (this.yEnd - this.ySta
rt); |
| 17753 } |
| 17754 |
| 17755 return this.yStart; |
| 17756 }, |
| 17757 |
| 17758 get isMouseDown() { |
| 17759 return this.mouseDownStart && !this.mouseUpStart; |
| 17760 }, |
| 17761 |
| 17762 resetInteractionState: function() { |
| 17763 this.maxRadius = 0; |
| 17764 this.mouseDownStart = 0; |
| 17765 this.mouseUpStart = 0; |
| 17766 |
| 17767 this.xStart = 0; |
| 17768 this.yStart = 0; |
| 17769 this.xEnd = 0; |
| 17770 this.yEnd = 0; |
| 17771 this.slideDistance = 0; |
| 17772 |
| 17773 this.containerMetrics = new ElementMetrics(this.element); |
| 17774 }, |
| 17775 |
| 17776 draw: function() { |
| 17777 var scale; |
| 17778 var translateString; |
| 17779 var dx; |
| 17780 var dy; |
| 17781 |
| 17782 this.wave.style.opacity = this.opacity; |
| 17783 |
| 17784 scale = this.radius / (this.containerMetrics.size / 2); |
| 17785 dx = this.xNow - (this.containerMetrics.width / 2); |
| 17786 dy = this.yNow - (this.containerMetrics.height / 2); |
| 17787 |
| 17788 |
| 17789 // 2d transform for safari because of border-radius and overflow:hidden
clipping bug. |
| 17790 // https://bugs.webkit.org/show_bug.cgi?id=98538 |
| 17791 this.waveContainer.style.webkitTransform = 'translate(' + dx + 'px, ' +
dy + 'px)'; |
| 17792 this.waveContainer.style.transform = 'translate3d(' + dx + 'px, ' + dy +
'px, 0)'; |
| 17793 this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')'; |
| 17794 this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)'; |
| 17795 }, |
| 17796 |
| 17797 /** @param {Event=} event */ |
| 17798 downAction: function(event) { |
| 17799 var xCenter = this.containerMetrics.width / 2; |
| 17800 var yCenter = this.containerMetrics.height / 2; |
| 17801 |
| 17802 this.resetInteractionState(); |
| 17803 this.mouseDownStart = Utility.now(); |
| 17804 |
| 17805 if (this.center) { |
| 17806 this.xStart = xCenter; |
| 17807 this.yStart = yCenter; |
| 17808 this.slideDistance = Utility.distance( |
| 17809 this.xStart, this.yStart, this.xEnd, this.yEnd |
| 17810 ); |
| 17811 } else { |
| 17812 this.xStart = event ? |
| 17813 event.detail.x - this.containerMetrics.boundingRect.left : |
| 17814 this.containerMetrics.width / 2; |
| 17815 this.yStart = event ? |
| 17816 event.detail.y - this.containerMetrics.boundingRect.top : |
| 17817 this.containerMetrics.height / 2; |
| 17818 } |
| 17819 |
| 17820 if (this.recenters) { |
| 17821 this.xEnd = xCenter; |
| 17822 this.yEnd = yCenter; |
| 17823 this.slideDistance = Utility.distance( |
| 17824 this.xStart, this.yStart, this.xEnd, this.yEnd |
| 17825 ); |
| 17826 } |
| 17827 |
| 17828 this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom( |
| 17829 this.xStart, |
| 17830 this.yStart |
| 17831 ); |
| 17832 |
| 17833 this.waveContainer.style.top = |
| 17834 (this.containerMetrics.height - this.containerMetrics.size) / 2 + 'px'
; |
| 17835 this.waveContainer.style.left = |
| 17836 (this.containerMetrics.width - this.containerMetrics.size) / 2 + 'px'; |
| 17837 |
| 17838 this.waveContainer.style.width = this.containerMetrics.size + 'px'; |
| 17839 this.waveContainer.style.height = this.containerMetrics.size + 'px'; |
| 17840 }, |
| 17841 |
| 17842 /** @param {Event=} event */ |
| 17843 upAction: function(event) { |
| 17844 if (!this.isMouseDown) { |
| 17845 return; |
| 17846 } |
| 17847 |
| 17848 this.mouseUpStart = Utility.now(); |
| 17849 }, |
| 17850 |
| 17851 remove: function() { |
| 17852 Polymer.dom(this.waveContainer.parentNode).removeChild( |
| 17853 this.waveContainer |
| 17854 ); |
| 17855 } |
| 17856 }; |
| 17857 |
| 17858 Polymer({ |
| 17859 is: 'paper-ripple', |
| 17860 |
| 17861 behaviors: [ |
| 17862 Polymer.IronA11yKeysBehavior |
| 17863 ], |
| 17864 |
| 17865 properties: { |
| 17866 /** |
| 17867 * The initial opacity set on the wave. |
| 17868 * |
| 17869 * @attribute initialOpacity |
| 17870 * @type number |
| 17871 * @default 0.25 |
| 17872 */ |
| 17873 initialOpacity: { |
| 17874 type: Number, |
| 17875 value: 0.25 |
| 17876 }, |
| 17877 |
| 17878 /** |
| 17879 * How fast (opacity per second) the wave fades out. |
| 17880 * |
| 17881 * @attribute opacityDecayVelocity |
| 17882 * @type number |
| 17883 * @default 0.8 |
| 17884 */ |
| 17885 opacityDecayVelocity: { |
| 17886 type: Number, |
| 17887 value: 0.8 |
| 17888 }, |
| 17889 |
| 17890 /** |
| 17891 * If true, ripples will exhibit a gravitational pull towards |
| 17892 * the center of their container as they fade away. |
| 17893 * |
| 17894 * @attribute recenters |
| 17895 * @type boolean |
| 17896 * @default false |
| 17897 */ |
| 17898 recenters: { |
| 17899 type: Boolean, |
| 17900 value: false |
| 17901 }, |
| 17902 |
| 17903 /** |
| 17904 * If true, ripples will center inside its container |
| 17905 * |
| 17906 * @attribute recenters |
| 17907 * @type boolean |
| 17908 * @default false |
| 17909 */ |
| 17910 center: { |
| 17911 type: Boolean, |
| 17912 value: false |
| 17913 }, |
| 17914 |
| 17915 /** |
| 17916 * A list of the visual ripples. |
| 17917 * |
| 17918 * @attribute ripples |
| 17919 * @type Array |
| 17920 * @default [] |
| 17921 */ |
| 17922 ripples: { |
| 17923 type: Array, |
| 17924 value: function() { |
| 17925 return []; |
| 17926 } |
| 17927 }, |
| 17928 |
| 17929 /** |
| 17930 * True when there are visible ripples animating within the |
| 17931 * element. |
| 17932 */ |
| 17933 animating: { |
| 17934 type: Boolean, |
| 17935 readOnly: true, |
| 17936 reflectToAttribute: true, |
| 17937 value: false |
| 17938 }, |
| 17939 |
| 17940 /** |
| 17941 * If true, the ripple will remain in the "down" state until `holdDown` |
| 17942 * is set to false again. |
| 17943 */ |
| 17944 holdDown: { |
| 17945 type: Boolean, |
| 17946 value: false, |
| 17947 observer: '_holdDownChanged' |
| 17948 }, |
| 17949 |
| 17950 /** |
| 17951 * If true, the ripple will not generate a ripple effect |
| 17952 * via pointer interaction. |
| 17953 * Calling ripple's imperative api like `simulatedRipple` will |
| 17954 * still generate the ripple effect. |
| 17955 */ |
| 17956 noink: { |
| 17957 type: Boolean, |
| 17958 value: false |
| 17959 }, |
| 17960 |
| 17961 _animating: { |
| 17962 type: Boolean |
| 17963 }, |
| 17964 |
| 17965 _boundAnimate: { |
| 17966 type: Function, |
| 17967 value: function() { |
| 17968 return this.animate.bind(this); |
| 17969 } |
| 17970 } |
| 17971 }, |
| 17972 |
| 17973 get target () { |
| 17974 return this.keyEventTarget; |
| 17975 }, |
| 17976 |
| 17977 keyBindings: { |
| 17978 'enter:keydown': '_onEnterKeydown', |
| 17979 'space:keydown': '_onSpaceKeydown', |
| 17980 'space:keyup': '_onSpaceKeyup' |
| 17981 }, |
| 17982 |
| 17983 attached: function() { |
| 17984 // Set up a11yKeysBehavior to listen to key events on the target, |
| 17985 // so that space and enter activate the ripple even if the target doesn'
t |
| 17986 // handle key events. The key handlers deal with `noink` themselves. |
| 17987 if (this.parentNode.nodeType == 11) { // DOCUMENT_FRAGMENT_NODE |
| 17988 this.keyEventTarget = Polymer.dom(this).getOwnerRoot().host; |
| 17989 } else { |
| 17990 this.keyEventTarget = this.parentNode; |
| 17991 } |
| 17992 var keyEventTarget = /** @type {!EventTarget} */ (this.keyEventTarget); |
| 17993 this.listen(keyEventTarget, 'up', 'uiUpAction'); |
| 17994 this.listen(keyEventTarget, 'down', 'uiDownAction'); |
| 17995 }, |
| 17996 |
| 17997 detached: function() { |
| 17998 this.unlisten(this.keyEventTarget, 'up', 'uiUpAction'); |
| 17999 this.unlisten(this.keyEventTarget, 'down', 'uiDownAction'); |
| 18000 this.keyEventTarget = null; |
| 18001 }, |
| 18002 |
| 18003 get shouldKeepAnimating () { |
| 18004 for (var index = 0; index < this.ripples.length; ++index) { |
| 18005 if (!this.ripples[index].isAnimationComplete) { |
| 18006 return true; |
| 18007 } |
| 18008 } |
| 18009 |
| 18010 return false; |
| 18011 }, |
| 18012 |
| 18013 simulatedRipple: function() { |
| 18014 this.downAction(null); |
| 18015 |
| 18016 // Please see polymer/polymer#1305 |
| 18017 this.async(function() { |
| 18018 this.upAction(); |
| 18019 }, 1); |
| 18020 }, |
| 18021 |
| 18022 /** |
| 18023 * Provokes a ripple down effect via a UI event, |
| 18024 * respecting the `noink` property. |
| 18025 * @param {Event=} event |
| 18026 */ |
| 18027 uiDownAction: function(event) { |
| 18028 if (!this.noink) { |
| 18029 this.downAction(event); |
| 18030 } |
| 18031 }, |
| 18032 |
| 18033 /** |
| 18034 * Provokes a ripple down effect via a UI event, |
| 18035 * *not* respecting the `noink` property. |
| 18036 * @param {Event=} event |
| 18037 */ |
| 18038 downAction: function(event) { |
| 18039 if (this.holdDown && this.ripples.length > 0) { |
| 18040 return; |
| 18041 } |
| 18042 |
| 18043 var ripple = this.addRipple(); |
| 18044 |
| 18045 ripple.downAction(event); |
| 18046 |
| 18047 if (!this._animating) { |
| 18048 this._animating = true; |
| 18049 this.animate(); |
| 18050 } |
| 18051 }, |
| 18052 |
| 18053 /** |
| 18054 * Provokes a ripple up effect via a UI event, |
| 18055 * respecting the `noink` property. |
| 18056 * @param {Event=} event |
| 18057 */ |
| 18058 uiUpAction: function(event) { |
| 18059 if (!this.noink) { |
| 18060 this.upAction(event); |
| 18061 } |
| 18062 }, |
| 18063 |
| 18064 /** |
| 18065 * Provokes a ripple up effect via a UI event, |
| 18066 * *not* respecting the `noink` property. |
| 18067 * @param {Event=} event |
| 18068 */ |
| 18069 upAction: function(event) { |
| 18070 if (this.holdDown) { |
| 18071 return; |
| 18072 } |
| 18073 |
| 18074 this.ripples.forEach(function(ripple) { |
| 18075 ripple.upAction(event); |
| 18076 }); |
| 18077 |
| 18078 this._animating = true; |
| 18079 this.animate(); |
| 18080 }, |
| 18081 |
| 18082 onAnimationComplete: function() { |
| 18083 this._animating = false; |
| 18084 this.$.background.style.backgroundColor = null; |
| 18085 this.fire('transitionend'); |
| 18086 }, |
| 18087 |
| 18088 addRipple: function() { |
| 18089 var ripple = new Ripple(this); |
| 18090 |
| 18091 Polymer.dom(this.$.waves).appendChild(ripple.waveContainer); |
| 18092 this.$.background.style.backgroundColor = ripple.color; |
| 18093 this.ripples.push(ripple); |
| 18094 |
| 18095 this._setAnimating(true); |
| 18096 |
| 18097 return ripple; |
| 18098 }, |
| 18099 |
| 18100 removeRipple: function(ripple) { |
| 18101 var rippleIndex = this.ripples.indexOf(ripple); |
| 18102 |
| 18103 if (rippleIndex < 0) { |
| 18104 return; |
| 18105 } |
| 18106 |
| 18107 this.ripples.splice(rippleIndex, 1); |
| 18108 |
| 18109 ripple.remove(); |
| 18110 |
| 18111 if (!this.ripples.length) { |
| 18112 this._setAnimating(false); |
| 18113 } |
| 18114 }, |
| 18115 |
| 18116 animate: function() { |
| 18117 if (!this._animating) { |
| 18118 return; |
| 18119 } |
| 18120 var index; |
| 18121 var ripple; |
| 18122 |
| 18123 for (index = 0; index < this.ripples.length; ++index) { |
| 18124 ripple = this.ripples[index]; |
| 18125 |
| 18126 ripple.draw(); |
| 18127 |
| 18128 this.$.background.style.opacity = ripple.outerOpacity; |
| 18129 |
| 18130 if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) { |
| 18131 this.removeRipple(ripple); |
| 18132 } |
| 18133 } |
| 18134 |
| 18135 if (!this.shouldKeepAnimating && this.ripples.length === 0) { |
| 18136 this.onAnimationComplete(); |
| 18137 } else { |
| 18138 window.requestAnimationFrame(this._boundAnimate); |
| 18139 } |
| 18140 }, |
| 18141 |
| 18142 _onEnterKeydown: function() { |
| 18143 this.uiDownAction(); |
| 18144 this.async(this.uiUpAction, 1); |
| 18145 }, |
| 18146 |
| 18147 _onSpaceKeydown: function() { |
| 18148 this.uiDownAction(); |
| 18149 }, |
| 18150 |
| 18151 _onSpaceKeyup: function() { |
| 18152 this.uiUpAction(); |
| 18153 }, |
| 18154 |
| 18155 // note: holdDown does not respect noink since it can be a focus based |
| 18156 // effect. |
| 18157 _holdDownChanged: function(newVal, oldVal) { |
| 18158 if (oldVal === undefined) { |
| 18159 return; |
| 18160 } |
| 18161 if (newVal) { |
| 18162 this.downAction(); |
| 18163 } else { |
| 18164 this.upAction(); |
| 18165 } |
| 18166 } |
| 18167 |
| 18168 /** |
| 18169 Fired when the animation finishes. |
| 18170 This is useful if you want to wait until |
| 18171 the ripple animation finishes to perform some action. |
| 18172 |
| 18173 @event transitionend |
| 18174 @param {{node: Object}} detail Contains the animated node. |
| 18175 */ |
| 18176 }); |
| 18177 })(); |
| 18178 </script> |
| 18179 <script> |
| 18180 /** |
| 18181 * `Polymer.PaperRippleBehavior` dynamically implements a ripple |
| 18182 * when the element has focus via pointer or keyboard. |
| 18183 * |
| 18184 * NOTE: This behavior is intended to be used in conjunction with and after |
| 18185 * `Polymer.IronButtonState` and `Polymer.IronControlState`. |
| 18186 * |
| 18187 * @polymerBehavior Polymer.PaperRippleBehavior |
| 18188 */ |
| 18189 Polymer.PaperRippleBehavior = { |
| 18190 properties: { |
| 18191 /** |
| 18192 * If true, the element will not produce a ripple effect when interacted |
| 18193 * with via the pointer. |
| 18194 */ |
| 18195 noink: { |
| 18196 type: Boolean, |
| 18197 observer: '_noinkChanged' |
| 18198 }, |
| 18199 |
| 18200 /** |
| 18201 * @type {Element|undefined} |
| 18202 */ |
| 18203 _rippleContainer: { |
| 18204 type: Object, |
| 18205 } |
| 18206 }, |
| 18207 |
| 18208 /** |
| 18209 * Ensures a `<paper-ripple>` element is available when the element is |
| 18210 * focused. |
| 18211 */ |
| 18212 _buttonStateChanged: function() { |
| 18213 if (this.focused) { |
| 18214 this.ensureRipple(); |
| 18215 } |
| 18216 }, |
| 18217 |
| 18218 /** |
| 18219 * In addition to the functionality provided in `IronButtonState`, ensures |
| 18220 * a ripple effect is created when the element is in a `pressed` state. |
| 18221 */ |
| 18222 _downHandler: function(event) { |
| 18223 Polymer.IronButtonStateImpl._downHandler.call(this, event); |
| 18224 if (this.pressed) { |
| 18225 this.ensureRipple(event); |
| 18226 } |
| 18227 }, |
| 18228 |
| 18229 /** |
| 18230 * Ensures this element contains a ripple effect. For startup efficiency |
| 18231 * the ripple effect is dynamically on demand when needed. |
| 18232 * @param {!Event=} optTriggeringEvent (optional) event that triggered the |
| 18233 * ripple. |
| 18234 */ |
| 18235 ensureRipple: function(optTriggeringEvent) { |
| 18236 if (!this.hasRipple()) { |
| 18237 this._ripple = this._createRipple(); |
| 18238 this._ripple.noink = this.noink; |
| 18239 var rippleContainer = this._rippleContainer || this.root; |
| 18240 if (rippleContainer) { |
| 18241 Polymer.dom(rippleContainer).appendChild(this._ripple); |
| 18242 } |
| 18243 if (optTriggeringEvent) { |
| 18244 // Check if the event happened inside of the ripple container |
| 18245 // Fall back to host instead of the root because distributed text |
| 18246 // nodes are not valid event targets |
| 18247 var domContainer = Polymer.dom(this._rippleContainer || this); |
| 18248 var target = Polymer.dom(optTriggeringEvent).rootTarget; |
| 18249 if (domContainer.deepContains( /** @type {Node} */(target))) { |
| 18250 this._ripple.uiDownAction(optTriggeringEvent); |
| 18251 } |
| 18252 } |
| 18253 } |
| 18254 }, |
| 18255 |
| 18256 /** |
| 18257 * Returns the `<paper-ripple>` element used by this element to create |
| 18258 * ripple effects. The element's ripple is created on demand, when |
| 18259 * necessary, and calling this method will force the |
| 18260 * ripple to be created. |
| 18261 */ |
| 18262 getRipple: function() { |
| 18263 this.ensureRipple(); |
| 18264 return this._ripple; |
| 18265 }, |
| 18266 |
| 18267 /** |
| 18268 * Returns true if this element currently contains a ripple effect. |
| 18269 * @return {boolean} |
| 18270 */ |
| 18271 hasRipple: function() { |
| 18272 return Boolean(this._ripple); |
| 18273 }, |
| 18274 |
| 18275 /** |
| 18276 * Create the element's ripple effect via creating a `<paper-ripple>`. |
| 18277 * Override this method to customize the ripple element. |
| 18278 * @return {!PaperRippleElement} Returns a `<paper-ripple>` element. |
| 18279 */ |
| 18280 _createRipple: function() { |
| 18281 return /** @type {!PaperRippleElement} */ ( |
| 18282 document.createElement('paper-ripple')); |
| 18283 }, |
| 18284 |
| 18285 _noinkChanged: function(noink) { |
| 18286 if (this.hasRipple()) { |
| 18287 this._ripple.noink = noink; |
| 18288 } |
| 18289 } |
| 18290 }; |
| 18291 </script> |
| 18292 <script> |
| 18293 /** |
| 18294 * `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has k
eyboard focus. |
| 18295 * |
| 18296 * @polymerBehavior Polymer.PaperInkyFocusBehavior |
| 18297 */ |
| 18298 Polymer.PaperInkyFocusBehaviorImpl = { |
| 18299 observers: [ |
| 18300 '_focusedChanged(receivedFocusFromKeyboard)' |
| 18301 ], |
| 18302 |
| 18303 _focusedChanged: function(receivedFocusFromKeyboard) { |
| 18304 if (receivedFocusFromKeyboard) { |
| 18305 this.ensureRipple(); |
| 18306 } |
| 18307 if (this.hasRipple()) { |
| 18308 this._ripple.holdDown = receivedFocusFromKeyboard; |
| 18309 } |
| 18310 }, |
| 18311 |
| 18312 _createRipple: function() { |
| 18313 var ripple = Polymer.PaperRippleBehavior._createRipple(); |
| 18314 ripple.id = 'ink'; |
| 18315 ripple.setAttribute('center', ''); |
| 18316 ripple.classList.add('circle'); |
| 18317 return ripple; |
| 18318 } |
| 18319 }; |
| 18320 |
| 18321 /** @polymerBehavior Polymer.PaperInkyFocusBehavior */ |
| 18322 Polymer.PaperInkyFocusBehavior = [ |
| 18323 Polymer.IronButtonState, |
| 18324 Polymer.IronControlState, |
| 18325 Polymer.PaperRippleBehavior, |
| 18326 Polymer.PaperInkyFocusBehaviorImpl |
| 18327 ]; |
| 18328 </script> |
| 18329 <script> |
| 18330 /** |
| 18331 * Use `Polymer.PaperCheckedElementBehavior` to implement a custom element |
| 18332 * that has a `checked` property similar to `Polymer.IronCheckedElementBehavio
r` |
| 18333 * and is compatible with having a ripple effect. |
| 18334 * @polymerBehavior Polymer.PaperCheckedElementBehavior |
| 18335 */ |
| 18336 Polymer.PaperCheckedElementBehaviorImpl = { |
| 18337 /** |
| 18338 * Synchronizes the element's checked state with its ripple effect. |
| 18339 */ |
| 18340 _checkedChanged: function() { |
| 18341 Polymer.IronCheckedElementBehaviorImpl._checkedChanged.call(this); |
| 18342 if (this.hasRipple()) { |
| 18343 if (this.checked) { |
| 18344 this._ripple.setAttribute('checked', ''); |
| 18345 } else { |
| 18346 this._ripple.removeAttribute('checked'); |
| 18347 } |
| 18348 } |
| 18349 }, |
| 18350 |
| 18351 /** |
| 18352 * Synchronizes the element's `active` and `checked` state. |
| 18353 */ |
| 18354 _buttonStateChanged: function() { |
| 18355 Polymer.PaperRippleBehavior._buttonStateChanged.call(this); |
| 18356 if (this.disabled) { |
| 18357 return; |
| 18358 } |
| 18359 if (this.isAttached) { |
| 18360 this.checked = this.active; |
| 18361 } |
| 18362 } |
| 18363 }; |
| 18364 |
| 18365 /** @polymerBehavior Polymer.PaperCheckedElementBehavior */ |
| 18366 Polymer.PaperCheckedElementBehavior = [ |
| 18367 Polymer.PaperInkyFocusBehavior, |
| 18368 Polymer.IronCheckedElementBehavior, |
| 18369 Polymer.PaperCheckedElementBehaviorImpl |
| 18370 ]; |
| 18371 </script> |
| 18372 |
| 18373 |
| 18374 <dom-module id="paper-checkbox" assetpath="/res/imp/bower_components/paper-check
box/"> |
| 18375 <template strip-whitespace=""> |
| 18376 <style> |
| 18377 :host { |
| 18378 display: inline-block; |
| 18379 white-space: nowrap; |
| 18380 cursor: pointer; |
| 18381 --calculated-paper-checkbox-size: var(--paper-checkbox-size, 18px); |
| 18382 @apply(--paper-font-common-base); |
| 18383 line-height: 0; |
| 18384 -webkit-tap-highlight-color: transparent; |
| 18385 } |
| 18386 |
| 18387 :host([hidden]) { |
| 18388 display: none !important; |
| 18389 } |
| 18390 |
| 18391 :host(:focus) { |
| 18392 outline: none; |
| 18393 } |
| 18394 |
| 18395 .hidden { |
| 18396 display: none; |
| 18397 } |
| 18398 |
| 18399 #checkboxContainer { |
| 18400 display: inline-block; |
| 18401 position: relative; |
| 18402 width: var(--calculated-paper-checkbox-size); |
| 18403 height: var(--calculated-paper-checkbox-size); |
| 18404 min-width: var(--calculated-paper-checkbox-size); |
| 18405 margin: var(--paper-checkbox-margin, initial); |
| 18406 vertical-align: var(--paper-checkbox-vertical-align, middle); |
| 18407 background-color: var(--paper-checkbox-unchecked-background-color, trans
parent); |
| 18408 } |
| 18409 |
| 18410 #ink { |
| 18411 position: absolute; |
| 18412 |
| 18413 /* Center the ripple in the checkbox by negative offsetting it by |
| 18414 * (inkWidth - rippleWidth) / 2 */ |
| 18415 top: calc(0px - (2.66 * var(--calculated-paper-checkbox-size) - var(--ca
lculated-paper-checkbox-size)) / 2); |
| 18416 left: calc(0px - (2.66 * var(--calculated-paper-checkbox-size) - var(--c
alculated-paper-checkbox-size)) / 2); |
| 18417 width: calc(2.66 * var(--calculated-paper-checkbox-size)); |
| 18418 height: calc(2.66 * var(--calculated-paper-checkbox-size)); |
| 18419 color: var(--paper-checkbox-unchecked-ink-color, --primary-text-color); |
| 18420 opacity: 0.6; |
| 18421 pointer-events: none; |
| 18422 } |
| 18423 |
| 18424 :host-context([dir="rtl"]) #ink { |
| 18425 right: calc(0px - (2.66 * var(--calculated-paper-checkbox-size) - var(--
calculated-paper-checkbox-size)) / 2); |
| 18426 left: auto; |
| 18427 } |
| 18428 |
| 18429 #ink[checked] { |
| 18430 color: var(--paper-checkbox-checked-ink-color, --primary-color); |
| 18431 } |
| 18432 |
| 18433 #checkbox { |
| 18434 position: relative; |
| 18435 box-sizing: border-box; |
| 18436 height: 100%; |
| 18437 border: solid 2px; |
| 18438 border-color: var(--paper-checkbox-unchecked-color, --primary-text-color
); |
| 18439 border-radius: 2px; |
| 18440 pointer-events: none; |
| 18441 -webkit-transition: background-color 140ms, border-color 140ms; |
| 18442 transition: background-color 140ms, border-color 140ms; |
| 18443 } |
| 18444 |
| 18445 /* checkbox checked animations */ |
| 18446 #checkbox.checked #checkmark { |
| 18447 -webkit-animation: checkmark-expand 140ms ease-out forwards; |
| 18448 animation: checkmark-expand 140ms ease-out forwards; |
| 18449 } |
| 18450 |
| 18451 @-webkit-keyframes checkmark-expand { |
| 18452 0% { |
| 18453 -webkit-transform: scale(0, 0) rotate(45deg); |
| 18454 } |
| 18455 100% { |
| 18456 -webkit-transform: scale(1, 1) rotate(45deg); |
| 18457 } |
| 18458 } |
| 18459 |
| 18460 @keyframes checkmark-expand { |
| 18461 0% { |
| 18462 transform: scale(0, 0) rotate(45deg); |
| 18463 } |
| 18464 100% { |
| 18465 transform: scale(1, 1) rotate(45deg); |
| 18466 } |
| 18467 } |
| 18468 |
| 18469 #checkbox.checked { |
| 18470 background-color: var(--paper-checkbox-checked-color, --primary-color); |
| 18471 border-color: var(--paper-checkbox-checked-color, --primary-color); |
| 18472 } |
| 18473 |
| 18474 #checkmark { |
| 18475 position: absolute; |
| 18476 width: 36%; |
| 18477 height: 70%; |
| 18478 border-style: solid; |
| 18479 border-top: none; |
| 18480 border-left: none; |
| 18481 border-right-width: calc(2/15 * var(--calculated-paper-checkbox-size)); |
| 18482 border-bottom-width: calc(2/15 * var(--calculated-paper-checkbox-size)); |
| 18483 border-color: var(--paper-checkbox-checkmark-color, white); |
| 18484 -webkit-transform-origin: 97% 86%; |
| 18485 transform-origin: 97% 86%; |
| 18486 box-sizing: content-box; /* protect against page-level box-sizing */ |
| 18487 } |
| 18488 |
| 18489 :host-context([dir="rtl"]) #checkmark { |
| 18490 -webkit-transform-origin: 50% 14%; |
| 18491 transform-origin: 50% 14%; |
| 18492 } |
| 18493 |
| 18494 /* label */ |
| 18495 #checkboxLabel { |
| 18496 position: relative; |
| 18497 display: inline-block; |
| 18498 vertical-align: middle; |
| 18499 padding-left: var(--paper-checkbox-label-spacing, 8px); |
| 18500 white-space: normal; |
| 18501 line-height: normal; |
| 18502 color: var(--paper-checkbox-label-color, --primary-text-color); |
| 18503 @apply(--paper-checkbox-label); |
| 18504 } |
| 18505 |
| 18506 :host([checked]) #checkboxLabel { |
| 18507 color: var(--paper-checkbox-label-checked-color, --paper-checkbox-label-
color); |
| 18508 @apply(--paper-checkbox-label-checked); |
| 18509 } |
| 18510 |
| 18511 :host-context([dir="rtl"]) #checkboxLabel { |
| 18512 padding-right: var(--paper-checkbox-label-spacing, 8px); |
| 18513 padding-left: 0; |
| 18514 } |
| 18515 |
| 18516 #checkboxLabel[hidden] { |
| 18517 display: none; |
| 18518 } |
| 18519 |
| 18520 /* disabled state */ |
| 18521 |
| 18522 :host([disabled]) #checkbox { |
| 18523 opacity: 0.5; |
| 18524 border-color: var(--paper-checkbox-unchecked-color, --primary-text-color
); |
| 18525 } |
| 18526 |
| 18527 :host([disabled][checked]) #checkbox { |
| 18528 background-color: var(--paper-checkbox-unchecked-color, --primary-text-c
olor); |
| 18529 opacity: 0.5; |
| 18530 } |
| 18531 |
| 18532 :host([disabled]) #checkboxLabel { |
| 18533 opacity: 0.65; |
| 18534 } |
| 18535 |
| 18536 /* invalid state */ |
| 18537 #checkbox.invalid:not(.checked) { |
| 18538 border-color: var(--paper-checkbox-error-color, --error-color); |
| 18539 } |
| 18540 </style> |
| 18541 |
| 18542 <div id="checkboxContainer"> |
| 18543 <div id="checkbox" class$="[[_computeCheckboxClass(checked, invalid)]]"> |
| 18544 <div id="checkmark" class$="[[_computeCheckmarkClass(checked)]]"></div> |
| 18545 </div> |
| 18546 </div> |
| 18547 |
| 18548 <div id="checkboxLabel"><content></content></div> |
| 18549 </template> |
| 18550 |
| 18551 <script> |
| 18552 Polymer({ |
| 18553 is: 'paper-checkbox', |
| 18554 |
| 18555 behaviors: [ |
| 18556 Polymer.PaperCheckedElementBehavior |
| 18557 ], |
| 18558 |
| 18559 hostAttributes: { |
| 18560 role: 'checkbox', |
| 18561 'aria-checked': false, |
| 18562 tabindex: 0 |
| 18563 }, |
| 18564 |
| 18565 properties: { |
| 18566 /** |
| 18567 * Fired when the checked state changes due to user interaction. |
| 18568 * |
| 18569 * @event change |
| 18570 */ |
| 18571 |
| 18572 /** |
| 18573 * Fired when the checked state changes. |
| 18574 * |
| 18575 * @event iron-change |
| 18576 */ |
| 18577 ariaActiveAttribute: { |
| 18578 type: String, |
| 18579 value: 'aria-checked' |
| 18580 } |
| 18581 }, |
| 18582 |
| 18583 _computeCheckboxClass: function(checked, invalid) { |
| 18584 var className = ''; |
| 18585 if (checked) { |
| 18586 className += 'checked '; |
| 18587 } |
| 18588 if (invalid) { |
| 18589 className += 'invalid'; |
| 18590 } |
| 18591 return className; |
| 18592 }, |
| 18593 |
| 18594 _computeCheckmarkClass: function(checked) { |
| 18595 return checked ? '' : 'hidden'; |
| 18596 }, |
| 18597 |
| 18598 // create ripple inside the checkboxContainer |
| 18599 _createRipple: function() { |
| 18600 this._rippleContainer = this.$.checkboxContainer; |
| 18601 return Polymer.PaperInkyFocusBehaviorImpl._createRipple.call(this); |
| 18602 } |
| 18603 |
| 18604 }); |
| 18605 </script> |
| 18606 </dom-module> |
| 18607 |
| 18608 |
| 18609 <dom-module id="paper-icon-button" assetpath="/res/imp/bower_components/paper-ic
on-button/"> |
| 18610 <template strip-whitespace=""> |
| 18611 <style> |
| 18612 :host { |
| 18613 display: inline-block; |
| 18614 position: relative; |
| 18615 padding: 8px; |
| 18616 outline: none; |
| 18617 -webkit-user-select: none; |
| 18618 -moz-user-select: none; |
| 18619 -ms-user-select: none; |
| 18620 user-select: none; |
| 18621 cursor: pointer; |
| 18622 z-index: 0; |
| 18623 line-height: 1; |
| 18624 |
| 18625 width: 40px; |
| 18626 height: 40px; |
| 18627 |
| 18628 /* NOTE: Both values are needed, since some phones require the value to
be `transparent`. */ |
| 18629 -webkit-tap-highlight-color: rgba(0, 0, 0, 0); |
| 18630 -webkit-tap-highlight-color: transparent; |
| 18631 |
| 18632 /* Because of polymer/2558, this style has lower specificity than * */ |
| 18633 box-sizing: border-box !important; |
| 18634 |
| 18635 @apply(--paper-icon-button); |
| 18636 } |
| 18637 |
| 18638 :host #ink { |
| 18639 color: var(--paper-icon-button-ink-color, --primary-text-color); |
| 18640 opacity: 0.6; |
| 18641 } |
| 18642 |
| 18643 :host([disabled]) { |
| 18644 color: var(--paper-icon-button-disabled-text, --disabled-text-color); |
| 18645 pointer-events: none; |
| 18646 cursor: auto; |
| 18647 |
| 18648 @apply(--paper-icon-button-disabled); |
| 18649 } |
| 18650 |
| 18651 :host(:hover) { |
| 18652 @apply(--paper-icon-button-hover); |
| 18653 } |
| 18654 |
| 18655 iron-icon { |
| 18656 --iron-icon-width: 100%; |
| 18657 --iron-icon-height: 100%; |
| 18658 } |
| 18659 </style> |
| 18660 |
| 18661 <iron-icon id="icon" src="[[src]]" icon="[[icon]]" alt$="[[alt]]"></iron-ico
n> |
| 18662 </template> |
| 18663 |
| 18664 <script> |
| 18665 Polymer({ |
| 18666 is: 'paper-icon-button', |
| 18667 |
| 18668 hostAttributes: { |
| 18669 role: 'button', |
| 18670 tabindex: '0' |
| 18671 }, |
| 18672 |
| 18673 behaviors: [ |
| 18674 Polymer.PaperInkyFocusBehavior |
| 18675 ], |
| 18676 |
| 18677 properties: { |
| 18678 /** |
| 18679 * The URL of an image for the icon. If the src property is specified, |
| 18680 * the icon property should not be. |
| 18681 */ |
| 18682 src: { |
| 18683 type: String |
| 18684 }, |
| 18685 |
| 18686 /** |
| 18687 * Specifies the icon name or index in the set of icons available in |
| 18688 * the icon's icon set. If the icon property is specified, |
| 18689 * the src property should not be. |
| 18690 */ |
| 18691 icon: { |
| 18692 type: String |
| 18693 }, |
| 18694 |
| 18695 /** |
| 18696 * Specifies the alternate text for the button, for accessibility. |
| 18697 */ |
| 18698 alt: { |
| 18699 type: String, |
| 18700 observer: "_altChanged" |
| 18701 } |
| 18702 }, |
| 18703 |
| 18704 _altChanged: function(newValue, oldValue) { |
| 18705 var label = this.getAttribute('aria-label'); |
| 18706 |
| 18707 // Don't stomp over a user-set aria-label. |
| 18708 if (!label || oldValue == label) { |
| 18709 this.setAttribute('aria-label', newValue); |
| 18710 } |
| 18711 } |
| 18712 }); |
| 18713 </script> |
| 18714 </dom-module> |
| 18715 |
| 18716 |
| 18717 <dom-module id="iron-a11y-announcer" assetpath="/res/imp/bower_components/iron-a
11y-announcer/"> |
| 18718 <template> |
| 18719 <style> |
| 18720 :host { |
| 18721 display: inline-block; |
| 18722 position: fixed; |
| 18723 clip: rect(0px,0px,0px,0px); |
| 18724 } |
| 18725 </style> |
| 18726 <div aria-live$="[[mode]]">[[_text]]</div> |
| 18727 </template> |
| 18728 |
| 18729 <script> |
| 18730 |
| 18731 (function() { |
| 18732 'use strict'; |
| 18733 |
| 18734 Polymer.IronA11yAnnouncer = Polymer({ |
| 18735 is: 'iron-a11y-announcer', |
| 18736 |
| 18737 properties: { |
| 18738 |
| 18739 /** |
| 18740 * The value of mode is used to set the `aria-live` attribute |
| 18741 * for the element that will be announced. Valid values are: `off`, |
| 18742 * `polite` and `assertive`. |
| 18743 */ |
| 18744 mode: { |
| 18745 type: String, |
| 18746 value: 'polite' |
| 18747 }, |
| 18748 |
| 18749 _text: { |
| 18750 type: String, |
| 18751 value: '' |
| 18752 } |
| 18753 }, |
| 18754 |
| 18755 created: function() { |
| 18756 if (!Polymer.IronA11yAnnouncer.instance) { |
| 18757 Polymer.IronA11yAnnouncer.instance = this; |
| 18758 } |
| 18759 |
| 18760 document.body.addEventListener('iron-announce', this._onIronAnnounce.b
ind(this)); |
| 18761 }, |
| 18762 |
| 18763 /** |
| 18764 * Cause a text string to be announced by screen readers. |
| 18765 * |
| 18766 * @param {string} text The text that should be announced. |
| 18767 */ |
| 18768 announce: function(text) { |
| 18769 this._text = ''; |
| 18770 this.async(function() { |
| 18771 this._text = text; |
| 18772 }, 100); |
| 18773 }, |
| 18774 |
| 18775 _onIronAnnounce: function(event) { |
| 18776 if (event.detail && event.detail.text) { |
| 18777 this.announce(event.detail.text); |
| 18778 } |
| 18779 } |
| 18780 }); |
| 18781 |
| 18782 Polymer.IronA11yAnnouncer.instance = null; |
| 18783 |
| 18784 Polymer.IronA11yAnnouncer.requestAvailability = function() { |
| 18785 if (!Polymer.IronA11yAnnouncer.instance) { |
| 18786 Polymer.IronA11yAnnouncer.instance = document.createElement('iron-a11y
-announcer'); |
| 18787 } |
| 18788 |
| 18789 document.body.appendChild(Polymer.IronA11yAnnouncer.instance); |
| 18790 }; |
| 18791 })(); |
| 18792 |
| 18793 </script> |
| 18794 </dom-module> |
| 18795 <script> |
| 18796 |
| 18797 /* |
| 18798 `<iron-input>` adds two-way binding and custom validators using `Polymer.IronVal
idatorBehavior` |
| 18799 to `<input>`. |
| 18800 |
| 18801 ### Two-way binding |
| 18802 |
| 18803 By default you can only get notified of changes to an `input`'s `value` due to u
ser input: |
| 18804 |
| 18805 <input value="{{myValue::input}}"> |
| 18806 |
| 18807 `iron-input` adds the `bind-value` property that mirrors the `value` property, a
nd can be used |
| 18808 for two-way data binding. `bind-value` will notify if it is changed either by us
er input or by script. |
| 18809 |
| 18810 <input is="iron-input" bind-value="{{myValue}}"> |
| 18811 |
| 18812 ### Custom validators |
| 18813 |
| 18814 You can use custom validators that implement `Polymer.IronValidatorBehavior` wit
h `<iron-input>`. |
| 18815 |
| 18816 <input is="iron-input" validator="my-custom-validator"> |
| 18817 |
| 18818 ### Stopping invalid input |
| 18819 |
| 18820 It may be desirable to only allow users to enter certain characters. You can use
the |
| 18821 `prevent-invalid-input` and `allowed-pattern` attributes together to accomplish
this. This feature |
| 18822 is separate from validation, and `allowed-pattern` does not affect how the input
is validated. |
| 18823 |
| 18824 <!-- only allow characters that match [0-9] --> |
| 18825 <input is="iron-input" prevent-invalid-input allowed-pattern="[0-9]"> |
| 18826 |
| 18827 @hero hero.svg |
| 18828 @demo demo/index.html |
| 18829 */ |
| 18830 |
| 18831 Polymer({ |
| 18832 |
| 18833 is: 'iron-input', |
| 18834 |
| 18835 extends: 'input', |
| 18836 |
| 18837 behaviors: [ |
| 18838 Polymer.IronValidatableBehavior |
| 18839 ], |
| 18840 |
| 18841 properties: { |
| 18842 |
| 18843 /** |
| 18844 * Use this property instead of `value` for two-way data binding. |
| 18845 */ |
| 18846 bindValue: { |
| 18847 observer: '_bindValueChanged', |
| 18848 type: String |
| 18849 }, |
| 18850 |
| 18851 /** |
| 18852 * Set to true to prevent the user from entering invalid input. If `allowe
dPattern` is set, |
| 18853 * any character typed by the user will be matched against that pattern, a
nd rejected if it's not a match. |
| 18854 * Pasted input will have each character checked individually; if any char
acter |
| 18855 * doesn't match `allowedPattern`, the entire pasted string will be reject
ed. |
| 18856 * If `allowedPattern` is not set, it will use the `type` attribute (only
supported for `type=number`). |
| 18857 */ |
| 18858 preventInvalidInput: { |
| 18859 type: Boolean |
| 18860 }, |
| 18861 |
| 18862 /** |
| 18863 * Regular expression that list the characters allowed as input. |
| 18864 * This pattern represents the allowed characters for the field; as the us
er inputs text, |
| 18865 * each individual character will be checked against the pattern (rather t
han checking |
| 18866 * the entire value as a whole). The recommended format should be a list o
f allowed characters; |
| 18867 * for example, `[a-zA-Z0-9.+-!;:]` |
| 18868 */ |
| 18869 allowedPattern: { |
| 18870 type: String, |
| 18871 observer: "_allowedPatternChanged" |
| 18872 }, |
| 18873 |
| 18874 _previousValidInput: { |
| 18875 type: String, |
| 18876 value: '' |
| 18877 }, |
| 18878 |
| 18879 _patternAlreadyChecked: { |
| 18880 type: Boolean, |
| 18881 value: false |
| 18882 } |
| 18883 |
| 18884 }, |
| 18885 |
| 18886 listeners: { |
| 18887 'input': '_onInput', |
| 18888 'keypress': '_onKeypress' |
| 18889 }, |
| 18890 |
| 18891 /** @suppress {checkTypes} */ |
| 18892 registered: function() { |
| 18893 // Feature detect whether we need to patch dispatchEvent (i.e. on FF and I
E). |
| 18894 if (!this._canDispatchEventOnDisabled()) { |
| 18895 this._origDispatchEvent = this.dispatchEvent; |
| 18896 this.dispatchEvent = this._dispatchEventFirefoxIE; |
| 18897 } |
| 18898 }, |
| 18899 |
| 18900 created: function() { |
| 18901 Polymer.IronA11yAnnouncer.requestAvailability(); |
| 18902 }, |
| 18903 |
| 18904 _canDispatchEventOnDisabled: function() { |
| 18905 var input = document.createElement('input'); |
| 18906 var canDispatch = false; |
| 18907 input.disabled = true; |
| 18908 |
| 18909 input.addEventListener('feature-check-dispatch-event', function() { |
| 18910 canDispatch = true; |
| 18911 }); |
| 18912 |
| 18913 try { |
| 18914 input.dispatchEvent(new Event('feature-check-dispatch-event')); |
| 18915 } catch(e) {} |
| 18916 |
| 18917 return canDispatch; |
| 18918 }, |
| 18919 |
| 18920 _dispatchEventFirefoxIE: function() { |
| 18921 // Due to Firefox bug, events fired on disabled form controls can throw |
| 18922 // errors; furthermore, neither IE nor Firefox will actually dispatch |
| 18923 // events from disabled form controls; as such, we toggle disable around |
| 18924 // the dispatch to allow notifying properties to notify |
| 18925 // See issue #47 for details |
| 18926 var disabled = this.disabled; |
| 18927 this.disabled = false; |
| 18928 this._origDispatchEvent.apply(this, arguments); |
| 18929 this.disabled = disabled; |
| 18930 }, |
| 18931 |
| 18932 get _patternRegExp() { |
| 18933 var pattern; |
| 18934 if (this.allowedPattern) { |
| 18935 pattern = new RegExp(this.allowedPattern); |
| 18936 } else { |
| 18937 switch (this.type) { |
| 18938 case 'number': |
| 18939 pattern = /[0-9.,e-]/; |
| 18940 break; |
| 18941 } |
| 18942 } |
| 18943 return pattern; |
| 18944 }, |
| 18945 |
| 18946 ready: function() { |
| 18947 this.bindValue = this.value; |
| 18948 }, |
| 18949 |
| 18950 /** |
| 18951 * @suppress {checkTypes} |
| 18952 */ |
| 18953 _bindValueChanged: function() { |
| 18954 if (this.value !== this.bindValue) { |
| 18955 this.value = !(this.bindValue || this.bindValue === 0 || this.bindValue
=== false) ? '' : this.bindValue; |
| 18956 } |
| 18957 // manually notify because we don't want to notify until after setting val
ue |
| 18958 this.fire('bind-value-changed', {value: this.bindValue}); |
| 18959 }, |
| 18960 |
| 18961 _allowedPatternChanged: function() { |
| 18962 // Force to prevent invalid input when an `allowed-pattern` is set |
| 18963 this.preventInvalidInput = this.allowedPattern ? true : false; |
| 18964 }, |
| 18965 |
| 18966 _onInput: function() { |
| 18967 // Need to validate each of the characters pasted if they haven't |
| 18968 // been validated inside `_onKeypress` already. |
| 18969 if (this.preventInvalidInput && !this._patternAlreadyChecked) { |
| 18970 var valid = this._checkPatternValidity(); |
| 18971 if (!valid) { |
| 18972 this._announceInvalidCharacter('Invalid string of characters not enter
ed.'); |
| 18973 this.value = this._previousValidInput; |
| 18974 } |
| 18975 } |
| 18976 |
| 18977 this.bindValue = this.value; |
| 18978 this._previousValidInput = this.value; |
| 18979 this._patternAlreadyChecked = false; |
| 18980 }, |
| 18981 |
| 18982 _isPrintable: function(event) { |
| 18983 // What a control/printable character is varies wildly based on the browse
r. |
| 18984 // - most control characters (arrows, backspace) do not send a `keypress`
event |
| 18985 // in Chrome, but the *do* on Firefox |
| 18986 // - in Firefox, when they do send a `keypress` event, control chars have |
| 18987 // a charCode = 0, keyCode = xx (for ex. 40 for down arrow) |
| 18988 // - printable characters always send a keypress event. |
| 18989 // - in Firefox, printable chars always have a keyCode = 0. In Chrome, the
keyCode |
| 18990 // always matches the charCode. |
| 18991 // None of this makes any sense. |
| 18992 |
| 18993 // For these keys, ASCII code == browser keycode. |
| 18994 var anyNonPrintable = |
| 18995 (event.keyCode == 8) || // backspace |
| 18996 (event.keyCode == 9) || // tab |
| 18997 (event.keyCode == 13) || // enter |
| 18998 (event.keyCode == 27); // escape |
| 18999 |
| 19000 // For these keys, make sure it's a browser keycode and not an ASCII code. |
| 19001 var mozNonPrintable = |
| 19002 (event.keyCode == 19) || // pause |
| 19003 (event.keyCode == 20) || // caps lock |
| 19004 (event.keyCode == 45) || // insert |
| 19005 (event.keyCode == 46) || // delete |
| 19006 (event.keyCode == 144) || // num lock |
| 19007 (event.keyCode == 145) || // scroll lock |
| 19008 (event.keyCode > 32 && event.keyCode < 41) || // page up/down, end, ho
me, arrows |
| 19009 (event.keyCode > 111 && event.keyCode < 124); // fn keys |
| 19010 |
| 19011 return !anyNonPrintable && !(event.charCode == 0 && mozNonPrintable); |
| 19012 }, |
| 19013 |
| 19014 _onKeypress: function(event) { |
| 19015 if (!this.preventInvalidInput && this.type !== 'number') { |
| 19016 return; |
| 19017 } |
| 19018 var regexp = this._patternRegExp; |
| 19019 if (!regexp) { |
| 19020 return; |
| 19021 } |
| 19022 |
| 19023 // Handle special keys and backspace |
| 19024 if (event.metaKey || event.ctrlKey || event.altKey) |
| 19025 return; |
| 19026 |
| 19027 // Check the pattern either here or in `_onInput`, but not in both. |
| 19028 this._patternAlreadyChecked = true; |
| 19029 |
| 19030 var thisChar = String.fromCharCode(event.charCode); |
| 19031 if (this._isPrintable(event) && !regexp.test(thisChar)) { |
| 19032 event.preventDefault(); |
| 19033 this._announceInvalidCharacter('Invalid character ' + thisChar + ' not e
ntered.'); |
| 19034 } |
| 19035 }, |
| 19036 |
| 19037 _checkPatternValidity: function() { |
| 19038 var regexp = this._patternRegExp; |
| 19039 if (!regexp) { |
| 19040 return true; |
| 19041 } |
| 19042 for (var i = 0; i < this.value.length; i++) { |
| 19043 if (!regexp.test(this.value[i])) { |
| 19044 return false; |
| 19045 } |
| 19046 } |
| 19047 return true; |
| 19048 }, |
| 19049 |
| 19050 /** |
| 19051 * Returns true if `value` is valid. The validator provided in `validator` w
ill be used first, |
| 19052 * then any constraints. |
| 19053 * @return {boolean} True if the value is valid. |
| 19054 */ |
| 19055 validate: function() { |
| 19056 // First, check what the browser thinks. Some inputs (like type=number) |
| 19057 // behave weirdly and will set the value to "" if something invalid is |
| 19058 // entered, but will set the validity correctly. |
| 19059 var valid = this.checkValidity(); |
| 19060 |
| 19061 // Only do extra checking if the browser thought this was valid. |
| 19062 if (valid) { |
| 19063 // Empty, required input is invalid |
| 19064 if (this.required && this.value === '') { |
| 19065 valid = false; |
| 19066 } else if (this.hasValidator()) { |
| 19067 valid = Polymer.IronValidatableBehavior.validate.call(this, this.value
); |
| 19068 } |
| 19069 } |
| 19070 |
| 19071 this.invalid = !valid; |
| 19072 this.fire('iron-input-validate'); |
| 19073 return valid; |
| 19074 }, |
| 19075 |
| 19076 _announceInvalidCharacter: function(message) { |
| 19077 this.fire('iron-announce', { text: message }); |
| 19078 } |
| 19079 }); |
| 19080 |
| 19081 /* |
| 19082 The `iron-input-validate` event is fired whenever `validate()` is called. |
| 19083 @event iron-input-validate |
| 19084 */ |
| 19085 |
| 19086 </script> |
| 19087 <script> |
| 19088 |
| 19089 // Generate unique, monotonically increasing IDs for labels (needed by |
| 19090 // aria-labelledby) and add-ons. |
| 19091 Polymer.PaperInputHelper = {}; |
| 19092 Polymer.PaperInputHelper.NextLabelID = 1; |
| 19093 Polymer.PaperInputHelper.NextAddonID = 1; |
| 19094 |
| 19095 /** |
| 19096 * Use `Polymer.PaperInputBehavior` to implement inputs with `<paper-input-con
tainer>`. This |
| 19097 * behavior is implemented by `<paper-input>`. It exposes a number of properti
es from |
| 19098 * `<paper-input-container>` and `<input is="iron-input">` and they should be
bound in your |
| 19099 * template. |
| 19100 * |
| 19101 * The input element can be accessed by the `inputElement` property if you nee
d to access |
| 19102 * properties or methods that are not exposed. |
| 19103 * @polymerBehavior Polymer.PaperInputBehavior |
| 19104 */ |
| 19105 Polymer.PaperInputBehaviorImpl = { |
| 19106 |
| 19107 properties: { |
| 19108 /** |
| 19109 * Fired when the input changes due to user interaction. |
| 19110 * |
| 19111 * @event change |
| 19112 */ |
| 19113 |
| 19114 /** |
| 19115 * The label for this input. If you're using PaperInputBehavior to |
| 19116 * implement your own paper-input-like element, bind this to |
| 19117 * `<label>`'s content and `hidden` property, e.g. |
| 19118 * `<label hidden$="[[!label]]">[[label]]</label>` in your `template` |
| 19119 */ |
| 19120 label: { |
| 19121 type: String |
| 19122 }, |
| 19123 |
| 19124 /** |
| 19125 * The value for this input. If you're using PaperInputBehavior to |
| 19126 * implement your own paper-input-like element, bind this to |
| 19127 * the `<input is="iron-input">`'s `bindValue` |
| 19128 * property, or the value property of your input that is `notify:true`. |
| 19129 */ |
| 19130 value: { |
| 19131 notify: true, |
| 19132 type: String |
| 19133 }, |
| 19134 |
| 19135 /** |
| 19136 * Set to true to disable this input. If you're using PaperInputBehavior t
o |
| 19137 * implement your own paper-input-like element, bind this to |
| 19138 * both the `<paper-input-container>`'s and the input's `disabled` propert
y. |
| 19139 */ |
| 19140 disabled: { |
| 19141 type: Boolean, |
| 19142 value: false |
| 19143 }, |
| 19144 |
| 19145 /** |
| 19146 * Returns true if the value is invalid. If you're using PaperInputBehavio
r to |
| 19147 * implement your own paper-input-like element, bind this to both the |
| 19148 * `<paper-input-container>`'s and the input's `invalid` property. |
| 19149 * |
| 19150 * If `autoValidate` is true, the `invalid` attribute is managed automatic
ally, |
| 19151 * which can clobber attempts to manage it manually. |
| 19152 */ |
| 19153 invalid: { |
| 19154 type: Boolean, |
| 19155 value: false, |
| 19156 notify: true |
| 19157 }, |
| 19158 |
| 19159 /** |
| 19160 * Set to true to prevent the user from entering invalid input. If you're |
| 19161 * using PaperInputBehavior to implement your own paper-input-like elemen
t, |
| 19162 * bind this to `<input is="iron-input">`'s `preventInvalidInput` property
. |
| 19163 */ |
| 19164 preventInvalidInput: { |
| 19165 type: Boolean |
| 19166 }, |
| 19167 |
| 19168 /** |
| 19169 * Set this to specify the pattern allowed by `preventInvalidInput`. If |
| 19170 * you're using PaperInputBehavior to implement your own paper-input-like |
| 19171 * element, bind this to the `<input is="iron-input">`'s `allowedPattern` |
| 19172 * property. |
| 19173 */ |
| 19174 allowedPattern: { |
| 19175 type: String |
| 19176 }, |
| 19177 |
| 19178 /** |
| 19179 * The type of the input. The supported types are `text`, `number` and `pa
ssword`. |
| 19180 * If you're using PaperInputBehavior to implement your own paper-input-li
ke element, |
| 19181 * bind this to the `<input is="iron-input">`'s `type` property. |
| 19182 */ |
| 19183 type: { |
| 19184 type: String |
| 19185 }, |
| 19186 |
| 19187 /** |
| 19188 * The datalist of the input (if any). This should match the id of an exis
ting `<datalist>`. |
| 19189 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19190 * element, bind this to the `<input is="iron-input">`'s `list` property. |
| 19191 */ |
| 19192 list: { |
| 19193 type: String |
| 19194 }, |
| 19195 |
| 19196 /** |
| 19197 * A pattern to validate the `input` with. If you're using PaperInputBehav
ior to |
| 19198 * implement your own paper-input-like element, bind this to |
| 19199 * the `<input is="iron-input">`'s `pattern` property. |
| 19200 */ |
| 19201 pattern: { |
| 19202 type: String |
| 19203 }, |
| 19204 |
| 19205 /** |
| 19206 * Set to true to mark the input as required. If you're using PaperInputBe
havior to |
| 19207 * implement your own paper-input-like element, bind this to |
| 19208 * the `<input is="iron-input">`'s `required` property. |
| 19209 */ |
| 19210 required: { |
| 19211 type: Boolean, |
| 19212 value: false |
| 19213 }, |
| 19214 |
| 19215 /** |
| 19216 * The error message to display when the input is invalid. If you're using |
| 19217 * PaperInputBehavior to implement your own paper-input-like element, |
| 19218 * bind this to the `<paper-input-error>`'s content, if using. |
| 19219 */ |
| 19220 errorMessage: { |
| 19221 type: String |
| 19222 }, |
| 19223 |
| 19224 /** |
| 19225 * Set to true to show a character counter. |
| 19226 */ |
| 19227 charCounter: { |
| 19228 type: Boolean, |
| 19229 value: false |
| 19230 }, |
| 19231 |
| 19232 /** |
| 19233 * Set to true to disable the floating label. If you're using PaperInputBe
havior to |
| 19234 * implement your own paper-input-like element, bind this to |
| 19235 * the `<paper-input-container>`'s `noLabelFloat` property. |
| 19236 */ |
| 19237 noLabelFloat: { |
| 19238 type: Boolean, |
| 19239 value: false |
| 19240 }, |
| 19241 |
| 19242 /** |
| 19243 * Set to true to always float the label. If you're using PaperInputBehavi
or to |
| 19244 * implement your own paper-input-like element, bind this to |
| 19245 * the `<paper-input-container>`'s `alwaysFloatLabel` property. |
| 19246 */ |
| 19247 alwaysFloatLabel: { |
| 19248 type: Boolean, |
| 19249 value: false |
| 19250 }, |
| 19251 |
| 19252 /** |
| 19253 * Set to true to auto-validate the input value. If you're using PaperInpu
tBehavior to |
| 19254 * implement your own paper-input-like element, bind this to |
| 19255 * the `<paper-input-container>`'s `autoValidate` property. |
| 19256 */ |
| 19257 autoValidate: { |
| 19258 type: Boolean, |
| 19259 value: false |
| 19260 }, |
| 19261 |
| 19262 /** |
| 19263 * Name of the validator to use. If you're using PaperInputBehavior to |
| 19264 * implement your own paper-input-like element, bind this to |
| 19265 * the `<input is="iron-input">`'s `validator` property. |
| 19266 */ |
| 19267 validator: { |
| 19268 type: String |
| 19269 }, |
| 19270 |
| 19271 // HTMLInputElement attributes for binding if needed |
| 19272 |
| 19273 /** |
| 19274 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19275 * element, bind this to the `<input is="iron-input">`'s `autocomplete` pr
operty. |
| 19276 */ |
| 19277 autocomplete: { |
| 19278 type: String, |
| 19279 value: 'off' |
| 19280 }, |
| 19281 |
| 19282 /** |
| 19283 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19284 * element, bind this to the `<input is="iron-input">`'s `autofocus` prope
rty. |
| 19285 */ |
| 19286 autofocus: { |
| 19287 type: Boolean, |
| 19288 observer: '_autofocusChanged' |
| 19289 }, |
| 19290 |
| 19291 /** |
| 19292 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19293 * element, bind this to the `<input is="iron-input">`'s `inputmode` prope
rty. |
| 19294 */ |
| 19295 inputmode: { |
| 19296 type: String |
| 19297 }, |
| 19298 |
| 19299 /** |
| 19300 * The minimum length of the input value. |
| 19301 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19302 * element, bind this to the `<input is="iron-input">`'s `minlength` prope
rty. |
| 19303 */ |
| 19304 minlength: { |
| 19305 type: Number |
| 19306 }, |
| 19307 |
| 19308 /** |
| 19309 * The maximum length of the input value. |
| 19310 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19311 * element, bind this to the `<input is="iron-input">`'s `maxlength` prope
rty. |
| 19312 */ |
| 19313 maxlength: { |
| 19314 type: Number |
| 19315 }, |
| 19316 |
| 19317 /** |
| 19318 * The minimum (numeric or date-time) input value. |
| 19319 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19320 * element, bind this to the `<input is="iron-input">`'s `min` property. |
| 19321 */ |
| 19322 min: { |
| 19323 type: String |
| 19324 }, |
| 19325 |
| 19326 /** |
| 19327 * The maximum (numeric or date-time) input value. |
| 19328 * Can be a String (e.g. `"2000-1-1"`) or a Number (e.g. `2`). |
| 19329 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19330 * element, bind this to the `<input is="iron-input">`'s `max` property. |
| 19331 */ |
| 19332 max: { |
| 19333 type: String |
| 19334 }, |
| 19335 |
| 19336 /** |
| 19337 * Limits the numeric or date-time increments. |
| 19338 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19339 * element, bind this to the `<input is="iron-input">`'s `step` property. |
| 19340 */ |
| 19341 step: { |
| 19342 type: String |
| 19343 }, |
| 19344 |
| 19345 /** |
| 19346 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19347 * element, bind this to the `<input is="iron-input">`'s `name` property. |
| 19348 */ |
| 19349 name: { |
| 19350 type: String |
| 19351 }, |
| 19352 |
| 19353 /** |
| 19354 * A placeholder string in addition to the label. If this is set, the labe
l will always float. |
| 19355 */ |
| 19356 placeholder: { |
| 19357 type: String, |
| 19358 // need to set a default so _computeAlwaysFloatLabel is run |
| 19359 value: '' |
| 19360 }, |
| 19361 |
| 19362 /** |
| 19363 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19364 * element, bind this to the `<input is="iron-input">`'s `readonly` proper
ty. |
| 19365 */ |
| 19366 readonly: { |
| 19367 type: Boolean, |
| 19368 value: false |
| 19369 }, |
| 19370 |
| 19371 /** |
| 19372 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19373 * element, bind this to the `<input is="iron-input">`'s `size` property. |
| 19374 */ |
| 19375 size: { |
| 19376 type: Number |
| 19377 }, |
| 19378 |
| 19379 // Nonstandard attributes for binding if needed |
| 19380 |
| 19381 /** |
| 19382 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19383 * element, bind this to the `<input is="iron-input">`'s `autocapitalize`
property. |
| 19384 */ |
| 19385 autocapitalize: { |
| 19386 type: String, |
| 19387 value: 'none' |
| 19388 }, |
| 19389 |
| 19390 /** |
| 19391 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19392 * element, bind this to the `<input is="iron-input">`'s `autocorrect` pro
perty. |
| 19393 */ |
| 19394 autocorrect: { |
| 19395 type: String, |
| 19396 value: 'off' |
| 19397 }, |
| 19398 |
| 19399 /** |
| 19400 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19401 * element, bind this to the `<input is="iron-input">`'s `autosave` proper
ty, |
| 19402 * used with type=search. |
| 19403 */ |
| 19404 autosave: { |
| 19405 type: String |
| 19406 }, |
| 19407 |
| 19408 /** |
| 19409 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19410 * element, bind this to the `<input is="iron-input">`'s `results` propert
y, |
| 19411 * used with type=search. |
| 19412 */ |
| 19413 results: { |
| 19414 type: Number |
| 19415 }, |
| 19416 |
| 19417 /** |
| 19418 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19419 * element, bind this to the `<input is="iron-input">`'s `accept` property
, |
| 19420 * used with type=file. |
| 19421 */ |
| 19422 accept: { |
| 19423 type: String |
| 19424 }, |
| 19425 |
| 19426 /** |
| 19427 * If you're using PaperInputBehavior to implement your own paper-input-li
ke |
| 19428 * element, bind this to the`<input is="iron-input">`'s `multiple` propert
y, |
| 19429 * used with type=file. |
| 19430 */ |
| 19431 multiple: { |
| 19432 type: Boolean |
| 19433 }, |
| 19434 |
| 19435 _ariaDescribedBy: { |
| 19436 type: String, |
| 19437 value: '' |
| 19438 }, |
| 19439 |
| 19440 _ariaLabelledBy: { |
| 19441 type: String, |
| 19442 value: '' |
| 19443 } |
| 19444 |
| 19445 }, |
| 19446 |
| 19447 listeners: { |
| 19448 'addon-attached': '_onAddonAttached', |
| 19449 }, |
| 19450 |
| 19451 keyBindings: { |
| 19452 'shift+tab:keydown': '_onShiftTabDown' |
| 19453 }, |
| 19454 |
| 19455 hostAttributes: { |
| 19456 tabindex: 0 |
| 19457 }, |
| 19458 |
| 19459 /** |
| 19460 * Returns a reference to the input element. |
| 19461 */ |
| 19462 get inputElement() { |
| 19463 return this.$.input; |
| 19464 }, |
| 19465 |
| 19466 /** |
| 19467 * Returns a reference to the focusable element. |
| 19468 */ |
| 19469 get _focusableElement() { |
| 19470 return this.inputElement; |
| 19471 }, |
| 19472 |
| 19473 registered: function() { |
| 19474 // These types have some default placeholder text; overlapping |
| 19475 // the label on top of it looks terrible. Auto-float the label in this cas
e. |
| 19476 this._typesThatHaveText = ["date", "datetime", "datetime-local", "month", |
| 19477 "time", "week", "file"]; |
| 19478 }, |
| 19479 |
| 19480 attached: function() { |
| 19481 this._updateAriaLabelledBy(); |
| 19482 |
| 19483 if (this.inputElement && |
| 19484 this._typesThatHaveText.indexOf(this.inputElement.type) !== -1) { |
| 19485 this.alwaysFloatLabel = true; |
| 19486 } |
| 19487 }, |
| 19488 |
| 19489 _appendStringWithSpace: function(str, more) { |
| 19490 if (str) { |
| 19491 str = str + ' ' + more; |
| 19492 } else { |
| 19493 str = more; |
| 19494 } |
| 19495 return str; |
| 19496 }, |
| 19497 |
| 19498 _onAddonAttached: function(event) { |
| 19499 var target = event.path ? event.path[0] : event.target; |
| 19500 if (target.id) { |
| 19501 this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedB
y, target.id); |
| 19502 } else { |
| 19503 var id = 'paper-input-add-on-' + Polymer.PaperInputHelper.NextAddonID++; |
| 19504 target.id = id; |
| 19505 this._ariaDescribedBy = this._appendStringWithSpace(this._ariaDescribedB
y, id); |
| 19506 } |
| 19507 }, |
| 19508 |
| 19509 /** |
| 19510 * Validates the input element and sets an error style if needed. |
| 19511 * |
| 19512 * @return {boolean} |
| 19513 */ |
| 19514 validate: function() { |
| 19515 return this.inputElement.validate(); |
| 19516 }, |
| 19517 |
| 19518 /** |
| 19519 * Forward focus to inputElement. Overriden from IronControlState. |
| 19520 */ |
| 19521 _focusBlurHandler: function(event) { |
| 19522 Polymer.IronControlState._focusBlurHandler.call(this, event); |
| 19523 |
| 19524 // Forward the focus to the nested input. |
| 19525 if (this.focused && !this._shiftTabPressed) |
| 19526 this._focusableElement.focus(); |
| 19527 }, |
| 19528 |
| 19529 /** |
| 19530 * Handler that is called when a shift+tab keypress is detected by the menu. |
| 19531 * |
| 19532 * @param {CustomEvent} event A key combination event. |
| 19533 */ |
| 19534 _onShiftTabDown: function(event) { |
| 19535 var oldTabIndex = this.getAttribute('tabindex'); |
| 19536 this._shiftTabPressed = true; |
| 19537 this.setAttribute('tabindex', '-1'); |
| 19538 this.async(function() { |
| 19539 this.setAttribute('tabindex', oldTabIndex); |
| 19540 this._shiftTabPressed = false; |
| 19541 }, 1); |
| 19542 }, |
| 19543 |
| 19544 /** |
| 19545 * If `autoValidate` is true, then validates the element. |
| 19546 */ |
| 19547 _handleAutoValidate: function() { |
| 19548 if (this.autoValidate) |
| 19549 this.validate(); |
| 19550 }, |
| 19551 |
| 19552 /** |
| 19553 * Restores the cursor to its original position after updating the value. |
| 19554 * @param {string} newValue The value that should be saved. |
| 19555 */ |
| 19556 updateValueAndPreserveCaret: function(newValue) { |
| 19557 // Not all elements might have selection, and even if they have the |
| 19558 // right properties, accessing them might throw an exception (like for |
| 19559 // <input type=number>) |
| 19560 try { |
| 19561 var start = this.inputElement.selectionStart; |
| 19562 this.value = newValue; |
| 19563 |
| 19564 // The cursor automatically jumps to the end after re-setting the value, |
| 19565 // so restore it to its original position. |
| 19566 this.inputElement.selectionStart = start; |
| 19567 this.inputElement.selectionEnd = start; |
| 19568 } catch (e) { |
| 19569 // Just set the value and give up on the caret. |
| 19570 this.value = newValue; |
| 19571 } |
| 19572 }, |
| 19573 |
| 19574 _computeAlwaysFloatLabel: function(alwaysFloatLabel, placeholder) { |
| 19575 return placeholder || alwaysFloatLabel; |
| 19576 }, |
| 19577 |
| 19578 _updateAriaLabelledBy: function() { |
| 19579 var label = Polymer.dom(this.root).querySelector('label'); |
| 19580 if (!label) { |
| 19581 this._ariaLabelledBy = ''; |
| 19582 return; |
| 19583 } |
| 19584 var labelledBy; |
| 19585 if (label.id) { |
| 19586 labelledBy = label.id; |
| 19587 } else { |
| 19588 labelledBy = 'paper-input-label-' + Polymer.PaperInputHelper.NextLabelID
++; |
| 19589 label.id = labelledBy; |
| 19590 } |
| 19591 this._ariaLabelledBy = labelledBy; |
| 19592 }, |
| 19593 |
| 19594 _onChange:function(event) { |
| 19595 // In the Shadow DOM, the `change` event is not leaked into the |
| 19596 // ancestor tree, so we must do this manually. |
| 19597 // See https://w3c.github.io/webcomponents/spec/shadow/#events-that-are-no
t-leaked-into-ancestor-trees. |
| 19598 if (this.shadowRoot) { |
| 19599 this.fire(event.type, {sourceEvent: event}, { |
| 19600 node: this, |
| 19601 bubbles: event.bubbles, |
| 19602 cancelable: event.cancelable |
| 19603 }); |
| 19604 } |
| 19605 }, |
| 19606 |
| 19607 _autofocusChanged: function() { |
| 19608 // Firefox doesn't respect the autofocus attribute if it's applied after |
| 19609 // the page is loaded (Chrome/WebKit do respect it), preventing an |
| 19610 // autofocus attribute specified in markup from taking effect when the |
| 19611 // element is upgraded. As a workaround, if the autofocus property is set, |
| 19612 // and the focus hasn't already been moved elsewhere, we take focus. |
| 19613 if (this.autofocus && this._focusableElement) { |
| 19614 |
| 19615 // In IE 11, the default document.activeElement can be the page's |
| 19616 // outermost html element, but there are also cases (under the |
| 19617 // polyfill?) in which the activeElement is not a real HTMLElement, but |
| 19618 // just a plain object. We identify the latter case as having no valid |
| 19619 // activeElement. |
| 19620 var activeElement = document.activeElement; |
| 19621 var isActiveElementValid = activeElement instanceof HTMLElement; |
| 19622 |
| 19623 // Has some other element has already taken the focus? |
| 19624 var isSomeElementActive = isActiveElementValid && |
| 19625 activeElement !== document.body && |
| 19626 activeElement !== document.documentElement; /* IE 11 */ |
| 19627 if (!isSomeElementActive) { |
| 19628 // No specific element has taken the focus yet, so we can take it. |
| 19629 this._focusableElement.focus(); |
| 19630 } |
| 19631 } |
| 19632 } |
| 19633 } |
| 19634 |
| 19635 /** @polymerBehavior */ |
| 19636 Polymer.PaperInputBehavior = [ |
| 19637 Polymer.IronControlState, |
| 19638 Polymer.IronA11yKeysBehavior, |
| 19639 Polymer.PaperInputBehaviorImpl |
| 19640 ]; |
| 19641 </script> |
| 19642 <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,
300,300italic,400italic,500,500italic,700,700italic"> |
| 19643 <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono
:400,700"> |
| 19644 <style is="custom-style"> |
| 19645 |
| 19646 :root { |
| 19647 |
| 19648 /* Shared Styles */ |
| 19649 --paper-font-common-base: { |
| 19650 font-family: 'Roboto', 'Noto', sans-serif; |
| 19651 -webkit-font-smoothing: antialiased; |
| 19652 }; |
| 19653 |
| 19654 --paper-font-common-code: { |
| 19655 font-family: 'Roboto Mono', 'Consolas', 'Menlo', monospace; |
| 19656 -webkit-font-smoothing: antialiased; |
| 19657 }; |
| 19658 |
| 19659 --paper-font-common-expensive-kerning: { |
| 19660 text-rendering: optimizeLegibility; |
| 19661 }; |
| 19662 |
| 19663 --paper-font-common-nowrap: { |
| 19664 white-space: nowrap; |
| 19665 overflow: hidden; |
| 19666 text-overflow: ellipsis; |
| 19667 }; |
| 19668 |
| 19669 /* Material Font Styles */ |
| 19670 |
| 19671 --paper-font-display4: { |
| 19672 @apply(--paper-font-common-base); |
| 19673 @apply(--paper-font-common-nowrap); |
| 19674 |
| 19675 font-size: 112px; |
| 19676 font-weight: 300; |
| 19677 letter-spacing: -.044em; |
| 19678 line-height: 120px; |
| 19679 }; |
| 19680 |
| 19681 --paper-font-display3: { |
| 19682 @apply(--paper-font-common-base); |
| 19683 @apply(--paper-font-common-nowrap); |
| 19684 |
| 19685 font-size: 56px; |
| 19686 font-weight: 400; |
| 19687 letter-spacing: -.026em; |
| 19688 line-height: 60px; |
| 19689 }; |
| 19690 |
| 19691 --paper-font-display2: { |
| 19692 @apply(--paper-font-common-base); |
| 19693 |
| 19694 font-size: 45px; |
| 19695 font-weight: 400; |
| 19696 letter-spacing: -.018em; |
| 19697 line-height: 48px; |
| 19698 }; |
| 19699 |
| 19700 --paper-font-display1: { |
| 19701 @apply(--paper-font-common-base); |
| 19702 |
| 19703 font-size: 34px; |
| 19704 font-weight: 400; |
| 19705 letter-spacing: -.01em; |
| 19706 line-height: 40px; |
| 19707 }; |
| 19708 |
| 19709 --paper-font-headline: { |
| 19710 @apply(--paper-font-common-base); |
| 19711 |
| 19712 font-size: 24px; |
| 19713 font-weight: 400; |
| 19714 letter-spacing: -.012em; |
| 19715 line-height: 32px; |
| 19716 }; |
| 19717 |
| 19718 --paper-font-title: { |
| 19719 @apply(--paper-font-common-base); |
| 19720 @apply(--paper-font-common-nowrap); |
| 19721 |
| 19722 font-size: 20px; |
| 19723 font-weight: 500; |
| 19724 line-height: 28px; |
| 19725 }; |
| 19726 |
| 19727 --paper-font-subhead: { |
| 19728 @apply(--paper-font-common-base); |
| 19729 |
| 19730 font-size: 16px; |
| 19731 font-weight: 400; |
| 19732 line-height: 24px; |
| 19733 }; |
| 19734 |
| 19735 --paper-font-body2: { |
| 19736 @apply(--paper-font-common-base); |
| 19737 |
| 19738 font-size: 14px; |
| 19739 font-weight: 500; |
| 19740 line-height: 24px; |
| 19741 }; |
| 19742 |
| 19743 --paper-font-body1: { |
| 19744 @apply(--paper-font-common-base); |
| 19745 |
| 19746 font-size: 14px; |
| 19747 font-weight: 400; |
| 19748 line-height: 20px; |
| 19749 }; |
| 19750 |
| 19751 --paper-font-caption: { |
| 19752 @apply(--paper-font-common-base); |
| 19753 @apply(--paper-font-common-nowrap); |
| 19754 |
| 19755 font-size: 12px; |
| 19756 font-weight: 400; |
| 19757 letter-spacing: 0.011em; |
| 19758 line-height: 20px; |
| 19759 }; |
| 19760 |
| 19761 --paper-font-menu: { |
| 19762 @apply(--paper-font-common-base); |
| 19763 @apply(--paper-font-common-nowrap); |
| 19764 |
| 19765 font-size: 13px; |
| 19766 font-weight: 500; |
| 19767 line-height: 24px; |
| 19768 }; |
| 19769 |
| 19770 --paper-font-button: { |
| 19771 @apply(--paper-font-common-base); |
| 19772 @apply(--paper-font-common-nowrap); |
| 19773 |
| 19774 font-size: 14px; |
| 19775 font-weight: 500; |
| 19776 letter-spacing: 0.018em; |
| 19777 line-height: 24px; |
| 19778 text-transform: uppercase; |
| 19779 }; |
| 19780 |
| 19781 --paper-font-code2: { |
| 19782 @apply(--paper-font-common-code); |
| 19783 |
| 19784 font-size: 14px; |
| 19785 font-weight: 700; |
| 19786 line-height: 20px; |
| 19787 }; |
| 19788 |
| 19789 --paper-font-code1: { |
| 19790 @apply(--paper-font-common-code); |
| 19791 |
| 19792 font-size: 14px; |
| 19793 font-weight: 500; |
| 19794 line-height: 20px; |
| 19795 }; |
| 19796 |
| 19797 } |
| 19798 |
| 19799 </style> |
| 19800 <script> |
| 19801 |
| 19802 /** |
| 19803 * Use `Polymer.PaperInputAddonBehavior` to implement an add-on for `<paper-in
put-container>`. A |
| 19804 * add-on appears below the input, and may display information based on the in
put value and |
| 19805 * validity such as a character counter or an error message. |
| 19806 * @polymerBehavior |
| 19807 */ |
| 19808 Polymer.PaperInputAddonBehavior = { |
| 19809 |
| 19810 hostAttributes: { |
| 19811 'add-on': '' |
| 19812 }, |
| 19813 |
| 19814 attached: function() { |
| 19815 this.fire('addon-attached'); |
| 19816 }, |
| 19817 |
| 19818 /** |
| 19819 * The function called by `<paper-input-container>` when the input value or
validity changes. |
| 19820 * @param {{ |
| 19821 * inputElement: (Element|undefined), |
| 19822 * value: (string|undefined), |
| 19823 * invalid: boolean |
| 19824 * }} state - |
| 19825 * inputElement: The input element. |
| 19826 * value: The input value. |
| 19827 * invalid: True if the input value is invalid. |
| 19828 */ |
| 19829 update: function(state) { |
| 19830 } |
| 19831 |
| 19832 }; |
| 19833 |
| 19834 </script> |
| 19835 |
| 19836 |
| 19837 <dom-module id="paper-input-char-counter" assetpath="/res/imp/bower_components/p
aper-input/"> |
| 19838 <template> |
| 19839 <style> |
| 19840 :host { |
| 19841 display: inline-block; |
| 19842 float: right; |
| 19843 |
| 19844 @apply(--paper-font-caption); |
| 19845 @apply(--paper-input-char-counter); |
| 19846 } |
| 19847 |
| 19848 :host([hidden]) { |
| 19849 display: none !important; |
| 19850 } |
| 19851 |
| 19852 :host-context([dir="rtl"]) { |
| 19853 float: left; |
| 19854 } |
| 19855 </style> |
| 19856 |
| 19857 <span>[[_charCounterStr]]</span> |
| 19858 </template> |
| 19859 </dom-module> |
| 19860 |
| 19861 <script> |
| 19862 Polymer({ |
| 19863 is: 'paper-input-char-counter', |
| 19864 |
| 19865 behaviors: [ |
| 19866 Polymer.PaperInputAddonBehavior |
| 19867 ], |
| 19868 |
| 19869 properties: { |
| 19870 _charCounterStr: { |
| 19871 type: String, |
| 19872 value: '0' |
| 19873 } |
| 19874 }, |
| 19875 |
| 19876 /** |
| 19877 * This overrides the update function in PaperInputAddonBehavior. |
| 19878 * @param {{ |
| 19879 * inputElement: (Element|undefined), |
| 19880 * value: (string|undefined), |
| 19881 * invalid: boolean |
| 19882 * }} state - |
| 19883 * inputElement: The input element. |
| 19884 * value: The input value. |
| 19885 * invalid: True if the input value is invalid. |
| 19886 */ |
| 19887 update: function(state) { |
| 19888 if (!state.inputElement) { |
| 19889 return; |
| 19890 } |
| 19891 |
| 19892 state.value = state.value || ''; |
| 19893 |
| 19894 var counter = state.value.toString().length.toString(); |
| 19895 |
| 19896 if (state.inputElement.hasAttribute('maxlength')) { |
| 19897 counter += '/' + state.inputElement.getAttribute('maxlength'); |
| 19898 } |
| 19899 |
| 19900 this._charCounterStr = counter; |
| 19901 } |
| 19902 }); |
| 19903 </script> |
| 19904 |
| 19905 |
| 19906 <dom-module id="paper-input-container" assetpath="/res/imp/bower_components/pape
r-input/"> |
| 19907 <template> |
| 19908 <style> |
| 19909 :host { |
| 19910 display: block; |
| 19911 padding: 8px 0; |
| 19912 |
| 19913 @apply(--paper-input-container); |
| 19914 } |
| 19915 |
| 19916 :host([inline]) { |
| 19917 display: inline-block; |
| 19918 } |
| 19919 |
| 19920 :host([disabled]) { |
| 19921 pointer-events: none; |
| 19922 opacity: 0.33; |
| 19923 |
| 19924 @apply(--paper-input-container-disabled); |
| 19925 } |
| 19926 |
| 19927 :host([hidden]) { |
| 19928 display: none !important; |
| 19929 } |
| 19930 |
| 19931 .floated-label-placeholder { |
| 19932 @apply(--paper-font-caption); |
| 19933 } |
| 19934 |
| 19935 .underline { |
| 19936 position: relative; |
| 19937 } |
| 19938 |
| 19939 .focused-line { |
| 19940 @apply(--layout-fit); |
| 19941 |
| 19942 background: var(--paper-input-container-focus-color, --primary-color); |
| 19943 height: 2px; |
| 19944 |
| 19945 -webkit-transform-origin: center center; |
| 19946 transform-origin: center center; |
| 19947 -webkit-transform: scale3d(0,1,1); |
| 19948 transform: scale3d(0,1,1); |
| 19949 |
| 19950 @apply(--paper-input-container-underline-focus); |
| 19951 } |
| 19952 |
| 19953 .underline.is-highlighted .focused-line { |
| 19954 -webkit-transform: none; |
| 19955 transform: none; |
| 19956 -webkit-transition: -webkit-transform 0.25s; |
| 19957 transition: transform 0.25s; |
| 19958 |
| 19959 @apply(--paper-transition-easing); |
| 19960 } |
| 19961 |
| 19962 .underline.is-invalid .focused-line { |
| 19963 background: var(--paper-input-container-invalid-color, --error-color); |
| 19964 -webkit-transform: none; |
| 19965 transform: none; |
| 19966 -webkit-transition: -webkit-transform 0.25s; |
| 19967 transition: transform 0.25s; |
| 19968 |
| 19969 @apply(--paper-transition-easing); |
| 19970 } |
| 19971 |
| 19972 .unfocused-line { |
| 19973 @apply(--layout-fit); |
| 19974 |
| 19975 background: var(--paper-input-container-color, --secondary-text-color); |
| 19976 height: 1px; |
| 19977 |
| 19978 @apply(--paper-input-container-underline); |
| 19979 } |
| 19980 |
| 19981 :host([disabled]) .unfocused-line { |
| 19982 border-bottom: 1px dashed; |
| 19983 border-color: var(--paper-input-container-color, --secondary-text-color)
; |
| 19984 background: transparent; |
| 19985 |
| 19986 @apply(--paper-input-container-underline-disabled); |
| 19987 } |
| 19988 |
| 19989 .label-and-input-container { |
| 19990 @apply(--layout-flex-auto); |
| 19991 @apply(--layout-relative); |
| 19992 |
| 19993 width: 100%; |
| 19994 max-width: 100%; |
| 19995 } |
| 19996 |
| 19997 .input-content { |
| 19998 @apply(--layout-horizontal); |
| 19999 @apply(--layout-center); |
| 20000 |
| 20001 position: relative; |
| 20002 } |
| 20003 |
| 20004 .input-content ::content label, |
| 20005 .input-content ::content .paper-input-label { |
| 20006 position: absolute; |
| 20007 top: 0; |
| 20008 right: 0; |
| 20009 left: 0; |
| 20010 width: 100%; |
| 20011 font: inherit; |
| 20012 color: var(--paper-input-container-color, --secondary-text-color); |
| 20013 -webkit-transition: -webkit-transform 0.25s, width 0.25s; |
| 20014 transition: transform 0.25s, width 0.25s; |
| 20015 -webkit-transform-origin: left top; |
| 20016 transform-origin: left top; |
| 20017 |
| 20018 @apply(--paper-font-common-nowrap); |
| 20019 @apply(--paper-font-subhead); |
| 20020 @apply(--paper-input-container-label); |
| 20021 @apply(--paper-transition-easing); |
| 20022 } |
| 20023 |
| 20024 .input-content.label-is-floating ::content label, |
| 20025 .input-content.label-is-floating ::content .paper-input-label { |
| 20026 -webkit-transform: translateY(-75%) scale(0.75); |
| 20027 transform: translateY(-75%) scale(0.75); |
| 20028 |
| 20029 /* Since we scale to 75/100 of the size, we actually have 100/75 of the |
| 20030 original space now available */ |
| 20031 width: 133%; |
| 20032 |
| 20033 @apply(--paper-input-container-label-floating); |
| 20034 } |
| 20035 |
| 20036 :host-context([dir="rtl"]) .input-content.label-is-floating ::content labe
l, |
| 20037 :host-context([dir="rtl"]) .input-content.label-is-floating ::content .pap
er-input-label { |
| 20038 /* TODO(noms): Figure out why leaving the width at 133% before the anima
tion |
| 20039 * actually makes |
| 20040 * it wider on the right side, not left side, as you would expect in RTL
*/ |
| 20041 width: 100%; |
| 20042 -webkit-transform-origin: right top; |
| 20043 transform-origin: right top; |
| 20044 } |
| 20045 |
| 20046 .input-content.label-is-highlighted ::content label, |
| 20047 .input-content.label-is-highlighted ::content .paper-input-label { |
| 20048 color: var(--paper-input-container-focus-color, --primary-color); |
| 20049 |
| 20050 @apply(--paper-input-container-label-focus); |
| 20051 } |
| 20052 |
| 20053 .input-content.is-invalid ::content label, |
| 20054 .input-content.is-invalid ::content .paper-input-label { |
| 20055 color: var(--paper-input-container-invalid-color, --error-color); |
| 20056 } |
| 20057 |
| 20058 .input-content.label-is-hidden ::content label, |
| 20059 .input-content.label-is-hidden ::content .paper-input-label { |
| 20060 visibility: hidden; |
| 20061 } |
| 20062 |
| 20063 .input-content ::content input, |
| 20064 .input-content ::content textarea, |
| 20065 .input-content ::content iron-autogrow-textarea, |
| 20066 .input-content ::content .paper-input-input { |
| 20067 position: relative; /* to make a stacking context */ |
| 20068 outline: none; |
| 20069 box-shadow: none; |
| 20070 padding: 0; |
| 20071 width: 100%; |
| 20072 max-width: 100%; |
| 20073 background: transparent; |
| 20074 border: none; |
| 20075 color: var(--paper-input-container-input-color, --primary-text-color); |
| 20076 -webkit-appearance: none; |
| 20077 text-align: inherit; |
| 20078 |
| 20079 @apply(--paper-font-subhead); |
| 20080 @apply(--paper-input-container-input); |
| 20081 } |
| 20082 |
| 20083 ::content [prefix] { |
| 20084 @apply(--paper-font-subhead); |
| 20085 |
| 20086 @apply(--paper-input-prefix); |
| 20087 @apply(--layout-flex-none); |
| 20088 } |
| 20089 |
| 20090 ::content [suffix] { |
| 20091 @apply(--paper-font-subhead); |
| 20092 |
| 20093 @apply(--paper-input-suffix); |
| 20094 @apply(--layout-flex-none); |
| 20095 } |
| 20096 |
| 20097 /* Firefox sets a min-width on the input, which can cause layout issues */ |
| 20098 .input-content ::content input { |
| 20099 min-width: 0; |
| 20100 } |
| 20101 |
| 20102 .input-content ::content textarea { |
| 20103 resize: none; |
| 20104 } |
| 20105 |
| 20106 .add-on-content { |
| 20107 position: relative; |
| 20108 } |
| 20109 |
| 20110 .add-on-content.is-invalid ::content * { |
| 20111 color: var(--paper-input-container-invalid-color, --error-color); |
| 20112 } |
| 20113 |
| 20114 .add-on-content.is-highlighted ::content * { |
| 20115 color: var(--paper-input-container-focus-color, --primary-color); |
| 20116 } |
| 20117 </style> |
| 20118 |
| 20119 <template is="dom-if" if="[[!noLabelFloat]]"> |
| 20120 <div class="floated-label-placeholder" aria-hidden="true"> </div> |
| 20121 </template> |
| 20122 |
| 20123 <div class$="[[_computeInputContentClass(noLabelFloat,alwaysFloatLabel,focus
ed,invalid,_inputHasContent)]]"> |
| 20124 <content select="[prefix]" id="prefix"></content> |
| 20125 |
| 20126 <div class="label-and-input-container" id="labelAndInputContainer"> |
| 20127 <content select=":not([add-on]):not([prefix]):not([suffix])"></content> |
| 20128 </div> |
| 20129 |
| 20130 <content select="[suffix]"></content> |
| 20131 </div> |
| 20132 |
| 20133 <div class$="[[_computeUnderlineClass(focused,invalid)]]"> |
| 20134 <div class="unfocused-line"></div> |
| 20135 <div class="focused-line"></div> |
| 20136 </div> |
| 20137 |
| 20138 <div class$="[[_computeAddOnContentClass(focused,invalid)]]"> |
| 20139 <content id="addOnContent" select="[add-on]"></content> |
| 20140 </div> |
| 20141 </template> |
| 20142 </dom-module> |
| 20143 |
| 20144 <script> |
| 20145 Polymer({ |
| 20146 is: 'paper-input-container', |
| 20147 |
| 20148 properties: { |
| 20149 /** |
| 20150 * Set to true to disable the floating label. The label disappears when th
e input value is |
| 20151 * not null. |
| 20152 */ |
| 20153 noLabelFloat: { |
| 20154 type: Boolean, |
| 20155 value: false |
| 20156 }, |
| 20157 |
| 20158 /** |
| 20159 * Set to true to always float the floating label. |
| 20160 */ |
| 20161 alwaysFloatLabel: { |
| 20162 type: Boolean, |
| 20163 value: false |
| 20164 }, |
| 20165 |
| 20166 /** |
| 20167 * The attribute to listen for value changes on. |
| 20168 */ |
| 20169 attrForValue: { |
| 20170 type: String, |
| 20171 value: 'bind-value' |
| 20172 }, |
| 20173 |
| 20174 /** |
| 20175 * Set to true to auto-validate the input value when it changes. |
| 20176 */ |
| 20177 autoValidate: { |
| 20178 type: Boolean, |
| 20179 value: false |
| 20180 }, |
| 20181 |
| 20182 /** |
| 20183 * True if the input is invalid. This property is set automatically when t
he input value |
| 20184 * changes if auto-validating, or when the `iron-input-validate` event is
heard from a child. |
| 20185 */ |
| 20186 invalid: { |
| 20187 observer: '_invalidChanged', |
| 20188 type: Boolean, |
| 20189 value: false |
| 20190 }, |
| 20191 |
| 20192 /** |
| 20193 * True if the input has focus. |
| 20194 */ |
| 20195 focused: { |
| 20196 readOnly: true, |
| 20197 type: Boolean, |
| 20198 value: false, |
| 20199 notify: true |
| 20200 }, |
| 20201 |
| 20202 _addons: { |
| 20203 type: Array |
| 20204 // do not set a default value here intentionally - it will be initialize
d lazily when a |
| 20205 // distributed child is attached, which may occur before configuration f
or this element |
| 20206 // in polyfill. |
| 20207 }, |
| 20208 |
| 20209 _inputHasContent: { |
| 20210 type: Boolean, |
| 20211 value: false |
| 20212 }, |
| 20213 |
| 20214 _inputSelector: { |
| 20215 type: String, |
| 20216 value: 'input,textarea,.paper-input-input' |
| 20217 }, |
| 20218 |
| 20219 _boundOnFocus: { |
| 20220 type: Function, |
| 20221 value: function() { |
| 20222 return this._onFocus.bind(this); |
| 20223 } |
| 20224 }, |
| 20225 |
| 20226 _boundOnBlur: { |
| 20227 type: Function, |
| 20228 value: function() { |
| 20229 return this._onBlur.bind(this); |
| 20230 } |
| 20231 }, |
| 20232 |
| 20233 _boundOnInput: { |
| 20234 type: Function, |
| 20235 value: function() { |
| 20236 return this._onInput.bind(this); |
| 20237 } |
| 20238 }, |
| 20239 |
| 20240 _boundValueChanged: { |
| 20241 type: Function, |
| 20242 value: function() { |
| 20243 return this._onValueChanged.bind(this); |
| 20244 } |
| 20245 } |
| 20246 }, |
| 20247 |
| 20248 listeners: { |
| 20249 'addon-attached': '_onAddonAttached', |
| 20250 'iron-input-validate': '_onIronInputValidate' |
| 20251 }, |
| 20252 |
| 20253 get _valueChangedEvent() { |
| 20254 return this.attrForValue + '-changed'; |
| 20255 }, |
| 20256 |
| 20257 get _propertyForValue() { |
| 20258 return Polymer.CaseMap.dashToCamelCase(this.attrForValue); |
| 20259 }, |
| 20260 |
| 20261 get _inputElement() { |
| 20262 return Polymer.dom(this).querySelector(this._inputSelector); |
| 20263 }, |
| 20264 |
| 20265 get _inputElementValue() { |
| 20266 return this._inputElement[this._propertyForValue] || this._inputElement.va
lue; |
| 20267 }, |
| 20268 |
| 20269 ready: function() { |
| 20270 if (!this._addons) { |
| 20271 this._addons = []; |
| 20272 } |
| 20273 this.addEventListener('focus', this._boundOnFocus, true); |
| 20274 this.addEventListener('blur', this._boundOnBlur, true); |
| 20275 }, |
| 20276 |
| 20277 attached: function() { |
| 20278 if (this.attrForValue) { |
| 20279 this._inputElement.addEventListener(this._valueChangedEvent, this._bound
ValueChanged); |
| 20280 } else { |
| 20281 this.addEventListener('input', this._onInput); |
| 20282 } |
| 20283 |
| 20284 // Only validate when attached if the input already has a value. |
| 20285 if (this._inputElementValue != '') { |
| 20286 this._handleValueAndAutoValidate(this._inputElement); |
| 20287 } else { |
| 20288 this._handleValue(this._inputElement); |
| 20289 } |
| 20290 }, |
| 20291 |
| 20292 _onAddonAttached: function(event) { |
| 20293 if (!this._addons) { |
| 20294 this._addons = []; |
| 20295 } |
| 20296 var target = event.target; |
| 20297 if (this._addons.indexOf(target) === -1) { |
| 20298 this._addons.push(target); |
| 20299 if (this.isAttached) { |
| 20300 this._handleValue(this._inputElement); |
| 20301 } |
| 20302 } |
| 20303 }, |
| 20304 |
| 20305 _onFocus: function() { |
| 20306 this._setFocused(true); |
| 20307 }, |
| 20308 |
| 20309 _onBlur: function() { |
| 20310 this._setFocused(false); |
| 20311 this._handleValueAndAutoValidate(this._inputElement); |
| 20312 }, |
| 20313 |
| 20314 _onInput: function(event) { |
| 20315 this._handleValueAndAutoValidate(event.target); |
| 20316 }, |
| 20317 |
| 20318 _onValueChanged: function(event) { |
| 20319 this._handleValueAndAutoValidate(event.target); |
| 20320 }, |
| 20321 |
| 20322 _handleValue: function(inputElement) { |
| 20323 var value = this._inputElementValue; |
| 20324 |
| 20325 // type="number" hack needed because this.value is empty until it's valid |
| 20326 if (value || value === 0 || (inputElement.type === 'number' && !inputEleme
nt.checkValidity())) { |
| 20327 this._inputHasContent = true; |
| 20328 } else { |
| 20329 this._inputHasContent = false; |
| 20330 } |
| 20331 |
| 20332 this.updateAddons({ |
| 20333 inputElement: inputElement, |
| 20334 value: value, |
| 20335 invalid: this.invalid |
| 20336 }); |
| 20337 }, |
| 20338 |
| 20339 _handleValueAndAutoValidate: function(inputElement) { |
| 20340 if (this.autoValidate) { |
| 20341 var valid; |
| 20342 if (inputElement.validate) { |
| 20343 valid = inputElement.validate(this._inputElementValue); |
| 20344 } else { |
| 20345 valid = inputElement.checkValidity(); |
| 20346 } |
| 20347 this.invalid = !valid; |
| 20348 } |
| 20349 |
| 20350 // Call this last to notify the add-ons. |
| 20351 this._handleValue(inputElement); |
| 20352 }, |
| 20353 |
| 20354 _onIronInputValidate: function(event) { |
| 20355 this.invalid = this._inputElement.invalid; |
| 20356 }, |
| 20357 |
| 20358 _invalidChanged: function() { |
| 20359 if (this._addons) { |
| 20360 this.updateAddons({invalid: this.invalid}); |
| 20361 } |
| 20362 }, |
| 20363 |
| 20364 /** |
| 20365 * Call this to update the state of add-ons. |
| 20366 * @param {Object} state Add-on state. |
| 20367 */ |
| 20368 updateAddons: function(state) { |
| 20369 for (var addon, index = 0; addon = this._addons[index]; index++) { |
| 20370 addon.update(state); |
| 20371 } |
| 20372 }, |
| 20373 |
| 20374 _computeInputContentClass: function(noLabelFloat, alwaysFloatLabel, focused,
invalid, _inputHasContent) { |
| 20375 var cls = 'input-content'; |
| 20376 if (!noLabelFloat) { |
| 20377 var label = this.querySelector('label'); |
| 20378 |
| 20379 if (alwaysFloatLabel || _inputHasContent) { |
| 20380 cls += ' label-is-floating'; |
| 20381 // If the label is floating, ignore any offsets that may have been |
| 20382 // applied from a prefix element. |
| 20383 this.$.labelAndInputContainer.style.position = 'static'; |
| 20384 |
| 20385 if (invalid) { |
| 20386 cls += ' is-invalid'; |
| 20387 } else if (focused) { |
| 20388 cls += " label-is-highlighted"; |
| 20389 } |
| 20390 } else { |
| 20391 // When the label is not floating, it should overlap the input element
. |
| 20392 if (label) { |
| 20393 this.$.labelAndInputContainer.style.position = 'relative'; |
| 20394 } |
| 20395 } |
| 20396 } else { |
| 20397 if (_inputHasContent) { |
| 20398 cls += ' label-is-hidden'; |
| 20399 } |
| 20400 } |
| 20401 return cls; |
| 20402 }, |
| 20403 |
| 20404 _computeUnderlineClass: function(focused, invalid) { |
| 20405 var cls = 'underline'; |
| 20406 if (invalid) { |
| 20407 cls += ' is-invalid'; |
| 20408 } else if (focused) { |
| 20409 cls += ' is-highlighted' |
| 20410 } |
| 20411 return cls; |
| 20412 }, |
| 20413 |
| 20414 _computeAddOnContentClass: function(focused, invalid) { |
| 20415 var cls = 'add-on-content'; |
| 20416 if (invalid) { |
| 20417 cls += ' is-invalid'; |
| 20418 } else if (focused) { |
| 20419 cls += ' is-highlighted' |
| 20420 } |
| 20421 return cls; |
| 20422 } |
| 20423 }); |
| 20424 </script> |
| 20425 |
| 20426 |
| 20427 <dom-module id="paper-input-error" assetpath="/res/imp/bower_components/paper-in
put/"> |
| 20428 <template> |
| 20429 <style> |
| 20430 :host { |
| 20431 display: inline-block; |
| 20432 visibility: hidden; |
| 20433 |
| 20434 color: var(--paper-input-container-invalid-color, --error-color); |
| 20435 |
| 20436 @apply(--paper-font-caption); |
| 20437 @apply(--paper-input-error); |
| 20438 position: absolute; |
| 20439 left:0; |
| 20440 right:0; |
| 20441 } |
| 20442 |
| 20443 :host([invalid]) { |
| 20444 visibility: visible; |
| 20445 }; |
| 20446 </style> |
| 20447 |
| 20448 <content></content> |
| 20449 </template> |
| 20450 </dom-module> |
| 20451 |
| 20452 <script> |
| 20453 Polymer({ |
| 20454 is: 'paper-input-error', |
| 20455 |
| 20456 behaviors: [ |
| 20457 Polymer.PaperInputAddonBehavior |
| 20458 ], |
| 20459 |
| 20460 properties: { |
| 20461 /** |
| 20462 * True if the error is showing. |
| 20463 */ |
| 20464 invalid: { |
| 20465 readOnly: true, |
| 20466 reflectToAttribute: true, |
| 20467 type: Boolean |
| 20468 } |
| 20469 }, |
| 20470 |
| 20471 /** |
| 20472 * This overrides the update function in PaperInputAddonBehavior. |
| 20473 * @param {{ |
| 20474 * inputElement: (Element|undefined), |
| 20475 * value: (string|undefined), |
| 20476 * invalid: boolean |
| 20477 * }} state - |
| 20478 * inputElement: The input element. |
| 20479 * value: The input value. |
| 20480 * invalid: True if the input value is invalid. |
| 20481 */ |
| 20482 update: function(state) { |
| 20483 this._setInvalid(state.invalid); |
| 20484 } |
| 20485 }); |
| 20486 </script> |
| 20487 |
| 20488 |
| 20489 <dom-module id="paper-input" assetpath="/res/imp/bower_components/paper-input/"> |
| 20490 <template> |
| 20491 <style> |
| 20492 :host { |
| 20493 display: block; |
| 20494 } |
| 20495 |
| 20496 :host([hidden]) { |
| 20497 display: none !important; |
| 20498 } |
| 20499 |
| 20500 input::-webkit-input-placeholder { |
| 20501 color: var(--paper-input-container-color, --secondary-text-color); |
| 20502 } |
| 20503 |
| 20504 input:-moz-placeholder { |
| 20505 color: var(--paper-input-container-color, --secondary-text-color); |
| 20506 } |
| 20507 |
| 20508 input::-moz-placeholder { |
| 20509 color: var(--paper-input-container-color, --secondary-text-color); |
| 20510 } |
| 20511 |
| 20512 input:-ms-input-placeholder { |
| 20513 color: var(--paper-input-container-color, --secondary-text-color); |
| 20514 } |
| 20515 </style> |
| 20516 |
| 20517 <paper-input-container no-label-float="[[noLabelFloat]]" always-float-label=
"[[_computeAlwaysFloatLabel(alwaysFloatLabel,placeholder)]]" auto-validate$="[[a
utoValidate]]" disabled$="[[disabled]]" invalid="[[invalid]]"> |
| 20518 |
| 20519 <content select="[prefix]"></content> |
| 20520 |
| 20521 <label hidden$="[[!label]]" aria-hidden="true" for="input">[[label]]</labe
l> |
| 20522 |
| 20523 <input is="iron-input" id="input" aria-labelledby$="[[_ariaLabelledBy]]" a
ria-describedby$="[[_ariaDescribedBy]]" disabled$="[[disabled]]" title$="[[title
]]" bind-value="{{value}}" invalid="{{invalid}}" prevent-invalid-input="[[preven
tInvalidInput]]" allowed-pattern="[[allowedPattern]]" validator="[[validator]]"
type$="[[type]]" pattern$="[[pattern]]" required$="[[required]]" autocomplete$="
[[autocomplete]]" autofocus$="[[autofocus]]" inputmode$="[[inputmode]]" minlengt
h$="[[minlength]]" maxlength$="[[maxlength]]" min$="[[min]]" max$="[[max]]" step
$="[[step]]" name$="[[name]]" placeholder$="[[placeholder]]" readonly$="[[readon
ly]]" list$="[[list]]" size$="[[size]]" autocapitalize$="[[autocapitalize]]" aut
ocorrect$="[[autocorrect]]" on-change="_onChange" tabindex$="[[tabindex]]" autos
ave$="[[autosave]]" results$="[[results]]" accept$="[[accept]]" multiple$="[[mul
tiple]]"> |
| 20524 |
| 20525 <content select="[suffix]"></content> |
| 20526 |
| 20527 <template is="dom-if" if="[[errorMessage]]"> |
| 20528 <paper-input-error aria-live="assertive">[[errorMessage]]</paper-input-e
rror> |
| 20529 </template> |
| 20530 |
| 20531 <template is="dom-if" if="[[charCounter]]"> |
| 20532 <paper-input-char-counter></paper-input-char-counter> |
| 20533 </template> |
| 20534 |
| 20535 </paper-input-container> |
| 20536 </template> |
| 20537 </dom-module> |
| 20538 |
| 20539 <script> |
| 20540 Polymer({ |
| 20541 is: 'paper-input', |
| 20542 |
| 20543 behaviors: [ |
| 20544 Polymer.IronFormElementBehavior, |
| 20545 Polymer.PaperInputBehavior |
| 20546 ] |
| 20547 }); |
| 20548 </script> |
| 20549 <dom-module id="bot-filters" assetpath="/res/imp/botlist/"> |
| 20550 <template> |
| 20551 <style is="custom-style" include="iron-flex iron-flex-alignment iron-positio
ning"> |
| 20552 :host { |
| 20553 display: block; |
| 20554 font-family: sans-serif; |
| 20555 } |
| 20556 #filter { |
| 20557 margin:0 5px; |
| 20558 } |
| 20559 |
| 20560 .container { |
| 20561 min-height: 120px; |
| 20562 width: 100%; |
| 20563 } |
| 20564 |
| 20565 .item { |
| 20566 border-bottom: 1px solid #EEE; |
| 20567 max-width: 250px; |
| 20568 min-height: 1.0em; |
| 20569 min-width: 100px; |
| 20570 padding: 0.1em 0.2em; |
| 20571 line-height: 1.5em; |
| 20572 } |
| 20573 |
| 20574 .header { |
| 20575 height: 2em; |
| 20576 padding: .25em; |
| 20577 line-height: 2em; |
| 20578 } |
| 20579 |
| 20580 .selector { |
| 20581 border: 1px solid black; |
| 20582 margin: 0 5px; |
| 20583 max-height: 200px; |
| 20584 min-height: 130px; |
| 20585 min-width: 200px; |
| 20586 overflow-y: auto; |
| 20587 overflow-x: hidden; |
| 20588 } |
| 20589 |
| 20590 .selectable { |
| 20591 cursor: pointer; |
| 20592 } |
| 20593 |
| 20594 .selectable:hover { |
| 20595 /* See https://sites.google.com/a/google.com/skia-infrastructure/design-
docs/general-design-guidance */ |
| 20596 background-color: #A6CEE3; |
| 20597 } |
| 20598 |
| 20599 .iron-selected { |
| 20600 /* See https://sites.google.com/a/google.com/skia-infrastructure/design-
docs/general-design-guidance */ |
| 20601 background-color: #1F78B4; |
| 20602 color: white; |
| 20603 } |
| 20604 |
| 20605 .icons { |
| 20606 cursor:pointer; |
| 20607 height:20px; |
| 20608 margin:2px; |
| 20609 width:20px; |
| 20610 flex-shrink: 0; |
| 20611 } |
| 20612 |
| 20613 .side-by-side { |
| 20614 display: inline-block; |
| 20615 vertical-align: top; |
| 20616 } |
| 20617 |
| 20618 .bold { |
| 20619 font-weight: bold; |
| 20620 } |
| 20621 |
| 20622 paper-checkbox { |
| 20623 max-height: 2em; |
| 20624 margin: 2px; |
| 20625 /* See https://sites.google.com/a/google.com/skia-infrastructure/design-
docs/general-design-guidance */ |
| 20626 --paper-checkbox-checked-color: black; |
| 20627 --paper-checkbox-checked-ink-color: black; |
| 20628 --paper-checkbox-unchecked-color: black; |
| 20629 --paper-checkbox-unchecked-ink-color: black; |
| 20630 --paper-checkbox-label-color: black; |
| 20631 } |
| 20632 </style> |
| 20633 |
| 20634 <div class="container horizontal layout"> |
| 20635 |
| 20636 |
| 20637 <div class="narrow-down-selector"> |
| 20638 <div> |
| 20639 <paper-input id="filter" label="Search columns and filters" placeholde
r="gpu nvidia" value="{{_query}}"></paper-input> |
| 20640 </div> |
| 20641 |
| 20642 <div class="selector side-by-side"> |
| 20643 <iron-selector attr-for-selected="label" selected="{{_primarySelected}
}"> |
| 20644 <template is="dom-repeat" items="[[_primaryItems]]" as="item"> |
| 20645 <div class="selectable item horizontal layout" label="[[item]]"> |
| 20646 |
| 20647 <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(ite
m,_query)]]</span>[[_afterBold(item,_query)]]</span> |
| 20648 <span class="flex"></span> |
| 20649 <paper-checkbox noink="" disabled$="[[_cantToggleColumn(item)]]"
checked="[[_columnState(item,columns.*)]]" on-change="_toggleColumn"> |
| 20650 </paper-checkbox> |
| 20651 </div> |
| 20652 </template> |
| 20653 </iron-selector> |
| 20654 </div> |
| 20655 |
| 20656 <div class="selector side-by-side"> |
| 20657 <template is="dom-repeat" id="secondaryList" items="[[_secondaryItems]
]" as="item"> |
| 20658 <div class="item horizontal layout" label="[[item]]"> |
| 20659 |
| 20660 <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(item,
_query)]]</span>[[_afterBold(item,_query)]]</span> |
| 20661 <span class="flex"></span> |
| 20662 <iron-icon class="icons" icon="icons:arrow-forward" hidden="[[_can
tAddFilter(_primarySelected,item,_filters.*)]]" on-tap="_addFilter"> |
| 20663 </iron-icon> |
| 20664 </div> |
| 20665 </template> |
| 20666 </div> |
| 20667 |
| 20668 <div class="selector side-by-side"> |
| 20669 <template is="dom-repeat" items="[[_filters]]" as="fil"> |
| 20670 <div class="item horizontal layout" label="[[fil]]"> |
| 20671 <span>[[fil]]</span> |
| 20672 <span class="flex"></span> |
| 20673 <iron-icon class="icons" icon="icons:remove-circle-outline" hidden
="[[_cantRemoveFilter(fil,_filters.*)]]" on-tap="_removeFilter"> |
| 20674 </iron-icon> |
| 20675 </div> |
| 20676 </template> |
| 20677 </div> |
| 20678 |
| 20679 <paper-checkbox checked="{{verbose}}">Verbose Entries</paper-checkbox> |
| 20680 </div> |
| 20681 |
| 20682 </div> |
| 20683 |
| 20684 </template> |
| 20685 <script> |
| 20686 (function(){ |
| 20687 var FILTER_SEP = " | "; |
| 20688 // filterMap is a map of primary -> function. The function returns a |
| 20689 // boolean "does the bot (first arg) match the second argument". These |
| 20690 // functions will have "this" be the botlist, and will have access to all |
| 20691 // functions defined in bot-list and bot-list-shared. |
| 20692 var filterMap = { |
| 20693 cores: function(bot, cores){ |
| 20694 var o = this._cores(bot); |
| 20695 return o.indexOf(cores) !== -1; |
| 20696 }, |
| 20697 cpu: function(bot, cpu){ |
| 20698 var o = this._dimension(bot, "cpu") || ["none"]; |
| 20699 return o.indexOf(cpu) !== -1; |
| 20700 }, |
| 20701 devices: function(bot, device){ |
| 20702 if (device === "none") { |
| 20703 return this._devices(bot).length === 0; |
| 20704 } |
| 20705 // extract the deviceType, if it is not "unknown". |
| 20706 device = this._unalias(device); |
| 20707 var found = false; |
| 20708 this._devices(bot).forEach(function(d) { |
| 20709 if (this._deviceType(d) === device) { |
| 20710 found = true; |
| 20711 } |
| 20712 }.bind(this)); |
| 20713 return found; |
| 20714 }, |
| 20715 gpu: function(bot, gpu){ |
| 20716 var o = this._dimension(bot, "gpu") || ["none"]; |
| 20717 return o.indexOf(this._unalias(gpu)) !== -1; |
| 20718 }, |
| 20719 id: function(bot, id) { |
| 20720 return bot.bot_id === id; |
| 20721 }, |
| 20722 os: function(bot, os){ |
| 20723 var o = this._dimension(bot, "os") || ["Unknown"]; |
| 20724 return o.indexOf(os) !== -1; |
| 20725 }, |
| 20726 pool: function(bot, pool){ |
| 20727 var o = this._dimension(bot, "pool") || ["Unknown"]; |
| 20728 return o.indexOf(pool) !== -1; |
| 20729 }, |
| 20730 status: function(bot, status){ |
| 20731 if (status === "quarantined") { |
| 20732 return bot.quarantined; |
| 20733 } else if (status === "dead") { |
| 20734 return bot.is_dead; |
| 20735 } else { |
| 20736 // Status must be "available". |
| 20737 return !bot.quarantined && !bot.is_dead; |
| 20738 } |
| 20739 }, |
| 20740 task: function(bot, task) { |
| 20741 if (task === "idle") { |
| 20742 return this._taskId(bot) === "idle"; |
| 20743 } |
| 20744 // Task must be "busy". |
| 20745 return this._taskId(bot) !== "idle"; |
| 20746 } |
| 20747 }; |
| 20748 |
| 20749 // Given a space separated list of queries, matchPartCaseInsensitive |
| 20750 // returns an object of any query that matches a part of str, case |
| 20751 // insensitive. The object has an idx (index) and the part that matched. |
| 20752 var matchPartCaseInsensitive = function(str, queries) { |
| 20753 if (!queries) { |
| 20754 return { |
| 20755 idx: 0, |
| 20756 part: "", |
| 20757 }; |
| 20758 } |
| 20759 if (!str) { |
| 20760 return { |
| 20761 idx: -1, |
| 20762 }; |
| 20763 } |
| 20764 queries = queries.trim().toLocaleLowerCase(); |
| 20765 str = str.toLocaleLowerCase(); |
| 20766 var xq = queries.split(" "); |
| 20767 for (var i = 0; i < xq.length; i++) { |
| 20768 var idx = str.indexOf(xq[i]); |
| 20769 if (idx !== -1) { |
| 20770 return { |
| 20771 idx: idx, |
| 20772 part: xq[i], |
| 20773 }; |
| 20774 } |
| 20775 } |
| 20776 return { |
| 20777 idx: -1, |
| 20778 }; |
| 20779 }; |
| 20780 |
| 20781 Polymer({ |
| 20782 is: "bot-filters", |
| 20783 properties: { |
| 20784 // input |
| 20785 primary_map: { |
| 20786 type: Object, |
| 20787 }, |
| 20788 primary_arr: { |
| 20789 type: Array, |
| 20790 }, |
| 20791 |
| 20792 // output |
| 20793 columns: { |
| 20794 type: Array, |
| 20795 value: function() { |
| 20796 // TODO(kjlubick) back these up to URL params and load them from |
| 20797 // there on reload. |
| 20798 return ["id","os","task","status"]; |
| 20799 }, |
| 20800 notify: true, |
| 20801 }, |
| 20802 filter: { |
| 20803 type: Object, |
| 20804 computed: "_makeFilter(_filters.*)", |
| 20805 notify: true, |
| 20806 }, |
| 20807 verbose: { |
| 20808 type: Boolean, |
| 20809 value: false, |
| 20810 notify: true, |
| 20811 }, |
| 20812 |
| 20813 // private |
| 20814 _filters: { |
| 20815 type:Array, |
| 20816 value: function() { |
| 20817 return []; |
| 20818 } |
| 20819 }, |
| 20820 _primaryItems: { |
| 20821 type: Array, |
| 20822 computed: "_primary(_query, primary_map, primary_arr, columns.*)", |
| 20823 }, |
| 20824 _primarySelected: { |
| 20825 type: String, |
| 20826 value: "", |
| 20827 }, |
| 20828 // query is treated as a space separated list. |
| 20829 _query: { |
| 20830 type:String, |
| 20831 value: "", |
| 20832 }, |
| 20833 _secondaryItems: { |
| 20834 type: Array, |
| 20835 computed: "_secondary(_primarySelected, _query, primary_map)", |
| 20836 }, |
| 20837 |
| 20838 }, |
| 20839 |
| 20840 _addFilter: function(e) { |
| 20841 // e.model.foo is a way to get access to the "foo" inside a dom-repeat |
| 20842 // that had the event (in our case, a tap) acted upon it. This name, |
| 20843 // "foo", is set by the dom-repeat above 'as="foo"' |
| 20844 var filterItem = e.model.item; |
| 20845 if (this._cantAddFilter(this._primarySelected, filterItem)) { |
| 20846 return; |
| 20847 } |
| 20848 var filter = this._primarySelected + FILTER_SEP + filterItem; |
| 20849 this.push("_filters", filter); |
| 20850 }, |
| 20851 |
| 20852 _removeFilter: function(e){ |
| 20853 var filter = e.model.fil; |
| 20854 if (this._cantRemoveFilter(filter)){ |
| 20855 return; |
| 20856 } |
| 20857 var idx = this._filters.indexOf(filter); |
| 20858 if (idx !== -1) { |
| 20859 this.splice("_filters", idx, 1); |
| 20860 } |
| 20861 }, |
| 20862 |
| 20863 _cantAddFilter: function(primarySelected, filterItem) { |
| 20864 // Check that everything is selected and this filter isn't already in |
| 20865 // the array. |
| 20866 if (!primarySelected || !filterItem) { |
| 20867 return true; |
| 20868 } |
| 20869 var filter = primarySelected + FILTER_SEP + filterItem; |
| 20870 return this._filters.indexOf(filter) !== -1; |
| 20871 }, |
| 20872 |
| 20873 _cantRemoveFilter: function(filter) { |
| 20874 return !filter || this._filters.indexOf(filter) === -1; |
| 20875 }, |
| 20876 |
| 20877 _toggleColumn: function(e) { |
| 20878 var col = e.model.item; |
| 20879 |
| 20880 if (this._cantToggleColumn(col)) { |
| 20881 return; |
| 20882 } |
| 20883 if (this._columnState(col)) { |
| 20884 var idx = this.columns.indexOf(col); |
| 20885 if (idx !== -1) { |
| 20886 this.splice("columns", idx, 1); |
| 20887 } |
| 20888 return; |
| 20889 } |
| 20890 this.push("columns", col); |
| 20891 }, |
| 20892 |
| 20893 _cantToggleColumn: function(col) { |
| 20894 // Don't allow the id column to be removed, as the bot list is basically |
| 20895 // meaningless without it. |
| 20896 return !col || col === "id" ; |
| 20897 }, |
| 20898 |
| 20899 _columnState: function(col) { |
| 20900 if (!col) { |
| 20901 return false; |
| 20902 } |
| 20903 return this.columns.indexOf(col) !== -1; |
| 20904 }, |
| 20905 |
| 20906 _makeFilter: function() { |
| 20907 // The filters belonging to the same primary key will be or'd together. |
| 20908 // Those groups will be and'd together. |
| 20909 // filterGroups will be a map of primary (i.e. column) -> array of |
| 20910 // options that should be filtered to. |
| 20911 // e.g. "os" -> ["Windows", "Linux"] |
| 20912 // Since they will be or'd together, order doesn't matter. |
| 20913 var filterGroups = {}; |
| 20914 this._filters.forEach(function(filterString){ |
| 20915 var idx = filterString.indexOf(FILTER_SEP); |
| 20916 var primary = filterString.slice(0, idx); |
| 20917 var param = filterString.slice(idx + FILTER_SEP.length); |
| 20918 var arr = filterGroups[primary] || []; |
| 20919 arr.push(param); |
| 20920 filterGroups[primary] = arr; |
| 20921 }); |
| 20922 return { |
| 20923 filter: function(bot){ |
| 20924 var retVal = true; |
| 20925 // Look up all the primary keys we are filter by, then look up how |
| 20926 // to filter (in filterMap) and apply the filter for each filter |
| 20927 // option. |
| 20928 for (primary in filterGroups){ |
| 20929 var params = filterGroups[primary]; |
| 20930 var filter = filterMap[primary]; |
| 20931 var groupResult = false; |
| 20932 if (filter) { |
| 20933 params.forEach(function(param){ |
| 20934 groupResult = groupResult || filter.bind(this)(bot,param); |
| 20935 }.bind(this)); |
| 20936 } |
| 20937 retVal = retVal && groupResult; |
| 20938 } |
| 20939 return retVal; |
| 20940 } |
| 20941 } |
| 20942 }, |
| 20943 |
| 20944 _primary: function(query, primary_map, primary_arr) { |
| 20945 // If the user has typed in a query, only show those primary keys that |
| 20946 // partially match the query or that have secondary values which |
| 20947 // partially match. |
| 20948 var arr = this.primary_arr.filter(function(s){ |
| 20949 if (matchPartCaseInsensitive(s, query).idx !== -1) { |
| 20950 return true; |
| 20951 } |
| 20952 var opts = primary_map[s]; |
| 20953 for (var i = 0; i < opts.length; i++) { |
| 20954 if (matchPartCaseInsensitive(opts[i], query).idx !== -1) { |
| 20955 return true; |
| 20956 } |
| 20957 } |
| 20958 return false; |
| 20959 }); |
| 20960 // Update the selected to be the current one (if it is still with being |
| 20961 // shown) or the first match. This saves the user from having to click |
| 20962 // the first result before seeing results. |
| 20963 if (query && arr.length > 0 && |
| 20964 arr.indexOf(this._primarySelected) === -1) { |
| 20965 this.set("_primarySelected", arr[0]); |
| 20966 } |
| 20967 return arr; |
| 20968 }, |
| 20969 |
| 20970 _secondary: function(primarySelected, query, primary_map) { |
| 20971 // Changing the secondary list doesn't always trigger a reorder of the |
| 20972 // secondary elements. So, we request it be done asynchronously. |
| 20973 requestAnimationFrame(function(){ |
| 20974 this.$.secondaryList.render(); |
| 20975 }.bind(this)); |
| 20976 |
| 20977 // Only show secondary options when a primary option has been selected. |
| 20978 // If the user has typed in a query, show all secondary elements if |
| 20979 // their primary element matches. If it doesn't match the primary |
| 20980 // element, only show those secondary elements that do. |
| 20981 if (!primarySelected) { |
| 20982 return []; |
| 20983 } |
| 20984 if (matchPartCaseInsensitive(primarySelected, query).idx !== -1) { |
| 20985 // Sort the secondaries alphabetically, but prioritize query matches. |
| 20986 return primary_map[primarySelected].sort(function(a, b){ |
| 20987 var aMatch = matchPartCaseInsensitive(a, query).idx !== -1; |
| 20988 var bMatch = matchPartCaseInsensitive(b, query).idx !== -1; |
| 20989 if (aMatch === bMatch) { |
| 20990 return swarming.naturalCompare(a,b); |
| 20991 } |
| 20992 // true == 1 and false == 0. So, put the one that matches first. |
| 20993 return bMatch - aMatch; |
| 20994 }); |
| 20995 } |
| 20996 // Otherwise, filter out those that do not match. |
| 20997 return primary_map[primarySelected].filter(function(s) { |
| 20998 return matchPartCaseInsensitive(s, query).idx !== -1; |
| 20999 }); |
| 21000 }, |
| 21001 |
| 21002 // These three methods (_beforeBold, _bold, _afterBold) bold the first |
| 21003 // instance of the filter query, making it easier to see why elements |
| 21004 // show up. |
| 21005 _beforeBold: function(item, query) { |
| 21006 var match = matchPartCaseInsensitive(item, query); |
| 21007 if (match.idx === -1) { |
| 21008 return item; |
| 21009 } |
| 21010 return item.substring(0, match.idx); |
| 21011 }, |
| 21012 |
| 21013 _bold: function(item, query) { |
| 21014 var match = matchPartCaseInsensitive(item, query); |
| 21015 if (match.idx === -1) { |
| 21016 return ""; |
| 21017 } |
| 21018 return item.substring(match.idx, match.idx + match.part.length); |
| 21019 }, |
| 21020 |
| 21021 _afterBold: function(item, query) { |
| 21022 var match = matchPartCaseInsensitive(item, query); |
| 21023 if (match.idx === -1) { |
| 21024 return ""; |
| 21025 } |
| 21026 return item.substring(match.idx + match.part.length); |
| 21027 }, |
| 21028 |
| 21029 }); |
| 21030 })(); |
| 21031 </script> |
| 21032 </dom-module><script> |
| 21033 |
| 21034 window.SwarmingBehaviors = window.SwarmingBehaviors || {}; |
| 21035 (function(){ |
| 21036 var ANDROID_ALIASES = { |
| 21037 "bullhead": "Nexus 5X", |
| 21038 "flo": "Nexus 7", |
| 21039 "hammerhead": "Nexus 5", |
| 21040 "mako": "Nexus 4", |
| 21041 "shamu": "Nexus 6", |
| 21042 }; |
| 21043 // Taken from http://developer.android.com/reference/android/os/BatteryManag
er.html |
| 21044 var BATTERY_HEALTH_UNKNOWN = 1; |
| 21045 var BATTERY_HEALTH_GOOD = 2; |
| 21046 var BATTERY_STATUS_CHARGING = 2; |
| 21047 |
| 21048 var UNAUTHENTICATED = "unauthenticated"; |
| 21049 var AVAILABLE = "available"; |
| 21050 |
| 21051 var GPU_ALIASES = { |
| 21052 "1002": "AMD", |
| 21053 "1002:6779": "AMD Radeon HD 6450/7450/8450", |
| 21054 "1002:6821": "AMD Radeon HD 8870M", |
| 21055 "102b": "Matrox", |
| 21056 "102b:0522": "Matrox MGA G200e", |
| 21057 "102b:0532": "Matrox MGA G200eW", |
| 21058 "102b:0534": "Matrox G200eR2", |
| 21059 "10de": "NVIDIA", |
| 21060 "10de:08aa": "NVIDIA GeForce 320M", |
| 21061 "10de:0fe9": "NVIDIA GeForce GT 750M Mac Edition", |
| 21062 "10de:104a": "NVIDIA GeForce GT 610", |
| 21063 "10de:11c0": "NVIDIA GeForce GTX 660", |
| 21064 "10de:1244": "NVIDIA GeForce GTX 550 Ti", |
| 21065 "10de:1401": "NVIDIA GeForce GTX 960", |
| 21066 "8086": "Intel", |
| 21067 "8086:041a": "Intel Xeon Integrated", |
| 21068 "8086:0a2e": "Intel Haswell Integrated", |
| 21069 "8086:0d26": "Intel Crystal Well Integrated", |
| 21070 } |
| 21071 |
| 21072 // For consistency, all aliases are displayed like: |
| 21073 // Nexus 5X (bullhead) |
| 21074 // This regex matches a string like "ALIAS (ORIG)", with ORIG as group 1. |
| 21075 var ALIAS_REGEXP = /.+ \((.*)\)/; |
| 21076 |
| 21077 // This behavior wraps up all the shared bot-list functionality. |
| 21078 SwarmingBehaviors.BotListBehavior = { |
| 21079 |
| 21080 _androidAlias: function(device) { |
| 21081 if (device.notReady) { |
| 21082 return UNAUTHENTICATED.toUpperCase(); |
| 21083 } |
| 21084 var t = this._deviceType(device); |
| 21085 var a = ANDROID_ALIASES[t]; |
| 21086 if (!a) { |
| 21087 return "UNKNOWN"; |
| 21088 } |
| 21089 return a; |
| 21090 }, |
| 21091 |
| 21092 // _applyAlias is the consistent way to modify a string to show its alias. |
| 21093 _applyAlias: function(orig, alias) { |
| 21094 return alias +" ("+orig+")"; |
| 21095 }, |
| 21096 |
| 21097 _cores: function(bot) { |
| 21098 // For whatever reason, sometimes cores are in dimensions and sometimes |
| 21099 // they are in state, but never both. |
| 21100 var c = (bot && bot.state && bot.state.cores); |
| 21101 if (c && c.length > 0) { |
| 21102 return c; |
| 21103 } |
| 21104 c = this._dimension(bot, "cores") || ["Unknown"]; |
| 21105 return c; |
| 21106 }, |
| 21107 |
| 21108 _devices: function(bot) { |
| 21109 var devices = []; |
| 21110 var d = (bot && bot.state && bot.state.devices) || {}; |
| 21111 // state.devices is like {Serial:Object}, so we need to keep the serial |
| 21112 for (key in d) { |
| 21113 var o = d[key]; |
| 21114 o.serial = key; |
| 21115 o.okay = (o.state === AVAILABLE); |
| 21116 devices.push(o); |
| 21117 } |
| 21118 return devices; |
| 21119 }, |
| 21120 |
| 21121 // _deviceType returns the codename of a given Android device. |
| 21122 _deviceType: function(device) { |
| 21123 if (!device || !device.build) { |
| 21124 return "unknown"; |
| 21125 } |
| 21126 var t = device.build["build.product"] || device.build["product.board"] |
| |
| 21127 device.build["product.device"] || "unknown"; |
| 21128 return t.toLowerCase(); |
| 21129 }, |
| 21130 |
| 21131 // _dimension returns the given dimension of a bot. If it is defined, it |
| 21132 // is typically an array of strings. |
| 21133 _dimension: function(bot, dim) { |
| 21134 if (!bot || !bot.dimensions || !dim) { |
| 21135 return undefined; |
| 21136 } |
| 21137 for (var i = 0; i < bot.dimensions.length; i++) { |
| 21138 if (bot.dimensions[i].key === dim) { |
| 21139 return bot.dimensions[i].value; |
| 21140 } |
| 21141 } |
| 21142 return undefined; |
| 21143 }, |
| 21144 |
| 21145 _gpuAlias: function(gpu) { |
| 21146 var a = GPU_ALIASES[gpu]; |
| 21147 if (!a) { |
| 21148 return "UNKNOWN"; |
| 21149 } |
| 21150 return a; |
| 21151 }, |
| 21152 |
| 21153 _not: function(a) { |
| 21154 return a; |
| 21155 }, |
| 21156 |
| 21157 _taskId: function(bot) { |
| 21158 if (bot && bot.task_id) { |
| 21159 return bot.task_id; |
| 21160 } |
| 21161 return "idle"; |
| 21162 }, |
| 21163 |
| 21164 // _unalias will return the base dimension/state with its alias removed |
| 21165 // if it had one. This is handy for sorting and filtering. |
| 21166 _unalias: function(str) { |
| 21167 var match = ALIAS_REGEXP.exec(str); |
| 21168 if (match) { |
| 21169 return match[1]; |
| 21170 } |
| 21171 return str; |
| 21172 }, |
| 21173 } |
| 21174 })() |
| 21175 </script> |
| 21176 <dom-module id="bot-list-data" assetpath="/res/imp/botlist/"> |
| 21177 <template> |
| 21178 <iron-ajax id="request" url="/_ah/api/swarming/v1/bots/list" headers="[[auth
_headers]]" handle-as="json" last-response="{{_data}}" loading="{{busy}}"> |
| 21179 </iron-ajax> |
| 21180 </template> |
| 21181 <script> |
| 21182 (function(){ |
| 21183 // TODO(kjlubick): Add more of these as well as things from state |
| 21184 // i.e. disk space remaining. |
| 21185 var DIMENSIONS = ["cores", "cpu", "id", "os", "pool"]; |
| 21186 // "gpu" and "devices" are added separately because we need to |
| 21187 // deal with aliases. |
| 21188 var BOT_PROPERTIES = ["gpu", "devices", "task", "status"]; |
| 21189 Polymer({ |
| 21190 is: 'bot-list-data', |
| 21191 properties: { |
| 21192 // inputs |
| 21193 auth_headers: { |
| 21194 type: Object, |
| 21195 observer: "signIn", |
| 21196 }, |
| 21197 |
| 21198 //outputs |
| 21199 bots: { |
| 21200 type: Array, |
| 21201 computed: "_bots(_data)", |
| 21202 notify: true, |
| 21203 }, |
| 21204 busy: { |
| 21205 type: Boolean, |
| 21206 notify: true, |
| 21207 }, |
| 21208 primary_map: { |
| 21209 type:Object, |
| 21210 computed: "_primaryMap(bots)", |
| 21211 notify: true, |
| 21212 }, |
| 21213 primary_arr: { |
| 21214 type:Array, |
| 21215 value: function() { |
| 21216 return DIMENSIONS.concat(BOT_PROPERTIES); |
| 21217 }, |
| 21218 notify: true, |
| 21219 }, |
| 21220 |
| 21221 // private |
| 21222 _data: { |
| 21223 type: Object, |
| 21224 }, |
| 21225 }, |
| 21226 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 21227 |
| 21228 signIn: function(){ |
| 21229 this.$.request.generateRequest(); |
| 21230 }, |
| 21231 |
| 21232 _bots: function(){ |
| 21233 if (!this._data || !this._data.items) { |
| 21234 return []; |
| 21235 } |
| 21236 this._data.items.forEach(function(o){ |
| 21237 o.state = JSON.parse(o.state); |
| 21238 }); |
| 21239 return this._data.items; |
| 21240 }, |
| 21241 |
| 21242 _primaryMap: function(bots){ |
| 21243 // map will keep track of dimensions that we have seen at least once. |
| 21244 // This will then basically get turned into an array to be used for |
| 21245 // filtering. |
| 21246 var map = {}; |
| 21247 DIMENSIONS.forEach(function(p){ |
| 21248 map[p] = {}; |
| 21249 }); |
| 21250 map["devices"] = {}; |
| 21251 map["gpu"] = {}; |
| 21252 bots.forEach(function(b){ |
| 21253 DIMENSIONS.forEach(function(d){ |
| 21254 var dims = this._dimension(b, d) || []; |
| 21255 dims.forEach(function(e){ |
| 21256 map[d][e] = true; |
| 21257 }); |
| 21258 }.bind(this)); |
| 21259 |
| 21260 // Add Android devices and their aliases |
| 21261 this._devices(b).forEach(function(d){ |
| 21262 var dt = this._deviceType(d); |
| 21263 var alias = this._androidAlias(d); |
| 21264 if (dt !== "unknown") { |
| 21265 dt = this._applyAlias(dt,alias); |
| 21266 } |
| 21267 map["devices"][dt] = true; |
| 21268 }.bind(this)); |
| 21269 map["devices"]["none"] = true; |
| 21270 |
| 21271 // Add GPUs and their aliases |
| 21272 var gpus = this._dimension(b, "gpu") || []; |
| 21273 gpus.forEach(function(g){ |
| 21274 var alias = this._gpuAlias(g); |
| 21275 if (alias !== "UNKNOWN") { |
| 21276 map["gpu"][this._applyAlias(g, alias)] = true; |
| 21277 } else { |
| 21278 map["gpu"][g] = true; |
| 21279 } |
| 21280 |
| 21281 }.bind(this)); |
| 21282 }.bind(this)); |
| 21283 |
| 21284 // Turn the Map<Object,Map<Boolean>> into a Map<Object,Array<String>> |
| 21285 // with all of the secondary elements sorted appropriately. |
| 21286 var pMap = {}; |
| 21287 for (key in map){ |
| 21288 pMap[key] = Object.keys(map[key]).sort(swarming.naturalCompare); |
| 21289 } |
| 21290 |
| 21291 // Create custom filter options |
| 21292 pMap["task"] = ["busy", "idle"]; |
| 21293 pMap["status"] = ["available", "dead", "quarantined"]; |
| 21294 return pMap; |
| 21295 }, |
| 21296 |
| 21297 }); |
| 21298 })(); |
| 21299 </script> |
| 21300 </dom-module><dom-module id="bot-list" assetpath="/res/imp/botlist/"> |
| 21301 <template> |
| 21302 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-
style"> |
| 21303 bot-filters { |
| 21304 margin-bottom: 5px; |
| 21305 } |
| 21306 .bot { |
| 21307 margin:5px; |
| 21308 max-width:400px; |
| 21309 min-height:100px; |
| 21310 min-width:300px; |
| 21311 } |
| 21312 table { |
| 21313 border-collapse: collapse; |
| 21314 margin-left: 5px; |
| 21315 } |
| 21316 td, th { |
| 21317 border: 1px solid #DDD; |
| 21318 padding: 5px; |
| 21319 } |
| 21320 |
| 21321 .quarantined, .bad-device { |
| 21322 background-color: #ffdddd; |
| 21323 } |
| 21324 .dead { |
| 21325 background-color: #cccccc; |
| 21326 } |
| 21327 |
| 21328 th { |
| 21329 position: relative; |
| 21330 } |
| 21331 sort-toggle { |
| 21332 position: absolute; |
| 21333 right: 0; |
| 21334 top: 0.4em; |
| 21335 } |
| 21336 .bot-list th > span { |
| 21337 /* Leave space for sort-toggle*/ |
| 21338 padding-right: 30px; |
| 21339 } |
| 21340 </style> |
| 21341 |
| 21342 <swarming-app auth_headers="{{auth_headers}}" busy="[[busy]]" name="Swarming
Bot List"> |
| 21343 |
| 21344 <bot-filters primary_map="[[primary_map]]" primary_arr="[[primary_arr]]" c
olumns="{{columns}}" filter="{{filter}}" verbose="{{verbose}}"> |
| 21345 </bot-filters> |
| 21346 |
| 21347 <bot-list-data auth_headers="[[auth_headers]]" bots="{{bots}}" busy="{{bus
y}}" primary_map="{{primary_map}}" primary_arr="{{primary_arr}}"> |
| 21348 </bot-list-data> |
| 21349 |
| 21350 <table class="bot-list"> |
| 21351 <thead on-sort_change="sortChange"> |
| 21352 |
| 21353 <tr><th> |
| 21354 <span>Bot Id</span> |
| 21355 <sort-toggle name="id" current="[[sort]]"> |
| 21356 </sort-toggle> |
| 21357 </th> |
| 21358 |
| 21359 <th hidden$="[[_hide('task', columns.*)]]"> |
| 21360 <span>Current Task</span> |
| 21361 <sort-toggle name="task" current="[[sort]]"> |
| 21362 </sort-toggle> |
| 21363 </th> |
| 21364 |
| 21365 <template is="dom-repeat" items="[[plain_columns]]" as="c"> |
| 21366 <th hidden$="[[_hide(c)]]"> |
| 21367 <span>[[_header(c)]]</span> |
| 21368 <sort-toggle name="[[c]]" current="[[sort]]"> |
| 21369 </sort-toggle> |
| 21370 </th> |
| 21371 </template> |
| 21372 </tr></thead> |
| 21373 <tbody> |
| 21374 <template id="bot_table" is="dom-repeat" items="[[bots]]" as="bot" ini
tial-count="50" filter="_filterBotTable"> |
| 21375 |
| 21376 <tr class$="[[_botClass(bot)]]"> |
| 21377 <td> |
| 21378 <a class="center" href$="[[_botLink(bot.bot_id)]]" target="_blan
k"> |
| 21379 [[bot.bot_id]] |
| 21380 </a> |
| 21381 </td> |
| 21382 <td hidden$="[[_hide('task', columns.*)]]"> |
| 21383 <a href$="[[_taskLink(bot)]]">[[_taskId(bot)]]</a> |
| 21384 </td> |
| 21385 |
| 21386 <template is="dom-repeat" items="[[plain_columns]]" as="c"> |
| 21387 <td hidden$="[[_hide(c)]]"> |
| 21388 [[_column(c, bot, verbose)]] |
| 21389 </td> |
| 21390 </template> |
| 21391 |
| 21392 </tr> |
| 21393 <template is="dom-repeat" items="[[_devices(bot)]]" as="device"> |
| 21394 <tr hidden$="[[_hide('devices', columns.*)]]" class$="[[_deviceCla
ss(device)]]"> |
| 21395 <td></td> |
| 21396 <td hidden$="[[_hide('task', columns.*)]]"></td> |
| 21397 <template is="dom-repeat" items="[[plain_columns]]" as="c"> |
| 21398 <td hidden$="[[_hide(c)]]"> |
| 21399 [[_deviceColumn(c, device, verbose)]] |
| 21400 </td> |
| 21401 </template> |
| 21402 </tr> |
| 21403 </template> |
| 21404 </template> |
| 21405 </tbody> |
| 21406 </table> |
| 21407 |
| 21408 </swarming-app> |
| 21409 |
| 21410 </template> |
| 21411 <script> |
| 21412 (function(){ |
| 21413 var special_columns = ["id", "task"]; |
| 21414 |
| 21415 var headerMap = { |
| 21416 // "id" and "task" are special, so they don't go here and have their |
| 21417 // headers hard-coded below. |
| 21418 "cores": "Cores", |
| 21419 "cpu": "CPU", |
| 21420 "devices": "Devices", |
| 21421 "gpu": "GPU", |
| 21422 "os": "OS", |
| 21423 "pool": "Pool", |
| 21424 "status": "Status", |
| 21425 }; |
| 21426 |
| 21427 // This maps column name to a function that will return the content for a |
| 21428 // given bot. These functions are bound to this element, and have access |
| 21429 // to all functions defined here and in bot-list-shared. |
| 21430 var columnMap = { |
| 21431 cores: function(bot){ |
| 21432 var cores = this._cores(bot); |
| 21433 if (this.verbose){ |
| 21434 return cores.join(" | "); |
| 21435 } |
| 21436 return cores[0]; |
| 21437 }, |
| 21438 cpu: function(bot){ |
| 21439 var cpus = this._dimension(bot, 'cpu') || ['Unknown']; |
| 21440 if (this.verbose){ |
| 21441 return cpus.join(" | "); |
| 21442 } |
| 21443 return cpus[0]; |
| 21444 }, |
| 21445 devices: function(bot){ |
| 21446 return this._devices(bot).length + " devices attached"; |
| 21447 }, |
| 21448 gpu: function(bot){ |
| 21449 var gpus = this._dimension(bot, 'gpu') |
| 21450 if (!gpus) { |
| 21451 return "none"; |
| 21452 } |
| 21453 var verbose = [] |
| 21454 var named = []; |
| 21455 // non-verbose mode has only the top level GPU info "e.g. NVidia" |
| 21456 // which is found by looking for gpu ids w/o a colon. |
| 21457 gpus.forEach(function(g){ |
| 21458 var alias = this._gpuAlias(g); |
| 21459 if (alias === "UNKNOWN") { |
| 21460 verbose.push(g); |
| 21461 if (g.indexOf(":") === -1) { |
| 21462 named.push(g); |
| 21463 } |
| 21464 return; |
| 21465 } |
| 21466 verbose.push(this._applyAlias(g, alias)); |
| 21467 if (g.indexOf(":") === -1) { |
| 21468 named.push(this._applyAlias(g, alias)); |
| 21469 } |
| 21470 }.bind(this)) |
| 21471 if (this.verbose) { |
| 21472 return verbose.join(" | "); |
| 21473 } |
| 21474 return named.join(" | "); |
| 21475 }, |
| 21476 id: function(bot) { |
| 21477 return bot.bot_id; |
| 21478 }, |
| 21479 os: function(bot) { |
| 21480 var os = this._dimension(bot, 'os') || ['Unknown']; |
| 21481 if (this.verbose){ |
| 21482 return os.join(" | "); |
| 21483 } |
| 21484 return os[0]; |
| 21485 }, |
| 21486 pool: function(bot) { |
| 21487 var pool = this._dimension(bot, 'pool') || ['Unknown']; |
| 21488 return pool.join(" | "); |
| 21489 }, |
| 21490 status: function(bot) { |
| 21491 // If a bot is both dead and quarantined, show the deadness over the |
| 21492 // quarentinedness. |
| 21493 if (bot.is_dead) { |
| 21494 return "Dead: " + bot.is_dead; |
| 21495 } |
| 21496 if (bot.quarantined) { |
| 21497 return "Quarantined: " + bot.quarantined; |
| 21498 } |
| 21499 return "Alive"; |
| 21500 }, |
| 21501 task: function(bot){ |
| 21502 return this._taskId(bot); |
| 21503 }, |
| 21504 }; |
| 21505 |
| 21506 Polymer({ |
| 21507 is: 'bot-list', |
| 21508 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 21509 |
| 21510 properties: { |
| 21511 |
| 21512 columns: { |
| 21513 type: Array, |
| 21514 }, |
| 21515 // Should have a property "filter" which is a function. |
| 21516 filter: { |
| 21517 type: Object, |
| 21518 }, |
| 21519 |
| 21520 plain_columns: { |
| 21521 type: Array, |
| 21522 computed: "_stripSpecial(columns.*)", |
| 21523 }, |
| 21524 |
| 21525 // sort is an Object {name:String, direction:String}. |
| 21526 sort: { |
| 21527 type: Object, |
| 21528 }, |
| 21529 |
| 21530 verbose: { |
| 21531 type: Boolean, |
| 21532 } |
| 21533 }, |
| 21534 |
| 21535 observers: [ |
| 21536 '_reRender(filter.*)', |
| 21537 '_checkSorts(columns.*)' |
| 21538 ], |
| 21539 |
| 21540 _botClass: function(bot) { |
| 21541 if (bot.is_dead) { |
| 21542 return "dead"; |
| 21543 } |
| 21544 if (bot.quarantined) { |
| 21545 return "quarantined"; |
| 21546 } |
| 21547 return ""; |
| 21548 }, |
| 21549 |
| 21550 _botLink: function(id) { |
| 21551 // TODO(kjlubick) Make this point to /newui/ when appropriate. |
| 21552 return "/restricted/bot/"+id; |
| 21553 }, |
| 21554 |
| 21555 // _checkSorts makes sure that if a column has been removed, the related |
| 21556 // sort is also removed. |
| 21557 _checkSorts: function() { |
| 21558 if (!this.sort) { |
| 21559 return; |
| 21560 } |
| 21561 this._reRender(); |
| 21562 }, |
| 21563 |
| 21564 _column: function(col, bot) { |
| 21565 return columnMap[col].bind(this)(bot); |
| 21566 }, |
| 21567 |
| 21568 _deviceColumn: function(col, device) { |
| 21569 if (col === "devices") { |
| 21570 var str = this._androidAlias(device); |
| 21571 if (device.okay) { |
| 21572 str = this._applyAlias(this._deviceType(device), str); |
| 21573 } |
| 21574 str += " S/N:"; |
| 21575 str += device.serial; |
| 21576 return str; |
| 21577 } |
| 21578 if (col === "status") { |
| 21579 return device.state; |
| 21580 } |
| 21581 return ""; |
| 21582 }, |
| 21583 |
| 21584 _deviceClass: function(device) { |
| 21585 if (!device.okay) { |
| 21586 return "bad-device"; |
| 21587 } |
| 21588 return ""; |
| 21589 }, |
| 21590 |
| 21591 _filterBotTable: function(bot) { |
| 21592 if (!this.filter || !this.filter.filter) { |
| 21593 return true; |
| 21594 } |
| 21595 return this.filter.filter.bind(this)(bot); |
| 21596 }, |
| 21597 |
| 21598 _header: function(col){ |
| 21599 return headerMap[col]; |
| 21600 }, |
| 21601 |
| 21602 _hide: function(col) { |
| 21603 return this.columns.indexOf(col) === -1; |
| 21604 }, |
| 21605 |
| 21606 _reRender: function(filter, sort) { |
| 21607 this.$.bot_table.render(); |
| 21608 }, |
| 21609 |
| 21610 _sortBotTable: function(botA, botB) { |
| 21611 if (!this.sort) { |
| 21612 return 0; |
| 21613 } |
| 21614 var dir = 1; |
| 21615 if (this.sort.direction === "desc") { |
| 21616 dir = -1; |
| 21617 } |
| 21618 var botACol = this._column(this.sort.name, botA); |
| 21619 var botBCol = this._column(this.sort.name, botB); |
| 21620 |
| 21621 return dir * swarming.naturalCompare(botACol, botBCol); |
| 21622 }, |
| 21623 |
| 21624 sortChange: function(e) { |
| 21625 // The event we get from sort-toggle tells us the name of what needs |
| 21626 // to be sorting and how to sort it. |
| 21627 if (!(e && e.detail && e.detail.name)) { |
| 21628 return; |
| 21629 } |
| 21630 this.set("sort", e.detail); |
| 21631 swarming.stableSort(this.bots, this._sortBotTable.bind(this)); |
| 21632 this._reRender(); |
| 21633 }, |
| 21634 |
| 21635 // _stripSpecial removes the special columns and sorts the remaining |
| 21636 // columns so they always appear in the same order, regardless of |
| 21637 // the order they are added. |
| 21638 _stripSpecial: function(){ |
| 21639 return this.columns.filter(function(c){ |
| 21640 return special_columns.indexOf(c) === -1; |
| 21641 }).sort(); |
| 21642 }, |
| 21643 |
| 21644 _taskLink: function(data) { |
| 21645 if (data && data.task_id) { |
| 21646 return "/user/task/" + data.task_id; |
| 21647 } |
| 21648 return undefined; |
| 21649 } |
| 21650 |
| 21651 }); |
| 21652 })(); |
| 21653 </script> |
| 14650 </dom-module></div></body></html> | 21654 </dom-module></div></body></html> |
| OLD | NEW |