/** * @group Polymer Mixins * * `Polymer.CoreFocusable` is a mixin for elements that the user can interact with. * Elements using this mixin will receive attributes reflecting the focus, pressed * and disabled states. * * @element Polymer.CoreFocusable * @status unstable */ Polymer.CoreFocusable = { mixinPublish: { /** * If true, the element is currently active either because the * user is touching it, or the button is a toggle * and is currently in the active state. * * @attribute active * @type boolean * @default false */ active: {value: false, reflect: true}, /** * If true, the element currently has focus due to keyboard * navigation. * * @attribute focused * @type boolean * @default false */ focused: {value: false, reflect: true}, /** * If true, the user is currently holding down the button. * * @attribute pressed * @type boolean * @default false */ pressed: {value: false, reflect: true}, /** * If true, the user cannot interact with this element. * * @attribute disabled * @type boolean * @default false */ disabled: {value: false, reflect: true}, /** * If true, the button toggles the active state with each tap. * Otherwise, the button becomes active when the user is holding * it down. * * @attribute toggle * @type boolean * @default false */ toggle: false }, mixinDelegates: { contextMenu: '_contextMenuAction', down: '_downAction', up: '_upAction', focus: '_focusAction', blur: '_blurAction' }, mixinObserve: { disabled: '_disabledChanged' }, _disabledChanged: function() { if (this.disabled) { this.style.pointerEvents = 'none'; this.removeAttribute('tabindex'); this.setAttribute('aria-disabled', ''); } else { this.style.pointerEvents = ''; this.setAttribute('tabindex', 0); this.removeAttribute('aria-disabled'); } }, _downAction: function() { this.pressed = true; if (this.toggle) { this.active = !this.active; } else { this.active = true; } }, // Pulling up the context menu for an item should focus it; but we need to // be careful about how we deal with down/up events surrounding context // menus. The up event typically does not fire until the context menu // closes: so we focus immediately. // // This fires _after_ downAction. _contextMenuAction: function(e) { // Note that upAction may fire _again_ on the actual up event. this._upAction(e); this._focusAction(); }, _upAction: function() { this.pressed = false; if (!this.toggle) { this.active = false; } }, _focusAction: function() { if (!this.pressed) { // Only render the "focused" state if the element gains focus due to // keyboard navigation. this.focused = true; } }, _blurAction: function() { this.focused = false; } }