traversal indention. Follow-up r79924
[lhc/web/wiklou.git] / resources / jquery.ui / jquery.ui.button.js
1 /*
2 * jQuery UI Button 1.8.2
3 *
4 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT (MIT-LICENSE.txt)
6 * and GPL (GPL-LICENSE.txt) licenses.
7 *
8 * http://docs.jquery.com/UI/Button
9 *
10 * Depends:
11 * jquery.ui.core.js
12 * jquery.ui.widget.js
13 */
14 (function( $ ) {
15
16 var lastActive,
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 ui-button-text-only",
20 formResetHandler = function( event ) {
21 $( ":ui-button", event.target.form ).each(function() {
22 var inst = $( this ).data( "button" );
23 setTimeout(function() {
24 inst.refresh();
25 }, 1 );
26 });
27 },
28 radioGroup = function( radio ) {
29 var name = radio.name,
30 form = radio.form,
31 radios = $( [] );
32 if ( name ) {
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 options: {
47 text: true,
48 label: null,
49 icons: {
50 primary: null,
51 secondary: null
52 }
53 },
54 _create: function() {
55 this.element.closest( "form" )
56 .unbind( "reset.button" )
57 .bind( "reset.button", formResetHandler );
58
59 this._determineButtonType();
60 this.hasTitle = !!this.buttonElement.attr( "title" );
61
62 var self = this,
63 options = this.options,
64 toggleButton = this.type === "checkbox" || this.type === "radio",
65 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
66 focusClass = "ui-state-focus";
67
68 if ( options.label === null ) {
69 options.label = this.buttonElement.html();
70 }
71
72 if ( this.element.is( ":disabled" ) ) {
73 options.disabled = true;
74 }
75
76 this.buttonElement
77 .addClass( baseClasses )
78 .attr( "role", "button" )
79 .bind( "mouseenter.button", function() {
80 if ( options.disabled ) {
81 return;
82 }
83 $( this ).addClass( "ui-state-hover" );
84 if ( this === lastActive ) {
85 $( this ).addClass( "ui-state-active" );
86 }
87 })
88 .bind( "mouseleave.button", function() {
89 if ( options.disabled ) {
90 return;
91 }
92 $( this ).removeClass( hoverClass );
93 })
94 .bind( "focus.button", function() {
95 // no need to check disabled, focus won't be triggered anyway
96 $( this ).addClass( focusClass );
97 })
98 .bind( "blur.button", function() {
99 $( this ).removeClass( focusClass );
100 });
101
102 if ( toggleButton ) {
103 this.element.bind( "change.button", function() {
104 self.refresh();
105 });
106 }
107
108 if ( this.type === "checkbox" ) {
109 this.buttonElement.bind( "click.button", function() {
110 if ( options.disabled ) {
111 return false;
112 }
113 $( this ).toggleClass( "ui-state-active" );
114 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
115 });
116 } else if ( this.type === "radio" ) {
117 this.buttonElement.bind( "click.button", function() {
118 if ( options.disabled ) {
119 return false;
120 }
121 $( this ).addClass( "ui-state-active" );
122 self.buttonElement.attr( "aria-pressed", true );
123
124 var radio = self.element[ 0 ];
125 radioGroup( radio )
126 .not( radio )
127 .map(function() {
128 return $( this ).button( "widget" )[ 0 ];
129 })
130 .removeClass( "ui-state-active" )
131 .attr( "aria-pressed", false );
132 });
133 } else {
134 this.buttonElement
135 .bind( "mousedown.button", function() {
136 if ( options.disabled ) {
137 return false;
138 }
139 $( this ).addClass( "ui-state-active" );
140 lastActive = this;
141 $( document ).one( "mouseup", function() {
142 lastActive = null;
143 });
144 })
145 .bind( "mouseup.button", function() {
146 if ( options.disabled ) {
147 return false;
148 }
149 $( this ).removeClass( "ui-state-active" );
150 })
151 .bind( "keydown.button", function(event) {
152 if ( options.disabled ) {
153 return false;
154 }
155 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
156 $( this ).addClass( "ui-state-active" );
157 }
158 })
159 .bind( "keyup.button", function() {
160 $( this ).removeClass( "ui-state-active" );
161 });
162
163 if ( this.buttonElement.is("a") ) {
164 this.buttonElement.keyup(function(event) {
165 if ( event.keyCode === $.ui.keyCode.SPACE ) {
166 // TODO pass through original event correctly (just as 2nd argument doesn't work)
167 $( this ).click();
168 }
169 });
170 }
171 }
172
173 // TODO: pull out $.Widget's handling for the disabled option into
174 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
175 // be overridden by individual plugins
176 this._setOption( "disabled", options.disabled );
177 },
178
179 _determineButtonType: function() {
180
181 if ( this.element.is(":checkbox") ) {
182 this.type = "checkbox";
183 } else {
184 if ( this.element.is(":radio") ) {
185 this.type = "radio";
186 } else {
187 if ( this.element.is("input") ) {
188 this.type = "input";
189 } else {
190 this.type = "button";
191 }
192 }
193 }
194
195 if ( this.type === "checkbox" || this.type === "radio" ) {
196 // we don't search against the document in case the element
197 // is disconnected from the DOM
198 this.buttonElement = this.element.parents().last()
199 .find( "[for=" + this.element.attr("id") + "]" );
200 this.element.addClass( "ui-helper-hidden-accessible" );
201
202 var checked = this.element.is( ":checked" );
203 if ( checked ) {
204 this.buttonElement.addClass( "ui-state-active" );
205 }
206 this.buttonElement.attr( "aria-pressed", checked );
207 } else {
208 this.buttonElement = this.element;
209 }
210 },
211
212 widget: function() {
213 return this.buttonElement;
214 },
215
216 destroy: function() {
217 this.element
218 .removeClass( "ui-helper-hidden-accessible" );
219 this.buttonElement
220 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
221 .removeAttr( "role" )
222 .removeAttr( "aria-pressed" )
223 .html( this.buttonElement.find(".ui-button-text").html() );
224
225 if ( !this.hasTitle ) {
226 this.buttonElement.removeAttr( "title" );
227 }
228
229 $.Widget.prototype.destroy.call( this );
230 },
231
232 _setOption: function( key, value ) {
233 $.Widget.prototype._setOption.apply( this, arguments );
234 if ( key === "disabled" ) {
235 if ( value ) {
236 this.element.attr( "disabled", true );
237 } else {
238 this.element.removeAttr( "disabled" );
239 }
240 }
241 this._resetButton();
242 },
243
244 refresh: function() {
245 var isDisabled = this.element.is( ":disabled" );
246 if ( isDisabled !== this.options.disabled ) {
247 this._setOption( "disabled", isDisabled );
248 }
249 if ( this.type === "radio" ) {
250 radioGroup( this.element[0] ).each(function() {
251 if ( $( this ).is( ":checked" ) ) {
252 $( this ).button( "widget" )
253 .addClass( "ui-state-active" )
254 .attr( "aria-pressed", true );
255 } else {
256 $( this ).button( "widget" )
257 .removeClass( "ui-state-active" )
258 .attr( "aria-pressed", false );
259 }
260 });
261 } else if ( this.type === "checkbox" ) {
262 if ( this.element.is( ":checked" ) ) {
263 this.buttonElement
264 .addClass( "ui-state-active" )
265 .attr( "aria-pressed", true );
266 } else {
267 this.buttonElement
268 .removeClass( "ui-state-active" )
269 .attr( "aria-pressed", false );
270 }
271 }
272 },
273
274 _resetButton: function() {
275 if ( this.type === "input" ) {
276 if ( this.options.label ) {
277 this.element.val( this.options.label );
278 }
279 return;
280 }
281 var buttonElement = this.buttonElement.removeClass( typeClasses ),
282 buttonText = $( "<span></span>" )
283 .addClass( "ui-button-text" )
284 .html( this.options.label )
285 .appendTo( buttonElement.empty() )
286 .text(),
287 icons = this.options.icons,
288 multipleIcons = icons.primary && icons.secondary;
289 if ( icons.primary || icons.secondary ) {
290 buttonElement.addClass( "ui-button-text-icon" +
291 ( multipleIcons ? "s" : "" ) );
292 if ( icons.primary ) {
293 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
294 }
295 if ( icons.secondary ) {
296 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
297 }
298 if ( !this.options.text ) {
299 buttonElement
300 .addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
301 .removeClass( "ui-button-text-icons ui-button-text-icon" );
302 if ( !this.hasTitle ) {
303 buttonElement.attr( "title", buttonText );
304 }
305 }
306 } else {
307 buttonElement.addClass( "ui-button-text-only" );
308 }
309 }
310 });
311
312 $.widget( "ui.buttonset", {
313 _create: function() {
314 this.element.addClass( "ui-buttonset" );
315 this._init();
316 },
317
318 _init: function() {
319 this.refresh();
320 },
321
322 _setOption: function( key, value ) {
323 if ( key === "disabled" ) {
324 this.buttons.button( "option", key, value );
325 }
326
327 $.Widget.prototype._setOption.apply( this, arguments );
328 },
329
330 refresh: function() {
331 this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
332 .filter( ":ui-button" )
333 .button( "refresh" )
334 .end()
335 .not( ":ui-button" )
336 .button()
337 .end()
338 .map(function() {
339 return $( this ).button( "widget" )[ 0 ];
340 })
341 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
342 .filter( ":first" )
343 .addClass( "ui-corner-left" )
344 .end()
345 .filter( ":last" )
346 .addClass( "ui-corner-right" )
347 .end()
348 .end();
349 },
350
351 destroy: function() {
352 this.element.removeClass( "ui-buttonset" );
353 this.buttons
354 .map(function() {
355 return $( this ).button( "widget" )[ 0 ];
356 })
357 .removeClass( "ui-corner-left ui-corner-right" )
358 .end()
359 .button( "destroy" );
360
361 $.Widget.prototype.destroy.call( this );
362 }
363 });
364
365 }( jQuery ) );