PageSourceSearch

https://echeminfo.com/sites/all/modules/jquery_update/replace/ui/1.8/ui/jquery.ui.accordion.js?v=1.8.24

js echeminfo.com collected 2026-10-02 13:44:30 UTC 16,243 bytes, 611 lines download raw bytes

1/*!
2 * jQuery UI Accordion 1.8.24
3 *
4 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
7 *
8 * http://docs.jquery.com/UI/Accordion
9 *
10 * Depends:
11 *	jquery.ui.core.js
12 *	jquery.ui.widget.js
13 */
14(function( $, undefined ) {
15
16$.widget( "ui.accordion", {
17	options: {
18		active: 0,
19		animated: "slide",
20		autoHeight: true,
21		clearStyle: false,
22		collapsible: false,
23		event: "click",
24		fillSpace: false,
25		header: "> li > :first-child,> :not(li):even",
26		icons: {
27			header: "ui-icon-triangle-1-e",
28			headerSelected: "ui-icon-triangle-1-s"
29		},
30		navigation: false,
31		navigationFilter: function() {
32			return this.href.toLowerCase() === location.href.toLowerCase();
33		}
34	},
35
36	_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				});
133		}
134
135		// only need links in tab order for Safari
136		if ( !$.browser.safari ) {
137			self.headers.find( "a" ).attr( "tabIndex", -1 );
138		}
139
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		}
146	},
147
148	_createIcons: function() {
149		var options = this.options;
150		if ( options.icons ) {
151			$( "<span></span>" )
152				.addClass( "ui-icon " + options.icons.header )
153				.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" );
158		}
159	},
160
161	_destroyIcons: function() {
162		this.headers.children( ".ui-icon" ).remove();
163		this.element.removeClass( "ui-accordion-icons" );
164	},
165
166	destroy: function() {
167		var options = this.options;
168
169		this.element
170			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
171			.removeAttr( "role" );
172
173		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" )
176			.removeAttr( "role" )
177			.removeAttr( "aria-expanded" )
178			.removeAttr( "aria-selected" )
179			.removeAttr( "tabIndex" );
180
181		this.headers.find( "a" ).removeAttr( "tabIndex" );
182		this._destroyIcons();
183		var contents = this.headers.next()
184			.css( "display", "" )
185			.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 ) {
188			contents.css( "height", "" );
189		}
190
191		return $.Widget.prototype.destroy.call( this );
192	},
193
194	_setOption: function( key, value ) {
195		$.Widget.prototype._setOption.apply( this, arguments );
196			
197		if ( key == "active" ) {
198			this.activate( value );
199		}
200		if ( key == "icons" ) {
201			this._destroyIcons();
202			if ( value ) {
203				this._createIcons();
204			}
205		}
206		// #5332 - opacity doesn't cascade to positioned elements in IE
207		// 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" );
212		}
213	},
214
215	_keydown: function( event ) {
216		if ( this.options.disabled || event.altKey || event.ctrlKey ) {
217			return;
218		}
219
220		var keyCode = $.ui.keyCode,
221			length = this.headers.length,
222			currentIndex = this.headers.index( event.target ),
223			toFocus = false;
224
225		switch ( event.keyCode ) {
226			case keyCode.RIGHT:
227			case keyCode.DOWN:
228				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
229				break;
230			case keyCode.LEFT:
231			case keyCode.UP:
232				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
233				break;
234			case keyCode.SPACE:
235			case keyCode.ENTER:
236				this._clickHandler( { target: event.target }, event.target );
237				event.preventDefault();
238		}
239
240		if ( toFocus ) {
241			$( event.target ).attr( "tabIndex", -1 );
242			$( toFocus ).attr( "tabIndex", 0 );
243			toFocus.focus();
244			return false;
245		}
246
247		return true;
248	},
249
250	resize: function() {
251		var options = this.options,
252			maxHeight;
253
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 );
262			}
263
264			this.headers.each(function() {
265				maxHeight -= $( this ).outerHeight( true );
266			});
267
268			this.headers.next()
269				.each(function() {
270					$( this ).height( Math.max( 0, maxHeight -
271						$( this ).innerHeight() + $( this ).height() ) );
272				})
273				.css( "overflow", "auto" );
274		} else if ( options.autoHeight ) {
275			maxHeight = 0;
276			this.headers.next()
277				.each(function() {
278					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
279				})
280				.height( maxHeight );
281		}
282
283		return this;
284	},
285
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
290		var active = this._findActive( index )[ 0 ];
291		this._clickHandler( { target: active }, active );
292
293		return this;
294	},
295
296	_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)" );
304	},
305
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;
336		}
337
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 );
347
348		// if animations are still active, or the active header is the target, ignore click
349		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
350			return;
351		}
352
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] );
365
366		// when the call to ._toggle() comes after the class changes
367		// it causes a very odd bug in IE 8 (see #6720)
368		this.active = clickedIsActive ? $([]) : clicked;
369		this._toggle( toShow, toHide, data, clickedIsActive, down );
370
371		// 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 )
377				.addClass( options.icons.header );
378		if ( !clickedIsActive ) {
379			clicked
380				.removeClass( "ui-state-default ui-corner-all" )
381				.addClass( "ui-state-active ui-corner-top" )
382				.children( ".ui-icon" )
383					.removeClass( options.icons.header )
384					.addClass( options.icons.headerSelected );
385			clicked
386				.next()
387				.addClass( "ui-accordion-content-active" );
388		}
389
390		return;
391	},
392
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;
450
451			var animations = $.ui.accordion.animations,
452				duration = options.duration,
453				easing = options.animated;
454
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 );
468		} else {
469			if ( options.collapsible && clickedIsActive ) {
470				toShow.toggle();
471			} else {
472				toHide.hide();
473				toShow.show();
474			}
475
476			complete( true );
477		}
478
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
485			})
486			.blur();
487		toShow.prev()
488			.attr({
489				"aria-expanded": "true",
490				"aria-selected": "true",
491				tabIndex: 0
492			})
493			.focus();
494	},
495
496	_completed: function( cancel ) {
497		this.running = cancel ? 0 : --this.running;
498		if ( this.running ) {
499			return;
500		}
501
502		if ( this.options.clearStyle ) {
503			this.toShow.add( this.toHide ).css({
504				height: "",
505				overflow: ""
506			});
507		}
508
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;
514		}
515
516		this._trigger( "change", null, this.data );
517	}
518});
519
520$.extend( $.ui.accordion, {
521	version: "1.8.24",
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;
535			}
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( s.parent().width()
554				- parseFloat( s.css( "paddingLeft" ) )
555				- parseFloat( s.css( "paddingRight" ) )
556				- ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 )
557				- ( parseFloat( s.css( "borderRightWidth" ) ) || 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", "" );
593					}
594					options.toShow.css({
595						width: originalWidth,
596						overflow: overflow
597					});
598					options.complete();
599				}
600			});
601		},
602		bounceslide: function( options ) {
603			this.slide( options, {
604				easing: options.down ? "easeOutBounce" : "swing",
605				duration: options.down ? 1000 : 200
606			});
607		}
608	}
609});
610
611})( jQuery );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.