<!-- @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: [ '_detectKeyboardFocus(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; } }, _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); }, _spaceKeyDownHandler: function(event) { var keyboardEvent = event.detail.keyboardEvent; keyboardEvent.preventDefault(); keyboardEvent.stopImmediatePropagation(); this._setPressed(true); }, _spaceKeyUpHandler: function() { 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>