| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview Assertion support. | 6 * @fileoverview Assertion support. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 /** | 9 /** |
| 10 * Verify |condition| is truthy and return |condition| if so. | 10 * Verify |condition| is truthy and return |condition| if so. |
| (...skipping 1974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1985 }); | 1985 }); |
| 1986 } | 1986 } |
| 1987 | 1987 |
| 1988 /** | 1988 /** |
| 1989 * `Polymer.IronA11yKeysBehavior` provides a normalized interface for proces
sing | 1989 * `Polymer.IronA11yKeysBehavior` provides a normalized interface for proces
sing |
| 1990 * keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3
.org/TR/wai-aria-practices/#kbd_general_binding). | 1990 * keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3
.org/TR/wai-aria-practices/#kbd_general_binding). |
| 1991 * The element takes care of browser differences with respect to Keyboard ev
ents | 1991 * The element takes care of browser differences with respect to Keyboard ev
ents |
| 1992 * and uses an expressive syntax to filter key presses. | 1992 * and uses an expressive syntax to filter key presses. |
| 1993 * | 1993 * |
| 1994 * Use the `keyBindings` prototype property to express what combination of k
eys | 1994 * Use the `keyBindings` prototype property to express what combination of k
eys |
| 1995 * will trigger the event to fire. | 1995 * will trigger the callback. A key binding has the format |
| 1996 * `"KEY+MODIFIER:EVENT": "callback"` (`"KEY": "callback"` or |
| 1997 * `"KEY:EVENT": "callback"` are valid as well). Some examples: |
| 1996 * | 1998 * |
| 1997 * Use the `key-event-target` attribute to set up event handlers on a specif
ic | 1999 * keyBindings: { |
| 2000 * 'space': '_onKeydown', // same as 'space:keydown' |
| 2001 * 'shift+tab': '_onKeydown', |
| 2002 * 'enter:keypress': '_onKeypress', |
| 2003 * 'esc:keyup': '_onKeyup' |
| 2004 * } |
| 2005 * |
| 2006 * The callback will receive with an event containing the following informat
ion in `event.detail`: |
| 2007 * |
| 2008 * _onKeydown: function(event) { |
| 2009 * console.log(event.detail.combo); // KEY+MODIFIER, e.g. "shift+tab" |
| 2010 * console.log(event.detail.key); // KEY only, e.g. "tab" |
| 2011 * console.log(event.detail.event); // EVENT, e.g. "keydown" |
| 2012 * console.log(event.detail.keyboardEvent); // the original KeyboardE
vent |
| 2013 * } |
| 2014 * |
| 2015 * Use the `keyEventTarget` attribute to set up event handlers on a specific |
| 1998 * node. | 2016 * node. |
| 1999 * The `keys-pressed` event will fire when one of the key combinations set w
ith the | 2017 * |
| 2000 * `keys` property is pressed. | 2018 * See the [demo source code](https://github.com/PolymerElements/iron-a11y-k
eys-behavior/blob/master/demo/x-key-aware.html) |
| 2019 * for an example. |
| 2001 * | 2020 * |
| 2002 * @demo demo/index.html | 2021 * @demo demo/index.html |
| 2003 * @polymerBehavior | 2022 * @polymerBehavior |
| 2004 */ | 2023 */ |
| 2005 Polymer.IronA11yKeysBehavior = { | 2024 Polymer.IronA11yKeysBehavior = { |
| 2006 properties: { | 2025 properties: { |
| 2007 /** | 2026 /** |
| 2008 * The EventTarget that will be firing relevant KeyboardEvents. Set it t
o | 2027 * The EventTarget that will be firing relevant KeyboardEvents. Set it t
o |
| 2009 * `null` to disable the listeners. | 2028 * `null` to disable the listeners. |
| 2010 * @type {?EventTarget} | 2029 * @type {?EventTarget} |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2039 value: function() { | 2058 value: function() { |
| 2040 return {}; | 2059 return {}; |
| 2041 } | 2060 } |
| 2042 } | 2061 } |
| 2043 }, | 2062 }, |
| 2044 | 2063 |
| 2045 observers: [ | 2064 observers: [ |
| 2046 '_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)' | 2065 '_resetKeyEventListeners(keyEventTarget, _boundKeyHandlers)' |
| 2047 ], | 2066 ], |
| 2048 | 2067 |
| 2068 |
| 2069 /** |
| 2070 * To be used to express what combination of keys will trigger the relati
ve |
| 2071 * callback. e.g. `keyBindings: { 'esc': '_onEscPressed'}` |
| 2072 * @type {Object} |
| 2073 */ |
| 2049 keyBindings: {}, | 2074 keyBindings: {}, |
| 2050 | 2075 |
| 2051 registered: function() { | 2076 registered: function() { |
| 2052 this._prepKeyBindings(); | 2077 this._prepKeyBindings(); |
| 2053 }, | 2078 }, |
| 2054 | 2079 |
| 2055 attached: function() { | 2080 attached: function() { |
| 2056 this._listenKeyEventListeners(); | 2081 this._listenKeyEventListeners(); |
| 2057 }, | 2082 }, |
| 2058 | 2083 |
| (...skipping 3545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5604 /** | 5629 /** |
| 5605 * `Polymer.PaperRippleBehavior` dynamically implements a ripple | 5630 * `Polymer.PaperRippleBehavior` dynamically implements a ripple |
| 5606 * when the element has focus via pointer or keyboard. | 5631 * when the element has focus via pointer or keyboard. |
| 5607 * | 5632 * |
| 5608 * NOTE: This behavior is intended to be used in conjunction with and after | 5633 * NOTE: This behavior is intended to be used in conjunction with and after |
| 5609 * `Polymer.IronButtonState` and `Polymer.IronControlState`. | 5634 * `Polymer.IronButtonState` and `Polymer.IronControlState`. |
| 5610 * | 5635 * |
| 5611 * @polymerBehavior Polymer.PaperRippleBehavior | 5636 * @polymerBehavior Polymer.PaperRippleBehavior |
| 5612 */ | 5637 */ |
| 5613 Polymer.PaperRippleBehavior = { | 5638 Polymer.PaperRippleBehavior = { |
| 5614 | |
| 5615 properties: { | 5639 properties: { |
| 5616 /** | 5640 /** |
| 5617 * If true, the element will not produce a ripple effect when interacted | 5641 * If true, the element will not produce a ripple effect when interacted |
| 5618 * with via the pointer. | 5642 * with via the pointer. |
| 5619 */ | 5643 */ |
| 5620 noink: { | 5644 noink: { |
| 5621 type: Boolean, | 5645 type: Boolean, |
| 5622 observer: '_noinkChanged' | 5646 observer: '_noinkChanged' |
| 5623 }, | 5647 }, |
| 5624 | 5648 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5705 _createRipple: function() { | 5729 _createRipple: function() { |
| 5706 return /** @type {!PaperRippleElement} */ ( | 5730 return /** @type {!PaperRippleElement} */ ( |
| 5707 document.createElement('paper-ripple')); | 5731 document.createElement('paper-ripple')); |
| 5708 }, | 5732 }, |
| 5709 | 5733 |
| 5710 _noinkChanged: function(noink) { | 5734 _noinkChanged: function(noink) { |
| 5711 if (this.hasRipple()) { | 5735 if (this.hasRipple()) { |
| 5712 this._ripple.noink = noink; | 5736 this._ripple.noink = noink; |
| 5713 } | 5737 } |
| 5714 } | 5738 } |
| 5715 | |
| 5716 }; | 5739 }; |
| 5717 /** @polymerBehavior Polymer.PaperButtonBehavior */ | 5740 /** @polymerBehavior Polymer.PaperButtonBehavior */ |
| 5718 Polymer.PaperButtonBehaviorImpl = { | 5741 Polymer.PaperButtonBehaviorImpl = { |
| 5719 | |
| 5720 properties: { | 5742 properties: { |
| 5721 | |
| 5722 /** | 5743 /** |
| 5723 * The z-depth of this element, from 0-5. Setting to 0 will remove the | 5744 * The z-depth of this element, from 0-5. Setting to 0 will remove the |
| 5724 * shadow, and each increasing number greater than 0 will be "deeper" | 5745 * shadow, and each increasing number greater than 0 will be "deeper" |
| 5725 * than the last. | 5746 * than the last. |
| 5726 * | 5747 * |
| 5727 * @attribute elevation | 5748 * @attribute elevation |
| 5728 * @type number | 5749 * @type number |
| 5729 * @default 1 | 5750 * @default 1 |
| 5730 */ | 5751 */ |
| 5731 elevation: { | 5752 elevation: { |
| 5732 type: Number, | 5753 type: Number, |
| 5733 reflectToAttribute: true, | 5754 reflectToAttribute: true, |
| 5734 readOnly: true | 5755 readOnly: true |
| 5735 } | 5756 } |
| 5736 | |
| 5737 }, | 5757 }, |
| 5738 | 5758 |
| 5739 observers: [ | 5759 observers: [ |
| 5740 '_calculateElevation(focused, disabled, active, pressed, receivedFocusFrom
Keyboard)', | 5760 '_calculateElevation(focused, disabled, active, pressed, receivedFocusFrom
Keyboard)', |
| 5741 '_computeKeyboardClass(receivedFocusFromKeyboard)' | 5761 '_computeKeyboardClass(receivedFocusFromKeyboard)' |
| 5742 ], | 5762 ], |
| 5743 | 5763 |
| 5744 hostAttributes: { | 5764 hostAttributes: { |
| 5745 role: 'button', | 5765 role: 'button', |
| 5746 tabindex: '0', | 5766 tabindex: '0', |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5782 * create a ripple up effect. | 5802 * create a ripple up effect. |
| 5783 * | 5803 * |
| 5784 * @param {!KeyboardEvent} event . | 5804 * @param {!KeyboardEvent} event . |
| 5785 */ | 5805 */ |
| 5786 _spaceKeyUpHandler: function(event) { | 5806 _spaceKeyUpHandler: function(event) { |
| 5787 Polymer.IronButtonStateImpl._spaceKeyUpHandler.call(this, event); | 5807 Polymer.IronButtonStateImpl._spaceKeyUpHandler.call(this, event); |
| 5788 if (this.hasRipple()) { | 5808 if (this.hasRipple()) { |
| 5789 this._ripple.uiUpAction(); | 5809 this._ripple.uiUpAction(); |
| 5790 } | 5810 } |
| 5791 } | 5811 } |
| 5792 | |
| 5793 }; | 5812 }; |
| 5794 | 5813 |
| 5795 /** @polymerBehavior */ | 5814 /** @polymerBehavior */ |
| 5796 Polymer.PaperButtonBehavior = [ | 5815 Polymer.PaperButtonBehavior = [ |
| 5797 Polymer.IronButtonState, | 5816 Polymer.IronButtonState, |
| 5798 Polymer.IronControlState, | 5817 Polymer.IronControlState, |
| 5799 Polymer.PaperRippleBehavior, | 5818 Polymer.PaperRippleBehavior, |
| 5800 Polymer.PaperButtonBehaviorImpl | 5819 Polymer.PaperButtonBehaviorImpl |
| 5801 ]; | 5820 ]; |
| 5802 Polymer({ | 5821 Polymer({ |
| (...skipping 1551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7354 title.trim().charAt(0).toLowerCase() === String.fromCharCode(event.k
eyCode).toLowerCase()) { | 7373 title.trim().charAt(0).toLowerCase() === String.fromCharCode(event.k
eyCode).toLowerCase()) { |
| 7355 this._setFocusedItem(item); | 7374 this._setFocusedItem(item); |
| 7356 break; | 7375 break; |
| 7357 } | 7376 } |
| 7358 } | 7377 } |
| 7359 }, | 7378 }, |
| 7360 | 7379 |
| 7361 /** | 7380 /** |
| 7362 * Focuses the previous item (relative to the currently focused item) in the | 7381 * Focuses the previous item (relative to the currently focused item) in the |
| 7363 * menu, disabled items will be skipped. | 7382 * menu, disabled items will be skipped. |
| 7383 * Loop until length + 1 to handle case of single item in menu. |
| 7364 */ | 7384 */ |
| 7365 _focusPrevious: function() { | 7385 _focusPrevious: function() { |
| 7366 var length = this.items.length; | 7386 var length = this.items.length; |
| 7367 var curFocusIndex = Number(this.indexOf(this.focusedItem)); | 7387 var curFocusIndex = Number(this.indexOf(this.focusedItem)); |
| 7368 for (var i = 1; i < length; i++) { | 7388 for (var i = 1; i < length + 1; i++) { |
| 7369 var item = this.items[(curFocusIndex - i + length) % length]; | 7389 var item = this.items[(curFocusIndex - i + length) % length]; |
| 7370 if (!item.hasAttribute('disabled')) { | 7390 if (!item.hasAttribute('disabled')) { |
| 7371 this._setFocusedItem(item); | 7391 this._setFocusedItem(item); |
| 7372 return; | 7392 return; |
| 7373 } | 7393 } |
| 7374 } | 7394 } |
| 7375 }, | 7395 }, |
| 7376 | 7396 |
| 7377 /** | 7397 /** |
| 7378 * Focuses the next item (relative to the currently focused item) in the | 7398 * Focuses the next item (relative to the currently focused item) in the |
| 7379 * menu, disabled items will be skipped. | 7399 * menu, disabled items will be skipped. |
| 7400 * Loop until length + 1 to handle case of single item in menu. |
| 7380 */ | 7401 */ |
| 7381 _focusNext: function() { | 7402 _focusNext: function() { |
| 7382 var length = this.items.length; | 7403 var length = this.items.length; |
| 7383 var curFocusIndex = Number(this.indexOf(this.focusedItem)); | 7404 var curFocusIndex = Number(this.indexOf(this.focusedItem)); |
| 7384 for (var i = 1; i < length; i++) { | 7405 for (var i = 1; i < length + 1; i++) { |
| 7385 var item = this.items[(curFocusIndex + i) % length]; | 7406 var item = this.items[(curFocusIndex + i) % length]; |
| 7386 if (!item.hasAttribute('disabled')) { | 7407 if (!item.hasAttribute('disabled')) { |
| 7387 this._setFocusedItem(item); | 7408 this._setFocusedItem(item); |
| 7388 return; | 7409 return; |
| 7389 } | 7410 } |
| 7390 } | 7411 } |
| 7391 }, | 7412 }, |
| 7392 | 7413 |
| 7393 /** | 7414 /** |
| 7394 * Mutates items in the menu based on provided selection details, so that | 7415 * Mutates items in the menu based on provided selection details, so that |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7778 } else { | 7799 } else { |
| 7779 this.fit(); | 7800 this.fit(); |
| 7780 } | 7801 } |
| 7781 } | 7802 } |
| 7782 }, | 7803 }, |
| 7783 | 7804 |
| 7784 /** | 7805 /** |
| 7785 * Positions and fits the element into the `fitInto` element. | 7806 * Positions and fits the element into the `fitInto` element. |
| 7786 */ | 7807 */ |
| 7787 fit: function() { | 7808 fit: function() { |
| 7788 this._discoverInfo(); | |
| 7789 this.position(); | 7809 this.position(); |
| 7790 this.constrain(); | 7810 this.constrain(); |
| 7791 this.center(); | 7811 this.center(); |
| 7792 }, | 7812 }, |
| 7793 | 7813 |
| 7794 /** | 7814 /** |
| 7795 * Memoize information needed to position and size the target element. | 7815 * Memoize information needed to position and size the target element. |
| 7796 * @suppress {deprecated} | 7816 * @suppress {deprecated} |
| 7797 */ | 7817 */ |
| 7798 _discoverInfo: function() { | 7818 _discoverInfo: function() { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7880 }, | 7900 }, |
| 7881 | 7901 |
| 7882 /** | 7902 /** |
| 7883 * Positions the element according to `horizontalAlign, verticalAlign`. | 7903 * Positions the element according to `horizontalAlign, verticalAlign`. |
| 7884 */ | 7904 */ |
| 7885 position: function() { | 7905 position: function() { |
| 7886 if (!this.horizontalAlign && !this.verticalAlign) { | 7906 if (!this.horizontalAlign && !this.verticalAlign) { |
| 7887 // needs to be centered, and it is done after constrain. | 7907 // needs to be centered, and it is done after constrain. |
| 7888 return; | 7908 return; |
| 7889 } | 7909 } |
| 7910 this._discoverInfo(); |
| 7890 | 7911 |
| 7891 this.style.position = 'fixed'; | 7912 this.style.position = 'fixed'; |
| 7892 // Need border-box for margin/padding. | 7913 // Need border-box for margin/padding. |
| 7893 this.sizingTarget.style.boxSizing = 'border-box'; | 7914 this.sizingTarget.style.boxSizing = 'border-box'; |
| 7894 // Set to 0, 0 in order to discover any offset caused by parent stacking c
ontexts. | 7915 // Set to 0, 0 in order to discover any offset caused by parent stacking c
ontexts. |
| 7895 this.style.left = '0px'; | 7916 this.style.left = '0px'; |
| 7896 this.style.top = '0px'; | 7917 this.style.top = '0px'; |
| 7897 | 7918 |
| 7898 var rect = this.getBoundingClientRect(); | 7919 var rect = this.getBoundingClientRect(); |
| 7899 var positionRect = this.__getNormalizedRect(this.positionTarget); | 7920 var positionRect = this.__getNormalizedRect(this.positionTarget); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7940 }, | 7961 }, |
| 7941 | 7962 |
| 7942 /** | 7963 /** |
| 7943 * Constrains the size of the element to `fitInto` by setting `max-height` | 7964 * Constrains the size of the element to `fitInto` by setting `max-height` |
| 7944 * and/or `max-width`. | 7965 * and/or `max-width`. |
| 7945 */ | 7966 */ |
| 7946 constrain: function() { | 7967 constrain: function() { |
| 7947 if (this.horizontalAlign || this.verticalAlign) { | 7968 if (this.horizontalAlign || this.verticalAlign) { |
| 7948 return; | 7969 return; |
| 7949 } | 7970 } |
| 7971 this._discoverInfo(); |
| 7972 |
| 7950 var info = this._fitInfo; | 7973 var info = this._fitInfo; |
| 7951 // position at (0px, 0px) if not already positioned, so we can measure the
natural size. | 7974 // position at (0px, 0px) if not already positioned, so we can measure the
natural size. |
| 7952 if (!info.positionedBy.vertically) { | 7975 if (!info.positionedBy.vertically) { |
| 7953 this.style.position = 'fixed'; | 7976 this.style.position = 'fixed'; |
| 7954 this.style.top = '0px'; | 7977 this.style.top = '0px'; |
| 7955 } | 7978 } |
| 7956 if (!info.positionedBy.horizontally) { | 7979 if (!info.positionedBy.horizontally) { |
| 7957 this.style.position = 'fixed'; | 7980 this.style.position = 'fixed'; |
| 7958 this.style.left = '0px'; | 7981 this.style.left = '0px'; |
| 7959 } | 7982 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7994 }, | 8017 }, |
| 7995 | 8018 |
| 7996 /** | 8019 /** |
| 7997 * Centers horizontally and vertically if not already positioned. This also
sets | 8020 * Centers horizontally and vertically if not already positioned. This also
sets |
| 7998 * `position:fixed`. | 8021 * `position:fixed`. |
| 7999 */ | 8022 */ |
| 8000 center: function() { | 8023 center: function() { |
| 8001 if (this.horizontalAlign || this.verticalAlign) { | 8024 if (this.horizontalAlign || this.verticalAlign) { |
| 8002 return; | 8025 return; |
| 8003 } | 8026 } |
| 8027 this._discoverInfo(); |
| 8028 |
| 8004 var positionedBy = this._fitInfo.positionedBy; | 8029 var positionedBy = this._fitInfo.positionedBy; |
| 8005 if (positionedBy.vertically && positionedBy.horizontally) { | 8030 if (positionedBy.vertically && positionedBy.horizontally) { |
| 8006 // Already positioned. | 8031 // Already positioned. |
| 8007 return; | 8032 return; |
| 8008 } | 8033 } |
| 8009 // Need position:fixed to center | 8034 // Need position:fixed to center |
| 8010 this.style.position = 'fixed'; | 8035 this.style.position = 'fixed'; |
| 8011 // Take into account the offset caused by parents that create stacking | 8036 // Take into account the offset caused by parents that create stacking |
| 8012 // contexts (e.g. with transform: translate3d). Translate to 0,0 and | 8037 // contexts (e.g. with transform: translate3d). Translate to 0,0 and |
| 8013 // measure the bounding rect. | 8038 // measure the bounding rect. |
| (...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8631 | 8656 |
| 8632 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass(); | 8657 Polymer.IronOverlayManager = new Polymer.IronOverlayManagerClass(); |
| 8633 (function() { | 8658 (function() { |
| 8634 'use strict'; | 8659 'use strict'; |
| 8635 | 8660 |
| 8636 /** | 8661 /** |
| 8637 Use `Polymer.IronOverlayBehavior` to implement an element that can be hidden or
shown, and displays | 8662 Use `Polymer.IronOverlayBehavior` to implement an element that can be hidden or
shown, and displays |
| 8638 on top of other content. It includes an optional backdrop, and can be used to im
plement a variety | 8663 on top of other content. It includes an optional backdrop, and can be used to im
plement a variety |
| 8639 of UI controls including dialogs and drop downs. Multiple overlays may be displa
yed at once. | 8664 of UI controls including dialogs and drop downs. Multiple overlays may be displa
yed at once. |
| 8640 | 8665 |
| 8666 See the [demo source code](https://github.com/PolymerElements/iron-overlay-behav
ior/blob/master/demo/simple-overlay.html) |
| 8667 for an example. |
| 8668 |
| 8641 ### Closing and canceling | 8669 ### Closing and canceling |
| 8642 | 8670 |
| 8643 A dialog may be hidden by closing or canceling. The difference between close and
cancel is user | 8671 An overlay may be hidden by closing or canceling. The difference between close a
nd cancel is user |
| 8644 intent. Closing generally implies that the user acknowledged the content on the
overlay. By default, | 8672 intent. Closing generally implies that the user acknowledged the content on the
overlay. By default, |
| 8645 it will cancel whenever the user taps outside it or presses the escape key. This
behavior is | 8673 it will cancel whenever the user taps outside it or presses the escape key. This
behavior is |
| 8646 configurable with the `no-cancel-on-esc-key` and the `no-cancel-on-outside-click
` properties. | 8674 configurable with the `no-cancel-on-esc-key` and the `no-cancel-on-outside-click
` properties. |
| 8647 `close()` should be called explicitly by the implementer when the user interacts
with a control | 8675 `close()` should be called explicitly by the implementer when the user interacts
with a control |
| 8648 in the overlay element. When the dialog is canceled, the overlay fires an 'iron-
overlay-canceled' | 8676 in the overlay element. When the dialog is canceled, the overlay fires an 'iron-
overlay-canceled' |
| 8649 event. Call `preventDefault` on this event to prevent the overlay from closing. | 8677 event. Call `preventDefault` on this event to prevent the overlay from closing. |
| 8650 | 8678 |
| 8651 ### Positioning | 8679 ### Positioning |
| 8652 | 8680 |
| 8653 By default the element is sized and positioned to fit and centered inside the wi
ndow. You can | 8681 By default the element is sized and positioned to fit and centered inside the wi
ndow. You can |
| 8654 position and size it manually using CSS. See `Polymer.IronFitBehavior`. | 8682 position and size it manually using CSS. See `Polymer.IronFitBehavior`. |
| 8655 | 8683 |
| 8656 ### Backdrop | 8684 ### Backdrop |
| 8657 | 8685 |
| 8658 Set the `with-backdrop` attribute to display a backdrop behind the overlay. The
backdrop is | 8686 Set the `with-backdrop` attribute to display a backdrop behind the overlay. The
backdrop is |
| 8659 appended to `<body>` and is of type `<iron-overlay-backdrop>`. See its doc page
for styling | 8687 appended to `<body>` and is of type `<iron-overlay-backdrop>`. See its doc page
for styling |
| 8660 options. | 8688 options. |
| 8661 | 8689 |
| 8690 In addition, `with-backdrop` will wrap the focus within the content in the light
DOM. |
| 8691 Override the [`_focusableNodes` getter](#Polymer.IronOverlayBehavior:property-_f
ocusableNodes) |
| 8692 to achieve a different behavior. |
| 8693 |
| 8662 ### Limitations | 8694 ### Limitations |
| 8663 | 8695 |
| 8664 The element is styled to appear on top of other content by setting its `z-index`
property. You | 8696 The element is styled to appear on top of other content by setting its `z-index`
property. You |
| 8665 must ensure no element has a stacking context with a higher `z-index` than its p
arent stacking | 8697 must ensure no element has a stacking context with a higher `z-index` than its p
arent stacking |
| 8666 context. You should place this element as a child of `<body>` whenever possible. | 8698 context. You should place this element as a child of `<body>` whenever possible. |
| 8667 | 8699 |
| 8668 @demo demo/index.html | 8700 @demo demo/index.html |
| 8669 @polymerBehavior Polymer.IronOverlayBehavior | 8701 @polymerBehavior Polymer.IronOverlayBehavior |
| 8670 */ | 8702 */ |
| 8671 | 8703 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 8687 * True if the overlay was canceled when it was last closed. | 8719 * True if the overlay was canceled when it was last closed. |
| 8688 */ | 8720 */ |
| 8689 canceled: { | 8721 canceled: { |
| 8690 observer: '_canceledChanged', | 8722 observer: '_canceledChanged', |
| 8691 readOnly: true, | 8723 readOnly: true, |
| 8692 type: Boolean, | 8724 type: Boolean, |
| 8693 value: false | 8725 value: false |
| 8694 }, | 8726 }, |
| 8695 | 8727 |
| 8696 /** | 8728 /** |
| 8697 * Set to true to display a backdrop behind the overlay. | 8729 * Set to true to display a backdrop behind the overlay. It traps the focu
s |
| 8730 * within the light DOM of the overlay. |
| 8698 */ | 8731 */ |
| 8699 withBackdrop: { | 8732 withBackdrop: { |
| 8700 observer: '_withBackdropChanged', | 8733 observer: '_withBackdropChanged', |
| 8701 type: Boolean | 8734 type: Boolean |
| 8702 }, | 8735 }, |
| 8703 | 8736 |
| 8704 /** | 8737 /** |
| 8705 * Set to true to disable auto-focusing the overlay or child nodes with | 8738 * Set to true to disable auto-focusing the overlay or child nodes with |
| 8706 * the `autofocus` attribute` when the overlay is opened. | 8739 * the `autofocus` attribute` when the overlay is opened. |
| 8707 */ | 8740 */ |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8952 this.__isAnimating = true; | 8985 this.__isAnimating = true; |
| 8953 | 8986 |
| 8954 // requestAnimationFrame for non-blocking rendering | 8987 // requestAnimationFrame for non-blocking rendering |
| 8955 this.__openChangedAsync = window.requestAnimationFrame(function() { | 8988 this.__openChangedAsync = window.requestAnimationFrame(function() { |
| 8956 this.__openChangedAsync = null; | 8989 this.__openChangedAsync = null; |
| 8957 if (this.opened) { | 8990 if (this.opened) { |
| 8958 this._manager.addOverlay(this); | 8991 this._manager.addOverlay(this); |
| 8959 this._prepareRenderOpened(); | 8992 this._prepareRenderOpened(); |
| 8960 this._renderOpened(); | 8993 this._renderOpened(); |
| 8961 } else { | 8994 } else { |
| 8995 // Move the focus before actually closing. |
| 8996 this._applyFocus(); |
| 8962 this._renderClosed(); | 8997 this._renderClosed(); |
| 8963 } | 8998 } |
| 8964 }.bind(this)); | 8999 }.bind(this)); |
| 8965 }, | 9000 }, |
| 8966 | 9001 |
| 8967 _canceledChanged: function() { | 9002 _canceledChanged: function() { |
| 8968 this.closingReason = this.closingReason || {}; | 9003 this.closingReason = this.closingReason || {}; |
| 8969 this.closingReason.canceled = this.canceled; | 9004 this.closingReason.canceled = this.canceled; |
| 8970 }, | 9005 }, |
| 8971 | 9006 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 8988 * @protected | 9023 * @protected |
| 8989 */ | 9024 */ |
| 8990 _prepareRenderOpened: function() { | 9025 _prepareRenderOpened: function() { |
| 8991 | 9026 |
| 8992 // Needed to calculate the size of the overlay so that transitions on its
size | 9027 // Needed to calculate the size of the overlay so that transitions on its
size |
| 8993 // will have the correct starting points. | 9028 // will have the correct starting points. |
| 8994 this._preparePositioning(); | 9029 this._preparePositioning(); |
| 8995 this.refit(); | 9030 this.refit(); |
| 8996 this._finishPositioning(); | 9031 this._finishPositioning(); |
| 8997 | 9032 |
| 9033 // Move the focus to the child node with [autofocus]. |
| 9034 this._applyFocus(); |
| 9035 |
| 8998 // Safari will apply the focus to the autofocus element when displayed for
the first time, | 9036 // Safari will apply the focus to the autofocus element when displayed for
the first time, |
| 8999 // so we blur it. Later, _applyFocus will set the focus if necessary. | 9037 // so we blur it. Later, _applyFocus will set the focus if necessary. |
| 9000 if (this.noAutoFocus && document.activeElement === this._focusNode) { | 9038 if (this.noAutoFocus && document.activeElement === this._focusNode) { |
| 9001 this._focusNode.blur(); | 9039 this._focusNode.blur(); |
| 9002 } | 9040 } |
| 9003 }, | 9041 }, |
| 9004 | 9042 |
| 9005 /** | 9043 /** |
| 9006 * Tasks which cause the overlay to actually open; typically play an animati
on. | 9044 * Tasks which cause the overlay to actually open; typically play an animati
on. |
| 9007 * @protected | 9045 * @protected |
| 9008 */ | 9046 */ |
| 9009 _renderOpened: function() { | 9047 _renderOpened: function() { |
| 9010 this._finishRenderOpened(); | 9048 this._finishRenderOpened(); |
| 9011 }, | 9049 }, |
| 9012 | 9050 |
| 9013 /** | 9051 /** |
| 9014 * Tasks which cause the overlay to actually close; typically play an animat
ion. | 9052 * Tasks which cause the overlay to actually close; typically play an animat
ion. |
| 9015 * @protected | 9053 * @protected |
| 9016 */ | 9054 */ |
| 9017 _renderClosed: function() { | 9055 _renderClosed: function() { |
| 9018 this._finishRenderClosed(); | 9056 this._finishRenderClosed(); |
| 9019 }, | 9057 }, |
| 9020 | 9058 |
| 9021 /** | 9059 /** |
| 9022 * Tasks to be performed at the end of open action. Will fire `iron-overlay-
opened`. | 9060 * Tasks to be performed at the end of open action. Will fire `iron-overlay-
opened`. |
| 9023 * @protected | 9061 * @protected |
| 9024 */ | 9062 */ |
| 9025 _finishRenderOpened: function() { | 9063 _finishRenderOpened: function() { |
| 9026 // Focus the child node with [autofocus] | |
| 9027 this._applyFocus(); | |
| 9028 | 9064 |
| 9029 this.notifyResize(); | 9065 this.notifyResize(); |
| 9030 this.__isAnimating = false; | 9066 this.__isAnimating = false; |
| 9031 | 9067 |
| 9032 // Store it so we don't query too much. | 9068 // Store it so we don't query too much. |
| 9033 var focusableNodes = this._focusableNodes; | 9069 var focusableNodes = this._focusableNodes; |
| 9034 this.__firstFocusableNode = focusableNodes[0]; | 9070 this.__firstFocusableNode = focusableNodes[0]; |
| 9035 this.__lastFocusableNode = focusableNodes[focusableNodes.length - 1]; | 9071 this.__lastFocusableNode = focusableNodes[focusableNodes.length - 1]; |
| 9036 | 9072 |
| 9037 this.fire('iron-overlay-opened'); | 9073 this.fire('iron-overlay-opened'); |
| 9038 }, | 9074 }, |
| 9039 | 9075 |
| 9040 /** | 9076 /** |
| 9041 * Tasks to be performed at the end of close action. Will fire `iron-overlay
-closed`. | 9077 * Tasks to be performed at the end of close action. Will fire `iron-overlay
-closed`. |
| 9042 * @protected | 9078 * @protected |
| 9043 */ | 9079 */ |
| 9044 _finishRenderClosed: function() { | 9080 _finishRenderClosed: function() { |
| 9045 // Hide the overlay and remove the backdrop. | 9081 // Hide the overlay and remove the backdrop. |
| 9046 this.style.display = 'none'; | 9082 this.style.display = 'none'; |
| 9047 // Reset z-index only at the end of the animation. | 9083 // Reset z-index only at the end of the animation. |
| 9048 this.style.zIndex = ''; | 9084 this.style.zIndex = ''; |
| 9049 | 9085 |
| 9050 this._applyFocus(); | |
| 9051 | |
| 9052 this.notifyResize(); | 9086 this.notifyResize(); |
| 9053 this.__isAnimating = false; | 9087 this.__isAnimating = false; |
| 9054 this.fire('iron-overlay-closed', this.closingReason); | 9088 this.fire('iron-overlay-closed', this.closingReason); |
| 9055 }, | 9089 }, |
| 9056 | 9090 |
| 9057 _preparePositioning: function() { | 9091 _preparePositioning: function() { |
| 9058 this.style.transition = this.style.webkitTransition = 'none'; | 9092 this.style.transition = this.style.webkitTransition = 'none'; |
| 9059 this.style.transform = this.style.webkitTransform = 'none'; | 9093 this.style.transform = this.style.webkitTransform = 'none'; |
| 9060 this.style.display = ''; | 9094 this.style.display = ''; |
| 9061 }, | 9095 }, |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9367 } | 9401 } |
| 9368 | 9402 |
| 9369 }; | 9403 }; |
| 9370 /** | 9404 /** |
| 9371 * `Polymer.NeonAnimationRunnerBehavior` adds a method to run animations. | 9405 * `Polymer.NeonAnimationRunnerBehavior` adds a method to run animations. |
| 9372 * | 9406 * |
| 9373 * @polymerBehavior Polymer.NeonAnimationRunnerBehavior | 9407 * @polymerBehavior Polymer.NeonAnimationRunnerBehavior |
| 9374 */ | 9408 */ |
| 9375 Polymer.NeonAnimationRunnerBehaviorImpl = { | 9409 Polymer.NeonAnimationRunnerBehaviorImpl = { |
| 9376 | 9410 |
| 9377 properties: { | 9411 _configureAnimations: function(configs) { |
| 9378 | 9412 var results = []; |
| 9379 /** @type {?Object} */ | 9413 if (configs.length > 0) { |
| 9380 _player: { | 9414 for (var config, index = 0; config = configs[index]; index++) { |
| 9381 type: Object | 9415 var neonAnimation = document.createElement(config.name); |
| 9382 } | |
| 9383 | |
| 9384 }, | |
| 9385 | |
| 9386 _configureAnimationEffects: function(allConfigs) { | |
| 9387 var allAnimations = []; | |
| 9388 if (allConfigs.length > 0) { | |
| 9389 for (var config, index = 0; config = allConfigs[index]; index++) { | |
| 9390 var animation = document.createElement(config.name); | |
| 9391 // is this element actually a neon animation? | 9416 // is this element actually a neon animation? |
| 9392 if (animation.isNeonAnimation) { | 9417 if (neonAnimation.isNeonAnimation) { |
| 9393 var effect = animation.configure(config); | 9418 var result = null; |
| 9394 if (effect) { | 9419 // configuration or play could fail if polyfills aren't loaded |
| 9395 allAnimations.push({ | 9420 try { |
| 9396 animation: animation, | 9421 result = neonAnimation.configure(config); |
| 9422 // Check if we have an Effect rather than an Animation |
| 9423 if (typeof result.cancel != 'function') { |
| 9424 result = document.timeline.play(result); |
| 9425 } |
| 9426 } catch (e) { |
| 9427 result = null; |
| 9428 console.warn('Couldnt play', '(', config.name, ').', e); |
| 9429 } |
| 9430 if (result) { |
| 9431 results.push({ |
| 9432 neonAnimation: neonAnimation, |
| 9397 config: config, | 9433 config: config, |
| 9398 effect: effect | 9434 animation: result, |
| 9399 }); | 9435 }); |
| 9400 } | 9436 } |
| 9401 } else { | 9437 } else { |
| 9402 console.warn(this.is + ':', config.name, 'not found!'); | 9438 console.warn(this.is + ':', config.name, 'not found!'); |
| 9403 } | 9439 } |
| 9404 } | 9440 } |
| 9405 } | 9441 } |
| 9406 return allAnimations; | 9442 return results; |
| 9407 }, | 9443 }, |
| 9408 | 9444 |
| 9409 _runAnimationEffects: function(allEffects) { | 9445 _shouldComplete: function(activeEntries) { |
| 9410 return document.timeline.play(new GroupEffect(allEffects)); | 9446 var finished = true; |
| 9447 for (var i = 0; i < activeEntries.length; i++) { |
| 9448 if (activeEntries[i].animation.playState != 'finished') { |
| 9449 finished = false; |
| 9450 break; |
| 9451 } |
| 9452 } |
| 9453 return finished; |
| 9411 }, | 9454 }, |
| 9412 | 9455 |
| 9413 _completeAnimations: function(allAnimations) { | 9456 _complete: function(activeEntries) { |
| 9414 for (var animation, index = 0; animation = allAnimations[index]; index++)
{ | 9457 for (var i = 0; i < activeEntries.length; i++) { |
| 9415 animation.animation.complete(animation.config); | 9458 activeEntries[i].neonAnimation.complete(activeEntries[i].config); |
| 9459 } |
| 9460 for (var i = 0; i < activeEntries.length; i++) { |
| 9461 activeEntries[i].animation.cancel(); |
| 9416 } | 9462 } |
| 9417 }, | 9463 }, |
| 9418 | 9464 |
| 9419 /** | 9465 /** |
| 9420 * Plays an animation with an optional `type`. | 9466 * Plays an animation with an optional `type`. |
| 9421 * @param {string=} type | 9467 * @param {string=} type |
| 9422 * @param {!Object=} cookie | 9468 * @param {!Object=} cookie |
| 9423 */ | 9469 */ |
| 9424 playAnimation: function(type, cookie) { | 9470 playAnimation: function(type, cookie) { |
| 9425 var allConfigs = this.getAnimationConfig(type); | 9471 var configs = this.getAnimationConfig(type); |
| 9426 if (!allConfigs) { | 9472 if (!configs) { |
| 9427 return; | 9473 return; |
| 9428 } | 9474 } |
| 9429 try { | 9475 this._active = this._active || {}; |
| 9430 var allAnimations = this._configureAnimationEffects(allConfigs); | 9476 if (this._active[type]) { |
| 9431 var allEffects = allAnimations.map(function(animation) { | 9477 this._complete(this._active[type]); |
| 9432 return animation.effect; | 9478 delete this._active[type]; |
| 9433 }); | 9479 } |
| 9434 | 9480 |
| 9435 if (allEffects.length > 0) { | 9481 var activeEntries = this._configureAnimations(configs); |
| 9436 this._player = this._runAnimationEffects(allEffects); | |
| 9437 this._player.onfinish = function() { | |
| 9438 this._completeAnimations(allAnimations); | |
| 9439 | 9482 |
| 9440 if (this._player) { | 9483 if (activeEntries.length == 0) { |
| 9441 this._player.cancel(); | 9484 this.fire('neon-animation-finish', cookie, {bubbles: false}); |
| 9442 this._player = null; | 9485 return; |
| 9443 } | 9486 } |
| 9444 | 9487 |
| 9488 this._active[type] = activeEntries; |
| 9489 |
| 9490 for (var i = 0; i < activeEntries.length; i++) { |
| 9491 activeEntries[i].animation.onfinish = function() { |
| 9492 if (this._shouldComplete(activeEntries)) { |
| 9493 this._complete(activeEntries); |
| 9494 delete this._active[type]; |
| 9445 this.fire('neon-animation-finish', cookie, {bubbles: false}); | 9495 this.fire('neon-animation-finish', cookie, {bubbles: false}); |
| 9446 }.bind(this); | 9496 } |
| 9447 return; | 9497 }.bind(this); |
| 9448 } | |
| 9449 } catch (e) { | |
| 9450 console.warn('Couldnt play', '(', type, allConfigs, ').', e); | |
| 9451 } | 9498 } |
| 9452 this.fire('neon-animation-finish', cookie, {bubbles: false}); | |
| 9453 }, | 9499 }, |
| 9454 | 9500 |
| 9455 /** | 9501 /** |
| 9456 * Cancels the currently running animation. | 9502 * Cancels the currently running animations. |
| 9457 */ | 9503 */ |
| 9458 cancelAnimation: function() { | 9504 cancelAnimation: function() { |
| 9459 if (this._player) { | 9505 for (var k in this._animations) { |
| 9460 this._player.cancel(); | 9506 this._animations[k].cancel(); |
| 9461 } | 9507 } |
| 9508 this._animations = {}; |
| 9462 } | 9509 } |
| 9463 }; | 9510 }; |
| 9464 | 9511 |
| 9465 /** @polymerBehavior Polymer.NeonAnimationRunnerBehavior */ | 9512 /** @polymerBehavior Polymer.NeonAnimationRunnerBehavior */ |
| 9466 Polymer.NeonAnimationRunnerBehavior = [ | 9513 Polymer.NeonAnimationRunnerBehavior = [ |
| 9467 Polymer.NeonAnimatableBehavior, | 9514 Polymer.NeonAnimatableBehavior, |
| 9468 Polymer.NeonAnimationRunnerBehaviorImpl | 9515 Polymer.NeonAnimationRunnerBehaviorImpl |
| 9469 ]; | 9516 ]; |
| 9470 /** | 9517 /** |
| 9471 * Use `Polymer.NeonAnimationBehavior` to implement an animation. | 9518 * Use `Polymer.NeonAnimationBehavior` to implement an animation. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9554 return this._effect; | 9601 return this._effect; |
| 9555 }, | 9602 }, |
| 9556 | 9603 |
| 9557 complete: function(config) { | 9604 complete: function(config) { |
| 9558 config.node.style.opacity = ''; | 9605 config.node.style.opacity = ''; |
| 9559 } | 9606 } |
| 9560 | 9607 |
| 9561 }); | 9608 }); |
| 9562 (function() { | 9609 (function() { |
| 9563 'use strict'; | 9610 'use strict'; |
| 9611 // Used to calculate the scroll direction during touch events. |
| 9612 var LAST_TOUCH_POSITION = { |
| 9613 pageX: 0, |
| 9614 pageY: 0 |
| 9615 }; |
| 9616 // Used to avoid computing event.path and filter scrollable nodes (better pe
rf). |
| 9617 var ROOT_TARGET = null; |
| 9618 var SCROLLABLE_NODES = []; |
| 9564 | 9619 |
| 9565 /** | 9620 /** |
| 9566 * The IronDropdownScrollManager is intended to provide a central source | 9621 * The IronDropdownScrollManager is intended to provide a central source |
| 9567 * of authority and control over which elements in a document are currently | 9622 * of authority and control over which elements in a document are currently |
| 9568 * allowed to scroll. | 9623 * allowed to scroll. |
| 9569 */ | 9624 */ |
| 9570 | 9625 |
| 9571 Polymer.IronDropdownScrollManager = { | 9626 Polymer.IronDropdownScrollManager = { |
| 9572 | 9627 |
| 9573 /** | 9628 /** |
| 9574 * The current element that defines the DOM boundaries of the | 9629 * The current element that defines the DOM boundaries of the |
| 9575 * scroll lock. This is always the most recently locking element. | 9630 * scroll lock. This is always the most recently locking element. |
| 9576 */ | 9631 */ |
| 9577 get currentLockingElement() { | 9632 get currentLockingElement() { |
| 9578 return this._lockingElements[this._lockingElements.length - 1]; | 9633 return this._lockingElements[this._lockingElements.length - 1]; |
| 9579 }, | 9634 }, |
| 9580 | 9635 |
| 9581 | |
| 9582 /** | 9636 /** |
| 9583 * Returns true if the provided element is "scroll locked," which is to | 9637 * Returns true if the provided element is "scroll locked", which is to |
| 9584 * say that it cannot be scrolled via pointer or keyboard interactions. | 9638 * say that it cannot be scrolled via pointer or keyboard interactions. |
| 9585 * | 9639 * |
| 9586 * @param {HTMLElement} element An HTML element instance which may or may | 9640 * @param {HTMLElement} element An HTML element instance which may or may |
| 9587 * not be scroll locked. | 9641 * not be scroll locked. |
| 9588 */ | 9642 */ |
| 9589 elementIsScrollLocked: function(element) { | 9643 elementIsScrollLocked: function(element) { |
| 9590 var currentLockingElement = this.currentLockingElement; | 9644 var currentLockingElement = this.currentLockingElement; |
| 9591 | 9645 |
| 9592 if (currentLockingElement === undefined) | 9646 if (currentLockingElement === undefined) |
| 9593 return false; | 9647 return false; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9666 this._unlockScrollInteractions(); | 9720 this._unlockScrollInteractions(); |
| 9667 } | 9721 } |
| 9668 }, | 9722 }, |
| 9669 | 9723 |
| 9670 _lockingElements: [], | 9724 _lockingElements: [], |
| 9671 | 9725 |
| 9672 _lockedElementCache: null, | 9726 _lockedElementCache: null, |
| 9673 | 9727 |
| 9674 _unlockedElementCache: null, | 9728 _unlockedElementCache: null, |
| 9675 | 9729 |
| 9676 _originalBodyStyles: {}, | |
| 9677 | |
| 9678 _isScrollingKeypress: function(event) { | 9730 _isScrollingKeypress: function(event) { |
| 9679 return Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys( | 9731 return Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys( |
| 9680 event, 'pageup pagedown home end up left down right'); | 9732 event, 'pageup pagedown home end up left down right'); |
| 9681 }, | 9733 }, |
| 9682 | 9734 |
| 9683 _hasCachedLockedElement: function(element) { | 9735 _hasCachedLockedElement: function(element) { |
| 9684 return this._lockedElementCache.indexOf(element) > -1; | 9736 return this._lockedElementCache.indexOf(element) > -1; |
| 9685 }, | 9737 }, |
| 9686 | 9738 |
| 9687 _hasCachedUnlockedElement: function(element) { | 9739 _hasCachedUnlockedElement: function(element) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 9715 if (this._composedTreeContains(distributedNodes[nodeIndex], child))
{ | 9767 if (this._composedTreeContains(distributedNodes[nodeIndex], child))
{ |
| 9716 return true; | 9768 return true; |
| 9717 } | 9769 } |
| 9718 } | 9770 } |
| 9719 } | 9771 } |
| 9720 | 9772 |
| 9721 return false; | 9773 return false; |
| 9722 }, | 9774 }, |
| 9723 | 9775 |
| 9724 _scrollInteractionHandler: function(event) { | 9776 _scrollInteractionHandler: function(event) { |
| 9725 var scrolledElement = | 9777 // Avoid canceling an event with cancelable=false, e.g. scrolling is in |
| 9726 /** @type {HTMLElement} */(Polymer.dom(event).rootTarget); | 9778 // progress and cannot be interrupted. |
| 9727 if (Polymer | 9779 if (event.cancelable && this._shouldPreventScrolling(event)) { |
| 9728 .IronDropdownScrollManager | |
| 9729 .elementIsScrollLocked(scrolledElement)) { | |
| 9730 if (event.type === 'keydown' && | |
| 9731 !Polymer.IronDropdownScrollManager._isScrollingKeypress(event)) { | |
| 9732 return; | |
| 9733 } | |
| 9734 | |
| 9735 event.preventDefault(); | 9780 event.preventDefault(); |
| 9736 } | 9781 } |
| 9782 // If event has targetTouches (touch event), update last touch position. |
| 9783 if (event.targetTouches) { |
| 9784 var touch = event.targetTouches[0]; |
| 9785 LAST_TOUCH_POSITION.pageX = touch.pageX; |
| 9786 LAST_TOUCH_POSITION.pageY = touch.pageY; |
| 9787 } |
| 9737 }, | 9788 }, |
| 9738 | 9789 |
| 9739 _lockScrollInteractions: function() { | 9790 _lockScrollInteractions: function() { |
| 9740 // Memoize body inline styles: | 9791 this._boundScrollHandler = this._boundScrollHandler || |
| 9741 this._originalBodyStyles.overflow = document.body.style.overflow; | 9792 this._scrollInteractionHandler.bind(this); |
| 9742 this._originalBodyStyles.overflowX = document.body.style.overflowX; | |
| 9743 this._originalBodyStyles.overflowY = document.body.style.overflowY; | |
| 9744 | |
| 9745 // Disable overflow scrolling on body: | |
| 9746 // TODO(cdata): It is technically not sufficient to hide overflow on | |
| 9747 // body alone. A better solution might be to traverse all ancestors of | |
| 9748 // the current scroll locking element and hide overflow on them. This | |
| 9749 // becomes expensive, though, as it would have to be redone every time | |
| 9750 // a new scroll locking element is added. | |
| 9751 document.body.style.overflow = 'hidden'; | |
| 9752 document.body.style.overflowX = 'hidden'; | |
| 9753 document.body.style.overflowY = 'hidden'; | |
| 9754 | |
| 9755 // Modern `wheel` event for mouse wheel scrolling: | 9793 // Modern `wheel` event for mouse wheel scrolling: |
| 9756 document.addEventListener('wheel', this._scrollInteractionHandler, true)
; | 9794 document.addEventListener('wheel', this._boundScrollHandler, true); |
| 9757 // Older, non-standard `mousewheel` event for some FF: | 9795 // Older, non-standard `mousewheel` event for some FF: |
| 9758 document.addEventListener('mousewheel', this._scrollInteractionHandler,
true); | 9796 document.addEventListener('mousewheel', this._boundScrollHandler, true); |
| 9759 // IE: | 9797 // IE: |
| 9760 document.addEventListener('DOMMouseScroll', this._scrollInteractionHandl
er, true); | 9798 document.addEventListener('DOMMouseScroll', this._boundScrollHandler, tr
ue); |
| 9799 // Save the SCROLLABLE_NODES on touchstart, to be used on touchmove. |
| 9800 document.addEventListener('touchstart', this._boundScrollHandler, true); |
| 9761 // Mobile devices can scroll on touch move: | 9801 // Mobile devices can scroll on touch move: |
| 9762 document.addEventListener('touchmove', this._scrollInteractionHandler, t
rue); | 9802 document.addEventListener('touchmove', this._boundScrollHandler, true); |
| 9763 // Capture keydown to prevent scrolling keys (pageup, pagedown etc.) | 9803 // Capture keydown to prevent scrolling keys (pageup, pagedown etc.) |
| 9764 document.addEventListener('keydown', this._scrollInteractionHandler, tru
e); | 9804 document.addEventListener('keydown', this._boundScrollHandler, true); |
| 9765 }, | 9805 }, |
| 9766 | 9806 |
| 9767 _unlockScrollInteractions: function() { | 9807 _unlockScrollInteractions: function() { |
| 9768 document.body.style.overflow = this._originalBodyStyles.overflow; | 9808 document.removeEventListener('wheel', this._boundScrollHandler, true); |
| 9769 document.body.style.overflowX = this._originalBodyStyles.overflowX; | 9809 document.removeEventListener('mousewheel', this._boundScrollHandler, tru
e); |
| 9770 document.body.style.overflowY = this._originalBodyStyles.overflowY; | 9810 document.removeEventListener('DOMMouseScroll', this._boundScrollHandler,
true); |
| 9811 document.removeEventListener('touchstart', this._boundScrollHandler, tru
e); |
| 9812 document.removeEventListener('touchmove', this._boundScrollHandler, true
); |
| 9813 document.removeEventListener('keydown', this._boundScrollHandler, true); |
| 9814 }, |
| 9771 | 9815 |
| 9772 document.removeEventListener('wheel', this._scrollInteractionHandler, tr
ue); | 9816 /** |
| 9773 document.removeEventListener('mousewheel', this._scrollInteractionHandle
r, true); | 9817 * Returns true if the event causes scroll outside the current locking |
| 9774 document.removeEventListener('DOMMouseScroll', this._scrollInteractionHa
ndler, true); | 9818 * element, e.g. pointer/keyboard interactions, or scroll "leaking" |
| 9775 document.removeEventListener('touchmove', this._scrollInteractionHandler
, true); | 9819 * outside the locking element when it is already at its scroll boundaries
. |
| 9776 document.removeEventListener('keydown', this._scrollInteractionHandler,
true); | 9820 * @param {!Event} event |
| 9821 * @return {boolean} |
| 9822 * @private |
| 9823 */ |
| 9824 _shouldPreventScrolling: function(event) { |
| 9825 // Avoid expensive checks if the event is not one of the observed keys. |
| 9826 if (event.type === 'keydown') { |
| 9827 // Prevent event if it is one of the scrolling keys. |
| 9828 return this._isScrollingKeypress(event); |
| 9829 } |
| 9830 |
| 9831 // Update if root target changed. For touch events, ensure we don't |
| 9832 // update during touchmove. |
| 9833 var target = Polymer.dom(event).rootTarget; |
| 9834 if (event.type !== 'touchmove' && ROOT_TARGET !== target) { |
| 9835 ROOT_TARGET = target; |
| 9836 SCROLLABLE_NODES = this._getScrollableNodes(Polymer.dom(event).path); |
| 9837 } |
| 9838 |
| 9839 // Prevent event if no scrollable nodes. |
| 9840 if (!SCROLLABLE_NODES.length) { |
| 9841 return true; |
| 9842 } |
| 9843 // Don't prevent touchstart event inside the locking element when it has |
| 9844 // scrollable nodes. |
| 9845 if (event.type === 'touchstart') { |
| 9846 return false; |
| 9847 } |
| 9848 // Get deltaX/Y. |
| 9849 var info = this._getScrollInfo(event); |
| 9850 // Prevent if there is no child that can scroll. |
| 9851 return !this._getScrollingNode(SCROLLABLE_NODES, info.deltaX, info.delta
Y); |
| 9852 }, |
| 9853 |
| 9854 /** |
| 9855 * Returns an array of scrollable nodes up to the current locking element, |
| 9856 * which is included too if scrollable. |
| 9857 * @param {!Array<Node>} nodes |
| 9858 * @return {Array<Node>} scrollables |
| 9859 * @private |
| 9860 */ |
| 9861 _getScrollableNodes: function(nodes) { |
| 9862 var scrollables = []; |
| 9863 var lockingIndex = nodes.indexOf(this.currentLockingElement); |
| 9864 // Loop from root target to locking element (included). |
| 9865 for (var i = 0; i <= lockingIndex; i++) { |
| 9866 var node = nodes[i]; |
| 9867 // Skip document fragments. |
| 9868 if (node.nodeType === 11) { |
| 9869 continue; |
| 9870 } |
| 9871 // Check inline style before checking computed style. |
| 9872 var style = node.style; |
| 9873 if (style.overflow !== 'scroll' && style.overflow !== 'auto') { |
| 9874 style = window.getComputedStyle(node); |
| 9875 } |
| 9876 if (style.overflow === 'scroll' || style.overflow === 'auto') { |
| 9877 scrollables.push(node); |
| 9878 } |
| 9879 } |
| 9880 return scrollables; |
| 9881 }, |
| 9882 |
| 9883 /** |
| 9884 * Returns the node that is scrolling. If there is no scrolling, |
| 9885 * returns undefined. |
| 9886 * @param {!Array<Node>} nodes |
| 9887 * @param {number} deltaX Scroll delta on the x-axis |
| 9888 * @param {number} deltaY Scroll delta on the y-axis |
| 9889 * @return {Node|undefined} |
| 9890 * @private |
| 9891 */ |
| 9892 _getScrollingNode: function(nodes, deltaX, deltaY) { |
| 9893 // No scroll. |
| 9894 if (!deltaX && !deltaY) { |
| 9895 return; |
| 9896 } |
| 9897 // Check only one axis according to where there is more scroll. |
| 9898 // Prefer vertical to horizontal. |
| 9899 var verticalScroll = Math.abs(deltaY) >= Math.abs(deltaX); |
| 9900 for (var i = 0; i < nodes.length; i++) { |
| 9901 var node = nodes[i]; |
| 9902 var canScroll = false; |
| 9903 if (verticalScroll) { |
| 9904 // delta < 0 is scroll up, delta > 0 is scroll down. |
| 9905 canScroll = deltaY < 0 ? node.scrollTop > 0 : |
| 9906 node.scrollTop < node.scrollHeight - node.clientHeight; |
| 9907 } else { |
| 9908 // delta < 0 is scroll left, delta > 0 is scroll right. |
| 9909 canScroll = deltaX < 0 ? node.scrollLeft > 0 : |
| 9910 node.scrollLeft < node.scrollWidth - node.clientWidth; |
| 9911 } |
| 9912 if (canScroll) { |
| 9913 return node; |
| 9914 } |
| 9915 } |
| 9916 }, |
| 9917 |
| 9918 /** |
| 9919 * Returns scroll `deltaX` and `deltaY`. |
| 9920 * @param {!Event} event The scroll event |
| 9921 * @return {{ |
| 9922 * deltaX: number The x-axis scroll delta (positive: scroll right, |
| 9923 * negative: scroll left, 0: no scroll), |
| 9924 * deltaY: number The y-axis scroll delta (positive: scroll down, |
| 9925 * negative: scroll up, 0: no scroll) |
| 9926 * }} info |
| 9927 * @private |
| 9928 */ |
| 9929 _getScrollInfo: function(event) { |
| 9930 var info = { |
| 9931 deltaX: event.deltaX, |
| 9932 deltaY: event.deltaY |
| 9933 }; |
| 9934 // Already available. |
| 9935 if ('deltaX' in event) { |
| 9936 // do nothing, values are already good. |
| 9937 } |
| 9938 // Safari has scroll info in `wheelDeltaX/Y`. |
| 9939 else if ('wheelDeltaX' in event) { |
| 9940 info.deltaX = -event.wheelDeltaX; |
| 9941 info.deltaY = -event.wheelDeltaY; |
| 9942 } |
| 9943 // Firefox has scroll info in `detail` and `axis`. |
| 9944 else if ('axis' in event) { |
| 9945 info.deltaX = event.axis === 1 ? event.detail : 0; |
| 9946 info.deltaY = event.axis === 2 ? event.detail : 0; |
| 9947 } |
| 9948 // On mobile devices, calculate scroll direction. |
| 9949 else if (event.targetTouches) { |
| 9950 var touch = event.targetTouches[0]; |
| 9951 // Touch moves from right to left => scrolling goes right. |
| 9952 info.deltaX = LAST_TOUCH_POSITION.pageX - touch.pageX; |
| 9953 // Touch moves from down to up => scrolling goes down. |
| 9954 info.deltaY = LAST_TOUCH_POSITION.pageY - touch.pageY; |
| 9955 } |
| 9956 return info; |
| 9777 } | 9957 } |
| 9778 }; | 9958 }; |
| 9779 })(); | 9959 })(); |
| 9780 (function() { | 9960 (function() { |
| 9781 'use strict'; | 9961 'use strict'; |
| 9782 | 9962 |
| 9783 Polymer({ | 9963 Polymer({ |
| 9784 is: 'iron-dropdown', | 9964 is: 'iron-dropdown', |
| 9785 | 9965 |
| 9786 behaviors: [ | 9966 behaviors: [ |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9848 | 10028 |
| 9849 /** | 10029 /** |
| 9850 * By default, the dropdown will constrain scrolling on the page | 10030 * By default, the dropdown will constrain scrolling on the page |
| 9851 * to itself when opened. | 10031 * to itself when opened. |
| 9852 * Set to true in order to prevent scroll from being constrained | 10032 * Set to true in order to prevent scroll from being constrained |
| 9853 * to the dropdown when it opens. | 10033 * to the dropdown when it opens. |
| 9854 */ | 10034 */ |
| 9855 allowOutsideScroll: { | 10035 allowOutsideScroll: { |
| 9856 type: Boolean, | 10036 type: Boolean, |
| 9857 value: false | 10037 value: false |
| 10038 }, |
| 10039 |
| 10040 /** |
| 10041 * Callback for scroll events. |
| 10042 * @type {Function} |
| 10043 * @private |
| 10044 */ |
| 10045 _boundOnCaptureScroll: { |
| 10046 type: Function, |
| 10047 value: function() { |
| 10048 return this._onCaptureScroll.bind(this); |
| 10049 } |
| 9858 } | 10050 } |
| 9859 }, | 10051 }, |
| 9860 | 10052 |
| 9861 listeners: { | 10053 listeners: { |
| 9862 'neon-animation-finish': '_onNeonAnimationFinish' | 10054 'neon-animation-finish': '_onNeonAnimationFinish' |
| 9863 }, | 10055 }, |
| 9864 | 10056 |
| 9865 observers: [ | 10057 observers: [ |
| 9866 '_updateOverlayPosition(positionTarget, verticalAlign, horizontalAlign
, verticalOffset, horizontalOffset)' | 10058 '_updateOverlayPosition(positionTarget, verticalAlign, horizontalAlign
, verticalOffset, horizontalOffset)' |
| 9867 ], | 10059 ], |
| 9868 | 10060 |
| 9869 /** | 10061 /** |
| 9870 * The element that is contained by the dropdown, if any. | 10062 * The element that is contained by the dropdown, if any. |
| 9871 */ | 10063 */ |
| 9872 get containedElement() { | 10064 get containedElement() { |
| 9873 return Polymer.dom(this.$.content).getDistributedNodes()[0]; | 10065 return Polymer.dom(this.$.content).getDistributedNodes()[0]; |
| 9874 }, | 10066 }, |
| 9875 | 10067 |
| 9876 /** | 10068 /** |
| 9877 * The element that should be focused when the dropdown opens. | 10069 * The element that should be focused when the dropdown opens. |
| 9878 * @deprecated | 10070 * @deprecated |
| 9879 */ | 10071 */ |
| 9880 get _focusTarget() { | 10072 get _focusTarget() { |
| 9881 return this.focusTarget || this.containedElement; | 10073 return this.focusTarget || this.containedElement; |
| 9882 }, | 10074 }, |
| 9883 | 10075 |
| 10076 ready: function() { |
| 10077 // Memoized scrolling position, used to block scrolling outside. |
| 10078 this._scrollTop = 0; |
| 10079 this._scrollLeft = 0; |
| 10080 // Used to perform a non-blocking refit on scroll. |
| 10081 this._refitOnScrollRAF = null; |
| 10082 }, |
| 10083 |
| 9884 detached: function() { | 10084 detached: function() { |
| 9885 this.cancelAnimation(); | 10085 this.cancelAnimation(); |
| 9886 Polymer.IronDropdownScrollManager.removeScrollLock(this); | 10086 Polymer.IronDropdownScrollManager.removeScrollLock(this); |
| 9887 }, | 10087 }, |
| 9888 | 10088 |
| 9889 /** | 10089 /** |
| 9890 * Called when the value of `opened` changes. | 10090 * Called when the value of `opened` changes. |
| 9891 * Overridden from `IronOverlayBehavior` | 10091 * Overridden from `IronOverlayBehavior` |
| 9892 */ | 10092 */ |
| 9893 _openedChanged: function() { | 10093 _openedChanged: function() { |
| 9894 if (this.opened && this.disabled) { | 10094 if (this.opened && this.disabled) { |
| 9895 this.cancel(); | 10095 this.cancel(); |
| 9896 } else { | 10096 } else { |
| 9897 this.cancelAnimation(); | 10097 this.cancelAnimation(); |
| 9898 this.sizingTarget = this.containedElement || this.sizingTarget; | 10098 this.sizingTarget = this.containedElement || this.sizingTarget; |
| 9899 this._updateAnimationConfig(); | 10099 this._updateAnimationConfig(); |
| 9900 if (this.opened && !this.allowOutsideScroll) { | 10100 this._saveScrollPosition(); |
| 9901 Polymer.IronDropdownScrollManager.pushScrollLock(this); | 10101 if (this.opened) { |
| 10102 document.addEventListener('scroll', this._boundOnCaptureScroll); |
| 10103 !this.allowOutsideScroll && Polymer.IronDropdownScrollManager.push
ScrollLock(this); |
| 9902 } else { | 10104 } else { |
| 10105 document.removeEventListener('scroll', this._boundOnCaptureScroll)
; |
| 9903 Polymer.IronDropdownScrollManager.removeScrollLock(this); | 10106 Polymer.IronDropdownScrollManager.removeScrollLock(this); |
| 9904 } | 10107 } |
| 9905 Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments
); | 10108 Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments
); |
| 9906 } | 10109 } |
| 9907 }, | 10110 }, |
| 9908 | 10111 |
| 9909 /** | 10112 /** |
| 9910 * Overridden from `IronOverlayBehavior`. | 10113 * Overridden from `IronOverlayBehavior`. |
| 9911 */ | 10114 */ |
| 9912 _renderOpened: function() { | 10115 _renderOpened: function() { |
| 9913 if (!this.noAnimations && this.animationConfig.open) { | 10116 if (!this.noAnimations && this.animationConfig.open) { |
| 9914 this.$.contentWrapper.classList.add('animating'); | 10117 this.$.contentWrapper.classList.add('animating'); |
| 9915 this.playAnimation('open'); | 10118 this.playAnimation('open'); |
| 9916 } else { | 10119 } else { |
| 9917 Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this, arguments)
; | 10120 Polymer.IronOverlayBehaviorImpl._renderOpened.apply(this, arguments)
; |
| 9918 } | 10121 } |
| 9919 }, | 10122 }, |
| 9920 | 10123 |
| 9921 /** | 10124 /** |
| 9922 * Overridden from `IronOverlayBehavior`. | 10125 * Overridden from `IronOverlayBehavior`. |
| 9923 */ | 10126 */ |
| 9924 _renderClosed: function() { | 10127 _renderClosed: function() { |
| 10128 |
| 9925 if (!this.noAnimations && this.animationConfig.close) { | 10129 if (!this.noAnimations && this.animationConfig.close) { |
| 9926 this.$.contentWrapper.classList.add('animating'); | 10130 this.$.contentWrapper.classList.add('animating'); |
| 9927 this.playAnimation('close'); | 10131 this.playAnimation('close'); |
| 9928 } else { | 10132 } else { |
| 9929 Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this, arguments)
; | 10133 Polymer.IronOverlayBehaviorImpl._renderClosed.apply(this, arguments)
; |
| 9930 } | 10134 } |
| 9931 }, | 10135 }, |
| 9932 | 10136 |
| 9933 /** | 10137 /** |
| 9934 * Called when animation finishes on the dropdown (when opening or | 10138 * Called when animation finishes on the dropdown (when opening or |
| 9935 * closing). Responsible for "completing" the process of opening or | 10139 * closing). Responsible for "completing" the process of opening or |
| 9936 * closing the dropdown by positioning it or setting its display to | 10140 * closing the dropdown by positioning it or setting its display to |
| 9937 * none. | 10141 * none. |
| 9938 */ | 10142 */ |
| 9939 _onNeonAnimationFinish: function() { | 10143 _onNeonAnimationFinish: function() { |
| 9940 this.$.contentWrapper.classList.remove('animating'); | 10144 this.$.contentWrapper.classList.remove('animating'); |
| 9941 if (this.opened) { | 10145 if (this.opened) { |
| 9942 this._finishRenderOpened(); | 10146 this._finishRenderOpened(); |
| 9943 } else { | 10147 } else { |
| 9944 this._finishRenderClosed(); | 10148 this._finishRenderClosed(); |
| 9945 } | 10149 } |
| 9946 }, | 10150 }, |
| 9947 | 10151 |
| 10152 _onCaptureScroll: function() { |
| 10153 if (!this.allowOutsideScroll) { |
| 10154 this._restoreScrollPosition(); |
| 10155 } else { |
| 10156 this._refitOnScrollRAF && window.cancelAnimationFrame(this._refitOnS
crollRAF); |
| 10157 this._refitOnScrollRAF = window.requestAnimationFrame(this.refit.bin
d(this)); |
| 10158 } |
| 10159 }, |
| 10160 |
| 10161 /** |
| 10162 * Memoizes the scroll position of the outside scrolling element. |
| 10163 * @private |
| 10164 */ |
| 10165 _saveScrollPosition: function() { |
| 10166 if (document.scrollingElement) { |
| 10167 this._scrollTop = document.scrollingElement.scrollTop; |
| 10168 this._scrollLeft = document.scrollingElement.scrollLeft; |
| 10169 } else { |
| 10170 // Since we don't know if is the body or html, get max. |
| 10171 this._scrollTop = Math.max(document.documentElement.scrollTop, docum
ent.body.scrollTop); |
| 10172 this._scrollLeft = Math.max(document.documentElement.scrollLeft, doc
ument.body.scrollLeft); |
| 10173 } |
| 10174 }, |
| 10175 |
| 10176 /** |
| 10177 * Resets the scroll position of the outside scrolling element. |
| 10178 * @private |
| 10179 */ |
| 10180 _restoreScrollPosition: function() { |
| 10181 if (document.scrollingElement) { |
| 10182 document.scrollingElement.scrollTop = this._scrollTop; |
| 10183 document.scrollingElement.scrollLeft = this._scrollLeft; |
| 10184 } else { |
| 10185 // Since we don't know if is the body or html, set both. |
| 10186 document.documentElement.scrollTop = this._scrollTop; |
| 10187 document.documentElement.scrollLeft = this._scrollLeft; |
| 10188 document.body.scrollTop = this._scrollTop; |
| 10189 document.body.scrollLeft = this._scrollLeft; |
| 10190 } |
| 10191 }, |
| 10192 |
| 9948 /** | 10193 /** |
| 9949 * Constructs the final animation config from different properties used | 10194 * Constructs the final animation config from different properties used |
| 9950 * to configure specific parts of the opening and closing animations. | 10195 * to configure specific parts of the opening and closing animations. |
| 9951 */ | 10196 */ |
| 9952 _updateAnimationConfig: function() { | 10197 _updateAnimationConfig: function() { |
| 9953 var animations = (this.openAnimationConfig || []).concat(this.closeAni
mationConfig || []); | 10198 var animations = (this.openAnimationConfig || []).concat(this.closeAni
mationConfig || []); |
| 9954 for (var i = 0; i < animations.length; i++) { | 10199 for (var i = 0; i < animations.length; i++) { |
| 9955 animations[i].node = this.containedElement; | 10200 animations[i].node = this.containedElement; |
| 9956 } | 10201 } |
| 9957 this.animationConfig = { | 10202 this.animationConfig = { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10108 height: height / 2 + 'px', | 10353 height: height / 2 + 'px', |
| 10109 transform: 'translateY(-20px)' | 10354 transform: 'translateY(-20px)' |
| 10110 }], this.timingFromConfig(config)); | 10355 }], this.timingFromConfig(config)); |
| 10111 | 10356 |
| 10112 return this._effect; | 10357 return this._effect; |
| 10113 } | 10358 } |
| 10114 }); | 10359 }); |
| 10115 (function() { | 10360 (function() { |
| 10116 'use strict'; | 10361 'use strict'; |
| 10117 | 10362 |
| 10363 var config = { |
| 10364 ANIMATION_CUBIC_BEZIER: 'cubic-bezier(.3,.95,.5,1)', |
| 10365 MAX_ANIMATION_TIME_MS: 400 |
| 10366 }; |
| 10367 |
| 10118 var PaperMenuButton = Polymer({ | 10368 var PaperMenuButton = Polymer({ |
| 10119 is: 'paper-menu-button', | 10369 is: 'paper-menu-button', |
| 10120 | 10370 |
| 10121 /** | 10371 /** |
| 10122 * Fired when the dropdown opens. | 10372 * Fired when the dropdown opens. |
| 10123 * | 10373 * |
| 10124 * @event paper-dropdown-open | 10374 * @event paper-dropdown-open |
| 10125 */ | 10375 */ |
| 10126 | 10376 |
| 10127 /** | 10377 /** |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10160 * The orientation against which to align the menu dropdown | 10410 * The orientation against which to align the menu dropdown |
| 10161 * vertically relative to the dropdown trigger. | 10411 * vertically relative to the dropdown trigger. |
| 10162 */ | 10412 */ |
| 10163 verticalAlign: { | 10413 verticalAlign: { |
| 10164 type: String, | 10414 type: String, |
| 10165 value: 'top', | 10415 value: 'top', |
| 10166 reflectToAttribute: true | 10416 reflectToAttribute: true |
| 10167 }, | 10417 }, |
| 10168 | 10418 |
| 10169 /** | 10419 /** |
| 10420 * If true, the `horizontalAlign` and `verticalAlign` properties will |
| 10421 * be considered preferences instead of strict requirements when |
| 10422 * positioning the dropdown and may be changed if doing so reduces |
| 10423 * the area of the dropdown falling outside of `fitInto`. |
| 10424 */ |
| 10425 dynamicAlign: { |
| 10426 type: Boolean |
| 10427 }, |
| 10428 |
| 10429 /** |
| 10170 * A pixel value that will be added to the position calculated for the | 10430 * A pixel value that will be added to the position calculated for the |
| 10171 * given `horizontalAlign`. Use a negative value to offset to the | 10431 * given `horizontalAlign`. Use a negative value to offset to the |
| 10172 * left, or a positive value to offset to the right. | 10432 * left, or a positive value to offset to the right. |
| 10173 */ | 10433 */ |
| 10174 horizontalOffset: { | 10434 horizontalOffset: { |
| 10175 type: Number, | 10435 type: Number, |
| 10176 value: 0, | 10436 value: 0, |
| 10177 notify: true | 10437 notify: true |
| 10178 }, | 10438 }, |
| 10179 | 10439 |
| 10180 /** | 10440 /** |
| 10181 * A pixel value that will be added to the position calculated for the | 10441 * A pixel value that will be added to the position calculated for the |
| 10182 * given `verticalAlign`. Use a negative value to offset towards the | 10442 * given `verticalAlign`. Use a negative value to offset towards the |
| 10183 * top, or a positive value to offset towards the bottom. | 10443 * top, or a positive value to offset towards the bottom. |
| 10184 */ | 10444 */ |
| 10185 verticalOffset: { | 10445 verticalOffset: { |
| 10186 type: Number, | 10446 type: Number, |
| 10187 value: 0, | 10447 value: 0, |
| 10188 notify: true | 10448 notify: true |
| 10189 }, | 10449 }, |
| 10190 | 10450 |
| 10191 /** | 10451 /** |
| 10452 * If true, the dropdown will be positioned so that it doesn't overlap |
| 10453 * the button. |
| 10454 */ |
| 10455 noOverlap: { |
| 10456 type: Boolean |
| 10457 }, |
| 10458 |
| 10459 /** |
| 10192 * Set to true to disable animations when opening and closing the | 10460 * Set to true to disable animations when opening and closing the |
| 10193 * dropdown. | 10461 * dropdown. |
| 10194 */ | 10462 */ |
| 10195 noAnimations: { | 10463 noAnimations: { |
| 10196 type: Boolean, | 10464 type: Boolean, |
| 10197 value: false | 10465 value: false |
| 10198 }, | 10466 }, |
| 10199 | 10467 |
| 10200 /** | 10468 /** |
| 10201 * Set to true to disable automatically closing the dropdown after | 10469 * Set to true to disable automatically closing the dropdown after |
| 10202 * a selection has been made. | 10470 * a selection has been made. |
| 10203 */ | 10471 */ |
| 10204 ignoreSelect: { | 10472 ignoreSelect: { |
| 10205 type: Boolean, | 10473 type: Boolean, |
| 10206 value: false | 10474 value: false |
| 10207 }, | 10475 }, |
| 10208 | 10476 |
| 10209 /** | 10477 /** |
| 10478 * Set to true to enable automatically closing the dropdown after an |
| 10479 * item has been activated, even if the selection did not change. |
| 10480 */ |
| 10481 closeOnActivate: { |
| 10482 type: Boolean, |
| 10483 value: false |
| 10484 }, |
| 10485 |
| 10486 /** |
| 10210 * An animation config. If provided, this will be used to animate the | 10487 * An animation config. If provided, this will be used to animate the |
| 10211 * opening of the dropdown. | 10488 * opening of the dropdown. |
| 10212 */ | 10489 */ |
| 10213 openAnimationConfig: { | 10490 openAnimationConfig: { |
| 10214 type: Object, | 10491 type: Object, |
| 10215 value: function() { | 10492 value: function() { |
| 10216 return [{ | 10493 return [{ |
| 10217 name: 'fade-in-animation', | 10494 name: 'fade-in-animation', |
| 10218 timing: { | 10495 timing: { |
| 10219 delay: 100, | 10496 delay: 100, |
| 10220 duration: 200 | 10497 duration: 200 |
| 10221 } | 10498 } |
| 10222 }, { | 10499 }, { |
| 10223 name: 'paper-menu-grow-width-animation', | 10500 name: 'paper-menu-grow-width-animation', |
| 10224 timing: { | 10501 timing: { |
| 10225 delay: 100, | 10502 delay: 100, |
| 10226 duration: 150, | 10503 duration: 150, |
| 10227 easing: PaperMenuButton.ANIMATION_CUBIC_BEZIER | 10504 easing: config.ANIMATION_CUBIC_BEZIER |
| 10228 } | 10505 } |
| 10229 }, { | 10506 }, { |
| 10230 name: 'paper-menu-grow-height-animation', | 10507 name: 'paper-menu-grow-height-animation', |
| 10231 timing: { | 10508 timing: { |
| 10232 delay: 100, | 10509 delay: 100, |
| 10233 duration: 275, | 10510 duration: 275, |
| 10234 easing: PaperMenuButton.ANIMATION_CUBIC_BEZIER | 10511 easing: config.ANIMATION_CUBIC_BEZIER |
| 10235 } | 10512 } |
| 10236 }]; | 10513 }]; |
| 10237 } | 10514 } |
| 10238 }, | 10515 }, |
| 10239 | 10516 |
| 10240 /** | 10517 /** |
| 10241 * An animation config. If provided, this will be used to animate the | 10518 * An animation config. If provided, this will be used to animate the |
| 10242 * closing of the dropdown. | 10519 * closing of the dropdown. |
| 10243 */ | 10520 */ |
| 10244 closeAnimationConfig: { | 10521 closeAnimationConfig: { |
| 10245 type: Object, | 10522 type: Object, |
| 10246 value: function() { | 10523 value: function() { |
| 10247 return [{ | 10524 return [{ |
| 10248 name: 'fade-out-animation', | 10525 name: 'fade-out-animation', |
| 10249 timing: { | 10526 timing: { |
| 10250 duration: 150 | 10527 duration: 150 |
| 10251 } | 10528 } |
| 10252 }, { | 10529 }, { |
| 10253 name: 'paper-menu-shrink-width-animation', | 10530 name: 'paper-menu-shrink-width-animation', |
| 10254 timing: { | 10531 timing: { |
| 10255 delay: 100, | 10532 delay: 100, |
| 10256 duration: 50, | 10533 duration: 50, |
| 10257 easing: PaperMenuButton.ANIMATION_CUBIC_BEZIER | 10534 easing: config.ANIMATION_CUBIC_BEZIER |
| 10258 } | 10535 } |
| 10259 }, { | 10536 }, { |
| 10260 name: 'paper-menu-shrink-height-animation', | 10537 name: 'paper-menu-shrink-height-animation', |
| 10261 timing: { | 10538 timing: { |
| 10262 duration: 200, | 10539 duration: 200, |
| 10263 easing: 'ease-in' | 10540 easing: 'ease-in' |
| 10264 } | 10541 } |
| 10265 }]; | 10542 }]; |
| 10266 } | 10543 } |
| 10267 }, | 10544 }, |
| 10545 |
| 10546 /** |
| 10547 * By default, the dropdown will constrain scrolling on the page |
| 10548 * to itself when opened. |
| 10549 * Set to true in order to prevent scroll from being constrained |
| 10550 * to the dropdown when it opens. |
| 10551 */ |
| 10552 allowOutsideScroll: { |
| 10553 type: Boolean, |
| 10554 value: false |
| 10555 }, |
| 10268 | 10556 |
| 10269 /** | 10557 /** |
| 10270 * This is the element intended to be bound as the focus target | 10558 * This is the element intended to be bound as the focus target |
| 10271 * for the `iron-dropdown` contained by `paper-menu-button`. | 10559 * for the `iron-dropdown` contained by `paper-menu-button`. |
| 10272 */ | 10560 */ |
| 10273 _dropdownContent: { | 10561 _dropdownContent: { |
| 10274 type: Object | 10562 type: Object |
| 10275 } | 10563 } |
| 10276 }, | 10564 }, |
| 10277 | 10565 |
| 10278 hostAttributes: { | 10566 hostAttributes: { |
| 10279 role: 'group', | 10567 role: 'group', |
| 10280 'aria-haspopup': 'true' | 10568 'aria-haspopup': 'true' |
| 10281 }, | 10569 }, |
| 10282 | 10570 |
| 10283 listeners: { | 10571 listeners: { |
| 10572 'iron-activate': '_onIronActivate', |
| 10284 'iron-select': '_onIronSelect' | 10573 'iron-select': '_onIronSelect' |
| 10285 }, | 10574 }, |
| 10286 | 10575 |
| 10287 /** | 10576 /** |
| 10288 * The content element that is contained by the menu button, if any. | 10577 * The content element that is contained by the menu button, if any. |
| 10289 */ | 10578 */ |
| 10290 get contentElement() { | 10579 get contentElement() { |
| 10291 return Polymer.dom(this.$.content).getDistributedNodes()[0]; | 10580 return Polymer.dom(this.$.content).getDistributedNodes()[0]; |
| 10292 }, | 10581 }, |
| 10293 | 10582 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10328 * @param {CustomEvent} event A CustomEvent instance with type | 10617 * @param {CustomEvent} event A CustomEvent instance with type |
| 10329 * set to `"iron-select"`. | 10618 * set to `"iron-select"`. |
| 10330 */ | 10619 */ |
| 10331 _onIronSelect: function(event) { | 10620 _onIronSelect: function(event) { |
| 10332 if (!this.ignoreSelect) { | 10621 if (!this.ignoreSelect) { |
| 10333 this.close(); | 10622 this.close(); |
| 10334 } | 10623 } |
| 10335 }, | 10624 }, |
| 10336 | 10625 |
| 10337 /** | 10626 /** |
| 10627 * Closes the dropdown when an `iron-activate` event is received if |
| 10628 * `closeOnActivate` is true. |
| 10629 * |
| 10630 * @param {CustomEvent} event A CustomEvent of type 'iron-activate'. |
| 10631 */ |
| 10632 _onIronActivate: function(event) { |
| 10633 if (this.closeOnActivate) { |
| 10634 this.close(); |
| 10635 } |
| 10636 }, |
| 10637 |
| 10638 /** |
| 10338 * When the dropdown opens, the `paper-menu-button` fires `paper-open`. | 10639 * When the dropdown opens, the `paper-menu-button` fires `paper-open`. |
| 10339 * When the dropdown closes, the `paper-menu-button` fires `paper-close`
. | 10640 * When the dropdown closes, the `paper-menu-button` fires `paper-close`
. |
| 10340 * | 10641 * |
| 10341 * @param {boolean} opened True if the dropdown is opened, otherwise fal
se. | 10642 * @param {boolean} opened True if the dropdown is opened, otherwise fal
se. |
| 10342 * @param {boolean} oldOpened The previous value of `opened`. | 10643 * @param {boolean} oldOpened The previous value of `opened`. |
| 10343 */ | 10644 */ |
| 10344 _openedChanged: function(opened, oldOpened) { | 10645 _openedChanged: function(opened, oldOpened) { |
| 10345 if (opened) { | 10646 if (opened) { |
| 10346 // TODO(cdata): Update this when we can measure changes in distribut
ed | 10647 // TODO(cdata): Update this when we can measure changes in distribut
ed |
| 10347 // children in an idiomatic way. | 10648 // children in an idiomatic way. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 10373 var target = Polymer.dom(uiEvent).rootTarget; | 10674 var target = Polymer.dom(uiEvent).rootTarget; |
| 10374 var trigger = this.$.trigger; | 10675 var trigger = this.$.trigger; |
| 10375 var path = Polymer.dom(uiEvent).path; | 10676 var path = Polymer.dom(uiEvent).path; |
| 10376 | 10677 |
| 10377 if (path.indexOf(trigger) > -1) { | 10678 if (path.indexOf(trigger) > -1) { |
| 10378 event.preventDefault(); | 10679 event.preventDefault(); |
| 10379 } | 10680 } |
| 10380 } | 10681 } |
| 10381 }); | 10682 }); |
| 10382 | 10683 |
| 10383 PaperMenuButton.ANIMATION_CUBIC_BEZIER = 'cubic-bezier(.3,.95,.5,1)'; | 10684 Object.keys(config).forEach(function (key) { |
| 10384 PaperMenuButton.MAX_ANIMATION_TIME_MS = 400; | 10685 PaperMenuButton[key] = config[key]; |
| 10686 }); |
| 10385 | 10687 |
| 10386 Polymer.PaperMenuButton = PaperMenuButton; | 10688 Polymer.PaperMenuButton = PaperMenuButton; |
| 10387 })(); | 10689 })(); |
| 10388 /** | 10690 /** |
| 10389 * `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has k
eyboard focus. | 10691 * `Polymer.PaperInkyFocusBehavior` implements a ripple when the element has k
eyboard focus. |
| 10390 * | 10692 * |
| 10391 * @polymerBehavior Polymer.PaperInkyFocusBehavior | 10693 * @polymerBehavior Polymer.PaperInkyFocusBehavior |
| 10392 */ | 10694 */ |
| 10393 Polymer.PaperInkyFocusBehaviorImpl = { | 10695 Polymer.PaperInkyFocusBehaviorImpl = { |
| 10394 | |
| 10395 observers: [ | 10696 observers: [ |
| 10396 '_focusedChanged(receivedFocusFromKeyboard)' | 10697 '_focusedChanged(receivedFocusFromKeyboard)' |
| 10397 ], | 10698 ], |
| 10398 | 10699 |
| 10399 _focusedChanged: function(receivedFocusFromKeyboard) { | 10700 _focusedChanged: function(receivedFocusFromKeyboard) { |
| 10400 if (receivedFocusFromKeyboard) { | 10701 if (receivedFocusFromKeyboard) { |
| 10401 this.ensureRipple(); | 10702 this.ensureRipple(); |
| 10402 } | 10703 } |
| 10403 if (this.hasRipple()) { | 10704 if (this.hasRipple()) { |
| 10404 this._ripple.holdDown = receivedFocusFromKeyboard; | 10705 this._ripple.holdDown = receivedFocusFromKeyboard; |
| 10405 } | 10706 } |
| 10406 }, | 10707 }, |
| 10407 | 10708 |
| 10408 _createRipple: function() { | 10709 _createRipple: function() { |
| 10409 var ripple = Polymer.PaperRippleBehavior._createRipple(); | 10710 var ripple = Polymer.PaperRippleBehavior._createRipple(); |
| 10410 ripple.id = 'ink'; | 10711 ripple.id = 'ink'; |
| 10411 ripple.setAttribute('center', ''); | 10712 ripple.setAttribute('center', ''); |
| 10412 ripple.classList.add('circle'); | 10713 ripple.classList.add('circle'); |
| 10413 return ripple; | 10714 return ripple; |
| 10414 } | 10715 } |
| 10415 | |
| 10416 }; | 10716 }; |
| 10417 | 10717 |
| 10418 /** @polymerBehavior Polymer.PaperInkyFocusBehavior */ | 10718 /** @polymerBehavior Polymer.PaperInkyFocusBehavior */ |
| 10419 Polymer.PaperInkyFocusBehavior = [ | 10719 Polymer.PaperInkyFocusBehavior = [ |
| 10420 Polymer.IronButtonState, | 10720 Polymer.IronButtonState, |
| 10421 Polymer.IronControlState, | 10721 Polymer.IronControlState, |
| 10422 Polymer.PaperRippleBehavior, | 10722 Polymer.PaperRippleBehavior, |
| 10423 Polymer.PaperInkyFocusBehaviorImpl | 10723 Polymer.PaperInkyFocusBehaviorImpl |
| 10424 ]; | 10724 ]; |
| 10425 Polymer({ | 10725 Polymer({ |
| (...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11648 Manager.get().updateItem_(index, data); | 11948 Manager.get().updateItem_(index, data); |
| 11649 }; | 11949 }; |
| 11650 | 11950 |
| 11651 return {Manager: Manager}; | 11951 return {Manager: Manager}; |
| 11652 }); | 11952 }); |
| 11653 // Copyright 2015 The Chromium Authors. All rights reserved. | 11953 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 11654 // Use of this source code is governed by a BSD-style license that can be | 11954 // Use of this source code is governed by a BSD-style license that can be |
| 11655 // found in the LICENSE file. | 11955 // found in the LICENSE file. |
| 11656 | 11956 |
| 11657 window.addEventListener('load', downloads.Manager.onLoad); | 11957 window.addEventListener('load', downloads.Manager.onLoad); |
| OLD | NEW |