57518db3052bf8a4ce407880bc47dc4c26836380
[myslice.git] / third-party / jquery-ui-1.10.2 / ui / jquery.ui.button.js
1 /*!
2  * jQuery UI Button 1.10.2
3  * http://jqueryui.com
4  *
5  * Copyright 2013 jQuery Foundation and other contributors
6  * Released under the MIT license.
7  * http://jquery.org/license
8  *
9  * http://api.jqueryui.com/button/
10  *
11  * Depends:
12  *      jquery.ui.core.js
13  *      jquery.ui.widget.js
14  */
15 (function( $, undefined ) {
16
17 var lastActive, startXPos, startYPos, clickDragged,
18         baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
19         stateClasses = "ui-state-hover ui-state-active ",
20         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",
21         formResetHandler = function() {
22                 var buttons = $( this ).find( ":ui-button" );
23                 setTimeout(function() {
24                         buttons.button( "refresh" );
25                 }, 1 );
26         },
27         radioGroup = function( radio ) {
28                 var name = radio.name,
29                         form = radio.form,
30                         radios = $( [] );
31                 if ( name ) {
32                         name = name.replace( /'/g, "\\'" );
33                         if ( form ) {
34                                 radios = $( form ).find( "[name='" + name + "']" );
35                         } else {
36                                 radios = $( "[name='" + name + "']", radio.ownerDocument )
37                                         .filter(function() {
38                                                 return !this.form;
39                                         });
40                         }
41                 }
42                 return radios;
43         };
44
45 $.widget( "ui.button", {
46         version: "1.10.2",
47         defaultElement: "<button>",
48         options: {
49                 disabled: null,
50                 text: true,
51                 label: null,
52                 icons: {
53                         primary: null,
54                         secondary: null
55                 }
56         },
57         _create: function() {
58                 this.element.closest( "form" )
59                         .unbind( "reset" + this.eventNamespace )
60                         .bind( "reset" + this.eventNamespace, formResetHandler );
61
62                 if ( typeof this.options.disabled !== "boolean" ) {
63                         this.options.disabled = !!this.element.prop( "disabled" );
64                 } else {
65                         this.element.prop( "disabled", this.options.disabled );
66                 }
67
68                 this._determineButtonType();
69                 this.hasTitle = !!this.buttonElement.attr( "title" );
70
71                 var that = this,
72                         options = this.options,
73                         toggleButton = this.type === "checkbox" || this.type === "radio",
74                         activeClass = !toggleButton ? "ui-state-active" : "",
75                         focusClass = "ui-state-focus";
76
77                 if ( options.label === null ) {
78                         options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
79                 }
80
81                 this._hoverable( this.buttonElement );
82
83                 this.buttonElement
84                         .addClass( baseClasses )
85                         .attr( "role", "button" )
86                         .bind( "mouseenter" + this.eventNamespace, function() {
87                                 if ( options.disabled ) {
88                                         return;
89                                 }
90                                 if ( this === lastActive ) {
91                                         $( this ).addClass( "ui-state-active" );
92                                 }
93                         })
94                         .bind( "mouseleave" + this.eventNamespace, function() {
95                                 if ( options.disabled ) {
96                                         return;
97                                 }
98                                 $( this ).removeClass( activeClass );
99                         })
100                         .bind( "click" + this.eventNamespace, function( event ) {
101                                 if ( options.disabled ) {
102                                         event.preventDefault();
103                                         event.stopImmediatePropagation();
104                                 }
105                         });
106
107                 this.element
108                         .bind( "focus" + this.eventNamespace, function() {
109                                 // no need to check disabled, focus won't be triggered anyway
110                                 that.buttonElement.addClass( focusClass );
111                         })
112                         .bind( "blur" + this.eventNamespace, function() {
113                                 that.buttonElement.removeClass( focusClass );
114                         });
115
116                 if ( toggleButton ) {
117                         this.element.bind( "change" + this.eventNamespace, function() {
118                                 if ( clickDragged ) {
119                                         return;
120                                 }
121                                 that.refresh();
122                         });
123                         // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
124                         // prevents issue where button state changes but checkbox/radio checked state
125                         // does not in Firefox (see ticket #6970)
126                         this.buttonElement
127                                 .bind( "mousedown" + this.eventNamespace, function( event ) {
128                                         if ( options.disabled ) {
129                                                 return;
130                                         }
131                                         clickDragged = false;
132                                         startXPos = event.pageX;
133                                         startYPos = event.pageY;
134                                 })
135                                 .bind( "mouseup" + this.eventNamespace, function( event ) {
136                                         if ( options.disabled ) {
137                                                 return;
138                                         }
139                                         if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
140                                                 clickDragged = true;
141                                         }
142                         });
143                 }
144
145                 if ( this.type === "checkbox" ) {
146                         this.buttonElement.bind( "click" + this.eventNamespace, function() {
147                                 if ( options.disabled || clickDragged ) {
148                                         return false;
149                                 }
150                         });
151                 } else if ( this.type === "radio" ) {
152                         this.buttonElement.bind( "click" + this.eventNamespace, function() {
153                                 if ( options.disabled || clickDragged ) {
154                                         return false;
155                                 }
156                                 $( this ).addClass( "ui-state-active" );
157                                 that.buttonElement.attr( "aria-pressed", "true" );
158
159                                 var radio = that.element[ 0 ];
160                                 radioGroup( radio )
161                                         .not( radio )
162                                         .map(function() {
163                                                 return $( this ).button( "widget" )[ 0 ];
164                                         })
165                                         .removeClass( "ui-state-active" )
166                                         .attr( "aria-pressed", "false" );
167                         });
168                 } else {
169                         this.buttonElement
170                                 .bind( "mousedown" + this.eventNamespace, function() {
171                                         if ( options.disabled ) {
172                                                 return false;
173                                         }
174                                         $( this ).addClass( "ui-state-active" );
175                                         lastActive = this;
176                                         that.document.one( "mouseup", function() {
177                                                 lastActive = null;
178                                         });
179                                 })
180                                 .bind( "mouseup" + this.eventNamespace, function() {
181                                         if ( options.disabled ) {
182                                                 return false;
183                                         }
184                                         $( this ).removeClass( "ui-state-active" );
185                                 })
186                                 .bind( "keydown" + this.eventNamespace, function(event) {
187                                         if ( options.disabled ) {
188                                                 return false;
189                                         }
190                                         if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
191                                                 $( this ).addClass( "ui-state-active" );
192                                         }
193                                 })
194                                 // see #8559, we bind to blur here in case the button element loses
195                                 // focus between keydown and keyup, it would be left in an "active" state
196                                 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
197                                         $( this ).removeClass( "ui-state-active" );
198                                 });
199
200                         if ( this.buttonElement.is("a") ) {
201                                 this.buttonElement.keyup(function(event) {
202                                         if ( event.keyCode === $.ui.keyCode.SPACE ) {
203                                                 // TODO pass through original event correctly (just as 2nd argument doesn't work)
204                                                 $( this ).click();
205                                         }
206                                 });
207                         }
208                 }
209
210                 // TODO: pull out $.Widget's handling for the disabled option into
211                 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
212                 // be overridden by individual plugins
213                 this._setOption( "disabled", options.disabled );
214                 this._resetButton();
215         },
216
217         _determineButtonType: function() {
218                 var ancestor, labelSelector, checked;
219
220                 if ( this.element.is("[type=checkbox]") ) {
221                         this.type = "checkbox";
222                 } else if ( this.element.is("[type=radio]") ) {
223                         this.type = "radio";
224                 } else if ( this.element.is("input") ) {
225                         this.type = "input";
226                 } else {
227                         this.type = "button";
228                 }
229
230                 if ( this.type === "checkbox" || this.type === "radio" ) {
231                         // we don't search against the document in case the element
232                         // is disconnected from the DOM
233                         ancestor = this.element.parents().last();
234                         labelSelector = "label[for='" + this.element.attr("id") + "']";
235                         this.buttonElement = ancestor.find( labelSelector );
236                         if ( !this.buttonElement.length ) {
237                                 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
238                                 this.buttonElement = ancestor.filter( labelSelector );
239                                 if ( !this.buttonElement.length ) {
240                                         this.buttonElement = ancestor.find( labelSelector );
241                                 }
242                         }
243                         this.element.addClass( "ui-helper-hidden-accessible" );
244
245                         checked = this.element.is( ":checked" );
246                         if ( checked ) {
247                                 this.buttonElement.addClass( "ui-state-active" );
248                         }
249                         this.buttonElement.prop( "aria-pressed", checked );
250                 } else {
251                         this.buttonElement = this.element;
252                 }
253         },
254
255         widget: function() {
256                 return this.buttonElement;
257         },
258
259         _destroy: function() {
260                 this.element
261                         .removeClass( "ui-helper-hidden-accessible" );
262                 this.buttonElement
263                         .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
264                         .removeAttr( "role" )
265                         .removeAttr( "aria-pressed" )
266                         .html( this.buttonElement.find(".ui-button-text").html() );
267
268                 if ( !this.hasTitle ) {
269                         this.buttonElement.removeAttr( "title" );
270                 }
271         },
272
273         _setOption: function( key, value ) {
274                 this._super( key, value );
275                 if ( key === "disabled" ) {
276                         if ( value ) {
277                                 this.element.prop( "disabled", true );
278                         } else {
279                                 this.element.prop( "disabled", false );
280                         }
281                         return;
282                 }
283                 this._resetButton();
284         },
285
286         refresh: function() {
287                 //See #8237 & #8828
288                 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
289
290                 if ( isDisabled !== this.options.disabled ) {
291                         this._setOption( "disabled", isDisabled );
292                 }
293                 if ( this.type === "radio" ) {
294                         radioGroup( this.element[0] ).each(function() {
295                                 if ( $( this ).is( ":checked" ) ) {
296                                         $( this ).button( "widget" )
297                                                 .addClass( "ui-state-active" )
298                                                 .attr( "aria-pressed", "true" );
299                                 } else {
300                                         $( this ).button( "widget" )
301                                                 .removeClass( "ui-state-active" )
302                                                 .attr( "aria-pressed", "false" );
303                                 }
304                         });
305                 } else if ( this.type === "checkbox" ) {
306                         if ( this.element.is( ":checked" ) ) {
307                                 this.buttonElement
308                                         .addClass( "ui-state-active" )
309                                         .attr( "aria-pressed", "true" );
310                         } else {
311                                 this.buttonElement
312                                         .removeClass( "ui-state-active" )
313                                         .attr( "aria-pressed", "false" );
314                         }
315                 }
316         },
317
318         _resetButton: function() {
319                 if ( this.type === "input" ) {
320                         if ( this.options.label ) {
321                                 this.element.val( this.options.label );
322                         }
323                         return;
324                 }
325                 var buttonElement = this.buttonElement.removeClass( typeClasses ),
326                         buttonText = $( "<span></span>", this.document[0] )
327                                 .addClass( "ui-button-text" )
328                                 .html( this.options.label )
329                                 .appendTo( buttonElement.empty() )
330                                 .text(),
331                         icons = this.options.icons,
332                         multipleIcons = icons.primary && icons.secondary,
333                         buttonClasses = [];
334
335                 if ( icons.primary || icons.secondary ) {
336                         if ( this.options.text ) {
337                                 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
338                         }
339
340                         if ( icons.primary ) {
341                                 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
342                         }
343
344                         if ( icons.secondary ) {
345                                 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
346                         }
347
348                         if ( !this.options.text ) {
349                                 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
350
351                                 if ( !this.hasTitle ) {
352                                         buttonElement.attr( "title", $.trim( buttonText ) );
353                                 }
354                         }
355                 } else {
356                         buttonClasses.push( "ui-button-text-only" );
357                 }
358                 buttonElement.addClass( buttonClasses.join( " " ) );
359         }
360 });
361
362 $.widget( "ui.buttonset", {
363         version: "1.10.2",
364         options: {
365                 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
366         },
367
368         _create: function() {
369                 this.element.addClass( "ui-buttonset" );
370         },
371
372         _init: function() {
373                 this.refresh();
374         },
375
376         _setOption: function( key, value ) {
377                 if ( key === "disabled" ) {
378                         this.buttons.button( "option", key, value );
379                 }
380
381                 this._super( key, value );
382         },
383
384         refresh: function() {
385                 var rtl = this.element.css( "direction" ) === "rtl";
386
387                 this.buttons = this.element.find( this.options.items )
388                         .filter( ":ui-button" )
389                                 .button( "refresh" )
390                         .end()
391                         .not( ":ui-button" )
392                                 .button()
393                         .end()
394                         .map(function() {
395                                 return $( this ).button( "widget" )[ 0 ];
396                         })
397                                 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
398                                 .filter( ":first" )
399                                         .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
400                                 .end()
401                                 .filter( ":last" )
402                                         .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
403                                 .end()
404                         .end();
405         },
406
407         _destroy: function() {
408                 this.element.removeClass( "ui-buttonset" );
409                 this.buttons
410                         .map(function() {
411                                 return $( this ).button( "widget" )[ 0 ];
412                         })
413                                 .removeClass( "ui-corner-left ui-corner-right" )
414                         .end()
415                         .button( "destroy" );
416         }
417 });
418
419 }( jQuery ) );