jellyfin-web/dashboard-ui/bower_components/iron-behaviors/iron-button-state.html
2015-08-10 20:14:15 -04:00

234 lines
5.9 KiB
HTML

<!--
@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');
}
},
_eventSourceIsPrimaryInput: function(event) {
event = event.detail.sourceEvent || event;
// Always true for non-mouse events....
if (!this._mouseEventRe.test(event.type)) {
return true;
}
// http://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
if ('buttons' in event) {
return event.buttons === 1;
}
// http://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which
if (typeof event.which === 'number') {
return event.which < 2;
}
// http://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
return event.button < 1;
},
_downHandler: function(event) {
if (!this._eventSourceIsPrimaryInput(event)) {
return;
}
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>