2 * jQuery UI Button 1.11.2
5 * Copyright 2014 jQuery Foundation and other contributors
6 * Released under the MIT license.
7 * http://jquery.org/license
9 * http://api.jqueryui.com/button/
11 (function( factory ) {
12 if ( typeof define === "function" && define.amd ) {
14 // AMD. Register as an anonymous module.
28 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
29 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",
30 formResetHandler = function() {
32 setTimeout(function() {
33 form.find( ":ui-button" ).button( "refresh" );
36 radioGroup = function( radio ) {
37 var name = radio.name,
41 name = name.replace( /'/g, "\\'" );
43 radios = $( form ).find( "[name='" + name + "'][type=radio]" );
45 radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument )
54 $.widget( "ui.button", {
56 defaultElement: "<button>",
67 this.element.closest( "form" )
68 .unbind( "reset" + this.eventNamespace )
69 .bind( "reset" + this.eventNamespace, formResetHandler );
71 if ( typeof this.options.disabled !== "boolean" ) {
72 this.options.disabled = !!this.element.prop( "disabled" );
74 this.element.prop( "disabled", this.options.disabled );
77 this._determineButtonType();
78 this.hasTitle = !!this.buttonElement.attr( "title" );
81 options = this.options,
82 toggleButton = this.type === "checkbox" || this.type === "radio",
83 activeClass = !toggleButton ? "ui-state-active" : "";
85 if ( options.label === null ) {
86 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
89 this._hoverable( this.buttonElement );
92 .addClass( baseClasses )
93 .attr( "role", "button" )
94 .bind( "mouseenter" + this.eventNamespace, function() {
95 if ( options.disabled ) {
98 if ( this === lastActive ) {
99 $( this ).addClass( "ui-state-active" );
102 .bind( "mouseleave" + this.eventNamespace, function() {
103 if ( options.disabled ) {
106 $( this ).removeClass( activeClass );
108 .bind( "click" + this.eventNamespace, function( event ) {
109 if ( options.disabled ) {
110 event.preventDefault();
111 event.stopImmediatePropagation();
115 // Can't use _focusable() because the element that receives focus
116 // and the element that gets the ui-state-focus class are different
119 this.buttonElement.addClass( "ui-state-focus" );
122 this.buttonElement.removeClass( "ui-state-focus" );
126 if ( toggleButton ) {
127 this.element.bind( "change" + this.eventNamespace, function() {
132 if ( this.type === "checkbox" ) {
133 this.buttonElement.bind( "click" + this.eventNamespace, function() {
134 if ( options.disabled ) {
138 } else if ( this.type === "radio" ) {
139 this.buttonElement.bind( "click" + this.eventNamespace, function() {
140 if ( options.disabled ) {
143 $( this ).addClass( "ui-state-active" );
144 that.buttonElement.attr( "aria-pressed", "true" );
146 var radio = that.element[ 0 ];
150 return $( this ).button( "widget" )[ 0 ];
152 .removeClass( "ui-state-active" )
153 .attr( "aria-pressed", "false" );
157 .bind( "mousedown" + this.eventNamespace, function() {
158 if ( options.disabled ) {
161 $( this ).addClass( "ui-state-active" );
163 that.document.one( "mouseup", function() {
167 .bind( "mouseup" + this.eventNamespace, function() {
168 if ( options.disabled ) {
171 $( this ).removeClass( "ui-state-active" );
173 .bind( "keydown" + this.eventNamespace, function(event) {
174 if ( options.disabled ) {
177 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
178 $( this ).addClass( "ui-state-active" );
181 // see #8559, we bind to blur here in case the button element loses
182 // focus between keydown and keyup, it would be left in an "active" state
183 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
184 $( this ).removeClass( "ui-state-active" );
187 if ( this.buttonElement.is("a") ) {
188 this.buttonElement.keyup(function(event) {
189 if ( event.keyCode === $.ui.keyCode.SPACE ) {
190 // TODO pass through original event correctly (just as 2nd argument doesn't work)
197 this._setOption( "disabled", options.disabled );
201 _determineButtonType: function() {
202 var ancestor, labelSelector, checked;
204 if ( this.element.is("[type=checkbox]") ) {
205 this.type = "checkbox";
206 } else if ( this.element.is("[type=radio]") ) {
208 } else if ( this.element.is("input") ) {
211 this.type = "button";
214 if ( this.type === "checkbox" || this.type === "radio" ) {
215 // we don't search against the document in case the element
216 // is disconnected from the DOM
217 ancestor = this.element.parents().last();
218 labelSelector = "label[for='" + this.element.attr("id") + "']";
219 this.buttonElement = ancestor.find( labelSelector );
220 if ( !this.buttonElement.length ) {
221 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
222 this.buttonElement = ancestor.filter( labelSelector );
223 if ( !this.buttonElement.length ) {
224 this.buttonElement = ancestor.find( labelSelector );
227 this.element.addClass( "ui-helper-hidden-accessible" );
229 checked = this.element.is( ":checked" );
231 this.buttonElement.addClass( "ui-state-active" );
233 this.buttonElement.prop( "aria-pressed", checked );
235 this.buttonElement = this.element;
240 return this.buttonElement;
243 _destroy: function() {
245 .removeClass( "ui-helper-hidden-accessible" );
247 .removeClass( baseClasses + " ui-state-active " + typeClasses )
248 .removeAttr( "role" )
249 .removeAttr( "aria-pressed" )
250 .html( this.buttonElement.find(".ui-button-text").html() );
252 if ( !this.hasTitle ) {
253 this.buttonElement.removeAttr( "title" );
257 _setOption: function( key, value ) {
258 this._super( key, value );
259 if ( key === "disabled" ) {
260 this.widget().toggleClass( "ui-state-disabled", !!value );
261 this.element.prop( "disabled", !!value );
263 if ( this.type === "checkbox" || this.type === "radio" ) {
264 this.buttonElement.removeClass( "ui-state-focus" );
266 this.buttonElement.removeClass( "ui-state-focus ui-state-active" );
274 refresh: function() {
276 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
278 if ( isDisabled !== this.options.disabled ) {
279 this._setOption( "disabled", isDisabled );
281 if ( this.type === "radio" ) {
282 radioGroup( this.element[0] ).each(function() {
283 if ( $( this ).is( ":checked" ) ) {
284 $( this ).button( "widget" )
285 .addClass( "ui-state-active" )
286 .attr( "aria-pressed", "true" );
288 $( this ).button( "widget" )
289 .removeClass( "ui-state-active" )
290 .attr( "aria-pressed", "false" );
293 } else if ( this.type === "checkbox" ) {
294 if ( this.element.is( ":checked" ) ) {
296 .addClass( "ui-state-active" )
297 .attr( "aria-pressed", "true" );
300 .removeClass( "ui-state-active" )
301 .attr( "aria-pressed", "false" );
306 _resetButton: function() {
307 if ( this.type === "input" ) {
308 if ( this.options.label ) {
309 this.element.val( this.options.label );
313 var buttonElement = this.buttonElement.removeClass( typeClasses ),
314 buttonText = $( "<span></span>", this.document[0] )
315 .addClass( "ui-button-text" )
316 .html( this.options.label )
317 .appendTo( buttonElement.empty() )
319 icons = this.options.icons,
320 multipleIcons = icons.primary && icons.secondary,
323 if ( icons.primary || icons.secondary ) {
324 if ( this.options.text ) {
325 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
328 if ( icons.primary ) {
329 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
332 if ( icons.secondary ) {
333 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
336 if ( !this.options.text ) {
337 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
339 if ( !this.hasTitle ) {
340 buttonElement.attr( "title", $.trim( buttonText ) );
344 buttonClasses.push( "ui-button-text-only" );
346 buttonElement.addClass( buttonClasses.join( " " ) );
350 $.widget( "ui.buttonset", {
353 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
356 _create: function() {
357 this.element.addClass( "ui-buttonset" );
364 _setOption: function( key, value ) {
365 if ( key === "disabled" ) {
366 this.buttons.button( "option", key, value );
369 this._super( key, value );
372 refresh: function() {
373 var rtl = this.element.css( "direction" ) === "rtl",
374 allButtons = this.element.find( this.options.items ),
375 existingButtons = allButtons.filter( ":ui-button" );
377 // Initialize new buttons
378 allButtons.not( ":ui-button" ).button();
380 // Refresh existing buttons
381 existingButtons.button( "refresh" );
383 this.buttons = allButtons
385 return $( this ).button( "widget" )[ 0 ];
387 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
389 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
392 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
397 _destroy: function() {
398 this.element.removeClass( "ui-buttonset" );
401 return $( this ).button( "widget" )[ 0 ];
403 .removeClass( "ui-corner-left ui-corner-right" )
405 .button( "destroy" );