| 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. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --><!-- |
| 10 @license |
| 3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. | 11 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 12 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 | 13 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 | 14 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 | 15 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 | 16 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --><!-- | 17 --><!-- |
| 10 @license | 18 @license |
| 11 Copyright (c) 2014 The Polymer Project Authors. All rights reserved. | 19 Copyright (c) 2014 The Polymer Project Authors. All rights reserved. |
| 12 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 20 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| (...skipping 9139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9152 this.generateRequest(); | 9160 this.generateRequest(); |
| 9153 } | 9161 } |
| 9154 }, this.debounceDuration); | 9162 }, this.debounceDuration); |
| 9155 }, | 9163 }, |
| 9156 | 9164 |
| 9157 }); | 9165 }); |
| 9158 </script> | 9166 </script> |
| 9159 | 9167 |
| 9160 | 9168 |
| 9161 <script> | 9169 <script> |
| 9170 Polymer.AppLayout = Polymer.AppLayout || {}; |
| 9171 |
| 9172 Polymer.AppLayout._scrollEffects = Polymer.AppLayout._scrollEffects || {}; |
| 9173 |
| 9174 Polymer.AppLayout.scrollTimingFunction = function easeOutQuad(t, b, c, d) { |
| 9175 t /= d; |
| 9176 return -c * t*(t-2) + b; |
| 9177 }; |
| 9178 |
| 9179 /** |
| 9180 * Registers a scroll effect to be used in elements that implement the |
| 9181 * `Polymer.AppScrollEffectsBehavior` behavior. |
| 9182 * |
| 9183 * @param {string} effectName The effect name. |
| 9184 * @param {Object} effectDef The effect definition. |
| 9185 */ |
| 9186 Polymer.AppLayout.registerEffect = function registerEffect(effectName, effectD
ef) { |
| 9187 if (Polymer.AppLayout._scrollEffects[effectName] != null) { |
| 9188 throw new Error('effect `'+ effectName + '` is already registered.'); |
| 9189 } |
| 9190 Polymer.AppLayout._scrollEffects[effectName] = effectDef; |
| 9191 }; |
| 9192 |
| 9193 /** |
| 9194 * Scrolls to a particular set of coordinates in a scroll target. |
| 9195 * If the scroll target is not defined, then it would use the main document as
the target. |
| 9196 * |
| 9197 * To scroll in a smooth fashion, you can set the option `behavior: 'smooth'`.
e.g. |
| 9198 * |
| 9199 * ```js |
| 9200 * Polymer.AppLayout.scroll({top: 0, behavior: 'smooth'}); |
| 9201 * ``` |
| 9202 * |
| 9203 * To scroll in a silent mode, without notifying scroll changes to any app-lay
out elements, |
| 9204 * you can set the option `behavior: 'silent'`. This is particularly useful we
you are using |
| 9205 * `app-header` and you desire to scroll to the top of a scrolling region with
out running |
| 9206 * scroll effects. e.g. |
| 9207 * |
| 9208 * ```js |
| 9209 * Polymer.AppLayout.scroll({top: 0, behavior: 'silent'}); |
| 9210 * ``` |
| 9211 * |
| 9212 * @param {Object} options {top: Number, left: Number, behavior: String(smooth
| silent)} |
| 9213 */ |
| 9214 Polymer.AppLayout.scroll = function scroll(options) { |
| 9215 options = options || {}; |
| 9216 |
| 9217 var docEl = document.documentElement; |
| 9218 var target = options.target || docEl; |
| 9219 var hasNativeScrollBehavior = 'scrollBehavior' in target.style && target.scr
oll; |
| 9220 var scrollClassName = 'app-layout-silent-scroll'; |
| 9221 var scrollTop = options.top || 0; |
| 9222 var scrollLeft = options.left || 0; |
| 9223 var scrollTo = target === docEl ? window.scrollTo : |
| 9224 function scrollTo(scrollLeft, scrollTop) { |
| 9225 target.scrollLeft = scrollLeft; |
| 9226 target.scrollTop = scrollTop; |
| 9227 }; |
| 9228 |
| 9229 if (options.behavior === 'smooth') { |
| 9230 |
| 9231 if (hasNativeScrollBehavior) { |
| 9232 |
| 9233 target.scroll(options); |
| 9234 |
| 9235 } else { |
| 9236 |
| 9237 var timingFn = Polymer.AppLayout.scrollTimingFunction; |
| 9238 var startTime = Date.now(); |
| 9239 var currentScrollTop = target === docEl ? window.pageYOffset : target.sc
rollTop; |
| 9240 var currentScrollLeft = target === docEl ? window.pageXOffset : target.s
crollLeft; |
| 9241 var deltaScrollTop = scrollTop - currentScrollTop; |
| 9242 var deltaScrollLeft = scrollLeft - currentScrollLeft; |
| 9243 var duration = 300; |
| 9244 var updateFrame = (function updateFrame() { |
| 9245 var now = Date.now(); |
| 9246 var elapsedTime = now - startTime; |
| 9247 |
| 9248 if (elapsedTime < duration) { |
| 9249 scrollTo(timingFn(elapsedTime, currentScrollLeft, deltaScrollLeft, d
uration), |
| 9250 timingFn(elapsedTime, currentScrollTop, deltaScrollTop, duration
)); |
| 9251 requestAnimationFrame(updateFrame); |
| 9252 } else { |
| 9253 scrollTo(scrollLeft, scrollTop); |
| 9254 } |
| 9255 }).bind(this); |
| 9256 |
| 9257 updateFrame(); |
| 9258 } |
| 9259 |
| 9260 } else if (options.behavior === 'silent') { |
| 9261 |
| 9262 docEl.classList.add(scrollClassName); |
| 9263 |
| 9264 // Browsers keep the scroll momentum even if the bottom of the scrolling c
ontent |
| 9265 // was reached. This means that calling scroll({top: 0, behavior: 'silent'
}) when |
| 9266 // the momentum is still going will result in more scroll events and thus
scroll effects. |
| 9267 // This seems to only apply when using document scrolling. |
| 9268 // Therefore, when should we remove the class from the document element? |
| 9269 |
| 9270 clearInterval(Polymer.AppLayout._scrollTimer); |
| 9271 |
| 9272 Polymer.AppLayout._scrollTimer = setTimeout(function() { |
| 9273 docEl.classList.remove(scrollClassName); |
| 9274 Polymer.AppLayout._scrollTimer = null; |
| 9275 }, 100); |
| 9276 |
| 9277 scrollTo(scrollLeft, scrollTop); |
| 9278 |
| 9279 } else { |
| 9280 |
| 9281 scrollTo(scrollLeft, scrollTop); |
| 9282 |
| 9283 } |
| 9284 }; |
| 9285 |
| 9286 </script> |
| 9287 |
| 9288 |
| 9289 <style> |
| 9290 /* IE 10 support for HTML5 hidden attr */ |
| 9291 [hidden] { |
| 9292 display: none !important; |
| 9293 } |
| 9294 </style> |
| 9295 |
| 9296 <style is="custom-style"> |
| 9297 :root { |
| 9298 |
| 9299 --layout: { |
| 9300 display: -ms-flexbox; |
| 9301 display: -webkit-flex; |
| 9302 display: flex; |
| 9303 }; |
| 9304 |
| 9305 --layout-inline: { |
| 9306 display: -ms-inline-flexbox; |
| 9307 display: -webkit-inline-flex; |
| 9308 display: inline-flex; |
| 9309 }; |
| 9310 |
| 9311 --layout-horizontal: { |
| 9312 @apply(--layout); |
| 9313 |
| 9314 -ms-flex-direction: row; |
| 9315 -webkit-flex-direction: row; |
| 9316 flex-direction: row; |
| 9317 }; |
| 9318 |
| 9319 --layout-horizontal-reverse: { |
| 9320 @apply(--layout); |
| 9321 |
| 9322 -ms-flex-direction: row-reverse; |
| 9323 -webkit-flex-direction: row-reverse; |
| 9324 flex-direction: row-reverse; |
| 9325 }; |
| 9326 |
| 9327 --layout-vertical: { |
| 9328 @apply(--layout); |
| 9329 |
| 9330 -ms-flex-direction: column; |
| 9331 -webkit-flex-direction: column; |
| 9332 flex-direction: column; |
| 9333 }; |
| 9334 |
| 9335 --layout-vertical-reverse: { |
| 9336 @apply(--layout); |
| 9337 |
| 9338 -ms-flex-direction: column-reverse; |
| 9339 -webkit-flex-direction: column-reverse; |
| 9340 flex-direction: column-reverse; |
| 9341 }; |
| 9342 |
| 9343 --layout-wrap: { |
| 9344 -ms-flex-wrap: wrap; |
| 9345 -webkit-flex-wrap: wrap; |
| 9346 flex-wrap: wrap; |
| 9347 }; |
| 9348 |
| 9349 --layout-wrap-reverse: { |
| 9350 -ms-flex-wrap: wrap-reverse; |
| 9351 -webkit-flex-wrap: wrap-reverse; |
| 9352 flex-wrap: wrap-reverse; |
| 9353 }; |
| 9354 |
| 9355 --layout-flex-auto: { |
| 9356 -ms-flex: 1 1 auto; |
| 9357 -webkit-flex: 1 1 auto; |
| 9358 flex: 1 1 auto; |
| 9359 }; |
| 9360 |
| 9361 --layout-flex-none: { |
| 9362 -ms-flex: none; |
| 9363 -webkit-flex: none; |
| 9364 flex: none; |
| 9365 }; |
| 9366 |
| 9367 --layout-flex: { |
| 9368 -ms-flex: 1 1 0.000000001px; |
| 9369 -webkit-flex: 1; |
| 9370 flex: 1; |
| 9371 -webkit-flex-basis: 0.000000001px; |
| 9372 flex-basis: 0.000000001px; |
| 9373 }; |
| 9374 |
| 9375 --layout-flex-2: { |
| 9376 -ms-flex: 2; |
| 9377 -webkit-flex: 2; |
| 9378 flex: 2; |
| 9379 }; |
| 9380 |
| 9381 --layout-flex-3: { |
| 9382 -ms-flex: 3; |
| 9383 -webkit-flex: 3; |
| 9384 flex: 3; |
| 9385 }; |
| 9386 |
| 9387 --layout-flex-4: { |
| 9388 -ms-flex: 4; |
| 9389 -webkit-flex: 4; |
| 9390 flex: 4; |
| 9391 }; |
| 9392 |
| 9393 --layout-flex-5: { |
| 9394 -ms-flex: 5; |
| 9395 -webkit-flex: 5; |
| 9396 flex: 5; |
| 9397 }; |
| 9398 |
| 9399 --layout-flex-6: { |
| 9400 -ms-flex: 6; |
| 9401 -webkit-flex: 6; |
| 9402 flex: 6; |
| 9403 }; |
| 9404 |
| 9405 --layout-flex-7: { |
| 9406 -ms-flex: 7; |
| 9407 -webkit-flex: 7; |
| 9408 flex: 7; |
| 9409 }; |
| 9410 |
| 9411 --layout-flex-8: { |
| 9412 -ms-flex: 8; |
| 9413 -webkit-flex: 8; |
| 9414 flex: 8; |
| 9415 }; |
| 9416 |
| 9417 --layout-flex-9: { |
| 9418 -ms-flex: 9; |
| 9419 -webkit-flex: 9; |
| 9420 flex: 9; |
| 9421 }; |
| 9422 |
| 9423 --layout-flex-10: { |
| 9424 -ms-flex: 10; |
| 9425 -webkit-flex: 10; |
| 9426 flex: 10; |
| 9427 }; |
| 9428 |
| 9429 --layout-flex-11: { |
| 9430 -ms-flex: 11; |
| 9431 -webkit-flex: 11; |
| 9432 flex: 11; |
| 9433 }; |
| 9434 |
| 9435 --layout-flex-12: { |
| 9436 -ms-flex: 12; |
| 9437 -webkit-flex: 12; |
| 9438 flex: 12; |
| 9439 }; |
| 9440 |
| 9441 /* alignment in cross axis */ |
| 9442 |
| 9443 --layout-start: { |
| 9444 -ms-flex-align: start; |
| 9445 -webkit-align-items: flex-start; |
| 9446 align-items: flex-start; |
| 9447 }; |
| 9448 |
| 9449 --layout-center: { |
| 9450 -ms-flex-align: center; |
| 9451 -webkit-align-items: center; |
| 9452 align-items: center; |
| 9453 }; |
| 9454 |
| 9455 --layout-end: { |
| 9456 -ms-flex-align: end; |
| 9457 -webkit-align-items: flex-end; |
| 9458 align-items: flex-end; |
| 9459 }; |
| 9460 |
| 9461 --layout-baseline: { |
| 9462 -ms-flex-align: baseline; |
| 9463 -webkit-align-items: baseline; |
| 9464 align-items: baseline; |
| 9465 }; |
| 9466 |
| 9467 /* alignment in main axis */ |
| 9468 |
| 9469 --layout-start-justified: { |
| 9470 -ms-flex-pack: start; |
| 9471 -webkit-justify-content: flex-start; |
| 9472 justify-content: flex-start; |
| 9473 }; |
| 9474 |
| 9475 --layout-center-justified: { |
| 9476 -ms-flex-pack: center; |
| 9477 -webkit-justify-content: center; |
| 9478 justify-content: center; |
| 9479 }; |
| 9480 |
| 9481 --layout-end-justified: { |
| 9482 -ms-flex-pack: end; |
| 9483 -webkit-justify-content: flex-end; |
| 9484 justify-content: flex-end; |
| 9485 }; |
| 9486 |
| 9487 --layout-around-justified: { |
| 9488 -ms-flex-pack: distribute; |
| 9489 -webkit-justify-content: space-around; |
| 9490 justify-content: space-around; |
| 9491 }; |
| 9492 |
| 9493 --layout-justified: { |
| 9494 -ms-flex-pack: justify; |
| 9495 -webkit-justify-content: space-between; |
| 9496 justify-content: space-between; |
| 9497 }; |
| 9498 |
| 9499 --layout-center-center: { |
| 9500 @apply(--layout-center); |
| 9501 @apply(--layout-center-justified); |
| 9502 }; |
| 9503 |
| 9504 /* self alignment */ |
| 9505 |
| 9506 --layout-self-start: { |
| 9507 -ms-align-self: flex-start; |
| 9508 -webkit-align-self: flex-start; |
| 9509 align-self: flex-start; |
| 9510 }; |
| 9511 |
| 9512 --layout-self-center: { |
| 9513 -ms-align-self: center; |
| 9514 -webkit-align-self: center; |
| 9515 align-self: center; |
| 9516 }; |
| 9517 |
| 9518 --layout-self-end: { |
| 9519 -ms-align-self: flex-end; |
| 9520 -webkit-align-self: flex-end; |
| 9521 align-self: flex-end; |
| 9522 }; |
| 9523 |
| 9524 --layout-self-stretch: { |
| 9525 -ms-align-self: stretch; |
| 9526 -webkit-align-self: stretch; |
| 9527 align-self: stretch; |
| 9528 }; |
| 9529 |
| 9530 --layout-self-baseline: { |
| 9531 -ms-align-self: baseline; |
| 9532 -webkit-align-self: baseline; |
| 9533 align-self: baseline; |
| 9534 }; |
| 9535 |
| 9536 /* multi-line alignment in main axis */ |
| 9537 |
| 9538 --layout-start-aligned: { |
| 9539 -ms-flex-line-pack: start; /* IE10 */ |
| 9540 -ms-align-content: flex-start; |
| 9541 -webkit-align-content: flex-start; |
| 9542 align-content: flex-start; |
| 9543 }; |
| 9544 |
| 9545 --layout-end-aligned: { |
| 9546 -ms-flex-line-pack: end; /* IE10 */ |
| 9547 -ms-align-content: flex-end; |
| 9548 -webkit-align-content: flex-end; |
| 9549 align-content: flex-end; |
| 9550 }; |
| 9551 |
| 9552 --layout-center-aligned: { |
| 9553 -ms-flex-line-pack: center; /* IE10 */ |
| 9554 -ms-align-content: center; |
| 9555 -webkit-align-content: center; |
| 9556 align-content: center; |
| 9557 }; |
| 9558 |
| 9559 --layout-between-aligned: { |
| 9560 -ms-flex-line-pack: justify; /* IE10 */ |
| 9561 -ms-align-content: space-between; |
| 9562 -webkit-align-content: space-between; |
| 9563 align-content: space-between; |
| 9564 }; |
| 9565 |
| 9566 --layout-around-aligned: { |
| 9567 -ms-flex-line-pack: distribute; /* IE10 */ |
| 9568 -ms-align-content: space-around; |
| 9569 -webkit-align-content: space-around; |
| 9570 align-content: space-around; |
| 9571 }; |
| 9572 |
| 9573 /******************************* |
| 9574 Other Layout |
| 9575 *******************************/ |
| 9576 |
| 9577 --layout-block: { |
| 9578 display: block; |
| 9579 }; |
| 9580 |
| 9581 --layout-invisible: { |
| 9582 visibility: hidden !important; |
| 9583 }; |
| 9584 |
| 9585 --layout-relative: { |
| 9586 position: relative; |
| 9587 }; |
| 9588 |
| 9589 --layout-fit: { |
| 9590 position: absolute; |
| 9591 top: 0; |
| 9592 right: 0; |
| 9593 bottom: 0; |
| 9594 left: 0; |
| 9595 }; |
| 9596 |
| 9597 --layout-scroll: { |
| 9598 -webkit-overflow-scrolling: touch; |
| 9599 overflow: auto; |
| 9600 }; |
| 9601 |
| 9602 --layout-fullbleed: { |
| 9603 margin: 0; |
| 9604 height: 100vh; |
| 9605 }; |
| 9606 |
| 9607 /* fixed position */ |
| 9608 |
| 9609 --layout-fixed-top: { |
| 9610 position: fixed; |
| 9611 top: 0; |
| 9612 left: 0; |
| 9613 right: 0; |
| 9614 }; |
| 9615 |
| 9616 --layout-fixed-right: { |
| 9617 position: fixed; |
| 9618 top: 0; |
| 9619 right: 0; |
| 9620 bottom: 0; |
| 9621 }; |
| 9622 |
| 9623 --layout-fixed-bottom: { |
| 9624 position: fixed; |
| 9625 right: 0; |
| 9626 bottom: 0; |
| 9627 left: 0; |
| 9628 }; |
| 9629 |
| 9630 --layout-fixed-left: { |
| 9631 position: fixed; |
| 9632 top: 0; |
| 9633 bottom: 0; |
| 9634 left: 0; |
| 9635 }; |
| 9636 |
| 9637 } |
| 9638 |
| 9639 </style> |
| 9640 |
| 9641 |
| 9642 <dom-module id="app-drawer" assetpath="bower_components/app-layout/app-drawer/"> |
| 9643 <template> |
| 9644 <style> |
| 9645 :host { |
| 9646 position: fixed; |
| 9647 top: -120px; |
| 9648 right: 0; |
| 9649 bottom: -120px; |
| 9650 left: 0; |
| 9651 |
| 9652 visibility: hidden; |
| 9653 |
| 9654 transition: visibility 0.2s ease; |
| 9655 } |
| 9656 |
| 9657 :host([opened]) { |
| 9658 visibility: visible; |
| 9659 } |
| 9660 |
| 9661 :host([persistent]) { |
| 9662 width: var(--app-drawer-width, 256px); |
| 9663 } |
| 9664 |
| 9665 :host([persistent][position=left]) { |
| 9666 right: auto; |
| 9667 } |
| 9668 |
| 9669 :host([persistent][position=right]) { |
| 9670 left: auto; |
| 9671 } |
| 9672 |
| 9673 #contentContainer { |
| 9674 position: absolute; |
| 9675 top: 0; |
| 9676 bottom: 0; |
| 9677 left: 0; |
| 9678 |
| 9679 width: var(--app-drawer-width, 256px); |
| 9680 padding: 120px 0; |
| 9681 |
| 9682 transition: 0.2s ease; |
| 9683 transition-property: -webkit-transform; |
| 9684 transition-property: transform; |
| 9685 -webkit-transform: translate3d(-100%, 0, 0); |
| 9686 transform: translate3d(-100%, 0, 0); |
| 9687 |
| 9688 background-color: #FFF; |
| 9689 |
| 9690 @apply(--app-drawer-content-container); |
| 9691 } |
| 9692 |
| 9693 :host([position=right]) > #contentContainer { |
| 9694 right: 0; |
| 9695 left: auto; |
| 9696 |
| 9697 -webkit-transform: translate3d(100%, 0, 0); |
| 9698 transform: translate3d(100%, 0, 0); |
| 9699 } |
| 9700 |
| 9701 :host([swipe-open]) > #contentContainer::after { |
| 9702 position: fixed; |
| 9703 top: 0; |
| 9704 bottom: 0; |
| 9705 left: 100%; |
| 9706 |
| 9707 visibility: visible; |
| 9708 |
| 9709 width: 20px; |
| 9710 |
| 9711 content: ''; |
| 9712 } |
| 9713 |
| 9714 :host([swipe-open][position=right]) > #contentContainer::after { |
| 9715 right: 100%; |
| 9716 left: auto; |
| 9717 } |
| 9718 |
| 9719 :host([opened]) > #contentContainer { |
| 9720 -webkit-transform: translate3d(0, 0, 0); |
| 9721 transform: translate3d(0, 0, 0); |
| 9722 } |
| 9723 |
| 9724 #scrim { |
| 9725 position: absolute; |
| 9726 top: 0; |
| 9727 right: 0; |
| 9728 bottom: 0; |
| 9729 left: 0; |
| 9730 |
| 9731 transition: opacity 0.2s ease; |
| 9732 -webkit-transform: translateZ(0); |
| 9733 transform: translateZ(0); |
| 9734 |
| 9735 opacity: 0; |
| 9736 background: var(--app-drawer-scrim-background, rgba(0, 0, 0, 0.5)); |
| 9737 } |
| 9738 |
| 9739 :host([opened]) > #scrim { |
| 9740 opacity: 1; |
| 9741 } |
| 9742 |
| 9743 :host([opened][persistent]) > #scrim { |
| 9744 visibility: hidden; |
| 9745 /** |
| 9746 * NOTE(keanulee): Keep both opacity: 0 and visibility: hidden to preven
t the |
| 9747 * scrim from showing when toggling between closed and opened/persistent
. |
| 9748 */ |
| 9749 |
| 9750 opacity: 0; |
| 9751 } |
| 9752 </style> |
| 9753 |
| 9754 <div id="scrim" on-tap="close"></div> |
| 9755 |
| 9756 <div id="contentContainer"> |
| 9757 <content></content> |
| 9758 </div> |
| 9759 </template> |
| 9760 |
| 9761 <script> |
| 9762 |
| 9763 Polymer({ |
| 9764 is: 'app-drawer', |
| 9765 |
| 9766 properties: { |
| 9767 /** |
| 9768 * The opened state of the drawer. |
| 9769 */ |
| 9770 opened: { |
| 9771 type: Boolean, |
| 9772 value: false, |
| 9773 notify: true, |
| 9774 reflectToAttribute: true |
| 9775 }, |
| 9776 |
| 9777 /** |
| 9778 * The drawer does not have a scrim and cannot be swiped close. |
| 9779 */ |
| 9780 persistent: { |
| 9781 type: Boolean, |
| 9782 value: false, |
| 9783 reflectToAttribute: true |
| 9784 }, |
| 9785 |
| 9786 /** |
| 9787 * The alignment of the drawer on the screen ('left', 'right', 'start' o
r 'end'). |
| 9788 * 'start' computes to left and 'end' to right in LTR layout and vice ve
rsa in RTL |
| 9789 * layout. |
| 9790 */ |
| 9791 align: { |
| 9792 type: String, |
| 9793 value: 'left' |
| 9794 }, |
| 9795 |
| 9796 /** |
| 9797 * The computed, read-only position of the drawer on the screen ('left'
or 'right'). |
| 9798 */ |
| 9799 position: { |
| 9800 type: String, |
| 9801 readOnly: true, |
| 9802 reflectToAttribute: true |
| 9803 }, |
| 9804 |
| 9805 /** |
| 9806 * Create an area at the edge of the screen to swipe open the drawer. |
| 9807 */ |
| 9808 swipeOpen: { |
| 9809 type: Boolean, |
| 9810 value: false, |
| 9811 reflectToAttribute: true |
| 9812 }, |
| 9813 |
| 9814 /** |
| 9815 * Trap keyboard focus when the drawer is opened and not persistent. |
| 9816 */ |
| 9817 noFocusTrap: { |
| 9818 type: Boolean, |
| 9819 value: false |
| 9820 } |
| 9821 }, |
| 9822 |
| 9823 observers: [ |
| 9824 'resetLayout(position, isAttached)', |
| 9825 '_resetPosition(align, isAttached)' |
| 9826 ], |
| 9827 |
| 9828 _translateOffset: 0, |
| 9829 |
| 9830 _trackDetails: null, |
| 9831 |
| 9832 _drawerState: 0, |
| 9833 |
| 9834 _boundEscKeydownHandler: null, |
| 9835 |
| 9836 _firstTabStop: null, |
| 9837 |
| 9838 _lastTabStop: null, |
| 9839 |
| 9840 ready: function() { |
| 9841 // Only transition the drawer after its first render (e.g. app-drawer-la
yout |
| 9842 // may need to set the initial opened state which should not be transiti
oned). |
| 9843 this._setTransitionDuration('0s'); |
| 9844 }, |
| 9845 |
| 9846 attached: function() { |
| 9847 // Only transition the drawer after its first render (e.g. app-drawer-la
yout |
| 9848 // may need to set the initial opened state which should not be transiti
oned). |
| 9849 Polymer.RenderStatus.afterNextRender(this, function() { |
| 9850 this._setTransitionDuration(''); |
| 9851 this._boundEscKeydownHandler = this._escKeydownHandler.bind(this); |
| 9852 this._resetDrawerState(); |
| 9853 |
| 9854 this.addEventListener('transitionend', this._transitionend.bind(this))
; |
| 9855 this.addEventListener('keydown', this._tabKeydownHandler.bind(this)) |
| 9856 |
| 9857 // Only listen for horizontal track so you can vertically scroll insid
e the drawer. |
| 9858 this.listen(this, 'track', '_track'); |
| 9859 this.setScrollDirection('y'); |
| 9860 }); |
| 9861 }, |
| 9862 |
| 9863 detached: function() { |
| 9864 document.removeEventListener('keydown', this._boundEscKeydownHandler); |
| 9865 }, |
| 9866 |
| 9867 /** |
| 9868 * Opens the drawer. |
| 9869 */ |
| 9870 open: function() { |
| 9871 this.opened = true; |
| 9872 }, |
| 9873 |
| 9874 /** |
| 9875 * Closes the drawer. |
| 9876 */ |
| 9877 close: function() { |
| 9878 this.opened = false; |
| 9879 }, |
| 9880 |
| 9881 /** |
| 9882 * Toggles the drawer open and close. |
| 9883 */ |
| 9884 toggle: function() { |
| 9885 this.opened = !this.opened; |
| 9886 }, |
| 9887 |
| 9888 /** |
| 9889 * Gets the width of the drawer. |
| 9890 * |
| 9891 * @return {number} The width of the drawer in pixels. |
| 9892 */ |
| 9893 getWidth: function() { |
| 9894 return this.$.contentContainer.offsetWidth; |
| 9895 }, |
| 9896 |
| 9897 /** |
| 9898 * Resets the layout. The event fired is used by app-drawer-layout to posi
tion the |
| 9899 * content. |
| 9900 * |
| 9901 * @method resetLayout |
| 9902 */ |
| 9903 resetLayout: function() { |
| 9904 this.fire('app-drawer-reset-layout'); |
| 9905 }, |
| 9906 |
| 9907 _isRTL: function() { |
| 9908 return window.getComputedStyle(this).direction === 'rtl'; |
| 9909 }, |
| 9910 |
| 9911 _resetPosition: function() { |
| 9912 switch (this.align) { |
| 9913 case 'start': |
| 9914 this._setPosition(this._isRTL() ? 'right' : 'left'); |
| 9915 return; |
| 9916 case 'end': |
| 9917 this._setPosition(this._isRTL() ? 'left' : 'right'); |
| 9918 return; |
| 9919 } |
| 9920 this._setPosition(this.align); |
| 9921 }, |
| 9922 |
| 9923 _escKeydownHandler: function(event) { |
| 9924 var ESC_KEYCODE = 27; |
| 9925 if (event.keyCode === ESC_KEYCODE) { |
| 9926 // Prevent any side effects if app-drawer closes. |
| 9927 event.preventDefault(); |
| 9928 this.close(); |
| 9929 } |
| 9930 }, |
| 9931 |
| 9932 _track: function(event) { |
| 9933 if (this.persistent) { |
| 9934 return; |
| 9935 } |
| 9936 |
| 9937 // Disable user selection on desktop. |
| 9938 event.preventDefault(); |
| 9939 |
| 9940 switch (event.detail.state) { |
| 9941 case 'start': |
| 9942 this._trackStart(event); |
| 9943 break; |
| 9944 case 'track': |
| 9945 this._trackMove(event); |
| 9946 break; |
| 9947 case 'end': |
| 9948 this._trackEnd(event); |
| 9949 break; |
| 9950 } |
| 9951 }, |
| 9952 |
| 9953 _trackStart: function(event) { |
| 9954 this._drawerState = this._DRAWER_STATE.TRACKING; |
| 9955 |
| 9956 // Disable transitions since style attributes will reflect user track ev
ents. |
| 9957 this._setTransitionDuration('0s'); |
| 9958 this.style.visibility = 'visible'; |
| 9959 |
| 9960 var rect = this.$.contentContainer.getBoundingClientRect(); |
| 9961 if (this.position === 'left') { |
| 9962 this._translateOffset = rect.left; |
| 9963 } else { |
| 9964 this._translateOffset = rect.right - window.innerWidth; |
| 9965 } |
| 9966 |
| 9967 this._trackDetails = []; |
| 9968 }, |
| 9969 |
| 9970 _trackMove: function(event) { |
| 9971 this._translateDrawer(event.detail.dx + this._translateOffset); |
| 9972 |
| 9973 // Use Date.now() since event.timeStamp is inconsistent across browsers
(e.g. most |
| 9974 // browsers use milliseconds but FF 44 uses microseconds). |
| 9975 this._trackDetails.push({ |
| 9976 dx: event.detail.dx, |
| 9977 timeStamp: Date.now() |
| 9978 }); |
| 9979 }, |
| 9980 |
| 9981 _trackEnd: function(event) { |
| 9982 var x = event.detail.dx + this._translateOffset; |
| 9983 var drawerWidth = this.getWidth(); |
| 9984 var isPositionLeft = this.position === 'left'; |
| 9985 var isInEndState = isPositionLeft ? (x >= 0 || x <= -drawerWidth) : |
| 9986 (x <= 0 || x >= drawerWidth); |
| 9987 |
| 9988 if (!isInEndState) { |
| 9989 // No longer need the track events after this method returns - allow t
hem to be GC'd. |
| 9990 var trackDetails = this._trackDetails; |
| 9991 this._trackDetails = null; |
| 9992 |
| 9993 this._flingDrawer(event, trackDetails); |
| 9994 if (this._drawerState === this._DRAWER_STATE.FLINGING) { |
| 9995 return; |
| 9996 } |
| 9997 } |
| 9998 |
| 9999 // If the drawer is not flinging, toggle the opened state based on the p
osition of |
| 10000 // the drawer. |
| 10001 var halfWidth = drawerWidth / 2; |
| 10002 if (event.detail.dx < -halfWidth) { |
| 10003 this.opened = this.position === 'right'; |
| 10004 } else if (event.detail.dx > halfWidth) { |
| 10005 this.opened = this.position === 'left'; |
| 10006 } |
| 10007 |
| 10008 // Trigger app-drawer-transitioned now since there will be no transition
end event. |
| 10009 if (isInEndState) { |
| 10010 this._resetDrawerState(); |
| 10011 } |
| 10012 |
| 10013 this._setTransitionDuration(''); |
| 10014 this._resetDrawerTranslate(); |
| 10015 this.style.visibility = ''; |
| 10016 }, |
| 10017 |
| 10018 _calculateVelocity: function(event, trackDetails) { |
| 10019 // Find the oldest track event that is within 100ms using binary search. |
| 10020 var now = Date.now(); |
| 10021 var timeLowerBound = now - 100; |
| 10022 var trackDetail; |
| 10023 var min = 0; |
| 10024 var max = trackDetails.length - 1; |
| 10025 |
| 10026 while (min <= max) { |
| 10027 // Floor of average of min and max. |
| 10028 var mid = (min + max) >> 1; |
| 10029 var d = trackDetails[mid]; |
| 10030 if (d.timeStamp >= timeLowerBound) { |
| 10031 trackDetail = d; |
| 10032 max = mid - 1; |
| 10033 } else { |
| 10034 min = mid + 1; |
| 10035 } |
| 10036 } |
| 10037 |
| 10038 if (trackDetail) { |
| 10039 var dx = event.detail.dx - trackDetail.dx; |
| 10040 var dt = (now - trackDetail.timeStamp) || 1; |
| 10041 return dx / dt; |
| 10042 } |
| 10043 return 0; |
| 10044 }, |
| 10045 |
| 10046 _flingDrawer: function(event, trackDetails) { |
| 10047 var velocity = this._calculateVelocity(event, trackDetails); |
| 10048 |
| 10049 // Do not fling if velocity is not above a threshold. |
| 10050 if (Math.abs(velocity) < this._MIN_FLING_THRESHOLD) { |
| 10051 return; |
| 10052 } |
| 10053 |
| 10054 this._drawerState = this._DRAWER_STATE.FLINGING; |
| 10055 |
| 10056 var x = event.detail.dx + this._translateOffset; |
| 10057 var drawerWidth = this.getWidth(); |
| 10058 var isPositionLeft = this.position === 'left'; |
| 10059 var isVelocityPositive = velocity > 0; |
| 10060 var isClosingLeft = !isVelocityPositive && isPositionLeft; |
| 10061 var isClosingRight = isVelocityPositive && !isPositionLeft; |
| 10062 var dx; |
| 10063 if (isClosingLeft) { |
| 10064 dx = -(x + drawerWidth); |
| 10065 } else if (isClosingRight) { |
| 10066 dx = (drawerWidth - x); |
| 10067 } else { |
| 10068 dx = -x; |
| 10069 } |
| 10070 |
| 10071 // Enforce a minimum transition velocity to make the drawer feel snappy. |
| 10072 if (isVelocityPositive) { |
| 10073 velocity = Math.max(velocity, this._MIN_TRANSITION_VELOCITY); |
| 10074 this.opened = this.position === 'left'; |
| 10075 } else { |
| 10076 velocity = Math.min(velocity, -this._MIN_TRANSITION_VELOCITY); |
| 10077 this.opened = this.position === 'right'; |
| 10078 } |
| 10079 |
| 10080 // Calculate the amount of time needed to finish the transition based on
the |
| 10081 // initial slope of the timing function. |
| 10082 this._setTransitionDuration((this._FLING_INITIAL_SLOPE * dx / velocity)
+ 'ms'); |
| 10083 this._setTransitionTimingFunction(this._FLING_TIMING_FUNCTION); |
| 10084 |
| 10085 this._resetDrawerTranslate(); |
| 10086 }, |
| 10087 |
| 10088 _transitionend: function(event) { |
| 10089 // contentContainer will transition on opened state changed, and scrim w
ill |
| 10090 // transition on persistent state changed when opened - these are the |
| 10091 // transitions we are interested in. |
| 10092 var target = Polymer.dom(event).rootTarget; |
| 10093 if (target === this.$.contentContainer || target === this.$.scrim) { |
| 10094 |
| 10095 // If the drawer was flinging, we need to reset the style attributes. |
| 10096 if (this._drawerState === this._DRAWER_STATE.FLINGING) { |
| 10097 this._setTransitionDuration(''); |
| 10098 this._setTransitionTimingFunction(''); |
| 10099 this.style.visibility = ''; |
| 10100 } |
| 10101 |
| 10102 this._resetDrawerState(); |
| 10103 } |
| 10104 }, |
| 10105 |
| 10106 _setTransitionDuration: function(duration) { |
| 10107 this.$.contentContainer.style.transitionDuration = duration; |
| 10108 this.$.scrim.style.transitionDuration = duration; |
| 10109 }, |
| 10110 |
| 10111 _setTransitionTimingFunction: function(timingFunction) { |
| 10112 this.$.contentContainer.style.transitionTimingFunction = timingFunction; |
| 10113 this.$.scrim.style.transitionTimingFunction = timingFunction; |
| 10114 }, |
| 10115 |
| 10116 _translateDrawer: function(x) { |
| 10117 var drawerWidth = this.getWidth(); |
| 10118 |
| 10119 if (this.position === 'left') { |
| 10120 x = Math.max(-drawerWidth, Math.min(x, 0)); |
| 10121 this.$.scrim.style.opacity = 1 + x / drawerWidth; |
| 10122 } else { |
| 10123 x = Math.max(0, Math.min(x, drawerWidth)); |
| 10124 this.$.scrim.style.opacity = 1 - x / drawerWidth; |
| 10125 } |
| 10126 |
| 10127 this.translate3d(x + 'px', '0', '0', this.$.contentContainer); |
| 10128 }, |
| 10129 |
| 10130 _resetDrawerTranslate: function() { |
| 10131 this.$.scrim.style.opacity = ''; |
| 10132 this.transform('', this.$.contentContainer); |
| 10133 }, |
| 10134 |
| 10135 _resetDrawerState: function() { |
| 10136 var oldState = this._drawerState; |
| 10137 if (this.opened) { |
| 10138 this._drawerState = this.persistent ? |
| 10139 this._DRAWER_STATE.OPENED_PERSISTENT : this._DRAWER_STATE.OPENED; |
| 10140 } else { |
| 10141 this._drawerState = this._DRAWER_STATE.CLOSED; |
| 10142 } |
| 10143 |
| 10144 if (oldState !== this._drawerState) { |
| 10145 if (this._drawerState === this._DRAWER_STATE.OPENED) { |
| 10146 this._setKeyboardFocusTrap(); |
| 10147 document.addEventListener('keydown', this._boundEscKeydownHandler); |
| 10148 document.body.style.overflow = 'hidden'; |
| 10149 } else { |
| 10150 document.removeEventListener('keydown', this._boundEscKeydownHandler
); |
| 10151 document.body.style.overflow = ''; |
| 10152 } |
| 10153 |
| 10154 // Don't fire the event on initial load. |
| 10155 if (oldState !== this._DRAWER_STATE.INIT) { |
| 10156 this.fire('app-drawer-transitioned'); |
| 10157 } |
| 10158 } |
| 10159 }, |
| 10160 |
| 10161 _setKeyboardFocusTrap: function() { |
| 10162 if (this.noFocusTrap) { |
| 10163 return; |
| 10164 } |
| 10165 |
| 10166 // NOTE: Unless we use /deep/ (which we shouldn't since it's deprecated)
, this will |
| 10167 // not select focusable elements inside shadow roots. |
| 10168 var focusableElementsSelector = [ |
| 10169 'a[href]:not([tabindex="-1"])', |
| 10170 'area[href]:not([tabindex="-1"])', |
| 10171 'input:not([disabled]):not([tabindex="-1"])', |
| 10172 'select:not([disabled]):not([tabindex="-1"])', |
| 10173 'textarea:not([disabled]):not([tabindex="-1"])', |
| 10174 'button:not([disabled]):not([tabindex="-1"])', |
| 10175 'iframe:not([tabindex="-1"])', |
| 10176 '[tabindex]:not([tabindex="-1"])', |
| 10177 '[contentEditable=true]:not([tabindex="-1"])' |
| 10178 ].join(','); |
| 10179 var focusableElements = Polymer.dom(this).querySelectorAll(focusableElem
entsSelector); |
| 10180 |
| 10181 if (focusableElements.length > 0) { |
| 10182 this._firstTabStop = focusableElements[0]; |
| 10183 this._lastTabStop = focusableElements[focusableElements.length - 1]; |
| 10184 } else { |
| 10185 // Reset saved tab stops when there are no focusable elements in the d
rawer. |
| 10186 this._firstTabStop = null; |
| 10187 this._lastTabStop = null; |
| 10188 } |
| 10189 |
| 10190 // Focus on app-drawer if it has non-zero tabindex. Otherwise, focus the
first focusable |
| 10191 // element in the drawer, if it exists. Use the tabindex attribute since
the this.tabIndex |
| 10192 // property in IE/Edge returns 0 (instead of -1) when the attribute is n
ot set. |
| 10193 var tabindex = this.getAttribute('tabindex'); |
| 10194 if (tabindex && parseInt(tabindex, 10) > -1) { |
| 10195 this.focus(); |
| 10196 } else if (this._firstTabStop) { |
| 10197 this._firstTabStop.focus(); |
| 10198 } |
| 10199 }, |
| 10200 |
| 10201 _tabKeydownHandler: function(event) { |
| 10202 if (this.noFocusTrap) { |
| 10203 return; |
| 10204 } |
| 10205 |
| 10206 var TAB_KEYCODE = 9; |
| 10207 if (this._drawerState === this._DRAWER_STATE.OPENED && event.keyCode ===
TAB_KEYCODE) { |
| 10208 if (event.shiftKey) { |
| 10209 if (this._firstTabStop && Polymer.dom(event).localTarget === this._f
irstTabStop) { |
| 10210 event.preventDefault(); |
| 10211 this._lastTabStop.focus(); |
| 10212 } |
| 10213 } else { |
| 10214 if (this._lastTabStop && Polymer.dom(event).localTarget === this._la
stTabStop) { |
| 10215 event.preventDefault(); |
| 10216 this._firstTabStop.focus(); |
| 10217 } |
| 10218 } |
| 10219 } |
| 10220 }, |
| 10221 |
| 10222 _MIN_FLING_THRESHOLD: 0.2, |
| 10223 |
| 10224 _MIN_TRANSITION_VELOCITY: 1.2, |
| 10225 |
| 10226 _FLING_TIMING_FUNCTION: 'cubic-bezier(0.667, 1, 0.667, 1)', |
| 10227 |
| 10228 _FLING_INITIAL_SLOPE: 1.5, |
| 10229 |
| 10230 _DRAWER_STATE: { |
| 10231 INIT: 0, |
| 10232 OPENED: 1, |
| 10233 OPENED_PERSISTENT: 2, |
| 10234 CLOSED: 3, |
| 10235 TRACKING: 4, |
| 10236 FLINGING: 5 |
| 10237 } |
| 10238 |
| 10239 /** |
| 10240 * Fired when the layout of app-drawer has changed. |
| 10241 * |
| 10242 * @event app-drawer-reset-layout |
| 10243 */ |
| 10244 |
| 10245 /** |
| 10246 * Fired when app-drawer has finished transitioning. |
| 10247 * |
| 10248 * @event app-drawer-transitioned |
| 10249 */ |
| 10250 }); |
| 10251 </script> |
| 10252 </dom-module> |
| 10253 |
| 10254 |
| 10255 <script> |
| 10256 |
| 10257 Polymer({ |
| 10258 |
| 10259 is: 'iron-media-query', |
| 10260 |
| 10261 properties: { |
| 10262 |
| 10263 /** |
| 10264 * The Boolean return value of the media query. |
| 10265 */ |
| 10266 queryMatches: { |
| 10267 type: Boolean, |
| 10268 value: false, |
| 10269 readOnly: true, |
| 10270 notify: true |
| 10271 }, |
| 10272 |
| 10273 /** |
| 10274 * The CSS media query to evaluate. |
| 10275 */ |
| 10276 query: { |
| 10277 type: String, |
| 10278 observer: 'queryChanged' |
| 10279 }, |
| 10280 |
| 10281 /** |
| 10282 * If true, the query attribute is assumed to be a complete media query |
| 10283 * string rather than a single media feature. |
| 10284 */ |
| 10285 full: { |
| 10286 type: Boolean, |
| 10287 value: false |
| 10288 }, |
| 10289 |
| 10290 /** |
| 10291 * @type {function(MediaQueryList)} |
| 10292 */ |
| 10293 _boundMQHandler: { |
| 10294 value: function() { |
| 10295 return this.queryHandler.bind(this); |
| 10296 } |
| 10297 }, |
| 10298 |
| 10299 /** |
| 10300 * @type {MediaQueryList} |
| 10301 */ |
| 10302 _mq: { |
| 10303 value: null |
| 10304 } |
| 10305 }, |
| 10306 |
| 10307 attached: function() { |
| 10308 this.style.display = 'none'; |
| 10309 this.queryChanged(); |
| 10310 }, |
| 10311 |
| 10312 detached: function() { |
| 10313 this._remove(); |
| 10314 }, |
| 10315 |
| 10316 _add: function() { |
| 10317 if (this._mq) { |
| 10318 this._mq.addListener(this._boundMQHandler); |
| 10319 } |
| 10320 }, |
| 10321 |
| 10322 _remove: function() { |
| 10323 if (this._mq) { |
| 10324 this._mq.removeListener(this._boundMQHandler); |
| 10325 } |
| 10326 this._mq = null; |
| 10327 }, |
| 10328 |
| 10329 queryChanged: function() { |
| 10330 this._remove(); |
| 10331 var query = this.query; |
| 10332 if (!query) { |
| 10333 return; |
| 10334 } |
| 10335 if (!this.full && query[0] !== '(') { |
| 10336 query = '(' + query + ')'; |
| 10337 } |
| 10338 this._mq = window.matchMedia(query); |
| 10339 this._add(); |
| 10340 this.queryHandler(this._mq); |
| 10341 }, |
| 10342 |
| 10343 queryHandler: function(mq) { |
| 10344 this._setQueryMatches(mq.matches); |
| 10345 } |
| 10346 |
| 10347 }); |
| 10348 |
| 10349 </script> |
| 10350 <script> |
| 10351 /** |
| 10352 * `IronResizableBehavior` is a behavior that can be used in Polymer elements
to |
| 10353 * coordinate the flow of resize events between "resizers" (elements that cont
rol the |
| 10354 * size or hidden state of their children) and "resizables" (elements that nee
d to be |
| 10355 * notified when they are resized or un-hidden by their parents in order to ta
ke |
| 10356 * action on their new measurements). |
| 10357 * |
| 10358 * Elements that perform measurement should add the `IronResizableBehavior` be
havior to |
| 10359 * their element definition and listen for the `iron-resize` event on themselv
es. |
| 10360 * This event will be fired when they become showing after having been hidden, |
| 10361 * when they are resized explicitly by another resizable, or when the window h
as been |
| 10362 * resized. |
| 10363 * |
| 10364 * Note, the `iron-resize` event is non-bubbling. |
| 10365 * |
| 10366 * @polymerBehavior Polymer.IronResizableBehavior |
| 10367 * @demo demo/index.html |
| 10368 **/ |
| 10369 Polymer.IronResizableBehavior = { |
| 10370 properties: { |
| 10371 /** |
| 10372 * The closest ancestor element that implements `IronResizableBehavior`. |
| 10373 */ |
| 10374 _parentResizable: { |
| 10375 type: Object, |
| 10376 observer: '_parentResizableChanged' |
| 10377 }, |
| 10378 |
| 10379 /** |
| 10380 * True if this element is currently notifying its descedant elements of |
| 10381 * resize. |
| 10382 */ |
| 10383 _notifyingDescendant: { |
| 10384 type: Boolean, |
| 10385 value: false |
| 10386 } |
| 10387 }, |
| 10388 |
| 10389 listeners: { |
| 10390 'iron-request-resize-notifications': '_onIronRequestResizeNotifications' |
| 10391 }, |
| 10392 |
| 10393 created: function() { |
| 10394 // We don't really need property effects on these, and also we want them |
| 10395 // to be created before the `_parentResizable` observer fires: |
| 10396 this._interestedResizables = []; |
| 10397 this._boundNotifyResize = this.notifyResize.bind(this); |
| 10398 }, |
| 10399 |
| 10400 attached: function() { |
| 10401 this.fire('iron-request-resize-notifications', null, { |
| 10402 node: this, |
| 10403 bubbles: true, |
| 10404 cancelable: true |
| 10405 }); |
| 10406 |
| 10407 if (!this._parentResizable) { |
| 10408 window.addEventListener('resize', this._boundNotifyResize); |
| 10409 this.notifyResize(); |
| 10410 } |
| 10411 }, |
| 10412 |
| 10413 detached: function() { |
| 10414 if (this._parentResizable) { |
| 10415 this._parentResizable.stopResizeNotificationsFor(this); |
| 10416 } else { |
| 10417 window.removeEventListener('resize', this._boundNotifyResize); |
| 10418 } |
| 10419 |
| 10420 this._parentResizable = null; |
| 10421 }, |
| 10422 |
| 10423 /** |
| 10424 * Can be called to manually notify a resizable and its descendant |
| 10425 * resizables of a resize change. |
| 10426 */ |
| 10427 notifyResize: function() { |
| 10428 if (!this.isAttached) { |
| 10429 return; |
| 10430 } |
| 10431 |
| 10432 this._interestedResizables.forEach(function(resizable) { |
| 10433 if (this.resizerShouldNotify(resizable)) { |
| 10434 this._notifyDescendant(resizable); |
| 10435 } |
| 10436 }, this); |
| 10437 |
| 10438 this._fireResize(); |
| 10439 }, |
| 10440 |
| 10441 /** |
| 10442 * Used to assign the closest resizable ancestor to this resizable |
| 10443 * if the ancestor detects a request for notifications. |
| 10444 */ |
| 10445 assignParentResizable: function(parentResizable) { |
| 10446 this._parentResizable = parentResizable; |
| 10447 }, |
| 10448 |
| 10449 /** |
| 10450 * Used to remove a resizable descendant from the list of descendants |
| 10451 * that should be notified of a resize change. |
| 10452 */ |
| 10453 stopResizeNotificationsFor: function(target) { |
| 10454 var index = this._interestedResizables.indexOf(target); |
| 10455 |
| 10456 if (index > -1) { |
| 10457 this._interestedResizables.splice(index, 1); |
| 10458 this.unlisten(target, 'iron-resize', '_onDescendantIronResize'); |
| 10459 } |
| 10460 }, |
| 10461 |
| 10462 /** |
| 10463 * This method can be overridden to filter nested elements that should or |
| 10464 * should not be notified by the current element. Return true if an element |
| 10465 * should be notified, or false if it should not be notified. |
| 10466 * |
| 10467 * @param {HTMLElement} element A candidate descendant element that |
| 10468 * implements `IronResizableBehavior`. |
| 10469 * @return {boolean} True if the `element` should be notified of resize. |
| 10470 */ |
| 10471 resizerShouldNotify: function(element) { return true; }, |
| 10472 |
| 10473 _onDescendantIronResize: function(event) { |
| 10474 if (this._notifyingDescendant) { |
| 10475 event.stopPropagation(); |
| 10476 return; |
| 10477 } |
| 10478 |
| 10479 // NOTE(cdata): In ShadowDOM, event retargetting makes echoing of the |
| 10480 // otherwise non-bubbling event "just work." We do it manually here for |
| 10481 // the case where Polymer is not using shadow roots for whatever reason: |
| 10482 if (!Polymer.Settings.useShadow) { |
| 10483 this._fireResize(); |
| 10484 } |
| 10485 }, |
| 10486 |
| 10487 _fireResize: function() { |
| 10488 this.fire('iron-resize', null, { |
| 10489 node: this, |
| 10490 bubbles: false |
| 10491 }); |
| 10492 }, |
| 10493 |
| 10494 _onIronRequestResizeNotifications: function(event) { |
| 10495 var target = event.path ? event.path[0] : event.target; |
| 10496 |
| 10497 if (target === this) { |
| 10498 return; |
| 10499 } |
| 10500 |
| 10501 if (this._interestedResizables.indexOf(target) === -1) { |
| 10502 this._interestedResizables.push(target); |
| 10503 this.listen(target, 'iron-resize', '_onDescendantIronResize'); |
| 10504 } |
| 10505 |
| 10506 target.assignParentResizable(this); |
| 10507 this._notifyDescendant(target); |
| 10508 |
| 10509 event.stopPropagation(); |
| 10510 }, |
| 10511 |
| 10512 _parentResizableChanged: function(parentResizable) { |
| 10513 if (parentResizable) { |
| 10514 window.removeEventListener('resize', this._boundNotifyResize); |
| 10515 } |
| 10516 }, |
| 10517 |
| 10518 _notifyDescendant: function(descendant) { |
| 10519 // NOTE(cdata): In IE10, attached is fired on children first, so it's |
| 10520 // important not to notify them if the parent is not attached yet (or |
| 10521 // else they will get redundantly notified when the parent attaches). |
| 10522 if (!this.isAttached) { |
| 10523 return; |
| 10524 } |
| 10525 |
| 10526 this._notifyingDescendant = true; |
| 10527 descendant.notifyResize(); |
| 10528 this._notifyingDescendant = false; |
| 10529 } |
| 10530 }; |
| 10531 </script> |
| 10532 |
| 10533 |
| 10534 |
| 10535 <dom-module id="app-drawer-layout" assetpath="bower_components/app-layout/app-dr
awer-layout/"> |
| 10536 <template> |
| 10537 <style> |
| 10538 :host { |
| 10539 display: block; |
| 10540 } |
| 10541 |
| 10542 :host([fullbleed]) { |
| 10543 @apply(--layout-fit); |
| 10544 } |
| 10545 |
| 10546 #contentContainer { |
| 10547 position: relative; |
| 10548 |
| 10549 height: 100%; |
| 10550 |
| 10551 transition: var(--app-drawer-layout-content-transition, none); |
| 10552 } |
| 10553 |
| 10554 #contentContainer:not(.narrow) > ::content [drawer-toggle] { |
| 10555 display: none; |
| 10556 } |
| 10557 </style> |
| 10558 |
| 10559 <div id="contentContainer"> |
| 10560 <content select=":not(app-drawer)"></content> |
| 10561 </div> |
| 10562 |
| 10563 <content id="drawerContent" select="app-drawer"></content> |
| 10564 |
| 10565 <iron-media-query query="[[_computeMediaQuery(forceNarrow, responsiveWidth)]
]" on-query-matches-changed="_onQueryMatchesChanged"></iron-media-query> |
| 10566 </template> |
| 10567 |
| 10568 <script> |
| 10569 Polymer({ |
| 10570 is: 'app-drawer-layout', |
| 10571 |
| 10572 behaviors: [ |
| 10573 Polymer.IronResizableBehavior |
| 10574 ], |
| 10575 |
| 10576 properties: { |
| 10577 /** |
| 10578 * If true, ignore `responsiveWidth` setting and force the narrow layout
. |
| 10579 */ |
| 10580 forceNarrow: { |
| 10581 type: Boolean, |
| 10582 value: false |
| 10583 }, |
| 10584 |
| 10585 /** |
| 10586 * If the viewport's width is smaller than this value, the panel will ch
ange to narrow |
| 10587 * layout. In the mode the drawer will be closed. |
| 10588 */ |
| 10589 responsiveWidth: { |
| 10590 type: String, |
| 10591 value: '640px' |
| 10592 }, |
| 10593 |
| 10594 /** |
| 10595 * Returns true if it is in narrow layout. This is useful if you need to
show/hide |
| 10596 * elements based on the layout. |
| 10597 */ |
| 10598 narrow: { |
| 10599 type: Boolean, |
| 10600 readOnly: true, |
| 10601 notify: true |
| 10602 } |
| 10603 }, |
| 10604 |
| 10605 listeners: { |
| 10606 'tap': '_tapHandler', |
| 10607 'app-drawer-reset-layout': 'resetLayout' |
| 10608 }, |
| 10609 |
| 10610 observers: [ |
| 10611 'resetLayout(narrow, isAttached)' |
| 10612 ], |
| 10613 |
| 10614 /** |
| 10615 * A reference to the app-drawer element. |
| 10616 * |
| 10617 * @property drawer |
| 10618 */ |
| 10619 get drawer() { |
| 10620 return Polymer.dom(this.$.drawerContent).getDistributedNodes()[0]; |
| 10621 }, |
| 10622 |
| 10623 _tapHandler: function(e) { |
| 10624 var target = Polymer.dom(e).localTarget; |
| 10625 if (target && target.hasAttribute('drawer-toggle')) { |
| 10626 this.drawer.toggle(); |
| 10627 } |
| 10628 }, |
| 10629 |
| 10630 resetLayout: function() { |
| 10631 this.debounce('_resetLayout', function() { |
| 10632 var drawer = this.drawer; |
| 10633 var contentContainer = this.$.contentContainer; |
| 10634 |
| 10635 if (this.narrow) { |
| 10636 drawer.opened = drawer.persistent = false; |
| 10637 contentContainer.classList.add('narrow'); |
| 10638 |
| 10639 contentContainer.style.marginLeft = ''; |
| 10640 contentContainer.style.marginRight = ''; |
| 10641 } else { |
| 10642 drawer.opened = drawer.persistent = true; |
| 10643 contentContainer.classList.remove('narrow'); |
| 10644 |
| 10645 var drawerWidth = this.drawer.getWidth(); |
| 10646 if (drawer.position == 'right') { |
| 10647 contentContainer.style.marginLeft = ''; |
| 10648 contentContainer.style.marginRight = drawerWidth + 'px'; |
| 10649 } else { |
| 10650 contentContainer.style.marginLeft = drawerWidth + 'px'; |
| 10651 contentContainer.style.marginRight = ''; |
| 10652 } |
| 10653 } |
| 10654 |
| 10655 this.notifyResize(); |
| 10656 }); |
| 10657 }, |
| 10658 |
| 10659 _onQueryMatchesChanged: function(event) { |
| 10660 this._setNarrow(event.detail.value); |
| 10661 }, |
| 10662 |
| 10663 _computeMediaQuery: function(forceNarrow, responsiveWidth) { |
| 10664 return forceNarrow ? '(min-width: 0px)' : '(max-width: ' + responsiveWid
th + ')'; |
| 10665 } |
| 10666 }); |
| 10667 </script> |
| 10668 </dom-module> |
| 10669 |
| 10670 |
| 10671 <dom-module id="app-grid-style" assetpath="bower_components/app-layout/app-grid/
"> |
| 10672 <template> |
| 10673 <style> |
| 10674 |
| 10675 :host { |
| 10676 /** |
| 10677 * The width for the expandible item is: |
| 10678 * ((100% - subPixelAdjustment) / columns * itemColumns - gutter * (colu
mns - itemColumns) |
| 10679 * |
| 10680 * - subPixelAdjustment: 0.1px (Required for IE 11) |
| 10681 * - gutter: var(--app-grid-gutter) |
| 10682 * - columns: var(--app-grid-columns) |
| 10683 * - itemColumn: var(--app-grid-expandible-item-columns) |
| 10684 */ |
| 10685 --app-grid-expandible-item: { |
| 10686 -webkit-flex-basis: calc((100% - 0.1px) / var(--app-grid-columns, 1) *
var(--app-grid-expandible-item-columns, 1) - (var(--app-grid-gutter, 0px) * (va
r(--app-grid-columns, 1) - var(--app-grid-expandible-item-columns, 1)))) !import
ant; |
| 10687 flex-basis: calc((100% - 0.1px) / var(--app-grid-columns, 1) * var(--a
pp-grid-expandible-item-columns, 1) - (var(--app-grid-gutter, 0px) * (var(--app-
grid-columns, 1) - var(--app-grid-expandible-item-columns, 1)))) !important; |
| 10688 max-width: calc((100% - 0.1px) / var(--app-grid-columns, 1) * var(--ap
p-grid-expandible-item-columns, 1) - (var(--app-grid-gutter, 0px) * (var(--app-g
rid-columns, 1) - var(--app-grid-expandible-item-columns, 1)))) !important; |
| 10689 |
| 10690 }; |
| 10691 } |
| 10692 |
| 10693 .app-grid { |
| 10694 display: -ms-flexbox; |
| 10695 display: -webkit-flex; |
| 10696 display: flex; |
| 10697 |
| 10698 -ms-flex-direction: row; |
| 10699 -webkit-flex-direction: row; |
| 10700 flex-direction: row; |
| 10701 |
| 10702 -ms-flex-wrap: wrap; |
| 10703 -webkit-flex-wrap: wrap; |
| 10704 flex-wrap: wrap; |
| 10705 |
| 10706 margin-top: var(--app-grid-gutter, 0px); |
| 10707 margin-left: var(--app-grid-gutter, 0px); |
| 10708 } |
| 10709 |
| 10710 .app-grid > * { |
| 10711 /* Required for IE 10 */ |
| 10712 -ms-flex: 1 1 100%; |
| 10713 -webkit-flex: 1; |
| 10714 flex: 1; |
| 10715 |
| 10716 /* The width for an item is: (100% - subPixelAdjustment - gutter * colum
ns) / columns */ |
| 10717 -webkit-flex-basis: calc((100% - 0.1px - (var(--app-grid-gutter, 0px) *
var(--app-grid-columns, 1))) / var(--app-grid-columns, 1)); |
| 10718 flex-basis: calc((100% - 0.1px - (var(--app-grid-gutter, 0px) * var(--ap
p-grid-columns, 1))) / var(--app-grid-columns, 1)); |
| 10719 |
| 10720 max-width: calc((100% - 0.1px - (var(--app-grid-gutter, 0px) * var(--app
-grid-columns, 1))) / var(--app-grid-columns, 1)); |
| 10721 margin-bottom: var(--app-grid-gutter, 0px); |
| 10722 margin-right: var(--app-grid-gutter, 0px); |
| 10723 height: var(--app-grid-item-height); |
| 10724 box-sizing: border-box; |
| 10725 } |
| 10726 |
| 10727 .app-grid[has-aspect-ratio] > * { |
| 10728 position: relative; |
| 10729 } |
| 10730 |
| 10731 .app-grid[has-aspect-ratio] > *::before { |
| 10732 display: block; |
| 10733 content: ""; |
| 10734 padding-top: var(--app-grid-item-height, 100%); |
| 10735 } |
| 10736 |
| 10737 .app-grid[has-aspect-ratio] > * > * { |
| 10738 position: absolute; |
| 10739 top: 0; |
| 10740 right: 0; |
| 10741 bottom: 0; |
| 10742 left: 0; |
| 10743 } |
| 10744 |
| 10745 </style> |
| 10746 </template> |
| 10747 </dom-module> |
| 10748 <script> |
| 10749 |
| 10750 /** |
| 10751 * `Polymer.IronScrollTargetBehavior` allows an element to respond to scroll e
vents from a |
| 10752 * designated scroll target. |
| 10753 * |
| 10754 * Elements that consume this behavior can override the `_scrollHandler` |
| 10755 * method to add logic on the scroll event. |
| 10756 * |
| 10757 * @demo demo/scrolling-region.html Scrolling Region |
| 10758 * @demo demo/document.html Document Element |
| 10759 * @polymerBehavior |
| 10760 */ |
| 10761 Polymer.IronScrollTargetBehavior = { |
| 10762 |
| 10763 properties: { |
| 10764 |
| 10765 /** |
| 10766 * Specifies the element that will handle the scroll event |
| 10767 * on the behalf of the current element. This is typically a reference to
an element, |
| 10768 * but there are a few more posibilities: |
| 10769 * |
| 10770 * ### Elements id |
| 10771 * |
| 10772 *```html |
| 10773 * <div id="scrollable-element" style="overflow: auto;"> |
| 10774 * <x-element scroll-target="scrollable-element"> |
| 10775 * <!-- Content--> |
| 10776 * </x-element> |
| 10777 * </div> |
| 10778 *``` |
| 10779 * In this case, the `scrollTarget` will point to the outer div element. |
| 10780 * |
| 10781 * ### Document scrolling |
| 10782 * |
| 10783 * For document scrolling, you can use the reserved word `document`: |
| 10784 * |
| 10785 *```html |
| 10786 * <x-element scroll-target="document"> |
| 10787 * <!-- Content --> |
| 10788 * </x-element> |
| 10789 *``` |
| 10790 * |
| 10791 * ### Elements reference |
| 10792 * |
| 10793 *```js |
| 10794 * appHeader.scrollTarget = document.querySelector('#scrollable-element'); |
| 10795 *``` |
| 10796 * |
| 10797 * @type {HTMLElement} |
| 10798 */ |
| 10799 scrollTarget: { |
| 10800 type: HTMLElement, |
| 10801 value: function() { |
| 10802 return this._defaultScrollTarget; |
| 10803 } |
| 10804 } |
| 10805 }, |
| 10806 |
| 10807 observers: [ |
| 10808 '_scrollTargetChanged(scrollTarget, isAttached)' |
| 10809 ], |
| 10810 |
| 10811 _scrollTargetChanged: function(scrollTarget, isAttached) { |
| 10812 var eventTarget; |
| 10813 |
| 10814 if (this._oldScrollTarget) { |
| 10815 eventTarget = this._oldScrollTarget === this._doc ? window : this._oldSc
rollTarget; |
| 10816 eventTarget.removeEventListener('scroll', this._boundScrollHandler); |
| 10817 this._oldScrollTarget = null; |
| 10818 } |
| 10819 |
| 10820 if (!isAttached) { |
| 10821 return; |
| 10822 } |
| 10823 // Support element id references |
| 10824 if (scrollTarget === 'document') { |
| 10825 |
| 10826 this.scrollTarget = this._doc; |
| 10827 |
| 10828 } else if (typeof scrollTarget === 'string') { |
| 10829 |
| 10830 this.scrollTarget = this.domHost ? this.domHost.$[scrollTarget] : |
| 10831 Polymer.dom(this.ownerDocument).querySelector('#' + scrollTarget); |
| 10832 |
| 10833 } else if (this._isValidScrollTarget()) { |
| 10834 |
| 10835 eventTarget = scrollTarget === this._doc ? window : scrollTarget; |
| 10836 this._boundScrollHandler = this._boundScrollHandler || this._scrollHandl
er.bind(this); |
| 10837 this._oldScrollTarget = scrollTarget; |
| 10838 |
| 10839 eventTarget.addEventListener('scroll', this._boundScrollHandler); |
| 10840 } |
| 10841 }, |
| 10842 |
| 10843 /** |
| 10844 * Runs on every scroll event. Consumer of this behavior may override this m
ethod. |
| 10845 * |
| 10846 * @protected |
| 10847 */ |
| 10848 _scrollHandler: function scrollHandler() {}, |
| 10849 |
| 10850 /** |
| 10851 * The default scroll target. Consumers of this behavior may want to customi
ze |
| 10852 * the default scroll target. |
| 10853 * |
| 10854 * @type {Element} |
| 10855 */ |
| 10856 get _defaultScrollTarget() { |
| 10857 return this._doc; |
| 10858 }, |
| 10859 |
| 10860 /** |
| 10861 * Shortcut for the document element |
| 10862 * |
| 10863 * @type {Element} |
| 10864 */ |
| 10865 get _doc() { |
| 10866 return this.ownerDocument.documentElement; |
| 10867 }, |
| 10868 |
| 10869 /** |
| 10870 * Gets the number of pixels that the content of an element is scrolled upwa
rd. |
| 10871 * |
| 10872 * @type {number} |
| 10873 */ |
| 10874 get _scrollTop() { |
| 10875 if (this._isValidScrollTarget()) { |
| 10876 return this.scrollTarget === this._doc ? window.pageYOffset : this.scrol
lTarget.scrollTop; |
| 10877 } |
| 10878 return 0; |
| 10879 }, |
| 10880 |
| 10881 /** |
| 10882 * Gets the number of pixels that the content of an element is scrolled to t
he left. |
| 10883 * |
| 10884 * @type {number} |
| 10885 */ |
| 10886 get _scrollLeft() { |
| 10887 if (this._isValidScrollTarget()) { |
| 10888 return this.scrollTarget === this._doc ? window.pageXOffset : this.scrol
lTarget.scrollLeft; |
| 10889 } |
| 10890 return 0; |
| 10891 }, |
| 10892 |
| 10893 /** |
| 10894 * Sets the number of pixels that the content of an element is scrolled upwa
rd. |
| 10895 * |
| 10896 * @type {number} |
| 10897 */ |
| 10898 set _scrollTop(top) { |
| 10899 if (this.scrollTarget === this._doc) { |
| 10900 window.scrollTo(window.pageXOffset, top); |
| 10901 } else if (this._isValidScrollTarget()) { |
| 10902 this.scrollTarget.scrollTop = top; |
| 10903 } |
| 10904 }, |
| 10905 |
| 10906 /** |
| 10907 * Sets the number of pixels that the content of an element is scrolled to t
he left. |
| 10908 * |
| 10909 * @type {number} |
| 10910 */ |
| 10911 set _scrollLeft(left) { |
| 10912 if (this.scrollTarget === this._doc) { |
| 10913 window.scrollTo(left, window.pageYOffset); |
| 10914 } else if (this._isValidScrollTarget()) { |
| 10915 this.scrollTarget.scrollLeft = left; |
| 10916 } |
| 10917 }, |
| 10918 |
| 10919 /** |
| 10920 * Scrolls the content to a particular place. |
| 10921 * |
| 10922 * @method scroll |
| 10923 * @param {number} left The left position |
| 10924 * @param {number} top The top position |
| 10925 */ |
| 10926 scroll: function(left, top) { |
| 10927 if (this.scrollTarget === this._doc) { |
| 10928 window.scrollTo(left, top); |
| 10929 } else if (this._isValidScrollTarget()) { |
| 10930 this.scrollTarget.scrollLeft = left; |
| 10931 this.scrollTarget.scrollTop = top; |
| 10932 } |
| 10933 }, |
| 10934 |
| 10935 /** |
| 10936 * Gets the width of the scroll target. |
| 10937 * |
| 10938 * @type {number} |
| 10939 */ |
| 10940 get _scrollTargetWidth() { |
| 10941 if (this._isValidScrollTarget()) { |
| 10942 return this.scrollTarget === this._doc ? window.innerWidth : this.scroll
Target.offsetWidth; |
| 10943 } |
| 10944 return 0; |
| 10945 }, |
| 10946 |
| 10947 /** |
| 10948 * Gets the height of the scroll target. |
| 10949 * |
| 10950 * @type {number} |
| 10951 */ |
| 10952 get _scrollTargetHeight() { |
| 10953 if (this._isValidScrollTarget()) { |
| 10954 return this.scrollTarget === this._doc ? window.innerHeight : this.scrol
lTarget.offsetHeight; |
| 10955 } |
| 10956 return 0; |
| 10957 }, |
| 10958 |
| 10959 /** |
| 10960 * Returns true if the scroll target is a valid HTMLElement. |
| 10961 * |
| 10962 * @return {boolean} |
| 10963 */ |
| 10964 _isValidScrollTarget: function() { |
| 10965 return this.scrollTarget instanceof HTMLElement; |
| 10966 } |
| 10967 }; |
| 10968 |
| 10969 </script> |
| 10970 <script> |
| 10971 /** |
| 10972 * `Polymer.AppScrollEffectsBehavior` provides an interface that allows an ele
ment to use scrolls effects. |
| 10973 * |
| 10974 * ### Importing the app-layout effects |
| 10975 * |
| 10976 * app-layout provides a set of scroll effects that can be used by explicitly
importing |
| 10977 * `app-scroll-effects.html`: |
| 10978 * |
| 10979 * ```html |
| 10980 * <link rel="import" href="/bower_components/app-layout/app-scroll-effects/ap
p-scroll-effects.html"> |
| 10981 * ``` |
| 10982 * |
| 10983 * The scroll effects can also be used by individually importing |
| 10984 * `app-layout/app-scroll-effects/effects/[effectName].html`. For example: |
| 10985 * |
| 10986 * ```html |
| 10987 * <link rel="import" href="/bower_components/app-layout/app-scroll-effects/e
ffects/waterfall.html"> |
| 10988 * ``` |
| 10989 * |
| 10990 * ### Consuming effects |
| 10991 * |
| 10992 * Effects can be consumed via the `effects` property. For example: |
| 10993 * |
| 10994 * ```html |
| 10995 * <app-header effects="waterfall"></app-header> |
| 10996 * ``` |
| 10997 * |
| 10998 * ### Creating scroll effects |
| 10999 * |
| 11000 * You may want to create a custom scroll effect if you need to modify the CSS
of an element |
| 11001 * based on the scroll position. |
| 11002 * |
| 11003 * A scroll effect definition is an object with `setUp()`, `tearDown()` and `r
un()` functions. |
| 11004 * |
| 11005 * To register the effect, you can use `Polymer.AppLayout.registerEffect(effec
tName, effectDef)` |
| 11006 * For example, let's define an effect that resizes the header's logo: |
| 11007 * |
| 11008 * ```js |
| 11009 * Polymer.AppLayout.registerEffect('resizable-logo', { |
| 11010 * setUp: function(config) { |
| 11011 * // the effect's config is passed to the setUp. |
| 11012 * this._fxResizeLogo = { logo: Polymer.dom(this).querySelector('[logo]')
}; |
| 11013 * }, |
| 11014 * |
| 11015 * run: function(progress) { |
| 11016 * // the progress of the effect |
| 11017 * this.transform('scale3d(' + progress + ', '+ progress +', 1)', this._
fxResizeLogo.logo); |
| 11018 * }, |
| 11019 * |
| 11020 * tearDown: function() { |
| 11021 * // clean up and reset of states |
| 11022 * delete this._fxResizeLogo; |
| 11023 * } |
| 11024 * }); |
| 11025 * ``` |
| 11026 * Now, you can consume the effect: |
| 11027 * |
| 11028 * ```html |
| 11029 * <app-header id="appHeader" effects="resizable-logo"> |
| 11030 * <img logo src="logo.svg"> |
| 11031 * </app-header> |
| 11032 * ``` |
| 11033 * |
| 11034 * ### Imperative API |
| 11035 * |
| 11036 * ```js |
| 11037 * var logoEffect = appHeader.createEffect('resizable-logo', effectConfig); |
| 11038 * // run the effect: logoEffect.run(progress); |
| 11039 * // tear down the effect: logoEffect.tearDown(); |
| 11040 * ``` |
| 11041 * |
| 11042 * ### Configuring effects |
| 11043 * |
| 11044 * For effects installed via the `effects` property, their configuration can b
e set |
| 11045 * via the `effectsConfig` property. For example: |
| 11046 * |
| 11047 * ```html |
| 11048 * <app-header effects="waterfall" |
| 11049 * effects-config='{"waterfall": {"startsAt": 0, "endsAt": 0.5}}'> |
| 11050 * </app-header> |
| 11051 * ``` |
| 11052 * |
| 11053 * All effects have a `startsAt` and `endsAt` config property. They specify at
what |
| 11054 * point the effect should start and end. This value goes from 0 to 1 inclusiv
e. |
| 11055 * |
| 11056 * @polymerBehavior |
| 11057 */ |
| 11058 Polymer.AppScrollEffectsBehavior = [ |
| 11059 Polymer.IronScrollTargetBehavior, |
| 11060 { |
| 11061 |
| 11062 properties: { |
| 11063 |
| 11064 /** |
| 11065 * A space-separated list of the effects names that will be triggered when
the user scrolls. |
| 11066 * e.g. `waterfall parallax-background` installs the `waterfall` and `para
llax-background`. |
| 11067 */ |
| 11068 effects: { |
| 11069 type: String |
| 11070 }, |
| 11071 |
| 11072 /** |
| 11073 * An object that configurates the effects installed via the `effects` pro
perty. e.g. |
| 11074 * ```js |
| 11075 * element.effectsConfig = { |
| 11076 * "blend-background": { |
| 11077 * "startsAt": 0.5 |
| 11078 * } |
| 11079 * }; |
| 11080 * ``` |
| 11081 * Every effect has at least two config properties: `startsAt` and `endsAt
`. |
| 11082 * These properties indicate when the event should start and end respectiv
ely |
| 11083 * and relative to the overall element progress. So for example, if `blend
-background` |
| 11084 * starts at `0.5`, the effect will only start once the current element re
aches 0.5 |
| 11085 * of its progress. In this context, the progress is a value in the range
of `[0, 1]` |
| 11086 * that indicates where this element is on the screen relative to the view
port. |
| 11087 */ |
| 11088 effectsConfig: { |
| 11089 type: Object, |
| 11090 value: function() { |
| 11091 return {}; |
| 11092 } |
| 11093 }, |
| 11094 |
| 11095 /** |
| 11096 * Disables CSS transitions and scroll effects on the element. |
| 11097 */ |
| 11098 disabled: { |
| 11099 type: Boolean, |
| 11100 reflectToAttribute: true, |
| 11101 value: false |
| 11102 } |
| 11103 }, |
| 11104 |
| 11105 observers: [ |
| 11106 '_effectsChanged(effects, effectsConfig, isAttached)' |
| 11107 ], |
| 11108 |
| 11109 /** |
| 11110 * Updates the scroll state. This method should be overridden |
| 11111 * by the consumer of this behavior. |
| 11112 * |
| 11113 * @method _updateScrollState |
| 11114 */ |
| 11115 _updateScrollState: function() {}, |
| 11116 |
| 11117 /** |
| 11118 * Returns true if the current element is on the screen. |
| 11119 * That is, visible in the current viewport. This method should be |
| 11120 * overridden by the consumer of this behavior. |
| 11121 * |
| 11122 * @method isOnScreen |
| 11123 * @return {boolean} |
| 11124 */ |
| 11125 isOnScreen: function() { |
| 11126 return false; |
| 11127 }, |
| 11128 |
| 11129 /** |
| 11130 * Returns true if there's content below the current element. This method |
| 11131 * should be overridden by the consumer of this behavior. |
| 11132 * |
| 11133 * @method isContentBelow |
| 11134 * @return {boolean} |
| 11135 */ |
| 11136 isContentBelow: function() { |
| 11137 return false; |
| 11138 }, |
| 11139 |
| 11140 /** |
| 11141 * List of effects handlers that will take place during scroll. |
| 11142 * |
| 11143 * @type {Array<Function>} |
| 11144 */ |
| 11145 _effectsRunFn: null, |
| 11146 |
| 11147 /** |
| 11148 * List of the effects definitions installed via the `effects` property. |
| 11149 * |
| 11150 * @type {Array<Object>} |
| 11151 */ |
| 11152 _effects: null, |
| 11153 |
| 11154 /** |
| 11155 * The clamped value of `_scrollTop`. |
| 11156 * @type number |
| 11157 */ |
| 11158 get _clampedScrollTop() { |
| 11159 return Math.max(0, this._scrollTop); |
| 11160 }, |
| 11161 |
| 11162 detached: function() { |
| 11163 this._tearDownEffects(); |
| 11164 }, |
| 11165 |
| 11166 /** |
| 11167 * Creates an effect object from an effect's name that can be used to run |
| 11168 * effects programmatically. |
| 11169 * |
| 11170 * @method createEffect |
| 11171 * @param {string} effectName The effect's name registered via `Polymer.AppL
ayout.registerEffect`. |
| 11172 * @param {Object=} effectConfig The effect config object. (Optional) |
| 11173 * @return {Object} An effect object with the following functions: |
| 11174 * |
| 11175 * * `effect.setUp()`, Sets up the requirements for the effect. |
| 11176 * This function is called automatically before the `effect` function
returns. |
| 11177 * * `effect.run(progress, y)`, Runs the effect given a `progress`. |
| 11178 * * `effect.tearDown()`, Cleans up any DOM nodes or element references use
d by the effect. |
| 11179 * |
| 11180 * Example: |
| 11181 * ```js |
| 11182 * var parallax = element.createEffect('parallax-background'); |
| 11183 * // runs the effect |
| 11184 * parallax.run(0.5, 0); |
| 11185 * ``` |
| 11186 */ |
| 11187 createEffect: function(effectName, effectConfig) { |
| 11188 var effectDef = Polymer.AppLayout._scrollEffects[effectName]; |
| 11189 if (!effectDef) { |
| 11190 throw new ReferenceError(this._getUndefinedMsg(effectName)); |
| 11191 } |
| 11192 var prop = this._boundEffect(effectDef, effectConfig || {}); |
| 11193 prop.setUp(); |
| 11194 return prop; |
| 11195 }, |
| 11196 |
| 11197 /** |
| 11198 * Called when `effects` or `effectsConfig` changes. |
| 11199 */ |
| 11200 _effectsChanged: function(effects, effectsConfig, isAttached) { |
| 11201 this._tearDownEffects(); |
| 11202 |
| 11203 if (effects === '' || !isAttached) { |
| 11204 return; |
| 11205 } |
| 11206 effects.split(' ').forEach(function(effectName) { |
| 11207 var effectDef; |
| 11208 if (effectName !== '') { |
| 11209 if ((effectDef = Polymer.AppLayout._scrollEffects[effectName])) { |
| 11210 this._effects.push(this._boundEffect(effectDef, effectsConfig[effect
Name])); |
| 11211 } else { |
| 11212 this._warn(this._logf('_effectsChanged', this._getUndefinedMsg(effec
tName))); |
| 11213 } |
| 11214 } |
| 11215 }, this); |
| 11216 |
| 11217 this._setUpEffect(); |
| 11218 }, |
| 11219 |
| 11220 /** |
| 11221 * Forces layout |
| 11222 */ |
| 11223 _layoutIfDirty: function() { |
| 11224 return this.offsetWidth; |
| 11225 }, |
| 11226 |
| 11227 /** |
| 11228 * Returns an effect object bound to the current context. |
| 11229 * |
| 11230 * @param {Object} effectDef |
| 11231 * @param {Object=} effectsConfig The effect config object if the effect acc
epts config values. (Optional) |
| 11232 */ |
| 11233 _boundEffect: function(effectDef, effectsConfig) { |
| 11234 effectsConfig = effectsConfig || {}; |
| 11235 var startsAt = parseFloat(effectsConfig.startsAt || 0); |
| 11236 var endsAt = parseFloat(effectsConfig.endsAt || 1); |
| 11237 var deltaS = endsAt - startsAt; |
| 11238 var noop = Function(); |
| 11239 // fast path if possible |
| 11240 var runFn = (startsAt === 0 && endsAt === 1) ? effectDef.run : |
| 11241 function(progress, y) { |
| 11242 effectDef.run.call(this, |
| 11243 Math.max(0, (progress - startsAt) / deltaS), y); |
| 11244 }; |
| 11245 return { |
| 11246 setUp: effectDef.setUp ? effectDef.setUp.bind(this, effectsConfig) : noo
p, |
| 11247 run: effectDef.run ? runFn.bind(this) : noop, |
| 11248 tearDown: effectDef.tearDown ? effectDef.tearDown.bind(this) : noop |
| 11249 }; |
| 11250 }, |
| 11251 |
| 11252 /** |
| 11253 * Sets up the effects. |
| 11254 */ |
| 11255 _setUpEffect: function() { |
| 11256 if (this.isAttached && this._effects) { |
| 11257 this._effectsRunFn = []; |
| 11258 this._effects.forEach(function(effectDef) { |
| 11259 // install the effect only if no error was reported |
| 11260 if (effectDef.setUp() !== false) { |
| 11261 this._effectsRunFn.push(effectDef.run); |
| 11262 } |
| 11263 }, this); |
| 11264 } |
| 11265 }, |
| 11266 |
| 11267 /** |
| 11268 * Tears down the effects. |
| 11269 */ |
| 11270 _tearDownEffects: function() { |
| 11271 if (this._effects) { |
| 11272 this._effects.forEach(function(effectDef) { |
| 11273 effectDef.tearDown(); |
| 11274 }); |
| 11275 } |
| 11276 this._effectsRunFn = []; |
| 11277 this._effects = []; |
| 11278 }, |
| 11279 |
| 11280 /** |
| 11281 * Runs the effects. |
| 11282 * |
| 11283 * @param {number} p The progress |
| 11284 * @param {number} y The top position of the current element relative to the
viewport. |
| 11285 */ |
| 11286 _runEffects: function(p, y) { |
| 11287 if (this._effectsRunFn) { |
| 11288 this._effectsRunFn.forEach(function(run) { |
| 11289 run(p, y); |
| 11290 }); |
| 11291 } |
| 11292 }, |
| 11293 |
| 11294 /** |
| 11295 * Overrides the `_scrollHandler`. |
| 11296 */ |
| 11297 _scrollHandler: function() { |
| 11298 if (!this.disabled) { |
| 11299 this._updateScrollState(this._clampedScrollTop); |
| 11300 } |
| 11301 }, |
| 11302 |
| 11303 /** |
| 11304 * Override this method to return a reference to a node in the local DOM. |
| 11305 * The node is consumed by a scroll effect. |
| 11306 * |
| 11307 * @param {string} id The id for the node. |
| 11308 */ |
| 11309 _getDOMRef: function(id) { |
| 11310 this._warn(this._logf('_getDOMRef', '`'+ id +'` is undefined')); |
| 11311 }, |
| 11312 |
| 11313 _getUndefinedMsg: function(effectName) { |
| 11314 return 'Scroll effect `' + effectName + '` is undefined. ' + |
| 11315 'Did you forget to import app-layout/app-scroll-effects/effects/' + ef
fectName + '.html ?'; |
| 11316 } |
| 11317 |
| 11318 }]; |
| 11319 |
| 11320 </script> |
| 11321 |
| 11322 |
| 11323 <dom-module id="app-header" assetpath="bower_components/app-layout/app-header/"> |
| 11324 <template> |
| 11325 <style> |
| 11326 :host { |
| 11327 position: relative; |
| 11328 display: block; |
| 11329 transition-timing-function: linear; |
| 11330 transition-property: -webkit-transform; |
| 11331 transition-property: transform; |
| 11332 } |
| 11333 |
| 11334 :host::after { |
| 11335 position: absolute; |
| 11336 right: 0px; |
| 11337 bottom: -5px; |
| 11338 left: 0px; |
| 11339 width: 100%; |
| 11340 height: 5px; |
| 11341 content: ""; |
| 11342 transition: opacity 0.4s; |
| 11343 pointer-events: none; |
| 11344 opacity: 0; |
| 11345 box-shadow: inset 0px 5px 6px -3px rgba(0, 0, 0, 0.4); |
| 11346 will-change: opacity; |
| 11347 @apply(--app-header-shadow); |
| 11348 } |
| 11349 |
| 11350 :host([shadow])::after { |
| 11351 opacity: 1; |
| 11352 } |
| 11353 |
| 11354 #contentContainer > ::content [condensed-title] { |
| 11355 -webkit-transform-origin: left top; |
| 11356 transform-origin: left top; |
| 11357 white-space: nowrap; |
| 11358 opacity: 0; |
| 11359 } |
| 11360 |
| 11361 #contentContainer > ::content [main-title] { |
| 11362 -webkit-transform-origin: left top; |
| 11363 transform-origin: left top; |
| 11364 white-space: nowrap; |
| 11365 } |
| 11366 |
| 11367 #background { |
| 11368 @apply(--layout-fit); |
| 11369 overflow: hidden; |
| 11370 } |
| 11371 |
| 11372 #backgroundFrontLayer, |
| 11373 #backgroundRearLayer { |
| 11374 @apply(--layout-fit); |
| 11375 height: 100%; |
| 11376 pointer-events: none; |
| 11377 background-size: cover; |
| 11378 } |
| 11379 |
| 11380 #backgroundFrontLayer { |
| 11381 @apply(--app-header-background-front-layer); |
| 11382 } |
| 11383 |
| 11384 #backgroundRearLayer { |
| 11385 opacity: 0; |
| 11386 @apply(--app-header-background-rear-layer); |
| 11387 } |
| 11388 |
| 11389 #contentContainer { |
| 11390 position: relative; |
| 11391 width: 100%; |
| 11392 height: 100%; |
| 11393 } |
| 11394 |
| 11395 :host([disabled]), |
| 11396 :host([disabled])::after, |
| 11397 :host([disabled]) #backgroundFrontLayer, |
| 11398 :host([disabled]) #backgroundRearLayer, |
| 11399 :host([disabled]) ::content > app-toolbar:first-of-type, |
| 11400 :host([disabled]) ::content > [sticky], |
| 11401 /* Silent scrolling should not run CSS transitions */ |
| 11402 :host-context(.app-layout-silent-scroll), |
| 11403 :host-context(.app-layout-silent-scroll)::after, |
| 11404 :host-context(.app-layout-silent-scroll) #backgroundFrontLayer, |
| 11405 :host-context(.app-layout-silent-scroll) #backgroundRearLayer, |
| 11406 :host-context(.app-layout-silent-scroll) ::content > app-toolbar:first-of-
type, |
| 11407 :host-context(.app-layout-silent-scroll) ::content > [sticky] { |
| 11408 transition: none !important; |
| 11409 } |
| 11410 </style> |
| 11411 <div id="contentContainer"> |
| 11412 <content id="content"></content> |
| 11413 </div> |
| 11414 </template> |
| 11415 |
| 11416 <script> |
| 11417 Polymer({ |
| 11418 is: 'app-header', |
| 11419 |
| 11420 behaviors: [ |
| 11421 Polymer.AppScrollEffectsBehavior, |
| 11422 Polymer.IronResizableBehavior |
| 11423 ], |
| 11424 |
| 11425 properties: { |
| 11426 /** |
| 11427 * If true, the header will automatically collapse when scrolling down. |
| 11428 * That is, the `sticky` element remains visible when the header is full
y condensed |
| 11429 * whereas the rest of the elements will collapse below `sticky` element
. |
| 11430 * |
| 11431 * By default, the `sticky` element is the first toolbar in the light DO
M: |
| 11432 * |
| 11433 *```html |
| 11434 * <app-header condenses> |
| 11435 * <app-toolbar>This toolbar remains on top</app-toolbar> |
| 11436 * <app-toolbar></app-toolbar> |
| 11437 * <app-toolbar></app-toolbar> |
| 11438 * </app-header> |
| 11439 * ``` |
| 11440 * |
| 11441 * Additionally, you can specify which toolbar or element remains visibl
e in condensed mode |
| 11442 * by adding the `sticky` attribute to that element. For example: if we
want the last |
| 11443 * toolbar to remain visible, we can add the `sticky` attribute to it. |
| 11444 * |
| 11445 *```html |
| 11446 * <app-header condenses> |
| 11447 * <app-toolbar></app-toolbar> |
| 11448 * <app-toolbar></app-toolbar> |
| 11449 * <app-toolbar sticky>This toolbar remains on top</app-toolbar> |
| 11450 * </app-header> |
| 11451 * ``` |
| 11452 * |
| 11453 * Note the `sticky` element must be a direct child of `app-header`. |
| 11454 */ |
| 11455 condenses: { |
| 11456 type: Boolean, |
| 11457 value: false |
| 11458 }, |
| 11459 |
| 11460 /** |
| 11461 * Mantains the header fixed at the top so it never moves away. |
| 11462 */ |
| 11463 fixed: { |
| 11464 type: Boolean, |
| 11465 value: false |
| 11466 }, |
| 11467 |
| 11468 /** |
| 11469 * Slides back the header when scrolling back up. |
| 11470 */ |
| 11471 reveals: { |
| 11472 type: Boolean, |
| 11473 value: false |
| 11474 }, |
| 11475 |
| 11476 /** |
| 11477 * Displays a shadow below the header. |
| 11478 */ |
| 11479 shadow: { |
| 11480 type: Boolean, |
| 11481 reflectToAttribute: true, |
| 11482 value: false |
| 11483 } |
| 11484 }, |
| 11485 |
| 11486 observers: [ |
| 11487 'resetLayout(isAttached, condenses, fixed)' |
| 11488 ], |
| 11489 |
| 11490 listeners: { |
| 11491 'iron-resize': '_resizeHandler' |
| 11492 }, |
| 11493 |
| 11494 /** |
| 11495 * A cached offsetHeight of the current element. |
| 11496 * |
| 11497 * @type {number} |
| 11498 */ |
| 11499 _height: 0, |
| 11500 |
| 11501 /** |
| 11502 * The distance in pixels the header will be translated to when scrolling. |
| 11503 * |
| 11504 * @type {number} |
| 11505 */ |
| 11506 _dHeight: 0, |
| 11507 |
| 11508 /** |
| 11509 * The offsetTop of `_stickyEl` |
| 11510 * |
| 11511 * @type {number} |
| 11512 */ |
| 11513 _stickyElTop: 0, |
| 11514 |
| 11515 /** |
| 11516 * The element that remains visible when the header condenses. |
| 11517 * |
| 11518 * @type {HTMLElement} |
| 11519 */ |
| 11520 _stickyEl: null, |
| 11521 |
| 11522 /** |
| 11523 * The header's top value used for the `transformY` |
| 11524 * |
| 11525 * @type {number} |
| 11526 */ |
| 11527 _top: 0, |
| 11528 |
| 11529 /** |
| 11530 * The current scroll progress. |
| 11531 * |
| 11532 * @type {number} |
| 11533 */ |
| 11534 _progress: 0, |
| 11535 |
| 11536 _wasScrollingDown: false, |
| 11537 _initScrollTop: 0, |
| 11538 _initTimestamp: 0, |
| 11539 _lastTimestamp: 0, |
| 11540 _lastScrollTop: 0, |
| 11541 |
| 11542 /** |
| 11543 * The distance the header is allowed to move away. |
| 11544 * |
| 11545 * @type {number} |
| 11546 */ |
| 11547 get _maxHeaderTop() { |
| 11548 return this.fixed ? this._dHeight : this._height + 5; |
| 11549 }, |
| 11550 |
| 11551 /** |
| 11552 * Returns a reference to the sticky element. |
| 11553 * |
| 11554 * @return {HTMLElement}? |
| 11555 */ |
| 11556 _getStickyEl: function() { |
| 11557 /** @type {HTMLElement} */ |
| 11558 var stickyEl; |
| 11559 var nodes = Polymer.dom(this.$.content).getDistributedNodes(); |
| 11560 |
| 11561 for (var i = 0; i < nodes.length; i++) { |
| 11562 if (nodes[i].nodeType === Node.ELEMENT_NODE) { |
| 11563 var node = /** @type {HTMLElement} */ (nodes[i]); |
| 11564 if (node.hasAttribute('sticky')) { |
| 11565 stickyEl = node; |
| 11566 break; |
| 11567 } else if (!stickyEl) { |
| 11568 stickyEl = node; |
| 11569 } |
| 11570 } |
| 11571 } |
| 11572 return stickyEl; |
| 11573 }, |
| 11574 |
| 11575 /** |
| 11576 * Resets the layout. If you changed the size of app-header via CSS |
| 11577 * you can notify the changes by either firing the `iron-resize` event |
| 11578 * or calling `resetLayout` directly. |
| 11579 * |
| 11580 * @method resetLayout |
| 11581 */ |
| 11582 resetLayout: function() { |
| 11583 this.fire('app-header-reset-layout'); |
| 11584 |
| 11585 this.debounce('_resetLayout', function() { |
| 11586 // noop if the header isn't visible |
| 11587 if (this.offsetWidth === 0 && this.offsetHeight === 0) { |
| 11588 return; |
| 11589 } |
| 11590 |
| 11591 var scrollTop = this._clampedScrollTop; |
| 11592 var firstSetup = this._height === 0 || scrollTop === 0; |
| 11593 var currentDisabled = this.disabled; |
| 11594 |
| 11595 this._height = this.offsetHeight; |
| 11596 this._stickyEl = this._getStickyEl(); |
| 11597 this.disabled = true; |
| 11598 |
| 11599 // prepare for measurement |
| 11600 if (!firstSetup) { |
| 11601 this._updateScrollState(0, true); |
| 11602 } |
| 11603 |
| 11604 if (this._mayMove()) { |
| 11605 this._dHeight = this._stickyEl ? this._height - this._stickyEl.offse
tHeight : 0; |
| 11606 } else { |
| 11607 this._dHeight = 0; |
| 11608 } |
| 11609 |
| 11610 this._stickyElTop = this._stickyEl ? this._stickyEl.offsetTop : 0; |
| 11611 this._setUpEffect(); |
| 11612 |
| 11613 if (firstSetup) { |
| 11614 this._updateScrollState(scrollTop, true); |
| 11615 } else { |
| 11616 this._updateScrollState(this._lastScrollTop, true); |
| 11617 this._layoutIfDirty(); |
| 11618 } |
| 11619 // restore no transition |
| 11620 this.disabled = currentDisabled; |
| 11621 }); |
| 11622 }, |
| 11623 |
| 11624 /** |
| 11625 * Updates the scroll state. |
| 11626 * |
| 11627 * @param {number} scrollTop |
| 11628 * @param {boolean=} forceUpdate (default: false) |
| 11629 */ |
| 11630 _updateScrollState: function(scrollTop, forceUpdate) { |
| 11631 if (this._height === 0) { |
| 11632 return; |
| 11633 } |
| 11634 |
| 11635 var progress = 0; |
| 11636 var top = 0; |
| 11637 var lastTop = this._top; |
| 11638 var lastScrollTop = this._lastScrollTop; |
| 11639 var maxHeaderTop = this._maxHeaderTop; |
| 11640 var dScrollTop = scrollTop - this._lastScrollTop; |
| 11641 var absDScrollTop = Math.abs(dScrollTop); |
| 11642 var isScrollingDown = scrollTop > this._lastScrollTop; |
| 11643 var now = Date.now(); |
| 11644 |
| 11645 if (this._mayMove()) { |
| 11646 top = this._clamp(this.reveals ? lastTop + dScrollTop : scrollTop, 0,
maxHeaderTop); |
| 11647 } |
| 11648 |
| 11649 if (scrollTop >= this._dHeight) { |
| 11650 top = this.condenses && !this.fixed ? Math.max(this._dHeight, top) : t
op; |
| 11651 this.style.transitionDuration = '0ms'; |
| 11652 } |
| 11653 |
| 11654 if (this.reveals && !this.disabled && absDScrollTop < 100) { |
| 11655 // set the initial scroll position |
| 11656 if (now - this._initTimestamp > 300 || this._wasScrollingDown !== isSc
rollingDown) { |
| 11657 this._initScrollTop = scrollTop; |
| 11658 this._initTimestamp = now; |
| 11659 } |
| 11660 |
| 11661 if (scrollTop >= maxHeaderTop) { |
| 11662 // check if the header is allowed to snap |
| 11663 if (Math.abs(this._initScrollTop - scrollTop) > 30 || absDScrollTop
> 10) { |
| 11664 if (isScrollingDown && scrollTop >= maxHeaderTop) { |
| 11665 top = maxHeaderTop; |
| 11666 } else if (!isScrollingDown && scrollTop >= this._dHeight) { |
| 11667 top = this.condenses && !this.fixed ? this._dHeight : 0; |
| 11668 } |
| 11669 var scrollVelocity = dScrollTop / (now - this._lastTimestamp); |
| 11670 this.style.transitionDuration = this._clamp((top - lastTop) / scro
llVelocity, 0, 300) + 'ms'; |
| 11671 } else { |
| 11672 top = this._top; |
| 11673 } |
| 11674 } |
| 11675 } |
| 11676 |
| 11677 if (this._dHeight === 0) { |
| 11678 progress = scrollTop > 0 ? 1 : 0; |
| 11679 } else { |
| 11680 progress = top / this._dHeight; |
| 11681 } |
| 11682 |
| 11683 if (!forceUpdate) { |
| 11684 this._lastScrollTop = scrollTop; |
| 11685 this._top = top; |
| 11686 this._wasScrollingDown = isScrollingDown; |
| 11687 this._lastTimestamp = now; |
| 11688 } |
| 11689 |
| 11690 if (forceUpdate || progress !== this._progress || lastTop !== top || scr
ollTop === 0) { |
| 11691 this._progress = progress; |
| 11692 this._runEffects(progress, top); |
| 11693 this._transformHeader(top); |
| 11694 } |
| 11695 }, |
| 11696 |
| 11697 /** |
| 11698 * Returns true if the current header is allowed to move as the user scrol
ls. |
| 11699 * |
| 11700 * @return {boolean} |
| 11701 */ |
| 11702 _mayMove: function() { |
| 11703 return this.condenses || !this.fixed; |
| 11704 }, |
| 11705 |
| 11706 /** |
| 11707 * Returns true if the current header will condense based on the size of t
he header |
| 11708 * and the `consenses` property. |
| 11709 * |
| 11710 * @return {boolean} |
| 11711 */ |
| 11712 willCondense: function() { |
| 11713 return this._dHeight > 0 && this.condenses; |
| 11714 }, |
| 11715 |
| 11716 /** |
| 11717 * Returns true if the current element is on the screen. |
| 11718 * That is, visible in the current viewport. |
| 11719 * |
| 11720 * @method isOnScreen |
| 11721 * @return {boolean} |
| 11722 */ |
| 11723 isOnScreen: function() { |
| 11724 return this._height !== 0 && this._top < this._height; |
| 11725 }, |
| 11726 |
| 11727 /** |
| 11728 * Returns true if there's content below the current element. |
| 11729 * |
| 11730 * @method isContentBelow |
| 11731 * @return {boolean} |
| 11732 */ |
| 11733 isContentBelow: function() { |
| 11734 if (this._top === 0) { |
| 11735 return this._clampedScrollTop > 0; |
| 11736 } |
| 11737 return this._clampedScrollTop - this._maxHeaderTop >= 0; |
| 11738 }, |
| 11739 |
| 11740 /** |
| 11741 * Transforms the header. |
| 11742 * |
| 11743 * @param {number} y |
| 11744 */ |
| 11745 _transformHeader: function(y) { |
| 11746 this.translate3d(0, (-y) + 'px', 0); |
| 11747 if (this._stickyEl && this.condenses && y >= this._stickyElTop) { |
| 11748 this.translate3d(0, (Math.min(y, this._dHeight) - this._stickyElTop) +
'px', 0, |
| 11749 this._stickyEl); |
| 11750 } |
| 11751 }, |
| 11752 |
| 11753 _resizeHandler: function() { |
| 11754 this.resetLayout(); |
| 11755 }, |
| 11756 |
| 11757 _clamp: function(v, min, max) { |
| 11758 return Math.min(max, Math.max(min, v)); |
| 11759 }, |
| 11760 |
| 11761 _ensureBgContainers: function() { |
| 11762 if (!this._bgContainer) { |
| 11763 this._bgContainer = document.createElement('div'); |
| 11764 this._bgContainer.id = 'background'; |
| 11765 |
| 11766 this._bgRear = document.createElement('div'); |
| 11767 this._bgRear.id = 'backgroundRearLayer'; |
| 11768 this._bgContainer.appendChild(this._bgRear); |
| 11769 |
| 11770 this._bgFront = document.createElement('div'); |
| 11771 this._bgFront.id = 'backgroundFrontLayer'; |
| 11772 this._bgContainer.appendChild(this._bgFront); |
| 11773 |
| 11774 Polymer.dom(this.root).insertBefore(this._bgContainer, this.$.contentC
ontainer); |
| 11775 } |
| 11776 }, |
| 11777 |
| 11778 _getDOMRef: function(id) { |
| 11779 switch (id) { |
| 11780 case 'backgroundFrontLayer': |
| 11781 this._ensureBgContainers(); |
| 11782 return this._bgFront; |
| 11783 case 'backgroundRearLayer': |
| 11784 this._ensureBgContainers(); |
| 11785 return this._bgRear; |
| 11786 case 'background': |
| 11787 this._ensureBgContainers(); |
| 11788 return this._bgContainer; |
| 11789 case 'mainTitle': |
| 11790 return Polymer.dom(this).querySelector('[main-title]'); |
| 11791 case 'condensedTitle': |
| 11792 return Polymer.dom(this).querySelector('[condensed-title]'); |
| 11793 } |
| 11794 return null; |
| 11795 }, |
| 11796 |
| 11797 /** |
| 11798 * Returns an object containing the progress value of the scroll effects |
| 11799 * and the top position of the header. |
| 11800 * |
| 11801 * @method getScrollState |
| 11802 * @return {Object} |
| 11803 */ |
| 11804 getScrollState: function() { |
| 11805 return { progress: this._progress, top: this._top }; |
| 11806 } |
| 11807 |
| 11808 /** |
| 11809 * Fires when the layout of `app-header` changed. |
| 11810 * |
| 11811 * @event app-header-reset-layout |
| 11812 */ |
| 11813 }); |
| 11814 </script> |
| 11815 </dom-module> |
| 11816 |
| 11817 |
| 11818 <dom-module id="app-header-layout" assetpath="bower_components/app-layout/app-he
ader-layout/"> |
| 11819 <template> |
| 11820 <style> |
| 11821 :host { |
| 11822 display: block; |
| 11823 /** |
| 11824 * Force app-header-layout to have its own stacking context so that its
parent can |
| 11825 * control the stacking of it relative to other elements (e.g. app-drawe
r-layout). |
| 11826 * This could be done using `isolation: isolate`, but that's not well su
pported |
| 11827 * across browsers. |
| 11828 */ |
| 11829 position: relative; |
| 11830 z-index: 0; |
| 11831 } |
| 11832 |
| 11833 :host > ::content > app-header { |
| 11834 @apply(--layout-fixed-top); |
| 11835 z-index: 1; |
| 11836 } |
| 11837 |
| 11838 :host([has-scrolling-region]) { |
| 11839 height: 100%; |
| 11840 } |
| 11841 |
| 11842 :host([has-scrolling-region]) > ::content > app-header { |
| 11843 position: absolute; |
| 11844 } |
| 11845 |
| 11846 :host([has-scrolling-region]) > #contentContainer { |
| 11847 @apply(--layout-fit); |
| 11848 overflow-y: auto; |
| 11849 -webkit-overflow-scrolling: touch; |
| 11850 } |
| 11851 |
| 11852 :host([fullbleed]) { |
| 11853 @apply(--layout-vertical); |
| 11854 @apply(--layout-fit); |
| 11855 } |
| 11856 |
| 11857 :host([fullbleed]) > #contentContainer { |
| 11858 @apply(--layout-vertical); |
| 11859 @apply(--layout-flex); |
| 11860 } |
| 11861 |
| 11862 #contentContainer { |
| 11863 /* Create a stacking context here so that all children appear below the
header. */ |
| 11864 position: relative; |
| 11865 z-index: 0; |
| 11866 } |
| 11867 |
| 11868 </style> |
| 11869 |
| 11870 <content id="header" select="app-header"></content> |
| 11871 |
| 11872 <div id="contentContainer"> |
| 11873 <content></content> |
| 11874 </div> |
| 11875 |
| 11876 </template> |
| 11877 |
| 11878 <script> |
| 11879 Polymer({ |
| 11880 is: 'app-header-layout', |
| 11881 |
| 11882 behaviors: [ |
| 11883 Polymer.IronResizableBehavior |
| 11884 ], |
| 11885 |
| 11886 properties: { |
| 11887 /** |
| 11888 * If true, the current element will have its own scrolling region. |
| 11889 * Otherwise, it will use the document scroll to control the header. |
| 11890 */ |
| 11891 hasScrollingRegion: { |
| 11892 type: Boolean, |
| 11893 value: false, |
| 11894 reflectToAttribute: true |
| 11895 } |
| 11896 }, |
| 11897 |
| 11898 listeners: { |
| 11899 'iron-resize': '_resizeHandler', |
| 11900 'app-header-reset-layout': 'resetLayout' |
| 11901 }, |
| 11902 |
| 11903 observers: [ |
| 11904 'resetLayout(isAttached, hasScrollingRegion)' |
| 11905 ], |
| 11906 |
| 11907 /** |
| 11908 * A reference to the app-header element. |
| 11909 * |
| 11910 * @property header |
| 11911 */ |
| 11912 get header() { |
| 11913 return Polymer.dom(this.$.header).getDistributedNodes()[0]; |
| 11914 }, |
| 11915 |
| 11916 /** |
| 11917 * Resets the layout. This method is automatically called when the element
is attached |
| 11918 * to the DOM. |
| 11919 * |
| 11920 * @method resetLayout |
| 11921 */ |
| 11922 resetLayout: function() { |
| 11923 this._updateScroller(); |
| 11924 this.debounce('_resetLayout', this._updateContentPosition); |
| 11925 }, |
| 11926 |
| 11927 _updateContentPosition: function() { |
| 11928 var header = this.header; |
| 11929 if (!this.isAttached || !header) { |
| 11930 return; |
| 11931 } |
| 11932 // Get header height here so that style reads are batched together befor
e style writes |
| 11933 // (i.e. getBoundingClientRect() below). |
| 11934 var headerHeight = header.offsetHeight; |
| 11935 // Update the header position. |
| 11936 if (!this.hasScrollingRegion) { |
| 11937 var rect = this.getBoundingClientRect(); |
| 11938 var rightOffset = document.documentElement.clientWidth - rect.right; |
| 11939 header.style.left = rect.left + 'px'; |
| 11940 header.style.right = rightOffset + 'px'; |
| 11941 } else { |
| 11942 header.style.left = ''; |
| 11943 header.style.right = ''; |
| 11944 } |
| 11945 // Update the content container position. |
| 11946 var containerStyle = this.$.contentContainer.style; |
| 11947 if (header.fixed && !header.willCondense() && this.hasScrollingRegion) { |
| 11948 // If the header size does not change and we're using a scrolling regi
on, exclude |
| 11949 // the header area from the scrolling region so that the header doesn'
t overlap |
| 11950 // the scrollbar. |
| 11951 containerStyle.marginTop = headerHeight + 'px'; |
| 11952 containerStyle.paddingTop = ''; |
| 11953 } else { |
| 11954 containerStyle.paddingTop = headerHeight + 'px'; |
| 11955 containerStyle.marginTop = ''; |
| 11956 } |
| 11957 }, |
| 11958 |
| 11959 _updateScroller: function() { |
| 11960 if (!this.isAttached) { |
| 11961 return; |
| 11962 } |
| 11963 var header = this.header; |
| 11964 if (header) { |
| 11965 header.scrollTarget = this.hasScrollingRegion ? |
| 11966 this.$.contentContainer : this.ownerDocument.documentElement; |
| 11967 } |
| 11968 }, |
| 11969 |
| 11970 _resizeHandler: function() { |
| 11971 this.resetLayout(); |
| 11972 } |
| 11973 }); |
| 11974 </script> |
| 11975 </dom-module> |
| 11976 |
| 11977 |
| 11978 <dom-module id="app-scrollpos-control" assetpath="bower_components/app-layout/ap
p-scrollpos-control/"> |
| 11979 <script> |
| 11980 Polymer({ |
| 11981 is: 'app-scrollpos-control', |
| 11982 |
| 11983 behaviors: [ |
| 11984 Polymer.IronScrollTargetBehavior |
| 11985 ], |
| 11986 |
| 11987 properties: { |
| 11988 /** |
| 11989 * The selected page. |
| 11990 */ |
| 11991 selected: { |
| 11992 type: String, |
| 11993 observer: '_selectedChanged' |
| 11994 }, |
| 11995 |
| 11996 /** |
| 11997 * Reset the scroll position to 0. |
| 11998 */ |
| 11999 reset: { |
| 12000 type: Boolean, |
| 12001 value: false |
| 12002 } |
| 12003 }, |
| 12004 |
| 12005 observers: [ |
| 12006 '_updateScrollPos(selected, reset)' |
| 12007 ], |
| 12008 |
| 12009 created: function() { |
| 12010 this._scrollposMap = {}; |
| 12011 }, |
| 12012 |
| 12013 _selectedChanged: function(selected, old) { |
| 12014 if (old != null) { |
| 12015 this._scrollposMap[old] = {x: this._scrollLeft, y: this._scrollTop}; |
| 12016 } |
| 12017 }, |
| 12018 |
| 12019 _updateScrollPos: function(selected, reset) { |
| 12020 this.debounce('_updateScrollPos', function() { |
| 12021 var pos = this._scrollposMap[this.selected]; |
| 12022 if (pos != null && !this.reset) { |
| 12023 this.scroll(pos.x, pos.y); |
| 12024 } else { |
| 12025 this.scroll(0, 0); |
| 12026 } |
| 12027 }); |
| 12028 } |
| 12029 }); |
| 12030 </script> |
| 12031 </dom-module> |
| 12032 |
| 12033 |
| 12034 <dom-module id="app-toolbar" assetpath="bower_components/app-layout/app-toolbar/
"> |
| 12035 <template> |
| 12036 <style> |
| 12037 :host { |
| 12038 position: relative; |
| 12039 |
| 12040 @apply(--layout-horizontal); |
| 12041 @apply(--layout-center); |
| 12042 |
| 12043 height: 64px; |
| 12044 padding: 0 16px; |
| 12045 |
| 12046 pointer-events: none; |
| 12047 |
| 12048 font-size: var(--app-toolbar-font-size, 20px); |
| 12049 } |
| 12050 |
| 12051 :host > ::content > * { |
| 12052 pointer-events: auto; |
| 12053 } |
| 12054 |
| 12055 :host > ::content > paper-icon-button { |
| 12056 /* paper-icon-button/issues/33 */ |
| 12057 font-size: 0; |
| 12058 } |
| 12059 |
| 12060 :host > ::content > [main-title], |
| 12061 :host > ::content > [condensed-title] { |
| 12062 pointer-events: none; |
| 12063 @apply(--layout-flex); |
| 12064 } |
| 12065 |
| 12066 :host > ::content > [bottom-item] { |
| 12067 position: absolute; |
| 12068 right: 0; |
| 12069 bottom: 0; |
| 12070 left: 0; |
| 12071 } |
| 12072 |
| 12073 :host > ::content > [top-item] { |
| 12074 position: absolute; |
| 12075 top: 0; |
| 12076 right: 0; |
| 12077 left: 0; |
| 12078 } |
| 12079 |
| 12080 :host > ::content > [spacer] { |
| 12081 margin-left: 64px; |
| 12082 } |
| 12083 </style> |
| 12084 |
| 12085 <content></content> |
| 12086 </template> |
| 12087 |
| 12088 <script> |
| 12089 Polymer({ |
| 12090 is: 'app-toolbar' |
| 12091 }); |
| 12092 </script> |
| 12093 </dom-module> |
| 12094 |
| 12095 |
| 12096 <dom-module id="app-box" assetpath="bower_components/app-layout/app-box/"> |
| 12097 <template> |
| 12098 <style> |
| 12099 :host { |
| 12100 position: relative; |
| 12101 |
| 12102 display: block; |
| 12103 } |
| 12104 |
| 12105 #background { |
| 12106 @apply(--layout-fit); |
| 12107 |
| 12108 overflow: hidden; |
| 12109 |
| 12110 height: 100%; |
| 12111 } |
| 12112 |
| 12113 #backgroundFrontLayer { |
| 12114 min-height: 100%; |
| 12115 |
| 12116 pointer-events: none; |
| 12117 |
| 12118 background-size: cover; |
| 12119 |
| 12120 @apply(--app-box-background-front-layer); |
| 12121 } |
| 12122 |
| 12123 #contentContainer { |
| 12124 position: relative; |
| 12125 |
| 12126 width: 100%; |
| 12127 height: 100%; |
| 12128 } |
| 12129 |
| 12130 :host([disabled]), |
| 12131 :host([disabled]) #backgroundFrontLayer { |
| 12132 transition: none !important; |
| 12133 } |
| 12134 </style> |
| 12135 |
| 12136 <div id="background"> |
| 12137 <div id="backgroundFrontLayer"> |
| 12138 <content select="[background]"></content> |
| 12139 </div> |
| 12140 </div> |
| 12141 <div id="contentContainer"> |
| 12142 <content id="content"></content> |
| 12143 </div> |
| 12144 </template> |
| 12145 |
| 12146 <script> |
| 12147 Polymer({ |
| 12148 is: 'app-box', |
| 12149 |
| 12150 behaviors: [ |
| 12151 Polymer.AppScrollEffectsBehavior, |
| 12152 Polymer.IronResizableBehavior |
| 12153 ], |
| 12154 |
| 12155 listeners: { |
| 12156 'iron-resize': '_resizeHandler' |
| 12157 }, |
| 12158 |
| 12159 /** |
| 12160 * The current scroll progress. |
| 12161 * |
| 12162 * @type {number} |
| 12163 */ |
| 12164 _progress: 0, |
| 12165 |
| 12166 attached: function() { |
| 12167 this.resetLayout(); |
| 12168 }, |
| 12169 |
| 12170 /** |
| 12171 * Resets the layout. This method is automatically called when the element
is attached to the DOM. |
| 12172 * |
| 12173 * @method resetLayout |
| 12174 */ |
| 12175 resetLayout: function() { |
| 12176 this.debounce('_resetLayout', function() { |
| 12177 // noop if the box isn't in the rendered tree |
| 12178 if (this.offsetWidth === 0 && this.offsetHeight === 0) { |
| 12179 return; |
| 12180 } |
| 12181 |
| 12182 var scrollTop = this._clampedScrollTop; |
| 12183 var savedDisabled = this.disabled; |
| 12184 |
| 12185 this.disabled = true; |
| 12186 this._elementTop = this._getElementTop(); |
| 12187 this._elementHeight = this.offsetHeight; |
| 12188 this._cachedScrollTargetHeight = this._scrollTargetHeight; |
| 12189 this._setUpEffect(); |
| 12190 this._updateScrollState(scrollTop); |
| 12191 this.disabled = savedDisabled; |
| 12192 }, 1); |
| 12193 }, |
| 12194 |
| 12195 _getElementTop: function() { |
| 12196 var currentNode = this; |
| 12197 var top = 0; |
| 12198 |
| 12199 while (currentNode && currentNode !== this.scrollTarget) { |
| 12200 top += currentNode.offsetTop; |
| 12201 currentNode = currentNode.offsetParent; |
| 12202 } |
| 12203 return top; |
| 12204 }, |
| 12205 |
| 12206 _updateScrollState: function(scrollTop) { |
| 12207 if (this.isOnScreen()) { |
| 12208 var viewportTop = this._elementTop - scrollTop; |
| 12209 this._progress = 1 - (viewportTop + this._elementHeight) / this._cache
dScrollTargetHeight; |
| 12210 this._runEffects(this._progress, scrollTop); |
| 12211 } |
| 12212 }, |
| 12213 |
| 12214 /** |
| 12215 * Returns true if this app-box is on the screen. |
| 12216 * That is, visible in the current viewport. |
| 12217 * |
| 12218 * @method isOnScreen |
| 12219 * @return {boolean} |
| 12220 */ |
| 12221 isOnScreen: function() { |
| 12222 return this._elementTop < this._scrollTop + this._cachedScrollTargetHeig
ht |
| 12223 && this._elementTop + this._elementHeight > this._scrollTop; |
| 12224 }, |
| 12225 |
| 12226 _resizeHandler: function() { |
| 12227 this.resetLayout(); |
| 12228 }, |
| 12229 |
| 12230 _getDOMRef: function(id) { |
| 12231 if (id === 'background') { |
| 12232 return this.$.background; |
| 12233 } |
| 12234 if (id === 'backgroundFrontLayer') { |
| 12235 return this.$.backgroundFrontLayer; |
| 12236 } |
| 12237 }, |
| 12238 |
| 12239 /** |
| 12240 * Returns an object containing the progress value of the scroll effects. |
| 12241 * |
| 12242 * @method getScrollState |
| 12243 * @return {Object} |
| 12244 */ |
| 12245 getScrollState: function() { |
| 12246 return { progress: this._progress }; |
| 12247 } |
| 12248 }); |
| 12249 </script> |
| 12250 </dom-module> |
| 12251 <style is="custom-style"> |
| 12252 |
| 12253 :root { |
| 12254 |
| 12255 /* Material Design color palette for Google products */ |
| 12256 |
| 12257 --google-red-100: #f4c7c3; |
| 12258 --google-red-300: #e67c73; |
| 12259 --google-red-500: #db4437; |
| 12260 --google-red-700: #c53929; |
| 12261 |
| 12262 --google-blue-100: #c6dafc; |
| 12263 --google-blue-300: #7baaf7; |
| 12264 --google-blue-500: #4285f4; |
| 12265 --google-blue-700: #3367d6; |
| 12266 |
| 12267 --google-green-100: #b7e1cd; |
| 12268 --google-green-300: #57bb8a; |
| 12269 --google-green-500: #0f9d58; |
| 12270 --google-green-700: #0b8043; |
| 12271 |
| 12272 --google-yellow-100: #fce8b2; |
| 12273 --google-yellow-300: #f7cb4d; |
| 12274 --google-yellow-500: #f4b400; |
| 12275 --google-yellow-700: #f09300; |
| 12276 |
| 12277 --google-grey-100: #f5f5f5; |
| 12278 --google-grey-300: #e0e0e0; |
| 12279 --google-grey-500: #9e9e9e; |
| 12280 --google-grey-700: #616161; |
| 12281 |
| 12282 /* Material Design color palette from online spec document */ |
| 12283 |
| 12284 --paper-red-50: #ffebee; |
| 12285 --paper-red-100: #ffcdd2; |
| 12286 --paper-red-200: #ef9a9a; |
| 12287 --paper-red-300: #e57373; |
| 12288 --paper-red-400: #ef5350; |
| 12289 --paper-red-500: #f44336; |
| 12290 --paper-red-600: #e53935; |
| 12291 --paper-red-700: #d32f2f; |
| 12292 --paper-red-800: #c62828; |
| 12293 --paper-red-900: #b71c1c; |
| 12294 --paper-red-a100: #ff8a80; |
| 12295 --paper-red-a200: #ff5252; |
| 12296 --paper-red-a400: #ff1744; |
| 12297 --paper-red-a700: #d50000; |
| 12298 |
| 12299 --paper-pink-50: #fce4ec; |
| 12300 --paper-pink-100: #f8bbd0; |
| 12301 --paper-pink-200: #f48fb1; |
| 12302 --paper-pink-300: #f06292; |
| 12303 --paper-pink-400: #ec407a; |
| 12304 --paper-pink-500: #e91e63; |
| 12305 --paper-pink-600: #d81b60; |
| 12306 --paper-pink-700: #c2185b; |
| 12307 --paper-pink-800: #ad1457; |
| 12308 --paper-pink-900: #880e4f; |
| 12309 --paper-pink-a100: #ff80ab; |
| 12310 --paper-pink-a200: #ff4081; |
| 12311 --paper-pink-a400: #f50057; |
| 12312 --paper-pink-a700: #c51162; |
| 12313 |
| 12314 --paper-purple-50: #f3e5f5; |
| 12315 --paper-purple-100: #e1bee7; |
| 12316 --paper-purple-200: #ce93d8; |
| 12317 --paper-purple-300: #ba68c8; |
| 12318 --paper-purple-400: #ab47bc; |
| 12319 --paper-purple-500: #9c27b0; |
| 12320 --paper-purple-600: #8e24aa; |
| 12321 --paper-purple-700: #7b1fa2; |
| 12322 --paper-purple-800: #6a1b9a; |
| 12323 --paper-purple-900: #4a148c; |
| 12324 --paper-purple-a100: #ea80fc; |
| 12325 --paper-purple-a200: #e040fb; |
| 12326 --paper-purple-a400: #d500f9; |
| 12327 --paper-purple-a700: #aa00ff; |
| 12328 |
| 12329 --paper-deep-purple-50: #ede7f6; |
| 12330 --paper-deep-purple-100: #d1c4e9; |
| 12331 --paper-deep-purple-200: #b39ddb; |
| 12332 --paper-deep-purple-300: #9575cd; |
| 12333 --paper-deep-purple-400: #7e57c2; |
| 12334 --paper-deep-purple-500: #673ab7; |
| 12335 --paper-deep-purple-600: #5e35b1; |
| 12336 --paper-deep-purple-700: #512da8; |
| 12337 --paper-deep-purple-800: #4527a0; |
| 12338 --paper-deep-purple-900: #311b92; |
| 12339 --paper-deep-purple-a100: #b388ff; |
| 12340 --paper-deep-purple-a200: #7c4dff; |
| 12341 --paper-deep-purple-a400: #651fff; |
| 12342 --paper-deep-purple-a700: #6200ea; |
| 12343 |
| 12344 --paper-indigo-50: #e8eaf6; |
| 12345 --paper-indigo-100: #c5cae9; |
| 12346 --paper-indigo-200: #9fa8da; |
| 12347 --paper-indigo-300: #7986cb; |
| 12348 --paper-indigo-400: #5c6bc0; |
| 12349 --paper-indigo-500: #3f51b5; |
| 12350 --paper-indigo-600: #3949ab; |
| 12351 --paper-indigo-700: #303f9f; |
| 12352 --paper-indigo-800: #283593; |
| 12353 --paper-indigo-900: #1a237e; |
| 12354 --paper-indigo-a100: #8c9eff; |
| 12355 --paper-indigo-a200: #536dfe; |
| 12356 --paper-indigo-a400: #3d5afe; |
| 12357 --paper-indigo-a700: #304ffe; |
| 12358 |
| 12359 --paper-blue-50: #e3f2fd; |
| 12360 --paper-blue-100: #bbdefb; |
| 12361 --paper-blue-200: #90caf9; |
| 12362 --paper-blue-300: #64b5f6; |
| 12363 --paper-blue-400: #42a5f5; |
| 12364 --paper-blue-500: #2196f3; |
| 12365 --paper-blue-600: #1e88e5; |
| 12366 --paper-blue-700: #1976d2; |
| 12367 --paper-blue-800: #1565c0; |
| 12368 --paper-blue-900: #0d47a1; |
| 12369 --paper-blue-a100: #82b1ff; |
| 12370 --paper-blue-a200: #448aff; |
| 12371 --paper-blue-a400: #2979ff; |
| 12372 --paper-blue-a700: #2962ff; |
| 12373 |
| 12374 --paper-light-blue-50: #e1f5fe; |
| 12375 --paper-light-blue-100: #b3e5fc; |
| 12376 --paper-light-blue-200: #81d4fa; |
| 12377 --paper-light-blue-300: #4fc3f7; |
| 12378 --paper-light-blue-400: #29b6f6; |
| 12379 --paper-light-blue-500: #03a9f4; |
| 12380 --paper-light-blue-600: #039be5; |
| 12381 --paper-light-blue-700: #0288d1; |
| 12382 --paper-light-blue-800: #0277bd; |
| 12383 --paper-light-blue-900: #01579b; |
| 12384 --paper-light-blue-a100: #80d8ff; |
| 12385 --paper-light-blue-a200: #40c4ff; |
| 12386 --paper-light-blue-a400: #00b0ff; |
| 12387 --paper-light-blue-a700: #0091ea; |
| 12388 |
| 12389 --paper-cyan-50: #e0f7fa; |
| 12390 --paper-cyan-100: #b2ebf2; |
| 12391 --paper-cyan-200: #80deea; |
| 12392 --paper-cyan-300: #4dd0e1; |
| 12393 --paper-cyan-400: #26c6da; |
| 12394 --paper-cyan-500: #00bcd4; |
| 12395 --paper-cyan-600: #00acc1; |
| 12396 --paper-cyan-700: #0097a7; |
| 12397 --paper-cyan-800: #00838f; |
| 12398 --paper-cyan-900: #006064; |
| 12399 --paper-cyan-a100: #84ffff; |
| 12400 --paper-cyan-a200: #18ffff; |
| 12401 --paper-cyan-a400: #00e5ff; |
| 12402 --paper-cyan-a700: #00b8d4; |
| 12403 |
| 12404 --paper-teal-50: #e0f2f1; |
| 12405 --paper-teal-100: #b2dfdb; |
| 12406 --paper-teal-200: #80cbc4; |
| 12407 --paper-teal-300: #4db6ac; |
| 12408 --paper-teal-400: #26a69a; |
| 12409 --paper-teal-500: #009688; |
| 12410 --paper-teal-600: #00897b; |
| 12411 --paper-teal-700: #00796b; |
| 12412 --paper-teal-800: #00695c; |
| 12413 --paper-teal-900: #004d40; |
| 12414 --paper-teal-a100: #a7ffeb; |
| 12415 --paper-teal-a200: #64ffda; |
| 12416 --paper-teal-a400: #1de9b6; |
| 12417 --paper-teal-a700: #00bfa5; |
| 12418 |
| 12419 --paper-green-50: #e8f5e9; |
| 12420 --paper-green-100: #c8e6c9; |
| 12421 --paper-green-200: #a5d6a7; |
| 12422 --paper-green-300: #81c784; |
| 12423 --paper-green-400: #66bb6a; |
| 12424 --paper-green-500: #4caf50; |
| 12425 --paper-green-600: #43a047; |
| 12426 --paper-green-700: #388e3c; |
| 12427 --paper-green-800: #2e7d32; |
| 12428 --paper-green-900: #1b5e20; |
| 12429 --paper-green-a100: #b9f6ca; |
| 12430 --paper-green-a200: #69f0ae; |
| 12431 --paper-green-a400: #00e676; |
| 12432 --paper-green-a700: #00c853; |
| 12433 |
| 12434 --paper-light-green-50: #f1f8e9; |
| 12435 --paper-light-green-100: #dcedc8; |
| 12436 --paper-light-green-200: #c5e1a5; |
| 12437 --paper-light-green-300: #aed581; |
| 12438 --paper-light-green-400: #9ccc65; |
| 12439 --paper-light-green-500: #8bc34a; |
| 12440 --paper-light-green-600: #7cb342; |
| 12441 --paper-light-green-700: #689f38; |
| 12442 --paper-light-green-800: #558b2f; |
| 12443 --paper-light-green-900: #33691e; |
| 12444 --paper-light-green-a100: #ccff90; |
| 12445 --paper-light-green-a200: #b2ff59; |
| 12446 --paper-light-green-a400: #76ff03; |
| 12447 --paper-light-green-a700: #64dd17; |
| 12448 |
| 12449 --paper-lime-50: #f9fbe7; |
| 12450 --paper-lime-100: #f0f4c3; |
| 12451 --paper-lime-200: #e6ee9c; |
| 12452 --paper-lime-300: #dce775; |
| 12453 --paper-lime-400: #d4e157; |
| 12454 --paper-lime-500: #cddc39; |
| 12455 --paper-lime-600: #c0ca33; |
| 12456 --paper-lime-700: #afb42b; |
| 12457 --paper-lime-800: #9e9d24; |
| 12458 --paper-lime-900: #827717; |
| 12459 --paper-lime-a100: #f4ff81; |
| 12460 --paper-lime-a200: #eeff41; |
| 12461 --paper-lime-a400: #c6ff00; |
| 12462 --paper-lime-a700: #aeea00; |
| 12463 |
| 12464 --paper-yellow-50: #fffde7; |
| 12465 --paper-yellow-100: #fff9c4; |
| 12466 --paper-yellow-200: #fff59d; |
| 12467 --paper-yellow-300: #fff176; |
| 12468 --paper-yellow-400: #ffee58; |
| 12469 --paper-yellow-500: #ffeb3b; |
| 12470 --paper-yellow-600: #fdd835; |
| 12471 --paper-yellow-700: #fbc02d; |
| 12472 --paper-yellow-800: #f9a825; |
| 12473 --paper-yellow-900: #f57f17; |
| 12474 --paper-yellow-a100: #ffff8d; |
| 12475 --paper-yellow-a200: #ffff00; |
| 12476 --paper-yellow-a400: #ffea00; |
| 12477 --paper-yellow-a700: #ffd600; |
| 12478 |
| 12479 --paper-amber-50: #fff8e1; |
| 12480 --paper-amber-100: #ffecb3; |
| 12481 --paper-amber-200: #ffe082; |
| 12482 --paper-amber-300: #ffd54f; |
| 12483 --paper-amber-400: #ffca28; |
| 12484 --paper-amber-500: #ffc107; |
| 12485 --paper-amber-600: #ffb300; |
| 12486 --paper-amber-700: #ffa000; |
| 12487 --paper-amber-800: #ff8f00; |
| 12488 --paper-amber-900: #ff6f00; |
| 12489 --paper-amber-a100: #ffe57f; |
| 12490 --paper-amber-a200: #ffd740; |
| 12491 --paper-amber-a400: #ffc400; |
| 12492 --paper-amber-a700: #ffab00; |
| 12493 |
| 12494 --paper-orange-50: #fff3e0; |
| 12495 --paper-orange-100: #ffe0b2; |
| 12496 --paper-orange-200: #ffcc80; |
| 12497 --paper-orange-300: #ffb74d; |
| 12498 --paper-orange-400: #ffa726; |
| 12499 --paper-orange-500: #ff9800; |
| 12500 --paper-orange-600: #fb8c00; |
| 12501 --paper-orange-700: #f57c00; |
| 12502 --paper-orange-800: #ef6c00; |
| 12503 --paper-orange-900: #e65100; |
| 12504 --paper-orange-a100: #ffd180; |
| 12505 --paper-orange-a200: #ffab40; |
| 12506 --paper-orange-a400: #ff9100; |
| 12507 --paper-orange-a700: #ff6500; |
| 12508 |
| 12509 --paper-deep-orange-50: #fbe9e7; |
| 12510 --paper-deep-orange-100: #ffccbc; |
| 12511 --paper-deep-orange-200: #ffab91; |
| 12512 --paper-deep-orange-300: #ff8a65; |
| 12513 --paper-deep-orange-400: #ff7043; |
| 12514 --paper-deep-orange-500: #ff5722; |
| 12515 --paper-deep-orange-600: #f4511e; |
| 12516 --paper-deep-orange-700: #e64a19; |
| 12517 --paper-deep-orange-800: #d84315; |
| 12518 --paper-deep-orange-900: #bf360c; |
| 12519 --paper-deep-orange-a100: #ff9e80; |
| 12520 --paper-deep-orange-a200: #ff6e40; |
| 12521 --paper-deep-orange-a400: #ff3d00; |
| 12522 --paper-deep-orange-a700: #dd2c00; |
| 12523 |
| 12524 --paper-brown-50: #efebe9; |
| 12525 --paper-brown-100: #d7ccc8; |
| 12526 --paper-brown-200: #bcaaa4; |
| 12527 --paper-brown-300: #a1887f; |
| 12528 --paper-brown-400: #8d6e63; |
| 12529 --paper-brown-500: #795548; |
| 12530 --paper-brown-600: #6d4c41; |
| 12531 --paper-brown-700: #5d4037; |
| 12532 --paper-brown-800: #4e342e; |
| 12533 --paper-brown-900: #3e2723; |
| 12534 |
| 12535 --paper-grey-50: #fafafa; |
| 12536 --paper-grey-100: #f5f5f5; |
| 12537 --paper-grey-200: #eeeeee; |
| 12538 --paper-grey-300: #e0e0e0; |
| 12539 --paper-grey-400: #bdbdbd; |
| 12540 --paper-grey-500: #9e9e9e; |
| 12541 --paper-grey-600: #757575; |
| 12542 --paper-grey-700: #616161; |
| 12543 --paper-grey-800: #424242; |
| 12544 --paper-grey-900: #212121; |
| 12545 |
| 12546 --paper-blue-grey-50: #eceff1; |
| 12547 --paper-blue-grey-100: #cfd8dc; |
| 12548 --paper-blue-grey-200: #b0bec5; |
| 12549 --paper-blue-grey-300: #90a4ae; |
| 12550 --paper-blue-grey-400: #78909c; |
| 12551 --paper-blue-grey-500: #607d8b; |
| 12552 --paper-blue-grey-600: #546e7a; |
| 12553 --paper-blue-grey-700: #455a64; |
| 12554 --paper-blue-grey-800: #37474f; |
| 12555 --paper-blue-grey-900: #263238; |
| 12556 |
| 12557 /* opacity for dark text on a light background */ |
| 12558 --dark-divider-opacity: 0.12; |
| 12559 --dark-disabled-opacity: 0.38; /* or hint text or icon */ |
| 12560 --dark-secondary-opacity: 0.54; |
| 12561 --dark-primary-opacity: 0.87; |
| 12562 |
| 12563 /* opacity for light text on a dark background */ |
| 12564 --light-divider-opacity: 0.12; |
| 12565 --light-disabled-opacity: 0.3; /* or hint text or icon */ |
| 12566 --light-secondary-opacity: 0.7; |
| 12567 --light-primary-opacity: 1.0; |
| 12568 |
| 12569 } |
| 12570 |
| 12571 </style> |
| 12572 <script> |
| 12573 |
| 12574 /** @polymerBehavior */ |
| 12575 Polymer.PaperSpinnerBehavior = { |
| 12576 |
| 12577 listeners: { |
| 12578 'animationend': '__reset', |
| 12579 'webkitAnimationEnd': '__reset' |
| 12580 }, |
| 12581 |
| 12582 properties: { |
| 12583 /** |
| 12584 * Displays the spinner. |
| 12585 */ |
| 12586 active: { |
| 12587 type: Boolean, |
| 12588 value: false, |
| 12589 reflectToAttribute: true, |
| 12590 observer: '__activeChanged' |
| 12591 }, |
| 12592 |
| 12593 /** |
| 12594 * Alternative text content for accessibility support. |
| 12595 * If alt is present, it will add an aria-label whose content matches alt
when active. |
| 12596 * If alt is not present, it will default to 'loading' as the alt value. |
| 12597 */ |
| 12598 alt: { |
| 12599 type: String, |
| 12600 value: 'loading', |
| 12601 observer: '__altChanged' |
| 12602 }, |
| 12603 |
| 12604 __coolingDown: { |
| 12605 type: Boolean, |
| 12606 value: false |
| 12607 } |
| 12608 }, |
| 12609 |
| 12610 __computeContainerClasses: function(active, coolingDown) { |
| 12611 return [ |
| 12612 active || coolingDown ? 'active' : '', |
| 12613 coolingDown ? 'cooldown' : '' |
| 12614 ].join(' '); |
| 12615 }, |
| 12616 |
| 12617 __activeChanged: function(active, old) { |
| 12618 this.__setAriaHidden(!active); |
| 12619 this.__coolingDown = !active && old; |
| 12620 }, |
| 12621 |
| 12622 __altChanged: function(alt) { |
| 12623 // user-provided `aria-label` takes precedence over prototype default |
| 12624 if (alt === this.getPropertyInfo('alt').value) { |
| 12625 this.alt = this.getAttribute('aria-label') || alt; |
| 12626 } else { |
| 12627 this.__setAriaHidden(alt===''); |
| 12628 this.setAttribute('aria-label', alt); |
| 12629 } |
| 12630 }, |
| 12631 |
| 12632 __setAriaHidden: function(hidden) { |
| 12633 var attr = 'aria-hidden'; |
| 12634 if (hidden) { |
| 12635 this.setAttribute(attr, 'true'); |
| 12636 } else { |
| 12637 this.removeAttribute(attr); |
| 12638 } |
| 12639 }, |
| 12640 |
| 12641 __reset: function() { |
| 12642 this.active = false; |
| 12643 this.__coolingDown = false; |
| 12644 } |
| 12645 }; |
| 12646 </script> |
| 12647 <dom-module id="paper-spinner-styles" assetpath="bower_components/paper-spinner/
"> |
| 12648 <template> |
| 12649 <style> |
| 12650 /* |
| 12651 /**************************/ |
| 12652 /* STYLES FOR THE SPINNER */ |
| 12653 /**************************/ |
| 12654 |
| 12655 /* |
| 12656 * Constants: |
| 12657 * ARCSIZE = 270 degrees (amount of circle the arc takes up) |
| 12658 * ARCTIME = 1333ms (time it takes to expand and contract arc) |
| 12659 * ARCSTARTROT = 216 degrees (how much the start location of the arc |
| 12660 * should rotate each time, 216 gives us a |
| 12661 * 5 pointed star shape (it's 360/5 * 3). |
| 12662 * For a 7 pointed star, we might do |
| 12663 * 360/7 * 3 = 154.286) |
| 12664 * SHRINK_TIME = 400ms |
| 12665 */ |
| 12666 |
| 12667 :host { |
| 12668 display: inline-block; |
| 12669 position: relative; |
| 12670 width: 28px; |
| 12671 height: 28px; |
| 12672 |
| 12673 /* 360 * ARCTIME / (ARCSTARTROT + (360-ARCSIZE)) */ |
| 12674 --paper-spinner-container-rotation-duration: 1568ms; |
| 12675 |
| 12676 /* ARCTIME */ |
| 12677 --paper-spinner-expand-contract-duration: 1333ms; |
| 12678 |
| 12679 /* 4 * ARCTIME */ |
| 12680 --paper-spinner-full-cycle-duration: 5332ms; |
| 12681 |
| 12682 /* SHRINK_TIME */ |
| 12683 --paper-spinner-cooldown-duration: 400ms; |
| 12684 } |
| 12685 |
| 12686 #spinnerContainer { |
| 12687 width: 100%; |
| 12688 height: 100%; |
| 12689 |
| 12690 /* The spinner does not have any contents that would have to be |
| 12691 * flipped if the direction changes. Always use ltr so that the |
| 12692 * style works out correctly in both cases. */ |
| 12693 direction: ltr; |
| 12694 } |
| 12695 |
| 12696 #spinnerContainer.active { |
| 12697 -webkit-animation: container-rotate var(--paper-spinner-container-rotati
on-duration) linear infinite; |
| 12698 animation: container-rotate var(--paper-spinner-container-rotation-durat
ion) linear infinite; |
| 12699 } |
| 12700 |
| 12701 @-webkit-keyframes container-rotate { |
| 12702 to { -webkit-transform: rotate(360deg) } |
| 12703 } |
| 12704 |
| 12705 @keyframes container-rotate { |
| 12706 to { transform: rotate(360deg) } |
| 12707 } |
| 12708 |
| 12709 .spinner-layer { |
| 12710 position: absolute; |
| 12711 width: 100%; |
| 12712 height: 100%; |
| 12713 opacity: 0; |
| 12714 white-space: nowrap; |
| 12715 border-color: var(--paper-spinner-color, --google-blue-500); |
| 12716 } |
| 12717 |
| 12718 .layer-1 { |
| 12719 border-color: var(--paper-spinner-layer-1-color, --google-blue-500); |
| 12720 } |
| 12721 |
| 12722 .layer-2 { |
| 12723 border-color: var(--paper-spinner-layer-2-color, --google-red-500); |
| 12724 } |
| 12725 |
| 12726 .layer-3 { |
| 12727 border-color: var(--paper-spinner-layer-3-color, --google-yellow-500); |
| 12728 } |
| 12729 |
| 12730 .layer-4 { |
| 12731 border-color: var(--paper-spinner-layer-4-color, --google-green-500); |
| 12732 } |
| 12733 |
| 12734 /** |
| 12735 * IMPORTANT NOTE ABOUT CSS ANIMATION PROPERTIES (keanulee): |
| 12736 * |
| 12737 * iOS Safari (tested on iOS 8.1) does not handle animation-delay very wel
l - it doesn't |
| 12738 * guarantee that the animation will start _exactly_ after that value. So
we avoid using |
| 12739 * animation-delay and instead set custom keyframes for each color (as lay
er-2undant as it |
| 12740 * seems). |
| 12741 */ |
| 12742 .active .spinner-layer { |
| 12743 -webkit-animation-name: fill-unfill-rotate; |
| 12744 -webkit-animation-duration: var(--paper-spinner-full-cycle-duration); |
| 12745 -webkit-animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1); |
| 12746 -webkit-animation-iteration-count: infinite; |
| 12747 animation-name: fill-unfill-rotate; |
| 12748 animation-duration: var(--paper-spinner-full-cycle-duration); |
| 12749 animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1); |
| 12750 animation-iteration-count: infinite; |
| 12751 opacity: 1; |
| 12752 } |
| 12753 |
| 12754 .active .spinner-layer.layer-1 { |
| 12755 -webkit-animation-name: fill-unfill-rotate, layer-1-fade-in-out; |
| 12756 animation-name: fill-unfill-rotate, layer-1-fade-in-out; |
| 12757 } |
| 12758 |
| 12759 .active .spinner-layer.layer-2 { |
| 12760 -webkit-animation-name: fill-unfill-rotate, layer-2-fade-in-out; |
| 12761 animation-name: fill-unfill-rotate, layer-2-fade-in-out; |
| 12762 } |
| 12763 |
| 12764 .active .spinner-layer.layer-3 { |
| 12765 -webkit-animation-name: fill-unfill-rotate, layer-3-fade-in-out; |
| 12766 animation-name: fill-unfill-rotate, layer-3-fade-in-out; |
| 12767 } |
| 12768 |
| 12769 .active .spinner-layer.layer-4 { |
| 12770 -webkit-animation-name: fill-unfill-rotate, layer-4-fade-in-out; |
| 12771 animation-name: fill-unfill-rotate, layer-4-fade-in-out; |
| 12772 } |
| 12773 |
| 12774 @-webkit-keyframes fill-unfill-rotate { |
| 12775 12.5% { -webkit-transform: rotate(135deg) } /* 0.5 * ARCSIZE */ |
| 12776 25% { -webkit-transform: rotate(270deg) } /* 1 * ARCSIZE */ |
| 12777 37.5% { -webkit-transform: rotate(405deg) } /* 1.5 * ARCSIZE */ |
| 12778 50% { -webkit-transform: rotate(540deg) } /* 2 * ARCSIZE */ |
| 12779 62.5% { -webkit-transform: rotate(675deg) } /* 2.5 * ARCSIZE */ |
| 12780 75% { -webkit-transform: rotate(810deg) } /* 3 * ARCSIZE */ |
| 12781 87.5% { -webkit-transform: rotate(945deg) } /* 3.5 * ARCSIZE */ |
| 12782 to { -webkit-transform: rotate(1080deg) } /* 4 * ARCSIZE */ |
| 12783 } |
| 12784 |
| 12785 @keyframes fill-unfill-rotate { |
| 12786 12.5% { transform: rotate(135deg) } /* 0.5 * ARCSIZE */ |
| 12787 25% { transform: rotate(270deg) } /* 1 * ARCSIZE */ |
| 12788 37.5% { transform: rotate(405deg) } /* 1.5 * ARCSIZE */ |
| 12789 50% { transform: rotate(540deg) } /* 2 * ARCSIZE */ |
| 12790 62.5% { transform: rotate(675deg) } /* 2.5 * ARCSIZE */ |
| 12791 75% { transform: rotate(810deg) } /* 3 * ARCSIZE */ |
| 12792 87.5% { transform: rotate(945deg) } /* 3.5 * ARCSIZE */ |
| 12793 to { transform: rotate(1080deg) } /* 4 * ARCSIZE */ |
| 12794 } |
| 12795 |
| 12796 @-webkit-keyframes layer-1-fade-in-out { |
| 12797 0% { opacity: 1 } |
| 12798 25% { opacity: 1 } |
| 12799 26% { opacity: 0 } |
| 12800 89% { opacity: 0 } |
| 12801 90% { opacity: 1 } |
| 12802 to { opacity: 1 } |
| 12803 } |
| 12804 |
| 12805 @keyframes layer-1-fade-in-out { |
| 12806 0% { opacity: 1 } |
| 12807 25% { opacity: 1 } |
| 12808 26% { opacity: 0 } |
| 12809 89% { opacity: 0 } |
| 12810 90% { opacity: 1 } |
| 12811 to { opacity: 1 } |
| 12812 } |
| 12813 |
| 12814 @-webkit-keyframes layer-2-fade-in-out { |
| 12815 0% { opacity: 0 } |
| 12816 15% { opacity: 0 } |
| 12817 25% { opacity: 1 } |
| 12818 50% { opacity: 1 } |
| 12819 51% { opacity: 0 } |
| 12820 to { opacity: 0 } |
| 12821 } |
| 12822 |
| 12823 @keyframes layer-2-fade-in-out { |
| 12824 0% { opacity: 0 } |
| 12825 15% { opacity: 0 } |
| 12826 25% { opacity: 1 } |
| 12827 50% { opacity: 1 } |
| 12828 51% { opacity: 0 } |
| 12829 to { opacity: 0 } |
| 12830 } |
| 12831 |
| 12832 @-webkit-keyframes layer-3-fade-in-out { |
| 12833 0% { opacity: 0 } |
| 12834 40% { opacity: 0 } |
| 12835 50% { opacity: 1 } |
| 12836 75% { opacity: 1 } |
| 12837 76% { opacity: 0 } |
| 12838 to { opacity: 0 } |
| 12839 } |
| 12840 |
| 12841 @keyframes layer-3-fade-in-out { |
| 12842 0% { opacity: 0 } |
| 12843 40% { opacity: 0 } |
| 12844 50% { opacity: 1 } |
| 12845 75% { opacity: 1 } |
| 12846 76% { opacity: 0 } |
| 12847 to { opacity: 0 } |
| 12848 } |
| 12849 |
| 12850 @-webkit-keyframes layer-4-fade-in-out { |
| 12851 0% { opacity: 0 } |
| 12852 65% { opacity: 0 } |
| 12853 75% { opacity: 1 } |
| 12854 90% { opacity: 1 } |
| 12855 to { opacity: 0 } |
| 12856 } |
| 12857 |
| 12858 @keyframes layer-4-fade-in-out { |
| 12859 0% { opacity: 0 } |
| 12860 65% { opacity: 0 } |
| 12861 75% { opacity: 1 } |
| 12862 90% { opacity: 1 } |
| 12863 to { opacity: 0 } |
| 12864 } |
| 12865 |
| 12866 .circle-clipper { |
| 12867 display: inline-block; |
| 12868 position: relative; |
| 12869 width: 50%; |
| 12870 height: 100%; |
| 12871 overflow: hidden; |
| 12872 border-color: inherit; |
| 12873 } |
| 12874 |
| 12875 /** |
| 12876 * Patch the gap that appear between the two adjacent div.circle-clipper w
hile the |
| 12877 * spinner is rotating (appears on Chrome 50, Safari 9.1.1, and Edge). |
| 12878 */ |
| 12879 .spinner-layer::after { |
| 12880 left: 45%; |
| 12881 width: 10%; |
| 12882 border-top-style: solid; |
| 12883 } |
| 12884 |
| 12885 .spinner-layer::after, |
| 12886 .circle-clipper::after { |
| 12887 content: ''; |
| 12888 box-sizing: border-box; |
| 12889 position: absolute; |
| 12890 top: 0; |
| 12891 border-width: var(--paper-spinner-stroke-width, 3px); |
| 12892 border-color: inherit; |
| 12893 border-radius: 50%; |
| 12894 } |
| 12895 |
| 12896 .circle-clipper::after { |
| 12897 bottom: 0; |
| 12898 width: 200%; |
| 12899 border-style: solid; |
| 12900 border-bottom-color: transparent !important; |
| 12901 } |
| 12902 |
| 12903 .circle-clipper.left::after { |
| 12904 left: 0; |
| 12905 border-right-color: transparent !important; |
| 12906 -webkit-transform: rotate(129deg); |
| 12907 transform: rotate(129deg); |
| 12908 } |
| 12909 |
| 12910 .circle-clipper.right::after { |
| 12911 left: -100%; |
| 12912 border-left-color: transparent !important; |
| 12913 -webkit-transform: rotate(-129deg); |
| 12914 transform: rotate(-129deg); |
| 12915 } |
| 12916 |
| 12917 .active .gap-patch::after, |
| 12918 .active .circle-clipper::after { |
| 12919 -webkit-animation-duration: var(--paper-spinner-expand-contract-duration
); |
| 12920 -webkit-animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1); |
| 12921 -webkit-animation-iteration-count: infinite; |
| 12922 animation-duration: var(--paper-spinner-expand-contract-duration); |
| 12923 animation-timing-function: cubic-bezier(0.4, 0.0, 0.2, 1); |
| 12924 animation-iteration-count: infinite; |
| 12925 } |
| 12926 |
| 12927 .active .circle-clipper.left::after { |
| 12928 -webkit-animation-name: left-spin; |
| 12929 animation-name: left-spin; |
| 12930 } |
| 12931 |
| 12932 .active .circle-clipper.right::after { |
| 12933 -webkit-animation-name: right-spin; |
| 12934 animation-name: right-spin; |
| 12935 } |
| 12936 |
| 12937 @-webkit-keyframes left-spin { |
| 12938 0% { -webkit-transform: rotate(130deg) } |
| 12939 50% { -webkit-transform: rotate(-5deg) } |
| 12940 to { -webkit-transform: rotate(130deg) } |
| 12941 } |
| 12942 |
| 12943 @keyframes left-spin { |
| 12944 0% { transform: rotate(130deg) } |
| 12945 50% { transform: rotate(-5deg) } |
| 12946 to { transform: rotate(130deg) } |
| 12947 } |
| 12948 |
| 12949 @-webkit-keyframes right-spin { |
| 12950 0% { -webkit-transform: rotate(-130deg) } |
| 12951 50% { -webkit-transform: rotate(5deg) } |
| 12952 to { -webkit-transform: rotate(-130deg) } |
| 12953 } |
| 12954 |
| 12955 @keyframes right-spin { |
| 12956 0% { transform: rotate(-130deg) } |
| 12957 50% { transform: rotate(5deg) } |
| 12958 to { transform: rotate(-130deg) } |
| 12959 } |
| 12960 |
| 12961 #spinnerContainer.cooldown { |
| 12962 -webkit-animation: container-rotate var(--paper-spinner-container-rotati
on-duration) linear infinite, fade-out var(--paper-spinner-cooldown-duration) cu
bic-bezier(0.4, 0.0, 0.2, 1); |
| 12963 animation: container-rotate var(--paper-spinner-container-rotation-durat
ion) linear infinite, fade-out var(--paper-spinner-cooldown-duration) cubic-bezi
er(0.4, 0.0, 0.2, 1); |
| 12964 } |
| 12965 |
| 12966 @-webkit-keyframes fade-out { |
| 12967 0% { opacity: 1 } |
| 12968 to { opacity: 0 } |
| 12969 } |
| 12970 |
| 12971 @keyframes fade-out { |
| 12972 0% { opacity: 1 } |
| 12973 to { opacity: 0 } |
| 12974 } |
| 12975 </style> |
| 12976 </template> |
| 12977 </dom-module> |
| 12978 |
| 12979 |
| 12980 <dom-module id="paper-spinner-lite" assetpath="bower_components/paper-spinner/"> |
| 12981 <template strip-whitespace=""> |
| 12982 <style include="paper-spinner-styles"></style> |
| 12983 |
| 12984 <div id="spinnerContainer" class-name="[[__computeContainerClasses(active, _
_coolingDown)]]"> |
| 12985 <div class="spinner-layer"> |
| 12986 <div class="circle-clipper left"></div> |
| 12987 <div class="circle-clipper right"></div> |
| 12988 </div> |
| 12989 </div> |
| 12990 </template> |
| 12991 |
| 12992 <script> |
| 12993 Polymer({ |
| 12994 is: 'paper-spinner-lite', |
| 12995 |
| 12996 behaviors: [ |
| 12997 Polymer.PaperSpinnerBehavior |
| 12998 ] |
| 12999 }); |
| 13000 </script> |
| 13001 </dom-module> |
| 13002 |
| 13003 <dom-module id="iron-flex" assetpath="bower_components/iron-flex-layout/"> |
| 13004 <template> |
| 13005 <style> |
| 13006 .layout.horizontal, |
| 13007 .layout.vertical { |
| 13008 display: -ms-flexbox; |
| 13009 display: -webkit-flex; |
| 13010 display: flex; |
| 13011 } |
| 13012 |
| 13013 .layout.inline { |
| 13014 display: -ms-inline-flexbox; |
| 13015 display: -webkit-inline-flex; |
| 13016 display: inline-flex; |
| 13017 } |
| 13018 |
| 13019 .layout.horizontal { |
| 13020 -ms-flex-direction: row; |
| 13021 -webkit-flex-direction: row; |
| 13022 flex-direction: row; |
| 13023 } |
| 13024 |
| 13025 .layout.vertical { |
| 13026 -ms-flex-direction: column; |
| 13027 -webkit-flex-direction: column; |
| 13028 flex-direction: column; |
| 13029 } |
| 13030 |
| 13031 .layout.wrap { |
| 13032 -ms-flex-wrap: wrap; |
| 13033 -webkit-flex-wrap: wrap; |
| 13034 flex-wrap: wrap; |
| 13035 } |
| 13036 |
| 13037 .layout.center, |
| 13038 .layout.center-center { |
| 13039 -ms-flex-align: center; |
| 13040 -webkit-align-items: center; |
| 13041 align-items: center; |
| 13042 } |
| 13043 |
| 13044 .layout.center-justified, |
| 13045 .layout.center-center { |
| 13046 -ms-flex-pack: center; |
| 13047 -webkit-justify-content: center; |
| 13048 justify-content: center; |
| 13049 } |
| 13050 |
| 13051 .flex { |
| 13052 -ms-flex: 1 1 0.000000001px; |
| 13053 -webkit-flex: 1; |
| 13054 flex: 1; |
| 13055 -webkit-flex-basis: 0.000000001px; |
| 13056 flex-basis: 0.000000001px; |
| 13057 } |
| 13058 |
| 13059 .flex-auto { |
| 13060 -ms-flex: 1 1 auto; |
| 13061 -webkit-flex: 1 1 auto; |
| 13062 flex: 1 1 auto; |
| 13063 } |
| 13064 |
| 13065 .flex-none { |
| 13066 -ms-flex: none; |
| 13067 -webkit-flex: none; |
| 13068 flex: none; |
| 13069 } |
| 13070 </style> |
| 13071 </template> |
| 13072 </dom-module> |
| 13073 |
| 13074 |
| 13075 <dom-module id="iron-flex-reverse" assetpath="bower_components/iron-flex-layout/
"> |
| 13076 <template> |
| 13077 <style> |
| 13078 .layout.horizontal-reverse, |
| 13079 .layout.vertical-reverse { |
| 13080 display: -ms-flexbox; |
| 13081 display: -webkit-flex; |
| 13082 display: flex; |
| 13083 } |
| 13084 |
| 13085 .layout.horizontal-reverse { |
| 13086 -ms-flex-direction: row-reverse; |
| 13087 -webkit-flex-direction: row-reverse; |
| 13088 flex-direction: row-reverse; |
| 13089 } |
| 13090 |
| 13091 .layout.vertical-reverse { |
| 13092 -ms-flex-direction: column-reverse; |
| 13093 -webkit-flex-direction: column-reverse; |
| 13094 flex-direction: column-reverse; |
| 13095 } |
| 13096 |
| 13097 .layout.wrap-reverse { |
| 13098 -ms-flex-wrap: wrap-reverse; |
| 13099 -webkit-flex-wrap: wrap-reverse; |
| 13100 flex-wrap: wrap-reverse; |
| 13101 } |
| 13102 </style> |
| 13103 </template> |
| 13104 </dom-module> |
| 13105 |
| 13106 |
| 13107 <dom-module id="iron-flex-alignment" assetpath="bower_components/iron-flex-layou
t/"> |
| 13108 <template> |
| 13109 <style> |
| 13110 /** |
| 13111 * Alignment in cross axis. |
| 13112 */ |
| 13113 .layout.start { |
| 13114 -ms-flex-align: start; |
| 13115 -webkit-align-items: flex-start; |
| 13116 align-items: flex-start; |
| 13117 } |
| 13118 |
| 13119 .layout.center, |
| 13120 .layout.center-center { |
| 13121 -ms-flex-align: center; |
| 13122 -webkit-align-items: center; |
| 13123 align-items: center; |
| 13124 } |
| 13125 |
| 13126 .layout.end { |
| 13127 -ms-flex-align: end; |
| 13128 -webkit-align-items: flex-end; |
| 13129 align-items: flex-end; |
| 13130 } |
| 13131 |
| 13132 .layout.baseline { |
| 13133 -ms-flex-align: baseline; |
| 13134 -webkit-align-items: baseline; |
| 13135 align-items: baseline; |
| 13136 } |
| 13137 |
| 13138 /** |
| 13139 * Alignment in main axis. |
| 13140 */ |
| 13141 .layout.start-justified { |
| 13142 -ms-flex-pack: start; |
| 13143 -webkit-justify-content: flex-start; |
| 13144 justify-content: flex-start; |
| 13145 } |
| 13146 |
| 13147 .layout.center-justified, |
| 13148 .layout.center-center { |
| 13149 -ms-flex-pack: center; |
| 13150 -webkit-justify-content: center; |
| 13151 justify-content: center; |
| 13152 } |
| 13153 |
| 13154 .layout.end-justified { |
| 13155 -ms-flex-pack: end; |
| 13156 -webkit-justify-content: flex-end; |
| 13157 justify-content: flex-end; |
| 13158 } |
| 13159 |
| 13160 .layout.around-justified { |
| 13161 -ms-flex-pack: distribute; |
| 13162 -webkit-justify-content: space-around; |
| 13163 justify-content: space-around; |
| 13164 } |
| 13165 |
| 13166 .layout.justified { |
| 13167 -ms-flex-pack: justify; |
| 13168 -webkit-justify-content: space-between; |
| 13169 justify-content: space-between; |
| 13170 } |
| 13171 |
| 13172 /** |
| 13173 * Self alignment. |
| 13174 */ |
| 13175 .self-start { |
| 13176 -ms-align-self: flex-start; |
| 13177 -webkit-align-self: flex-start; |
| 13178 align-self: flex-start; |
| 13179 } |
| 13180 |
| 13181 .self-center { |
| 13182 -ms-align-self: center; |
| 13183 -webkit-align-self: center; |
| 13184 align-self: center; |
| 13185 } |
| 13186 |
| 13187 .self-end { |
| 13188 -ms-align-self: flex-end; |
| 13189 -webkit-align-self: flex-end; |
| 13190 align-self: flex-end; |
| 13191 } |
| 13192 |
| 13193 .self-stretch { |
| 13194 -ms-align-self: stretch; |
| 13195 -webkit-align-self: stretch; |
| 13196 align-self: stretch; |
| 13197 } |
| 13198 |
| 13199 .self-baseline { |
| 13200 -ms-align-self: baseline; |
| 13201 -webkit-align-self: baseline; |
| 13202 align-self: baseline; |
| 13203 }; |
| 13204 |
| 13205 /** |
| 13206 * multi-line alignment in main axis. |
| 13207 */ |
| 13208 .layout.start-aligned { |
| 13209 -ms-flex-line-pack: start; /* IE10 */ |
| 13210 -ms-align-content: flex-start; |
| 13211 -webkit-align-content: flex-start; |
| 13212 align-content: flex-start; |
| 13213 } |
| 13214 |
| 13215 .layout.end-aligned { |
| 13216 -ms-flex-line-pack: end; /* IE10 */ |
| 13217 -ms-align-content: flex-end; |
| 13218 -webkit-align-content: flex-end; |
| 13219 align-content: flex-end; |
| 13220 } |
| 13221 |
| 13222 .layout.center-aligned { |
| 13223 -ms-flex-line-pack: center; /* IE10 */ |
| 13224 -ms-align-content: center; |
| 13225 -webkit-align-content: center; |
| 13226 align-content: center; |
| 13227 } |
| 13228 |
| 13229 .layout.between-aligned { |
| 13230 -ms-flex-line-pack: justify; /* IE10 */ |
| 13231 -ms-align-content: space-between; |
| 13232 -webkit-align-content: space-between; |
| 13233 align-content: space-between; |
| 13234 } |
| 13235 |
| 13236 .layout.around-aligned { |
| 13237 -ms-flex-line-pack: distribute; /* IE10 */ |
| 13238 -ms-align-content: space-around; |
| 13239 -webkit-align-content: space-around; |
| 13240 align-content: space-around; |
| 13241 } |
| 13242 </style> |
| 13243 </template> |
| 13244 </dom-module> |
| 13245 |
| 13246 <dom-module id="iron-flex-factors" assetpath="bower_components/iron-flex-layout/
"> |
| 13247 <template> |
| 13248 <style> |
| 13249 .flex, |
| 13250 .flex-1 { |
| 13251 -ms-flex: 1 1 0.000000001px; |
| 13252 -webkit-flex: 1; |
| 13253 flex: 1; |
| 13254 -webkit-flex-basis: 0.000000001px; |
| 13255 flex-basis: 0.000000001px; |
| 13256 } |
| 13257 |
| 13258 .flex-2 { |
| 13259 -ms-flex: 2; |
| 13260 -webkit-flex: 2; |
| 13261 flex: 2; |
| 13262 } |
| 13263 |
| 13264 .flex-3 { |
| 13265 -ms-flex: 3; |
| 13266 -webkit-flex: 3; |
| 13267 flex: 3; |
| 13268 } |
| 13269 |
| 13270 .flex-4 { |
| 13271 -ms-flex: 4; |
| 13272 -webkit-flex: 4; |
| 13273 flex: 4; |
| 13274 } |
| 13275 |
| 13276 .flex-5 { |
| 13277 -ms-flex: 5; |
| 13278 -webkit-flex: 5; |
| 13279 flex: 5; |
| 13280 } |
| 13281 |
| 13282 .flex-6 { |
| 13283 -ms-flex: 6; |
| 13284 -webkit-flex: 6; |
| 13285 flex: 6; |
| 13286 } |
| 13287 |
| 13288 .flex-7 { |
| 13289 -ms-flex: 7; |
| 13290 -webkit-flex: 7; |
| 13291 flex: 7; |
| 13292 } |
| 13293 |
| 13294 .flex-8 { |
| 13295 -ms-flex: 8; |
| 13296 -webkit-flex: 8; |
| 13297 flex: 8; |
| 13298 } |
| 13299 |
| 13300 .flex-9 { |
| 13301 -ms-flex: 9; |
| 13302 -webkit-flex: 9; |
| 13303 flex: 9; |
| 13304 } |
| 13305 |
| 13306 .flex-10 { |
| 13307 -ms-flex: 10; |
| 13308 -webkit-flex: 10; |
| 13309 flex: 10; |
| 13310 } |
| 13311 |
| 13312 .flex-11 { |
| 13313 -ms-flex: 11; |
| 13314 -webkit-flex: 11; |
| 13315 flex: 11; |
| 13316 } |
| 13317 |
| 13318 .flex-12 { |
| 13319 -ms-flex: 12; |
| 13320 -webkit-flex: 12; |
| 13321 flex: 12; |
| 13322 } |
| 13323 </style> |
| 13324 </template> |
| 13325 </dom-module> |
| 13326 |
| 13327 |
| 13328 <dom-module id="iron-positioning" assetpath="bower_components/iron-flex-layout/"
> |
| 13329 <template> |
| 13330 <style> |
| 13331 .block { |
| 13332 display: block; |
| 13333 } |
| 13334 |
| 13335 /* IE 10 support for HTML5 hidden attr */ |
| 13336 [hidden] { |
| 13337 display: none !important; |
| 13338 } |
| 13339 |
| 13340 .invisible { |
| 13341 visibility: hidden !important; |
| 13342 } |
| 13343 |
| 13344 .relative { |
| 13345 position: relative; |
| 13346 } |
| 13347 |
| 13348 .fit { |
| 13349 position: absolute; |
| 13350 top: 0; |
| 13351 right: 0; |
| 13352 bottom: 0; |
| 13353 left: 0; |
| 13354 } |
| 13355 |
| 13356 body.fullbleed { |
| 13357 margin: 0; |
| 13358 height: 100vh; |
| 13359 } |
| 13360 |
| 13361 .scroll { |
| 13362 -webkit-overflow-scrolling: touch; |
| 13363 overflow: auto; |
| 13364 } |
| 13365 |
| 13366 /* fixed position */ |
| 13367 .fixed-bottom, |
| 13368 .fixed-left, |
| 13369 .fixed-right, |
| 13370 .fixed-top { |
| 13371 position: fixed; |
| 13372 } |
| 13373 |
| 13374 .fixed-top { |
| 13375 top: 0; |
| 13376 left: 0; |
| 13377 right: 0; |
| 13378 } |
| 13379 |
| 13380 .fixed-right { |
| 13381 top: 0; |
| 13382 right: 0; |
| 13383 bottom: 0; |
| 13384 } |
| 13385 |
| 13386 .fixed-bottom { |
| 13387 right: 0; |
| 13388 bottom: 0; |
| 13389 left: 0; |
| 13390 } |
| 13391 |
| 13392 .fixed-left { |
| 13393 top: 0; |
| 13394 bottom: 0; |
| 13395 left: 0; |
| 13396 } |
| 13397 </style> |
| 13398 </template> |
| 13399 </dom-module> |
| 13400 <script> |
| 9162 (function() { | 13401 (function() { |
| 9163 "use strict"; | 13402 "use strict"; |
| 9164 /** | 13403 /** |
| 9165 `Polymer.IronJsonpLibraryBehavior` loads a jsonp library. | 13404 `Polymer.IronJsonpLibraryBehavior` loads a jsonp library. |
| 9166 Multiple components can request same library, only one copy will load. | 13405 Multiple components can request same library, only one copy will load. |
| 9167 | 13406 |
| 9168 Some libraries require a specific global function be defined. | 13407 Some libraries require a specific global function be defined. |
| 9169 If this is the case, specify the `callbackName` property. | 13408 If this is the case, specify the `callbackName` property. |
| 9170 | 13409 |
| 9171 You should use an HTML Import to load library dependencies | 13410 You should use an HTML Import to load library dependencies |
| (...skipping 1047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10219 } | 14458 } |
| 10220 }); | 14459 }); |
| 10221 })(); | 14460 })(); |
| 10222 </script> | 14461 </script> |
| 10223 <dom-module id="auth-signin" assetpath="imp/common/"> | 14462 <dom-module id="auth-signin" assetpath="imp/common/"> |
| 10224 <template> | 14463 <template> |
| 10225 <style> | 14464 <style> |
| 10226 #avatar { | 14465 #avatar { |
| 10227 border-radius: 5px; | 14466 border-radius: 5px; |
| 10228 } | 14467 } |
| 10229 #signinContainer { | 14468 a { |
| 10230 margin-top: 14px; | 14469 color: white; |
| 14470 } |
| 14471 .center { |
| 14472 vertical-align: middle; |
| 10231 } | 14473 } |
| 10232 </style> | 14474 </style> |
| 10233 | 14475 |
| 10234 <google-signin-aware id="aware" client-id="[[clientId]]" scopes="email" on-g
oogle-signin-aware-success="_onSignin" on-google-signin-aware-signed-out="_onSig
nout"> | 14476 <google-signin-aware id="aware" client-id="[[clientId]]" scopes="email" on-g
oogle-signin-aware-success="_onSignin" on-google-signin-aware-signed-out="_onSig
nout"> |
| 10235 </google-signin-aware> | 14477 </google-signin-aware> |
| 10236 | 14478 |
| 10237 <template is="dom-if" if="[[!signedIn]]"> | 14479 <template is="dom-if" if="[[!signedIn]]"> |
| 10238 <div id="signinContainer"> | 14480 <div id="signinContainer"> |
| 10239 <a on-tap="signIn" href="#">Sign in</a> | 14481 <a on-tap="signIn" href="#">Sign in</a> |
| 10240 </div> | 14482 </div> |
| 10241 </template> | 14483 </template> |
| 10242 | 14484 |
| 10243 <template is="dom-if" if="[[signedIn]]"> | 14485 <template is="dom-if" if="[[signedIn]]"> |
| 10244 <img id="avatar" src="[[profile.imageUrl]]" width="30" height="30"> | 14486 <img class="center" id="avatar" src="[[profile.imageUrl]]" width="30" heig
ht="30"> |
| 10245 <span>[[profile.email]]</span> | 14487 <span class="center">[[profile.email]]</span> |
| 10246 <span>|</span> | 14488 <span class="center">|</span> |
| 10247 <a on-tap="signOut" href="#">Sign out</a> | 14489 <a class="center" on-tap="signOut" href="#">Sign out</a> |
| 10248 </template> | 14490 </template> |
| 10249 </template> | 14491 </template> |
| 10250 <script> | 14492 <script> |
| 10251 'use strict'; | 14493 'use strict'; |
| 10252 Polymer({ | 14494 Polymer({ |
| 10253 is: 'auth-signin', | 14495 is: 'auth-signin', |
| 10254 properties: { | 14496 properties: { |
| 10255 authHeaders: { | 14497 authHeaders: { |
| 10256 type: Object, | 14498 type: Object, |
| 10257 computed: "_makeHeader(authResponse)", | 14499 computed: "_makeHeader(authResponse)", |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10303 | 14545 |
| 10304 signIn: function() { | 14546 signIn: function() { |
| 10305 this.$.aware.signIn(); | 14547 this.$.aware.signIn(); |
| 10306 }, | 14548 }, |
| 10307 | 14549 |
| 10308 signOut: function() { | 14550 signOut: function() { |
| 10309 this.$.aware.signOut(); | 14551 this.$.aware.signOut(); |
| 10310 } | 14552 } |
| 10311 }); | 14553 }); |
| 10312 </script> | 14554 </script> |
| 14555 </dom-module><dom-module id="swarming-app" assetpath="imp/common/"> |
| 14556 <template> |
| 14557 <style include="iron-flex"> |
| 14558 :host { |
| 14559 position: absolute; |
| 14560 top: 0; |
| 14561 bottom: 0; |
| 14562 left: 0; |
| 14563 right: 0; |
| 14564 } |
| 14565 |
| 14566 app-toolbar { |
| 14567 background-color: #4285f4; |
| 14568 color: #fff; |
| 14569 } |
| 14570 |
| 14571 app-toolbar a { |
| 14572 color: #fff; |
| 14573 } |
| 14574 .left { |
| 14575 margin-right:15px; |
| 14576 } |
| 14577 .right { |
| 14578 margin-left:15px; |
| 14579 } |
| 14580 |
| 14581 paper-spinner-lite { |
| 14582 --paper-spinner-color: var(--google-yellow-500); |
| 14583 } |
| 14584 </style> |
| 14585 <app-header-layout> |
| 14586 <app-header fixed=""> |
| 14587 <app-toolbar> |
| 14588 <div class="title left">[[name]]</div> |
| 14589 <paper-spinner-lite class="left" active="[[busy]]"></paper-spinner-lit
e> |
| 14590 |
| 14591 <a class="left" href="/newui/">Home</a> |
| 14592 <a class="left" href="/newui/botlist">Bot List</a> |
| 14593 <div class="flex"></div> |
| 14594 |
| 14595 <auth-signin class="right" client-id="20770472288-t5smpbpjptka4nd888fv
0ctd23ftba2o.apps.googleusercontent.com" auth-headers="{{auth_headers}}"> |
| 14596 </auth-signin> |
| 14597 </app-toolbar> |
| 14598 </app-header> |
| 14599 <div on-swarming-busy-start="_busyStart()" on-swarming-busy-end="_busyEnd(
)"> |
| 14600 <content></content> |
| 14601 </div> |
| 14602 </app-header-layout> |
| 14603 |
| 14604 </template> |
| 14605 <script> |
| 14606 Polymer({ |
| 14607 is: 'swarming-app', |
| 14608 properties: { |
| 14609 auth_headers: { |
| 14610 type: Object, |
| 14611 notify: true, |
| 14612 }, |
| 14613 busy: { |
| 14614 type: Boolean, |
| 14615 }, |
| 14616 name: { |
| 14617 type: String, |
| 14618 }, |
| 14619 }, |
| 14620 |
| 14621 }); |
| 14622 </script> |
| 10313 </dom-module><dom-module id="swarming-index" assetpath="imp/index/"> | 14623 </dom-module><dom-module id="swarming-index" assetpath="imp/index/"> |
| 10314 <template> | 14624 <template> |
| 10315 <style> | 14625 <style> |
| 10316 :host { | 14626 :host { |
| 10317 display: block; | 14627 display: block; |
| 10318 } | 14628 } |
| 10319 </style> | 14629 </style> |
| 10320 | 14630 |
| 10321 <h1>HELLO WORLD</h1><h1> | 14631 <swarming-app auth_headers="{{auth_headers}}" name="Swarming" busy="[[busy]]
"> |
| 10322 | 14632 |
| 10323 | 14633 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers=
"[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{
{busy}}"> |
| 10324 <auth-signin auth-headers="{{auth}}" client-id="20770472288-t5smpbpjptka4nd8
88fv0ctd23ftba2o.apps.googleusercontent.com" on-auth-signin="signIn"> | 14634 </iron-ajax> |
| 10325 </auth-signin> | |
| 10326 | 14635 |
| 10327 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers="[
[auth]]" handle-as="json" on-response="handleResponse"> | 14636 <h1>HELLO WORLD</h1> |
| 10328 </iron-ajax> | |
| 10329 | 14637 |
| 10330 </h1></template> | 14638 <div>Server Version: [[serverDetails.server_version]]</div> |
| 14639 |
| 14640 </swarming-app> |
| 14641 |
| 14642 </template> |
| 10331 <script> | 14643 <script> |
| 10332 Polymer({ | 14644 Polymer({ |
| 10333 is: 'swarming-index', | 14645 is: 'swarming-index', |
| 10334 | 14646 |
| 14647 properties: { |
| 14648 auth_headers: { |
| 14649 type: Object, |
| 14650 observer: "signIn", |
| 14651 }, |
| 14652 |
| 14653 serverDetails: { |
| 14654 type: String, |
| 14655 } |
| 14656 }, |
| 14657 |
| 10335 signIn: function(){ | 14658 signIn: function(){ |
| 10336 this.$.request.generateRequest(); | 14659 this.$.request.generateRequest(); |
| 10337 }, | 14660 }, |
| 10338 | 14661 |
| 10339 handleResponse: function(a,b){ | |
| 10340 console.log(this.$.request.lastResponse); | |
| 10341 } | |
| 10342 }); | 14662 }); |
| 10343 </script> | 14663 </script> |
| 10344 </dom-module></div> | 14664 </dom-module></div> |
| 10345 <swarming-index></swarming-index> | 14665 <swarming-index></swarming-index> |
| 10346 | 14666 |
| 10347 | 14667 |
| 10348 </body></html> | 14668 </body></html> |
| OLD | NEW |