2 * jQuery UI Button 1.8.16
4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
8 * http://docs.jquery.com/UI/Button
14 (function( $, undefined ) {
16 var lastActive
, startXPos
, startYPos
, clickDragged
,
17 baseClasses
= "ui-button ui-widget ui-state-default ui-corner-all",
18 stateClasses
= "ui-state-hover ui-state-active ",
19 typeClasses
= "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
20 formResetHandler = function() {
21 var buttons
= $( this ).find( ":ui-button" );
22 setTimeout(function() {
23 buttons
.button( "refresh" );
26 radioGroup = function( radio
) {
27 var name
= radio
.name
,
32 radios
= $( form
).find( "[name='" + name
+ "']" );
34 radios
= $( "[name='" + name
+ "']", radio
.ownerDocument
)
43 $.widget( "ui.button", {
54 this.element
.closest( "form" )
55 .unbind( "reset.button" )
56 .bind( "reset.button", formResetHandler
);
58 if ( typeof this.options
.disabled
!== "boolean" ) {
59 this.options
.disabled
= this.element
.propAttr( "disabled" );
62 this._determineButtonType();
63 this.hasTitle
= !!this.buttonElement
.attr( "title" );
66 options
= this.options
,
67 toggleButton
= this.type
=== "checkbox" || this.type
=== "radio",
68 hoverClass
= "ui-state-hover" + ( !toggleButton
? " ui-state-active" : "" ),
69 focusClass
= "ui-state-focus";
71 if ( options
.label
=== null ) {
72 options
.label
= this.buttonElement
.html();
75 if ( this.element
.is( ":disabled" ) ) {
76 options
.disabled
= true;
80 .addClass( baseClasses
)
81 .attr( "role", "button" )
82 .bind( "mouseenter.button", function() {
83 if ( options
.disabled
) {
86 $( this ).addClass( "ui-state-hover" );
87 if ( this === lastActive
) {
88 $( this ).addClass( "ui-state-active" );
91 .bind( "mouseleave.button", function() {
92 if ( options
.disabled
) {
95 $( this ).removeClass( hoverClass
);
97 .bind( "click.button", function( event
) {
98 if ( options
.disabled
) {
99 event
.preventDefault();
100 event
.stopImmediatePropagation();
105 .bind( "focus.button", function() {
106 // no need to check disabled, focus won't be triggered anyway
107 self
.buttonElement
.addClass( focusClass
);
109 .bind( "blur.button", function() {
110 self
.buttonElement
.removeClass( focusClass
);
113 if ( toggleButton
) {
114 this.element
.bind( "change.button", function() {
115 if ( clickDragged
) {
120 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
121 // prevents issue where button state changes but checkbox/radio checked state
122 // does not in Firefox (see ticket #6970)
124 .bind( "mousedown.button", function( event
) {
125 if ( options
.disabled
) {
128 clickDragged
= false;
129 startXPos
= event
.pageX
;
130 startYPos
= event
.pageY
;
132 .bind( "mouseup.button", function( event
) {
133 if ( options
.disabled
) {
136 if ( startXPos
!== event
.pageX
|| startYPos
!== event
.pageY
) {
142 if ( this.type
=== "checkbox" ) {
143 this.buttonElement
.bind( "click.button", function() {
144 if ( options
.disabled
|| clickDragged
) {
147 $( this ).toggleClass( "ui-state-active" );
148 self
.buttonElement
.attr( "aria-pressed", self
.element
[0].checked
);
150 } else if ( this.type
=== "radio" ) {
151 this.buttonElement
.bind( "click.button", function() {
152 if ( options
.disabled
|| clickDragged
) {
155 $( this ).addClass( "ui-state-active" );
156 self
.buttonElement
.attr( "aria-pressed", "true" );
158 var radio
= self
.element
[ 0 ];
162 return $( this ).button( "widget" )[ 0 ];
164 .removeClass( "ui-state-active" )
165 .attr( "aria-pressed", "false" );
169 .bind( "mousedown.button", function() {
170 if ( options
.disabled
) {
173 $( this ).addClass( "ui-state-active" );
175 $( document
).one( "mouseup", function() {
179 .bind( "mouseup.button", function() {
180 if ( options
.disabled
) {
183 $( this ).removeClass( "ui-state-active" );
185 .bind( "keydown.button", function(event
) {
186 if ( options
.disabled
) {
189 if ( event
.keyCode
== $.ui
.keyCode
.SPACE
|| event
.keyCode
== $.ui
.keyCode
.ENTER
) {
190 $( this ).addClass( "ui-state-active" );
193 .bind( "keyup.button", function() {
194 $( this ).removeClass( "ui-state-active" );
197 if ( this.buttonElement
.is("a") ) {
198 this.buttonElement
.keyup(function(event
) {
199 if ( event
.keyCode
=== $.ui
.keyCode
.SPACE
) {
200 // TODO pass through original event correctly (just as 2nd argument doesn't work)
207 // TODO: pull out $.Widget's handling for the disabled option into
208 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
209 // be overridden by individual plugins
210 this._setOption( "disabled", options
.disabled
);
214 _determineButtonType: function() {
216 if ( this.element
.is(":checkbox") ) {
217 this.type
= "checkbox";
218 } else if ( this.element
.is(":radio") ) {
220 } else if ( this.element
.is("input") ) {
223 this.type
= "button";
226 if ( this.type
=== "checkbox" || this.type
=== "radio" ) {
227 // we don't search against the document in case the element
228 // is disconnected from the DOM
229 var ancestor
= this.element
.parents().filter(":last"),
230 labelSelector
= "label[for='" + this.element
.attr("id") + "']";
231 this.buttonElement
= ancestor
.find( labelSelector
);
232 if ( !this.buttonElement
.length
) {
233 ancestor
= ancestor
.length
? ancestor
.siblings() : this.element
.siblings();
234 this.buttonElement
= ancestor
.filter( labelSelector
);
235 if ( !this.buttonElement
.length
) {
236 this.buttonElement
= ancestor
.find( labelSelector
);
239 this.element
.addClass( "ui-helper-hidden-accessible" );
241 var checked
= this.element
.is( ":checked" );
243 this.buttonElement
.addClass( "ui-state-active" );
245 this.buttonElement
.attr( "aria-pressed", checked
);
247 this.buttonElement
= this.element
;
252 return this.buttonElement
;
255 destroy: function() {
257 .removeClass( "ui-helper-hidden-accessible" );
259 .removeClass( baseClasses
+ " " + stateClasses
+ " " + typeClasses
)
260 .removeAttr( "role" )
261 .removeAttr( "aria-pressed" )
262 .html( this.buttonElement
.find(".ui-button-text").html() );
264 if ( !this.hasTitle
) {
265 this.buttonElement
.removeAttr( "title" );
268 $.Widget
.prototype.destroy
.call( this );
271 _setOption: function( key
, value
) {
272 $.Widget
.prototype._setOption
.apply( this, arguments
);
273 if ( key
=== "disabled" ) {
275 this.element
.propAttr( "disabled", true );
277 this.element
.propAttr( "disabled", false );
284 refresh: function() {
285 var isDisabled
= this.element
.is( ":disabled" );
286 if ( isDisabled
!== this.options
.disabled
) {
287 this._setOption( "disabled", isDisabled
);
289 if ( this.type
=== "radio" ) {
290 radioGroup( this.element
[0] ).each(function() {
291 if ( $( this ).is( ":checked" ) ) {
292 $( this ).button( "widget" )
293 .addClass( "ui-state-active" )
294 .attr( "aria-pressed", "true" );
296 $( this ).button( "widget" )
297 .removeClass( "ui-state-active" )
298 .attr( "aria-pressed", "false" );
301 } else if ( this.type
=== "checkbox" ) {
302 if ( this.element
.is( ":checked" ) ) {
304 .addClass( "ui-state-active" )
305 .attr( "aria-pressed", "true" );
308 .removeClass( "ui-state-active" )
309 .attr( "aria-pressed", "false" );
314 _resetButton: function() {
315 if ( this.type
=== "input" ) {
316 if ( this.options
.label
) {
317 this.element
.val( this.options
.label
);
321 var buttonElement
= this.buttonElement
.removeClass( typeClasses
),
322 buttonText
= $( "<span></span>" )
323 .addClass( "ui-button-text" )
324 .html( this.options
.label
)
325 .appendTo( buttonElement
.empty() )
327 icons
= this.options
.icons
,
328 multipleIcons
= icons
.primary
&& icons
.secondary
,
331 if ( icons
.primary
|| icons
.secondary
) {
332 if ( this.options
.text
) {
333 buttonClasses
.push( "ui-button-text-icon" + ( multipleIcons
? "s" : ( icons
.primary
? "-primary" : "-secondary" ) ) );
336 if ( icons
.primary
) {
337 buttonElement
.prepend( "<span class='ui-button-icon-primary ui-icon " + icons
.primary
+ "'></span>" );
340 if ( icons
.secondary
) {
341 buttonElement
.append( "<span class='ui-button-icon-secondary ui-icon " + icons
.secondary
+ "'></span>" );
344 if ( !this.options
.text
) {
345 buttonClasses
.push( multipleIcons
? "ui-button-icons-only" : "ui-button-icon-only" );
347 if ( !this.hasTitle
) {
348 buttonElement
.attr( "title", buttonText
);
352 buttonClasses
.push( "ui-button-text-only" );
354 buttonElement
.addClass( buttonClasses
.join( " " ) );
358 $.widget( "ui.buttonset", {
360 items
: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
363 _create: function() {
364 this.element
.addClass( "ui-buttonset" );
371 _setOption: function( key
, value
) {
372 if ( key
=== "disabled" ) {
373 this.buttons
.button( "option", key
, value
);
376 $.Widget
.prototype._setOption
.apply( this, arguments
);
379 refresh: function() {
380 var ltr
= this.element
.css( "direction" ) === "ltr";
382 this.buttons
= this.element
.find( this.options
.items
)
383 .filter( ":ui-button" )
390 return $( this ).button( "widget" )[ 0 ];
392 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
394 .addClass( ltr
? "ui-corner-left" : "ui-corner-right" )
397 .addClass( ltr
? "ui-corner-right" : "ui-corner-left" )
402 destroy: function() {
403 this.element
.removeClass( "ui-buttonset" );
406 return $( this ).button( "widget" )[ 0 ];
408 .removeClass( "ui-corner-left ui-corner-right" )
410 .button( "destroy" );
412 $.Widget
.prototype.destroy
.call( this );