Projet

Général

Profil

Révision 503b3f7b

Ajouté par Assos Assos il y a environ 10 ans

Weekly update of contrib modules

Voir les différences:

drupal7/sites/all/modules/jquery_update/replace/ui/ui/jquery.ui.accordion.js
1
/*
2
 * jQuery UI Accordion 1.8.11
1
/*!
2
 * jQuery UI Accordion 1.10.2
3
 * http://jqueryui.com
3 4
 *
4
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5
 * Dual licensed under the MIT or GPL Version 2 licenses.
5
 * Copyright 2013 jQuery Foundation and other contributors
6
 * Released under the MIT license.
6 7
 * http://jquery.org/license
7 8
 *
8
 * http://docs.jquery.com/UI/Accordion
9
 * http://api.jqueryui.com/accordion/
9 10
 *
10 11
 * Depends:
11 12
 *	jquery.ui.core.js
......
13 14
 */
14 15
(function( $, undefined ) {
15 16

  
17
var uid = 0,
18
	hideProps = {},
19
	showProps = {};
20

  
21
hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
22
	hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
23
showProps.height = showProps.paddingTop = showProps.paddingBottom =
24
	showProps.borderTopWidth = showProps.borderBottomWidth = "show";
25

  
16 26
$.widget( "ui.accordion", {
27
	version: "1.10.2",
17 28
	options: {
18 29
		active: 0,
19
		animated: "slide",
20
		autoHeight: true,
21
		clearStyle: false,
30
		animate: {},
22 31
		collapsible: false,
23 32
		event: "click",
24
		fillSpace: false,
25 33
		header: "> li > :first-child,> :not(li):even",
34
		heightStyle: "auto",
26 35
		icons: {
27
			header: "ui-icon-triangle-1-e",
28
			headerSelected: "ui-icon-triangle-1-s"
36
			activeHeader: "ui-icon-triangle-1-s",
37
			header: "ui-icon-triangle-1-e"
29 38
		},
30
		navigation: false,
31
		navigationFilter: function() {
32
			return this.href.toLowerCase() === location.href.toLowerCase();
33
		}
39

  
40
		// callbacks
41
		activate: null,
42
		beforeActivate: null
34 43
	},
35 44

  
36 45
	_create: function() {
37
		var self = this,
38
			options = self.options;
39

  
40
		self.running = 0;
41

  
42
		self.element
43
			.addClass( "ui-accordion ui-widget ui-helper-reset" )
44
			// in lack of child-selectors in CSS
45
			// we need to mark top-LIs in a UL-accordion for some IE-fix
46
			.children( "li" )
47
				.addClass( "ui-accordion-li-fix" );
48

  
49
		self.headers = self.element.find( options.header )
50
			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
51
			.bind( "mouseenter.accordion", function() {
52
				if ( options.disabled ) {
53
					return;
54
				}
55
				$( this ).addClass( "ui-state-hover" );
56
			})
57
			.bind( "mouseleave.accordion", function() {
58
				if ( options.disabled ) {
59
					return;
60
				}
61
				$( this ).removeClass( "ui-state-hover" );
62
			})
63
			.bind( "focus.accordion", function() {
64
				if ( options.disabled ) {
65
					return;
66
				}
67
				$( this ).addClass( "ui-state-focus" );
68
			})
69
			.bind( "blur.accordion", function() {
70
				if ( options.disabled ) {
71
					return;
72
				}
73
				$( this ).removeClass( "ui-state-focus" );
74
			});
75

  
76
		self.headers.next()
77
			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
78

  
79
		if ( options.navigation ) {
80
			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
81
			if ( current.length ) {
82
				var header = current.closest( ".ui-accordion-header" );
83
				if ( header.length ) {
84
					// anchor within header
85
					self.active = header;
86
				} else {
87
					// anchor within content
88
					self.active = current.closest( ".ui-accordion-content" ).prev();
89
				}
90
			}
91
		}
92

  
93
		self.active = self._findActive( self.active || options.active )
94
			.addClass( "ui-state-default ui-state-active" )
95
			.toggleClass( "ui-corner-all" )
96
			.toggleClass( "ui-corner-top" );
97
		self.active.next().addClass( "ui-accordion-content-active" );
98

  
99
		self._createIcons();
100
		self.resize();
101
		
102
		// ARIA
103
		self.element.attr( "role", "tablist" );
104

  
105
		self.headers
106
			.attr( "role", "tab" )
107
			.bind( "keydown.accordion", function( event ) {
108
				return self._keydown( event );
109
			})
110
			.next()
111
				.attr( "role", "tabpanel" );
112

  
113
		self.headers
114
			.not( self.active || "" )
115
			.attr({
116
				"aria-expanded": "false",
117
				"aria-selected": "false",
118
				tabIndex: -1
119
			})
120
			.next()
121
				.hide();
122

  
123
		// make sure at least one header is in the tab order
124
		if ( !self.active.length ) {
125
			self.headers.eq( 0 ).attr( "tabIndex", 0 );
126
		} else {
127
			self.active
128
				.attr({
129
					"aria-expanded": "true",
130
					"aria-selected": "true",
131
					tabIndex: 0
132
				});
46
		var options = this.options;
47
		this.prevShow = this.prevHide = $();
48
		this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
49
			// ARIA
50
			.attr( "role", "tablist" );
51

  
52
		// don't allow collapsible: false and active: false / null
53
		if ( !options.collapsible && (options.active === false || options.active == null) ) {
54
			options.active = 0;
133 55
		}
134 56

  
135
		// only need links in tab order for Safari
136
		if ( !$.browser.safari ) {
137
			self.headers.find( "a" ).attr( "tabIndex", -1 );
57
		this._processPanels();
58
		// handle negative values
59
		if ( options.active < 0 ) {
60
			options.active += this.headers.length;
138 61
		}
62
		this._refresh();
63
	},
139 64

  
140
		if ( options.event ) {
141
			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
142
				self._clickHandler.call( self, event, this );
143
				event.preventDefault();
144
			});
145
		}
65
	_getCreateEventData: function() {
66
		return {
67
			header: this.active,
68
			panel: !this.active.length ? $() : this.active.next(),
69
			content: !this.active.length ? $() : this.active.next()
70
		};
146 71
	},
147 72

  
148 73
	_createIcons: function() {
149
		var options = this.options;
150
		if ( options.icons ) {
151
			$( "<span></span>" )
152
				.addClass( "ui-icon " + options.icons.header )
74
		var icons = this.options.icons;
75
		if ( icons ) {
76
			$( "<span>" )
77
				.addClass( "ui-accordion-header-icon ui-icon " + icons.header )
153 78
				.prependTo( this.headers );
154
			this.active.children( ".ui-icon" )
155
				.toggleClass(options.icons.header)
156
				.toggleClass(options.icons.headerSelected);
157
			this.element.addClass( "ui-accordion-icons" );
79
			this.active.children( ".ui-accordion-header-icon" )
80
				.removeClass( icons.header )
81
				.addClass( icons.activeHeader );
82
			this.headers.addClass( "ui-accordion-icons" );
158 83
		}
159 84
	},
160 85

  
161 86
	_destroyIcons: function() {
162
		this.headers.children( ".ui-icon" ).remove();
163
		this.element.removeClass( "ui-accordion-icons" );
87
		this.headers
88
			.removeClass( "ui-accordion-icons" )
89
			.children( ".ui-accordion-header-icon" )
90
				.remove();
164 91
	},
165 92

  
166
	destroy: function() {
167
		var options = this.options;
93
	_destroy: function() {
94
		var contents;
168 95

  
96
		// clean up main element
169 97
		this.element
170 98
			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
171 99
			.removeAttr( "role" );
172 100

  
101
		// clean up headers
173 102
		this.headers
174
			.unbind( ".accordion" )
175
			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
103
			.removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
176 104
			.removeAttr( "role" )
177
			.removeAttr( "aria-expanded" )
178 105
			.removeAttr( "aria-selected" )
179
			.removeAttr( "tabIndex" );
180

  
181
		this.headers.find( "a" ).removeAttr( "tabIndex" );
106
			.removeAttr( "aria-controls" )
107
			.removeAttr( "tabIndex" )
108
			.each(function() {
109
				if ( /^ui-accordion/.test( this.id ) ) {
110
					this.removeAttribute( "id" );
111
				}
112
			});
182 113
		this._destroyIcons();
183
		var contents = this.headers.next()
114

  
115
		// clean up content panels
116
		contents = this.headers.next()
184 117
			.css( "display", "" )
185 118
			.removeAttr( "role" )
186
			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
187
		if ( options.autoHeight || options.fillHeight ) {
119
			.removeAttr( "aria-expanded" )
120
			.removeAttr( "aria-hidden" )
121
			.removeAttr( "aria-labelledby" )
122
			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
123
			.each(function() {
124
				if ( /^ui-accordion/.test( this.id ) ) {
125
					this.removeAttribute( "id" );
126
				}
127
			});
128
		if ( this.options.heightStyle !== "content" ) {
188 129
			contents.css( "height", "" );
189 130
		}
190

  
191
		return $.Widget.prototype.destroy.call( this );
192 131
	},
193 132

  
194 133
	_setOption: function( key, value ) {
195
		$.Widget.prototype._setOption.apply( this, arguments );
196
			
197
		if ( key == "active" ) {
198
			this.activate( value );
134
		if ( key === "active" ) {
135
			// _activate() will handle invalid values and update this.options
136
			this._activate( value );
137
			return;
199 138
		}
200
		if ( key == "icons" ) {
139

  
140
		if ( key === "event" ) {
141
			if ( this.options.event ) {
142
				this._off( this.headers, this.options.event );
143
			}
144
			this._setupEvents( value );
145
		}
146

  
147
		this._super( key, value );
148

  
149
		// setting collapsible: false while collapsed; open first panel
150
		if ( key === "collapsible" && !value && this.options.active === false ) {
151
			this._activate( 0 );
152
		}
153

  
154
		if ( key === "icons" ) {
201 155
			this._destroyIcons();
202 156
			if ( value ) {
203 157
				this._createIcons();
204 158
			}
205 159
		}
160

  
206 161
		// #5332 - opacity doesn't cascade to positioned elements in IE
207 162
		// so we need to add the disabled class to the headers and panels
208
		if ( key == "disabled" ) {
209
			this.headers.add(this.headers.next())
210
				[ value ? "addClass" : "removeClass" ](
211
					"ui-accordion-disabled ui-state-disabled" );
163
		if ( key === "disabled" ) {
164
			this.headers.add( this.headers.next() )
165
				.toggleClass( "ui-state-disabled", !!value );
212 166
		}
213 167
	},
214 168

  
215 169
	_keydown: function( event ) {
216
		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
170
		/*jshint maxcomplexity:15*/
171
		if ( event.altKey || event.ctrlKey ) {
217 172
			return;
218 173
		}
219 174

  
......
233 188
				break;
234 189
			case keyCode.SPACE:
235 190
			case keyCode.ENTER:
236
				this._clickHandler( { target: event.target }, event.target );
237
				event.preventDefault();
191
				this._eventHandler( event );
192
				break;
193
			case keyCode.HOME:
194
				toFocus = this.headers[ 0 ];
195
				break;
196
			case keyCode.END:
197
				toFocus = this.headers[ length - 1 ];
198
				break;
238 199
		}
239 200

  
240 201
		if ( toFocus ) {
241 202
			$( event.target ).attr( "tabIndex", -1 );
242 203
			$( toFocus ).attr( "tabIndex", 0 );
243 204
			toFocus.focus();
244
			return false;
205
			event.preventDefault();
245 206
		}
246

  
247
		return true;
248 207
	},
249 208

  
250
	resize: function() {
251
		var options = this.options,
252
			maxHeight;
209
	_panelKeyDown : function( event ) {
210
		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
211
			$( event.currentTarget ).prev().focus();
212
		}
213
	},
253 214

  
254
		if ( options.fillSpace ) {
255
			if ( $.browser.msie ) {
256
				var defOverflow = this.element.parent().css( "overflow" );
257
				this.element.parent().css( "overflow", "hidden");
258
			}
259
			maxHeight = this.element.parent().height();
260
			if ($.browser.msie) {
261
				this.element.parent().css( "overflow", defOverflow );
215
	refresh: function() {
216
		var options = this.options;
217
		this._processPanels();
218

  
219
		// was collapsed or no panel
220
		if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
221
			options.active = false;
222
			this.active = $();
223
		// active false only when collapsible is true
224
		} if ( options.active === false ) {
225
			this._activate( 0 );
226
		// was active, but active panel is gone
227
		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
228
			// all remaining panel are disabled
229
			if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
230
				options.active = false;
231
				this.active = $();
232
			// activate previous panel
233
			} else {
234
				this._activate( Math.max( 0, options.active - 1 ) );
262 235
			}
236
		// was active, active panel still exists
237
		} else {
238
			// make sure active index is correct
239
			options.active = this.headers.index( this.active );
240
		}
241

  
242
		this._destroyIcons();
243

  
244
		this._refresh();
245
	},
246

  
247
	_processPanels: function() {
248
		this.headers = this.element.find( this.options.header )
249
			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
250

  
251
		this.headers.next()
252
			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
253
			.filter(":not(.ui-accordion-content-active)")
254
			.hide();
255
	},
256

  
257
	_refresh: function() {
258
		var maxHeight,
259
			options = this.options,
260
			heightStyle = options.heightStyle,
261
			parent = this.element.parent(),
262
			accordionId = this.accordionId = "ui-accordion-" +
263
				(this.element.attr( "id" ) || ++uid);
264

  
265
		this.active = this._findActive( options.active )
266
			.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
267
			.removeClass( "ui-corner-all" );
268
		this.active.next()
269
			.addClass( "ui-accordion-content-active" )
270
			.show();
271

  
272
		this.headers
273
			.attr( "role", "tab" )
274
			.each(function( i ) {
275
				var header = $( this ),
276
					headerId = header.attr( "id" ),
277
					panel = header.next(),
278
					panelId = panel.attr( "id" );
279
				if ( !headerId ) {
280
					headerId = accordionId + "-header-" + i;
281
					header.attr( "id", headerId );
282
				}
283
				if ( !panelId ) {
284
					panelId = accordionId + "-panel-" + i;
285
					panel.attr( "id", panelId );
286
				}
287
				header.attr( "aria-controls", panelId );
288
				panel.attr( "aria-labelledby", headerId );
289
			})
290
			.next()
291
				.attr( "role", "tabpanel" );
292

  
293
		this.headers
294
			.not( this.active )
295
			.attr({
296
				"aria-selected": "false",
297
				tabIndex: -1
298
			})
299
			.next()
300
				.attr({
301
					"aria-expanded": "false",
302
					"aria-hidden": "true"
303
				})
304
				.hide();
305

  
306
		// make sure at least one header is in the tab order
307
		if ( !this.active.length ) {
308
			this.headers.eq( 0 ).attr( "tabIndex", 0 );
309
		} else {
310
			this.active.attr({
311
				"aria-selected": "true",
312
				tabIndex: 0
313
			})
314
			.next()
315
				.attr({
316
					"aria-expanded": "true",
317
					"aria-hidden": "false"
318
				});
319
		}
320

  
321
		this._createIcons();
322

  
323
		this._setupEvents( options.event );
324

  
325
		if ( heightStyle === "fill" ) {
326
			maxHeight = parent.height();
327
			this.element.siblings( ":visible" ).each(function() {
328
				var elem = $( this ),
329
					position = elem.css( "position" );
330

  
331
				if ( position === "absolute" || position === "fixed" ) {
332
					return;
333
				}
334
				maxHeight -= elem.outerHeight( true );
335
			});
263 336

  
264 337
			this.headers.each(function() {
265 338
				maxHeight -= $( this ).outerHeight( true );
......
271 344
						$( this ).innerHeight() + $( this ).height() ) );
272 345
				})
273 346
				.css( "overflow", "auto" );
274
		} else if ( options.autoHeight ) {
347
		} else if ( heightStyle === "auto" ) {
275 348
			maxHeight = 0;
276 349
			this.headers.next()
277 350
				.each(function() {
278
					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
351
					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
279 352
				})
280 353
				.height( maxHeight );
281 354
		}
282

  
283
		return this;
284 355
	},
285 356

  
286
	activate: function( index ) {
287
		// TODO this gets called on init, changing the option without an explicit call for that
288
		this.options.active = index;
289
		// call clickHandler with custom event
357
	_activate: function( index ) {
290 358
		var active = this._findActive( index )[ 0 ];
291
		this._clickHandler( { target: active }, active );
292 359

  
293
		return this;
360
		// trying to activate the already active panel
361
		if ( active === this.active[ 0 ] ) {
362
			return;
363
		}
364

  
365
		// trying to collapse, simulate a click on the currently active header
366
		active = active || this.active[ 0 ];
367

  
368
		this._eventHandler({
369
			target: active,
370
			currentTarget: active,
371
			preventDefault: $.noop
372
		});
294 373
	},
295 374

  
296 375
	_findActive: function( selector ) {
297
		return selector
298
			? typeof selector === "number"
299
				? this.headers.filter( ":eq(" + selector + ")" )
300
				: this.headers.not( this.headers.not( selector ) )
301
			: selector === false
302
				? $( [] )
303
				: this.headers.filter( ":eq(0)" );
376
		return typeof selector === "number" ? this.headers.eq( selector ) : $();
304 377
	},
305 378

  
306
	// TODO isn't event.target enough? why the separate target argument?
307
	_clickHandler: function( event, target ) {
308
		var options = this.options;
309
		if ( options.disabled ) {
310
			return;
311
		}
312

  
313
		// called only when using activate(false) to close all parts programmatically
314
		if ( !event.target ) {
315
			if ( !options.collapsible ) {
316
				return;
317
			}
318
			this.active
319
				.removeClass( "ui-state-active ui-corner-top" )
320
				.addClass( "ui-state-default ui-corner-all" )
321
				.children( ".ui-icon" )
322
					.removeClass( options.icons.headerSelected )
323
					.addClass( options.icons.header );
324
			this.active.next().addClass( "ui-accordion-content-active" );
325
			var toHide = this.active.next(),
326
				data = {
327
					options: options,
328
					newHeader: $( [] ),
329
					oldHeader: options.active,
330
					newContent: $( [] ),
331
					oldContent: toHide
332
				},
333
				toShow = ( this.active = $( [] ) );
334
			this._toggle( toShow, toHide, data );
335
			return;
379
	_setupEvents: function( event ) {
380
		var events = {
381
			keydown: "_keydown"
382
		};
383
		if ( event ) {
384
			$.each( event.split(" "), function( index, eventName ) {
385
				events[ eventName ] = "_eventHandler";
386
			});
336 387
		}
337 388

  
338
		// get the click target
339
		var clicked = $( event.currentTarget || target ),
340
			clickedIsActive = clicked[0] === this.active[0];
341

  
342
		// TODO the option is changed, is that correct?
343
		// TODO if it is correct, shouldn't that happen after determining that the click is valid?
344
		options.active = options.collapsible && clickedIsActive ?
345
			false :
346
			this.headers.index( clicked );
389
		this._off( this.headers.add( this.headers.next() ) );
390
		this._on( this.headers, events );
391
		this._on( this.headers.next(), { keydown: "_panelKeyDown" });
392
		this._hoverable( this.headers );
393
		this._focusable( this.headers );
394
	},
347 395

  
348
		// if animations are still active, or the active header is the target, ignore click
349
		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
396
	_eventHandler: function( event ) {
397
		var options = this.options,
398
			active = this.active,
399
			clicked = $( event.currentTarget ),
400
			clickedIsActive = clicked[ 0 ] === active[ 0 ],
401
			collapsing = clickedIsActive && options.collapsible,
402
			toShow = collapsing ? $() : clicked.next(),
403
			toHide = active.next(),
404
			eventData = {
405
				oldHeader: active,
406
				oldPanel: toHide,
407
				newHeader: collapsing ? $() : clicked,
408
				newPanel: toShow
409
			};
410

  
411
		event.preventDefault();
412

  
413
		if (
414
				// click on active header, but not collapsible
415
				( clickedIsActive && !options.collapsible ) ||
416
				// allow canceling activation
417
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
350 418
			return;
351 419
		}
352 420

  
353
		// find elements to show and hide
354
		var active = this.active,
355
			toShow = clicked.next(),
356
			toHide = this.active.next(),
357
			data = {
358
				options: options,
359
				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
360
				oldHeader: this.active,
361
				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
362
				oldContent: toHide
363
			},
364
			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
421
		options.active = collapsing ? false : this.headers.index( clicked );
365 422

  
366 423
		// when the call to ._toggle() comes after the class changes
367 424
		// it causes a very odd bug in IE 8 (see #6720)
368
		this.active = clickedIsActive ? $([]) : clicked;
369
		this._toggle( toShow, toHide, data, clickedIsActive, down );
425
		this.active = clickedIsActive ? $() : clicked;
426
		this._toggle( eventData );
370 427

  
371 428
		// switch classes
372
		active
373
			.removeClass( "ui-state-active ui-corner-top" )
374
			.addClass( "ui-state-default ui-corner-all" )
375
			.children( ".ui-icon" )
376
				.removeClass( options.icons.headerSelected )
429
		// corner classes on the previously active header stay after the animation
430
		active.removeClass( "ui-accordion-header-active ui-state-active" );
431
		if ( options.icons ) {
432
			active.children( ".ui-accordion-header-icon" )
433
				.removeClass( options.icons.activeHeader )
377 434
				.addClass( options.icons.header );
435
		}
436

  
378 437
		if ( !clickedIsActive ) {
379 438
			clicked
380
				.removeClass( "ui-state-default ui-corner-all" )
381
				.addClass( "ui-state-active ui-corner-top" )
382
				.children( ".ui-icon" )
439
				.removeClass( "ui-corner-all" )
440
				.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
441
			if ( options.icons ) {
442
				clicked.children( ".ui-accordion-header-icon" )
383 443
					.removeClass( options.icons.header )
384
					.addClass( options.icons.headerSelected );
444
					.addClass( options.icons.activeHeader );
445
			}
446

  
385 447
			clicked
386 448
				.next()
387 449
				.addClass( "ui-accordion-content-active" );
388 450
		}
389

  
390
		return;
391 451
	},
392 452

  
393
	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {
394
		var self = this,
395
			options = self.options;
396

  
397
		self.toShow = toShow;
398
		self.toHide = toHide;
399
		self.data = data;
400

  
401
		var complete = function() {
402
			if ( !self ) {
403
				return;
404
			}
405
			return self._completed.apply( self, arguments );
406
		};
407

  
408
		// trigger changestart event
409
		self._trigger( "changestart", null, self.data );
410

  
411
		// count elements to animate
412
		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
413

  
414
		if ( options.animated ) {
415
			var animOptions = {};
416

  
417
			if ( options.collapsible && clickedIsActive ) {
418
				animOptions = {
419
					toShow: $( [] ),
420
					toHide: toHide,
421
					complete: complete,
422
					down: down,
423
					autoHeight: options.autoHeight || options.fillSpace
424
				};
425
			} else {
426
				animOptions = {
427
					toShow: toShow,
428
					toHide: toHide,
429
					complete: complete,
430
					down: down,
431
					autoHeight: options.autoHeight || options.fillSpace
432
				};
433
			}
434

  
435
			if ( !options.proxied ) {
436
				options.proxied = options.animated;
437
			}
438

  
439
			if ( !options.proxiedDuration ) {
440
				options.proxiedDuration = options.duration;
441
			}
442

  
443
			options.animated = $.isFunction( options.proxied ) ?
444
				options.proxied( animOptions ) :
445
				options.proxied;
446

  
447
			options.duration = $.isFunction( options.proxiedDuration ) ?
448
				options.proxiedDuration( animOptions ) :
449
				options.proxiedDuration;
453
	_toggle: function( data ) {
454
		var toShow = data.newPanel,
455
			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
450 456

  
451
			var animations = $.ui.accordion.animations,
452
				duration = options.duration,
453
				easing = options.animated;
457
		// handle activating a panel during the animation for another activation
458
		this.prevShow.add( this.prevHide ).stop( true, true );
459
		this.prevShow = toShow;
460
		this.prevHide = toHide;
454 461

  
455
			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
456
				easing = "slide";
457
			}
458
			if ( !animations[ easing ] ) {
459
				animations[ easing ] = function( options ) {
460
					this.slide( options, {
461
						easing: easing,
462
						duration: duration || 700
463
					});
464
				};
465
			}
466

  
467
			animations[ easing ]( animOptions );
462
		if ( this.options.animate ) {
463
			this._animate( toShow, toHide, data );
468 464
		} else {
469
			if ( options.collapsible && clickedIsActive ) {
470
				toShow.toggle();
471
			} else {
472
				toHide.hide();
473
				toShow.show();
474
			}
475

  
476
			complete( true );
465
			toHide.hide();
466
			toShow.show();
467
			this._toggleComplete( data );
477 468
		}
478 469

  
479
		// TODO assert that the blur and focus triggers are really necessary, remove otherwise
480
		toHide.prev()
481
			.attr({
482
				"aria-expanded": "false",
483
				"aria-selected": "false",
484
				tabIndex: -1
470
		toHide.attr({
471
			"aria-expanded": "false",
472
			"aria-hidden": "true"
473
		});
474
		toHide.prev().attr( "aria-selected", "false" );
475
		// if we're switching panels, remove the old header from the tab order
476
		// if we're opening from collapsed state, remove the previous header from the tab order
477
		// if we're collapsing, then keep the collapsing header in the tab order
478
		if ( toShow.length && toHide.length ) {
479
			toHide.prev().attr( "tabIndex", -1 );
480
		} else if ( toShow.length ) {
481
			this.headers.filter(function() {
482
				return $( this ).attr( "tabIndex" ) === 0;
485 483
			})
486
			.blur();
487
		toShow.prev()
484
			.attr( "tabIndex", -1 );
485
		}
486

  
487
		toShow
488 488
			.attr({
489 489
				"aria-expanded": "true",
490
				"aria-selected": "true",
491
				tabIndex: 0
490
				"aria-hidden": "false"
492 491
			})
493
			.focus();
492
			.prev()
493
				.attr({
494
					"aria-selected": "true",
495
					tabIndex: 0
496
				});
494 497
	},
495 498

  
496
	_completed: function( cancel ) {
497
		this.running = cancel ? 0 : --this.running;
498
		if ( this.running ) {
499
			return;
499
	_animate: function( toShow, toHide, data ) {
500
		var total, easing, duration,
501
			that = this,
502
			adjust = 0,
503
			down = toShow.length &&
504
				( !toHide.length || ( toShow.index() < toHide.index() ) ),
505
			animate = this.options.animate || {},
506
			options = down && animate.down || animate,
507
			complete = function() {
508
				that._toggleComplete( data );
509
			};
510

  
511
		if ( typeof options === "number" ) {
512
			duration = options;
500 513
		}
501

  
502
		if ( this.options.clearStyle ) {
503
			this.toShow.add( this.toHide ).css({
504
				height: "",
505
				overflow: ""
506
			});
514
		if ( typeof options === "string" ) {
515
			easing = options;
507 516
		}
517
		// fall back from options to animation in case of partial down settings
518
		easing = easing || options.easing || animate.easing;
519
		duration = duration || options.duration || animate.duration;
508 520

  
509
		// other classes are removed before the animation; this one needs to stay until completed
510
		this.toHide.removeClass( "ui-accordion-content-active" );
511
		// Work around for rendering bug in IE (#5421)
512
		if ( this.toHide.length ) {
513
			this.toHide.parent()[0].className = this.toHide.parent()[0].className;
521
		if ( !toHide.length ) {
522
			return toShow.animate( showProps, duration, easing, complete );
523
		}
524
		if ( !toShow.length ) {
525
			return toHide.animate( hideProps, duration, easing, complete );
514 526
		}
515 527

  
516
		this._trigger( "change", null, this.data );
517
	}
518
});
519

  
520
$.extend( $.ui.accordion, {
521
	version: "1.8.11",
522
	animations: {
523
		slide: function( options, additions ) {
524
			options = $.extend({
525
				easing: "swing",
526
				duration: 300
527
			}, options, additions );
528
			if ( !options.toHide.size() ) {
529
				options.toShow.animate({
530
					height: "show",
531
					paddingTop: "show",
532
					paddingBottom: "show"
533
				}, options );
534
				return;
528
		total = toShow.show().outerHeight();
529
		toHide.animate( hideProps, {
530
			duration: duration,
531
			easing: easing,
532
			step: function( now, fx ) {
533
				fx.now = Math.round( now );
535 534
			}
536
			if ( !options.toShow.size() ) {
537
				options.toHide.animate({
538
					height: "hide",
539
					paddingTop: "hide",
540
					paddingBottom: "hide"
541
				}, options );
542
				return;
543
			}
544
			var overflow = options.toShow.css( "overflow" ),
545
				percentDone = 0,
546
				showProps = {},
547
				hideProps = {},
548
				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
549
				originalWidth;
550
			// fix width before calculating height of hidden element
551
			var s = options.toShow;
552
			originalWidth = s[0].style.width;
553
			s.width( parseInt( s.parent().width(), 10 )
554
				- parseInt( s.css( "paddingLeft" ), 10 )
555
				- parseInt( s.css( "paddingRight" ), 10 )
556
				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
557
				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
558

  
559
			$.each( fxAttrs, function( i, prop ) {
560
				hideProps[ prop ] = "hide";
561

  
562
				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
563
				showProps[ prop ] = {
564
					value: parts[ 1 ],
565
					unit: parts[ 2 ] || "px"
566
				};
567
			});
568
			options.toShow.css({ height: 0, overflow: "hidden" }).show();
569
			options.toHide
570
				.filter( ":hidden" )
571
					.each( options.complete )
572
				.end()
573
				.filter( ":visible" )
574
				.animate( hideProps, {
575
				step: function( now, settings ) {
576
					// only calculate the percent when animating height
577
					// IE gets very inconsistent results when animating elements
578
					// with small values, which is common for padding
579
					if ( settings.prop == "height" ) {
580
						percentDone = ( settings.end - settings.start === 0 ) ? 0 :
581
							( settings.now - settings.start ) / ( settings.end - settings.start );
582
					}
583

  
584
					options.toShow[ 0 ].style[ settings.prop ] =
585
						( percentDone * showProps[ settings.prop ].value )
586
						+ showProps[ settings.prop ].unit;
587
				},
588
				duration: options.duration,
589
				easing: options.easing,
590
				complete: function() {
591
					if ( !options.autoHeight ) {
592
						options.toShow.css( "height", "" );
535
		});
536
		toShow
537
			.hide()
538
			.animate( showProps, {
539
				duration: duration,
540
				easing: easing,
541
				complete: complete,
542
				step: function( now, fx ) {
543
					fx.now = Math.round( now );
544
					if ( fx.prop !== "height" ) {
545
						adjust += fx.now;
546
					} else if ( that.options.heightStyle !== "content" ) {
547
						fx.now = Math.round( total - toHide.outerHeight() - adjust );
548
						adjust = 0;
593 549
					}
594
					options.toShow.css({
595
						width: originalWidth,
596
						overflow: overflow
597
					});
598
					options.complete();
599 550
				}
600 551
			});
601
		},
602
		bounceslide: function( options ) {
603
			this.slide( options, {
604
				easing: options.down ? "easeOutBounce" : "swing",
605
				duration: options.down ? 1000 : 200
606
			});
552
	},
553

  
554
	_toggleComplete: function( data ) {
555
		var toHide = data.oldPanel;
556

  
557
		toHide
558
			.removeClass( "ui-accordion-content-active" )
559
			.prev()
560
				.removeClass( "ui-corner-top" )
561
				.addClass( "ui-corner-all" );
562

  
563
		// Work around for rendering bug in IE (#5421)
564
		if ( toHide.length ) {
565
			toHide.parent()[0].className = toHide.parent()[0].className;
607 566
		}
567

  
568
		this._trigger( "activate", null, data );
608 569
	}
609 570
});
610 571

  

Formats disponibles : Unified diff