awips2/components/core-focusable/core-focusable.js
2016-04-03 22:04:09 -05:00

134 lines
3 KiB
JavaScript

/**
* @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;
}
}