diff options
Diffstat (limited to 'catapult/third_party/polymer/components/iron-behaviors/iron-button-state.html')
-rw-r--r-- | catapult/third_party/polymer/components/iron-behaviors/iron-button-state.html | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/catapult/third_party/polymer/components/iron-behaviors/iron-button-state.html b/catapult/third_party/polymer/components/iron-behaviors/iron-button-state.html new file mode 100644 index 00000000..c5221b8e --- /dev/null +++ b/catapult/third_party/polymer/components/iron-behaviors/iron-button-state.html @@ -0,0 +1,236 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html"> +<link rel="import" href="iron-control-state.html"> + +<script> + + /** + * @demo demo/index.html + * @polymerBehavior Polymer.IronButtonState + */ + Polymer.IronButtonStateImpl = { + + properties: { + + /** + * If true, the user is currently holding down the button. + */ + pressed: { + type: Boolean, + readOnly: true, + value: false, + reflectToAttribute: true, + observer: '_pressedChanged' + }, + + /** + * If true, the button toggles the active state with each tap or press + * of the spacebar. + */ + toggles: { + type: Boolean, + value: false, + reflectToAttribute: true + }, + + /** + * If true, the button is a toggle and is currently in the active state. + */ + active: { + type: Boolean, + value: false, + notify: true, + reflectToAttribute: true + }, + + /** + * True if the element is currently being pressed by a "pointer," which + * is loosely defined as mouse or touch input (but specifically excluding + * keyboard input). + */ + pointerDown: { + type: Boolean, + readOnly: true, + value: false + }, + + /** + * True if the input device that caused the element to receive focus + * was a keyboard. + */ + receivedFocusFromKeyboard: { + type: Boolean, + readOnly: true + }, + + /** + * The aria attribute to be set if the button is a toggle and in the + * active state. + */ + ariaActiveAttribute: { + type: String, + value: 'aria-pressed', + observer: '_ariaActiveAttributeChanged' + } + }, + + listeners: { + down: '_downHandler', + up: '_upHandler', + tap: '_tapHandler' + }, + + observers: [ + '_focusChanged(focused)', + '_activeChanged(active, ariaActiveAttribute)' + ], + + keyBindings: { + 'enter:keydown': '_asyncClick', + 'space:keydown': '_spaceKeyDownHandler', + 'space:keyup': '_spaceKeyUpHandler', + }, + + _mouseEventRe: /^mouse/, + + _tapHandler: function() { + if (this.toggles) { + // a tap is needed to toggle the active state + this._userActivate(!this.active); + } else { + this.active = false; + } + }, + + _focusChanged: function(focused) { + this._detectKeyboardFocus(focused); + + if (!focused) { + this._setPressed(false); + } + }, + + _detectKeyboardFocus: function(focused) { + this._setReceivedFocusFromKeyboard(!this.pointerDown && focused); + }, + + // to emulate native checkbox, (de-)activations from a user interaction fire + // 'change' events + _userActivate: function(active) { + if (this.active !== active) { + this.active = active; + this.fire('change'); + } + }, + + _downHandler: function(event) { + this._setPointerDown(true); + this._setPressed(true); + this._setReceivedFocusFromKeyboard(false); + }, + + _upHandler: function() { + this._setPointerDown(false); + this._setPressed(false); + }, + + /** + * @param {!KeyboardEvent} event . + */ + _spaceKeyDownHandler: function(event) { + var keyboardEvent = event.detail.keyboardEvent; + var target = Polymer.dom(keyboardEvent).localTarget; + + // Ignore the event if this is coming from a focused light child, since that + // element will deal with it. + if (this.isLightDescendant(/** @type {Node} */(target))) + return; + + keyboardEvent.preventDefault(); + keyboardEvent.stopImmediatePropagation(); + this._setPressed(true); + }, + + /** + * @param {!KeyboardEvent} event . + */ + _spaceKeyUpHandler: function(event) { + var keyboardEvent = event.detail.keyboardEvent; + var target = Polymer.dom(keyboardEvent).localTarget; + + // Ignore the event if this is coming from a focused light child, since that + // element will deal with it. + if (this.isLightDescendant(/** @type {Node} */(target))) + return; + + if (this.pressed) { + this._asyncClick(); + } + this._setPressed(false); + }, + + // trigger click asynchronously, the asynchrony is useful to allow one + // event handler to unwind before triggering another event + _asyncClick: function() { + this.async(function() { + this.click(); + }, 1); + }, + + // any of these changes are considered a change to button state + + _pressedChanged: function(pressed) { + this._changedButtonState(); + }, + + _ariaActiveAttributeChanged: function(value, oldValue) { + if (oldValue && oldValue != value && this.hasAttribute(oldValue)) { + this.removeAttribute(oldValue); + } + }, + + _activeChanged: function(active, ariaActiveAttribute) { + if (this.toggles) { + this.setAttribute(this.ariaActiveAttribute, + active ? 'true' : 'false'); + } else { + this.removeAttribute(this.ariaActiveAttribute); + } + this._changedButtonState(); + }, + + _controlStateChanged: function() { + if (this.disabled) { + this._setPressed(false); + } else { + this._changedButtonState(); + } + }, + + // provide hook for follow-on behaviors to react to button-state + + _changedButtonState: function() { + if (this._buttonStateChanged) { + this._buttonStateChanged(); // abstract + } + } + + }; + + /** @polymerBehavior */ + Polymer.IronButtonState = [ + Polymer.IronA11yKeysBehavior, + Polymer.IronButtonStateImpl + ]; + +</script> |