1/* 2 * jQuery UI Accordion 1.6 3 * 4 * Copyright (c) 2007 Jörn Zaefferer 5 * 6 * http://docs.jquery.com/UI/Accordion 7 * 8 * Dual licensed under the MIT and GPL licenses: 9 * http://www.opensource.org/licenses/mit-license.php 10 * http://www.gnu.org/licenses/gpl.html 11 * 12 * Revision: $Id: jquery.accordion.js 4876 2008-03-08 11:49:04Z joern.zaefferer $ 13 * 14 */ 15 16;(function($) { 17 18// If the UI scope is not available, add it 19$.ui = $.ui || {}; 20 21$.fn.extend({ 22 accordion: function(options, data) { 23 var args = Array.prototype.slice.call(arguments, 1); 24 25 return this.each(function() { 26 if (typeof options == "string") { 27 var accordion = $.data(this, "ui-accordion"); 28 accordion[options].apply(accordion, args); 29 // INIT with optional options 30 } else if (!$(this).is(".ui-accordion")) 31 $.data(this, "ui-accordion", new $.ui.accordion(this, options)); 32 }); 33 }, 34 // deprecated, use accordion("activate", index) instead 35 activate: function(index) { 36 return this.accordion("activate", index); 37 } 38}); 39 40$.ui.accordion = function(container, options) { 41 42 // setup configuration 43 this.options = options = $.extend({}, $.ui.accordion.defaults, options); 44 this.element = container; 45 46 $(container).addClass("ui-accordion"); 47 48 if ( options.navigation ) { 49 var current = $(container).find("a").filter(options.navigationFilter); 50 if ( current.length ) { 51 if ( current.filter(options.header).length ) { 52 options.active = current; 53 } else { 54 options.active = current.parent().parent().prev(); 55 current.addClass("current"); 56 } 57 } 58 } 59 60 // calculate active if not specified, using the first header 61 options.headers = $(container).find(options.header); 62 options.active = findActive(options.headers, options.active); 63 64 if ( options.fillSpace ) { 65 var maxHeight = $(container).parent().height(); 66 options.headers.each(function() { 67 maxHeight -= $(this).outerHeight(); 68 }); 69 var maxPadding = 0; 70 options.headers.next().each(function() { 71 maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height()); 72 }).height(maxHeight - maxPadding); 73 } else if ( options.autoheight ) { 74 var maxHeight = 0; 75 options.headers.next().each(function() { 76 maxHeight = Math.max(maxHeight, $(this).outerHeight()); 77 }).height(maxHeight); 78 } 79 80 options.headers 81 .not(options.active || "") 82 .next() 83 .hide(); 84 options.active.parent().andSelf().addClass(options.selectedClass); 85 86 if (options.event) 87 $(container).bind((options.event) + ".ui-accordion", clickHandler); 88}; 89 90$.ui.accordion.prototype = { 91 activate: function(index) { 92 // call clickHandler with custom event 93 clickHandler.call(this.element, { 94 target: findActive( this.options.headers, index )[0] 95 }); 96 }, 97 98 enable: function() { 99 this.options.disabled = false; 100 }, 101 disable: function() { 102 this.options.disabled = true; 103 }, 104 destroy: function() { 105 this.options.headers.next().css("display", ""); 106 if ( this.options.fillSpace || this.options.autoheight ) { 107 this.options.headers.next().css("height", ""); 108 } 109 $.removeData(this.element, "ui-accordion"); 110 $(this.element).removeClass("ui-accordion").unbind(".ui-accordion"); 111 } 112} 113 114function scopeCallback(callback, scope) { 115 return function() { 116 return callback.apply(scope, arguments); 117 }; 118} 119 120function completed(cancel) { 121 // if removed while animated data can be empty 122 if (!$.data(this, "ui-accordion")) 123 return; 124 var instance = $.data(this, "ui-accordion"); 125 var options = instance.options; 126 options.running = cancel ? 0 : --options.running; 127 if ( options.running ) 128 return; 129 if ( options.clearStyle ) { 130 options.toShow.add(options.toHide).css({ 131 height: "", 132 overflow: "" 133 }); 134 } 135 $(this).triggerHandler("change.ui-accordion", [options.data], options.change); 136} 137 138function toggle(toShow, toHide, data, clickedActive, down) { 139 var options = $.data(this, "ui-accordion").options; 140 options.toShow = toShow; 141 options.toHide = toHide; 142 options.data = data; 143 var complete = scopeCallback(completed, this); 144 145 // count elements to animate 146 options.running = toHide.size() == 0 ? toShow.size() : toHide.size(); 147 148 if ( options.animated ) { 149 if ( !options.alwaysOpen && clickedActive ) { 150 $.ui.accordion.animations[options.animated]({ 151 toShow: jQuery([]), 152 toHide: toHide, 153 complete: complete, 154 down: down, 155 autoheight: options.autoheight 156 }); 157 } else { 158 $.ui.accordion.animations[options.animated]({ 159 toShow: toShow, 160 toHide: toHide, 161 complete: complete, 162 down: down, 163 autoheight: options.autoheight 164 }); 165 } 166 } else { 167 if ( !options.alwaysOpen && clickedActive ) { 168 toShow.toggle(); 169 } else { 170 toHide.hide(); 171 toShow.show(); 172 } 173 complete(true); 174 } 175} 176 177function clickHandler(event) { 178 var options = $.data(this, "ui-accordion").options; 179 if (options.disabled) 180 return false;
181 182 // called only when using activate(false) to close all parts programmatically 183 if ( !event.target && !options.alwaysOpen ) { 184 options.active.parent().andSelf().toggleClass(options.selectedClass); 185 var toHide = options.active.next(), 186 data = { 187 instance: this, 188 options: options, 189 newHeader: jQuery([]), 190 oldHeader: options.active, 191 newContent: jQuery([]), 192 oldContent: toHide 193 }, 194 toShow = options.active = $([]); 195 toggle.call(this, toShow, toHide, data ); 196 return false; 197 } 198 // get the click target 199 var clicked = $(event.target); 200 201 // due to the event delegation model, we have to check if one 202 // of the parent elements is our actual header, and find that 203 if ( clicked.parents(options.header).length ) 204 while ( !clicked.is(options.header) ) 205 clicked = clicked.parent(); 206 207 var clickedActive = clicked[0] == options.active[0]; 208 209 // if animations are still active, or the active header is the target, ignore click 210 if (options.running || (options.alwaysOpen && clickedActive)) 211 return false; 212 if (!clicked.is(options.header)) 213 return; 214 215 // switch classes 216 options.active.parent().andSelf().toggleClass(options.selectedClass); 217 if ( !clickedActive ) { 218 clicked.parent().andSelf().addClass(options.selectedClass); 219 } 220 221 // find elements to show and hide 222 var toShow = clicked.next(), 223 toHide = options.active.next(), 224 //data = [clicked, options.active, toShow, toHide], 225 data = { 226 instance: this, 227 options: options, 228 newHeader: clicked, 229 oldHeader: options.active, 230 newContent: toShow, 231 oldContent: toHide 232 }, 233 down = options.headers.index( options.active[0] ) > options.headers.index( clicked[0] ); 234 235 options.active = clickedActive ? $([]) : clicked; 236 toggle.call(this, toShow, toHide, data, clickedActive, down ); 237 238 return false; 239}; 240 241function findActive(headers, selector) { 242 return selector != undefined 243 ? typeof selector == "number" 244 ? headers.filter(":eq(" + selector + ")") 245 : headers.not(headers.not(selector)) 246 : selector === false 247 ? $([]) 248 : headers.filter(":eq(0)"); 249} 250 251$.extend($.ui.accordion, { 252 defaults: { 253 selectedClass: "selected", 254 alwaysOpen: true, 255 animated: 'slide', 256 event: "click", 257 header: "a", 258 autoheight: true, 259 running: 0, 260 navigationFilter: function() { 261 return this.href.toLowerCase() == location.href.toLowerCase(); 262 } 263 }, 264 animations: { 265 slide: function(options, additions) { 266 options = $.extend({ 267 easing: "swing", 268 duration: 300 269 }, options, additions); 270 if ( !options.toHide.size() ) { 271 options.toShow.animate({height: "show"}, options); 272 return; 273 } 274 var hideHeight = options.toHide.height(), 275 showHeight = options.toShow.height(), 276 difference = showHeight / hideHeight; 277 options.toShow.css({ height: 0, overflow: 'hidden' }).show(); 278 options.toHide.filter(":hidden").each(options.complete).end().filter(":visible").animate({height:"hide"},{ 279 step: function(now) { 280 var current = (hideHeight - now) * difference; 281 if ($.browser.msie || $.browser.opera) { 282 current = Math.ceil(current); 283 } 284 options.toShow.height( current ); 285 }, 286 duration: options.duration, 287 easing: options.easing, 288 complete: function() { 289 if ( !options.autoheight ) { 290 options.toShow.css("height", "auto"); 291 } 292 options.complete(); 293 } 294 }); 295 }, 296 bounceslide: function(options) { 297 this.slide(options, { 298 easing: options.down ? "bounceout" : "swing", 299 duration: options.down ? 1000 : 200 300 }); 301 }, 302 easeslide: function(options) { 303 this.slide(options, { 304 easing: "easeinout", 305 duration: 700 306 }) 307 } 308 } 309}); 310 311})(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.