2 * @demo demo/index.html
3 * @polymerBehavior Polymer.IronButtonState
5 Polymer
.IronButtonStateImpl
= {
10 * If true, the user is currently holding down the button.
16 reflectToAttribute
: true,
17 observer
: '_pressedChanged'
21 * If true, the button toggles the active state with each tap or press
27 reflectToAttribute
: true
31 * If true, the button is a toggle and is currently in the active state.
37 reflectToAttribute
: true
41 * True if the element is currently being pressed by a "pointer," which
42 * is loosely defined as mouse or touch input (but specifically excluding
52 * True if the input device that caused the element to receive focus
55 receivedFocusFromKeyboard
: {
61 * The aria attribute to be set if the button is a toggle and in the
64 ariaActiveAttribute
: {
66 value
: 'aria-pressed',
67 observer
: '_ariaActiveAttributeChanged'
78 '_detectKeyboardFocus(focused)',
79 '_activeChanged(active, ariaActiveAttribute)'
83 'enter:keydown': '_asyncClick',
84 'space:keydown': '_spaceKeyDownHandler',
85 'space:keyup': '_spaceKeyUpHandler',
88 _mouseEventRe
: /^mouse/,
90 _tapHandler: function() {
92 // a tap is needed to toggle the active state
93 this._userActivate(!this.active
);
99 _detectKeyboardFocus: function(focused
) {
100 this._setReceivedFocusFromKeyboard(!this.pointerDown
&& focused
);
103 // to emulate native checkbox, (de-)activations from a user interaction fire
105 _userActivate: function(active
) {
106 if (this.active
!== active
) {
107 this.active
= active
;
112 _eventSourceIsPrimaryInput: function(event
) {
113 event
= event
.detail
.sourceEvent
|| event
;
115 // Always true for non-mouse events....
116 if (!this._mouseEventRe
.test(event
.type
)) {
120 // http://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
121 if ('buttons' in event
) {
122 return event
.buttons
=== 1;
125 // http://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/which
126 if (typeof event
.which
=== 'number') {
127 return event
.which
< 2;
130 // http://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
131 return event
.button
< 1;
134 _downHandler: function(event
) {
135 if (!this._eventSourceIsPrimaryInput(event
)) {
139 this._setPointerDown(true);
140 this._setPressed(true);
141 this._setReceivedFocusFromKeyboard(false);
144 _upHandler: function() {
145 this._setPointerDown(false);
146 this._setPressed(false);
149 _spaceKeyDownHandler: function(event
) {
150 var keyboardEvent
= event
.detail
.keyboardEvent
;
151 keyboardEvent
.preventDefault();
152 keyboardEvent
.stopImmediatePropagation();
153 this._setPressed(true);
156 _spaceKeyUpHandler: function() {
160 this._setPressed(false);
163 // trigger click asynchronously, the asynchrony is useful to allow one
164 // event handler to unwind before triggering another event
165 _asyncClick: function() {
166 this.async(function() {
171 // any of these changes are considered a change to button state
173 _pressedChanged: function(pressed
) {
174 this._changedButtonState();
177 _ariaActiveAttributeChanged: function(value
, oldValue
) {
178 if (oldValue
&& oldValue
!= value
&& this.hasAttribute(oldValue
)) {
179 this.removeAttribute(oldValue
);
183 _activeChanged: function(active
, ariaActiveAttribute
) {
185 this.setAttribute(this.ariaActiveAttribute
,
186 active
? 'true' : 'false');
188 this.removeAttribute(this.ariaActiveAttribute
);
190 this._changedButtonState();
193 _controlStateChanged: function() {
195 this._setPressed(false);
197 this._changedButtonState();
201 // provide hook for follow-on behaviors to react to button-state
203 _changedButtonState: function() {
204 if (this._buttonStateChanged
) {
205 this._buttonStateChanged(); // abstract
211 /** @polymerBehavior */
212 Polymer
.IronButtonState
= [
213 Polymer
.IronA11yKeysBehavior
,
214 Polymer
.IronButtonStateImpl