[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 /*! 2 * jQuery UI Accordion 1.9.2 3 * http://jqueryui.com 4 * 5 * Copyright 2012 jQuery Foundation and other contributors 6 * Released under the MIT license. 7 * http://jquery.org/license 8 * 9 * http://api.jqueryui.com/accordion/ 10 * 11 * Depends: 12 * jquery.ui.core.js 13 * jquery.ui.widget.js 14 */ 15 (function( $, undefined ) { 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 26 $.widget( "ui.accordion", { 27 version: "1.9.2", 28 options: { 29 active: 0, 30 animate: {}, 31 collapsible: false, 32 event: "click", 33 header: "> li > :first-child,> :not(li):even", 34 heightStyle: "auto", 35 icons: { 36 activeHeader: "ui-icon-triangle-1-s", 37 header: "ui-icon-triangle-1-e" 38 }, 39 40 // callbacks 41 activate: null, 42 beforeActivate: null 43 }, 44 45 _create: function() { 46 var accordionId = this.accordionId = "ui-accordion-" + 47 (this.element.attr( "id" ) || ++uid), 48 options = this.options; 49 50 this.prevShow = this.prevHide = $(); 51 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ); 52 53 this.headers = this.element.find( options.header ) 54 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); 55 this._hoverable( this.headers ); 56 this._focusable( this.headers ); 57 58 this.headers.next() 59 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) 60 .hide(); 61 62 // don't allow collapsible: false and active: false / null 63 if ( !options.collapsible && (options.active === false || options.active == null) ) { 64 options.active = 0; 65 } 66 // handle negative values 67 if ( options.active < 0 ) { 68 options.active += this.headers.length; 69 } 70 this.active = this._findActive( options.active ) 71 .addClass( "ui-accordion-header-active ui-state-active" ) 72 .toggleClass( "ui-corner-all ui-corner-top" ); 73 this.active.next() 74 .addClass( "ui-accordion-content-active" ) 75 .show(); 76 77 this._createIcons(); 78 this.refresh(); 79 80 // ARIA 81 this.element.attr( "role", "tablist" ); 82 83 this.headers 84 .attr( "role", "tab" ) 85 .each(function( i ) { 86 var header = $( this ), 87 headerId = header.attr( "id" ), 88 panel = header.next(), 89 panelId = panel.attr( "id" ); 90 if ( !headerId ) { 91 headerId = accordionId + "-header-" + i; 92 header.attr( "id", headerId ); 93 } 94 if ( !panelId ) { 95 panelId = accordionId + "-panel-" + i; 96 panel.attr( "id", panelId ); 97 } 98 header.attr( "aria-controls", panelId ); 99 panel.attr( "aria-labelledby", headerId ); 100 }) 101 .next() 102 .attr( "role", "tabpanel" ); 103 104 this.headers 105 .not( this.active ) 106 .attr({ 107 "aria-selected": "false", 108 tabIndex: -1 109 }) 110 .next() 111 .attr({ 112 "aria-expanded": "false", 113 "aria-hidden": "true" 114 }) 115 .hide(); 116 117 // make sure at least one header is in the tab order 118 if ( !this.active.length ) { 119 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 120 } else { 121 this.active.attr({ 122 "aria-selected": "true", 123 tabIndex: 0 124 }) 125 .next() 126 .attr({ 127 "aria-expanded": "true", 128 "aria-hidden": "false" 129 }); 130 } 131 132 this._on( this.headers, { keydown: "_keydown" }); 133 this._on( this.headers.next(), { keydown: "_panelKeyDown" }); 134 this._setupEvents( options.event ); 135 }, 136 137 _getCreateEventData: function() { 138 return { 139 header: this.active, 140 content: !this.active.length ? $() : this.active.next() 141 }; 142 }, 143 144 _createIcons: function() { 145 var icons = this.options.icons; 146 if ( icons ) { 147 $( "<span>" ) 148 .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) 149 .prependTo( this.headers ); 150 this.active.children( ".ui-accordion-header-icon" ) 151 .removeClass( icons.header ) 152 .addClass( icons.activeHeader ); 153 this.headers.addClass( "ui-accordion-icons" ); 154 } 155 }, 156 157 _destroyIcons: function() { 158 this.headers 159 .removeClass( "ui-accordion-icons" ) 160 .children( ".ui-accordion-header-icon" ) 161 .remove(); 162 }, 163 164 _destroy: function() { 165 var contents; 166 167 // clean up main element 168 this.element 169 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) 170 .removeAttr( "role" ); 171 172 // clean up headers 173 this.headers 174 .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" ) 175 .removeAttr( "role" ) 176 .removeAttr( "aria-selected" ) 177 .removeAttr( "aria-controls" ) 178 .removeAttr( "tabIndex" ) 179 .each(function() { 180 if ( /^ui-accordion/.test( this.id ) ) { 181 this.removeAttribute( "id" ); 182 } 183 }); 184 this._destroyIcons(); 185 186 // clean up content panels 187 contents = this.headers.next() 188 .css( "display", "" ) 189 .removeAttr( "role" ) 190 .removeAttr( "aria-expanded" ) 191 .removeAttr( "aria-hidden" ) 192 .removeAttr( "aria-labelledby" ) 193 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) 194 .each(function() { 195 if ( /^ui-accordion/.test( this.id ) ) { 196 this.removeAttribute( "id" ); 197 } 198 }); 199 if ( this.options.heightStyle !== "content" ) { 200 contents.css( "height", "" ); 201 } 202 }, 203 204 _setOption: function( key, value ) { 205 if ( key === "active" ) { 206 // _activate() will handle invalid values and update this.options 207 this._activate( value ); 208 return; 209 } 210 211 if ( key === "event" ) { 212 if ( this.options.event ) { 213 this._off( this.headers, this.options.event ); 214 } 215 this._setupEvents( value ); 216 } 217 218 this._super( key, value ); 219 220 // setting collapsible: false while collapsed; open first panel 221 if ( key === "collapsible" && !value && this.options.active === false ) { 222 this._activate( 0 ); 223 } 224 225 if ( key === "icons" ) { 226 this._destroyIcons(); 227 if ( value ) { 228 this._createIcons(); 229 } 230 } 231 232 // #5332 - opacity doesn't cascade to positioned elements in IE 233 // so we need to add the disabled class to the headers and panels 234 if ( key === "disabled" ) { 235 this.headers.add( this.headers.next() ) 236 .toggleClass( "ui-state-disabled", !!value ); 237 } 238 }, 239 240 _keydown: function( event ) { 241 if ( event.altKey || event.ctrlKey ) { 242 return; 243 } 244 245 var keyCode = $.ui.keyCode, 246 length = this.headers.length, 247 currentIndex = this.headers.index( event.target ), 248 toFocus = false; 249 250 switch ( event.keyCode ) { 251 case keyCode.RIGHT: 252 case keyCode.DOWN: 253 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 254 break; 255 case keyCode.LEFT: 256 case keyCode.UP: 257 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 258 break; 259 case keyCode.SPACE: 260 case keyCode.ENTER: 261 this._eventHandler( event ); 262 break; 263 case keyCode.HOME: 264 toFocus = this.headers[ 0 ]; 265 break; 266 case keyCode.END: 267 toFocus = this.headers[ length - 1 ]; 268 break; 269 } 270 271 if ( toFocus ) { 272 $( event.target ).attr( "tabIndex", -1 ); 273 $( toFocus ).attr( "tabIndex", 0 ); 274 toFocus.focus(); 275 event.preventDefault(); 276 } 277 }, 278 279 _panelKeyDown : function( event ) { 280 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 281 $( event.currentTarget ).prev().focus(); 282 } 283 }, 284 285 refresh: function() { 286 var maxHeight, overflow, 287 heightStyle = this.options.heightStyle, 288 parent = this.element.parent(); 289 290 291 if ( heightStyle === "fill" ) { 292 // IE 6 treats height like minHeight, so we need to turn off overflow 293 // in order to get a reliable height 294 // we use the minHeight support test because we assume that only 295 // browsers that don't support minHeight will treat height as minHeight 296 if ( !$.support.minHeight ) { 297 overflow = parent.css( "overflow" ); 298 parent.css( "overflow", "hidden"); 299 } 300 maxHeight = parent.height(); 301 this.element.siblings( ":visible" ).each(function() { 302 var elem = $( this ), 303 position = elem.css( "position" ); 304 305 if ( position === "absolute" || position === "fixed" ) { 306 return; 307 } 308 maxHeight -= elem.outerHeight( true ); 309 }); 310 if ( overflow ) { 311 parent.css( "overflow", overflow ); 312 } 313 314 this.headers.each(function() { 315 maxHeight -= $( this ).outerHeight( true ); 316 }); 317 318 this.headers.next() 319 .each(function() { 320 $( this ).height( Math.max( 0, maxHeight - 321 $( this ).innerHeight() + $( this ).height() ) ); 322 }) 323 .css( "overflow", "auto" ); 324 } else if ( heightStyle === "auto" ) { 325 maxHeight = 0; 326 this.headers.next() 327 .each(function() { 328 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 329 }) 330 .height( maxHeight ); 331 } 332 }, 333 334 _activate: function( index ) { 335 var active = this._findActive( index )[ 0 ]; 336 337 // trying to activate the already active panel 338 if ( active === this.active[ 0 ] ) { 339 return; 340 } 341 342 // trying to collapse, simulate a click on the currently active header 343 active = active || this.active[ 0 ]; 344 345 this._eventHandler({ 346 target: active, 347 currentTarget: active, 348 preventDefault: $.noop 349 }); 350 }, 351 352 _findActive: function( selector ) { 353 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 354 }, 355 356 _setupEvents: function( event ) { 357 var events = {}; 358 if ( !event ) { 359 return; 360 } 361 $.each( event.split(" "), function( index, eventName ) { 362 events[ eventName ] = "_eventHandler"; 363 }); 364 this._on( this.headers, events ); 365 }, 366 367 _eventHandler: function( event ) { 368 var options = this.options, 369 active = this.active, 370 clicked = $( event.currentTarget ), 371 clickedIsActive = clicked[ 0 ] === active[ 0 ], 372 collapsing = clickedIsActive && options.collapsible, 373 toShow = collapsing ? $() : clicked.next(), 374 toHide = active.next(), 375 eventData = { 376 oldHeader: active, 377 oldPanel: toHide, 378 newHeader: collapsing ? $() : clicked, 379 newPanel: toShow 380 }; 381 382 event.preventDefault(); 383 384 if ( 385 // click on active header, but not collapsible 386 ( clickedIsActive && !options.collapsible ) || 387 // allow canceling activation 388 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 389 return; 390 } 391 392 options.active = collapsing ? false : this.headers.index( clicked ); 393 394 // when the call to ._toggle() comes after the class changes 395 // it causes a very odd bug in IE 8 (see #6720) 396 this.active = clickedIsActive ? $() : clicked; 397 this._toggle( eventData ); 398 399 // switch classes 400 // corner classes on the previously active header stay after the animation 401 active.removeClass( "ui-accordion-header-active ui-state-active" ); 402 if ( options.icons ) { 403 active.children( ".ui-accordion-header-icon" ) 404 .removeClass( options.icons.activeHeader ) 405 .addClass( options.icons.header ); 406 } 407 408 if ( !clickedIsActive ) { 409 clicked 410 .removeClass( "ui-corner-all" ) 411 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); 412 if ( options.icons ) { 413 clicked.children( ".ui-accordion-header-icon" ) 414 .removeClass( options.icons.header ) 415 .addClass( options.icons.activeHeader ); 416 } 417 418 clicked 419 .next() 420 .addClass( "ui-accordion-content-active" ); 421 } 422 }, 423 424 _toggle: function( data ) { 425 var toShow = data.newPanel, 426 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 427 428 // handle activating a panel during the animation for another activation 429 this.prevShow.add( this.prevHide ).stop( true, true ); 430 this.prevShow = toShow; 431 this.prevHide = toHide; 432 433 if ( this.options.animate ) { 434 this._animate( toShow, toHide, data ); 435 } else { 436 toHide.hide(); 437 toShow.show(); 438 this._toggleComplete( data ); 439 } 440 441 toHide.attr({ 442 "aria-expanded": "false", 443 "aria-hidden": "true" 444 }); 445 toHide.prev().attr( "aria-selected", "false" ); 446 // if we're switching panels, remove the old header from the tab order 447 // if we're opening from collapsed state, remove the previous header from the tab order 448 // if we're collapsing, then keep the collapsing header in the tab order 449 if ( toShow.length && toHide.length ) { 450 toHide.prev().attr( "tabIndex", -1 ); 451 } else if ( toShow.length ) { 452 this.headers.filter(function() { 453 return $( this ).attr( "tabIndex" ) === 0; 454 }) 455 .attr( "tabIndex", -1 ); 456 } 457 458 toShow 459 .attr({ 460 "aria-expanded": "true", 461 "aria-hidden": "false" 462 }) 463 .prev() 464 .attr({ 465 "aria-selected": "true", 466 tabIndex: 0 467 }); 468 }, 469 470 _animate: function( toShow, toHide, data ) { 471 var total, easing, duration, 472 that = this, 473 adjust = 0, 474 down = toShow.length && 475 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 476 animate = this.options.animate || {}, 477 options = down && animate.down || animate, 478 complete = function() { 479 that._toggleComplete( data ); 480 }; 481 482 if ( typeof options === "number" ) { 483 duration = options; 484 } 485 if ( typeof options === "string" ) { 486 easing = options; 487 } 488 // fall back from options to animation in case of partial down settings 489 easing = easing || options.easing || animate.easing; 490 duration = duration || options.duration || animate.duration; 491 492 if ( !toHide.length ) { 493 return toShow.animate( showProps, duration, easing, complete ); 494 } 495 if ( !toShow.length ) { 496 return toHide.animate( hideProps, duration, easing, complete ); 497 } 498 499 total = toShow.show().outerHeight(); 500 toHide.animate( hideProps, { 501 duration: duration, 502 easing: easing, 503 step: function( now, fx ) { 504 fx.now = Math.round( now ); 505 } 506 }); 507 toShow 508 .hide() 509 .animate( showProps, { 510 duration: duration, 511 easing: easing, 512 complete: complete, 513 step: function( now, fx ) { 514 fx.now = Math.round( now ); 515 if ( fx.prop !== "height" ) { 516 adjust += fx.now; 517 } else if ( that.options.heightStyle !== "content" ) { 518 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 519 adjust = 0; 520 } 521 } 522 }); 523 }, 524 525 _toggleComplete: function( data ) { 526 var toHide = data.oldPanel; 527 528 toHide 529 .removeClass( "ui-accordion-content-active" ) 530 .prev() 531 .removeClass( "ui-corner-top" ) 532 .addClass( "ui-corner-all" ); 533 534 // Work around for rendering bug in IE (#5421) 535 if ( toHide.length ) { 536 toHide.parent()[0].className = toHide.parent()[0].className; 537 } 538 539 this._trigger( "activate", null, data ); 540 } 541 }); 542 543 544 545 // DEPRECATED 546 if ( $.uiBackCompat !== false ) { 547 // navigation options 548 (function( $, prototype ) { 549 $.extend( prototype.options, { 550 navigation: false, 551 navigationFilter: function() { 552 return this.href.toLowerCase() === location.href.toLowerCase(); 553 } 554 }); 555 556 var _create = prototype._create; 557 prototype._create = function() { 558 if ( this.options.navigation ) { 559 var that = this, 560 headers = this.element.find( this.options.header ), 561 content = headers.next(), 562 current = headers.add( content ) 563 .find( "a" ) 564 .filter( this.options.navigationFilter ) 565 [ 0 ]; 566 if ( current ) { 567 headers.add( content ).each( function( index ) { 568 if ( $.contains( this, current ) ) { 569 that.options.active = Math.floor( index / 2 ); 570 return false; 571 } 572 }); 573 } 574 } 575 _create.call( this ); 576 }; 577 }( jQuery, jQuery.ui.accordion.prototype ) ); 578 579 // height options 580 (function( $, prototype ) { 581 $.extend( prototype.options, { 582 heightStyle: null, // remove default so we fall back to old values 583 autoHeight: true, // use heightStyle: "auto" 584 clearStyle: false, // use heightStyle: "content" 585 fillSpace: false // use heightStyle: "fill" 586 }); 587 588 var _create = prototype._create, 589 _setOption = prototype._setOption; 590 591 $.extend( prototype, { 592 _create: function() { 593 this.options.heightStyle = this.options.heightStyle || 594 this._mergeHeightStyle(); 595 596 _create.call( this ); 597 }, 598 599 _setOption: function( key ) { 600 if ( key === "autoHeight" || key === "clearStyle" || key === "fillSpace" ) { 601 this.options.heightStyle = this._mergeHeightStyle(); 602 } 603 _setOption.apply( this, arguments ); 604 }, 605 606 _mergeHeightStyle: function() { 607 var options = this.options; 608 609 if ( options.fillSpace ) { 610 return "fill"; 611 } 612 613 if ( options.clearStyle ) { 614 return "content"; 615 } 616 617 if ( options.autoHeight ) { 618 return "auto"; 619 } 620 } 621 }); 622 }( jQuery, jQuery.ui.accordion.prototype ) ); 623 624 // icon options 625 (function( $, prototype ) { 626 $.extend( prototype.options.icons, { 627 activeHeader: null, // remove default so we fall back to old values 628 headerSelected: "ui-icon-triangle-1-s" 629 }); 630 631 var _createIcons = prototype._createIcons; 632 prototype._createIcons = function() { 633 if ( this.options.icons ) { 634 this.options.icons.activeHeader = this.options.icons.activeHeader || 635 this.options.icons.headerSelected; 636 } 637 _createIcons.call( this ); 638 }; 639 }( jQuery, jQuery.ui.accordion.prototype ) ); 640 641 // expanded active option, activate method 642 (function( $, prototype ) { 643 prototype.activate = prototype._activate; 644 645 var _findActive = prototype._findActive; 646 prototype._findActive = function( index ) { 647 if ( index === -1 ) { 648 index = false; 649 } 650 if ( index && typeof index !== "number" ) { 651 index = this.headers.index( this.headers.filter( index ) ); 652 if ( index === -1 ) { 653 index = false; 654 } 655 } 656 return _findActive.call( this, index ); 657 }; 658 }( jQuery, jQuery.ui.accordion.prototype ) ); 659 660 // resize method 661 jQuery.ui.accordion.prototype.resize = jQuery.ui.accordion.prototype.refresh; 662 663 // change events 664 (function( $, prototype ) { 665 $.extend( prototype.options, { 666 change: null, 667 changestart: null 668 }); 669 670 var _trigger = prototype._trigger; 671 prototype._trigger = function( type, event, data ) { 672 var ret = _trigger.apply( this, arguments ); 673 if ( !ret ) { 674 return false; 675 } 676 677 if ( type === "beforeActivate" ) { 678 ret = _trigger.call( this, "changestart", event, { 679 oldHeader: data.oldHeader, 680 oldContent: data.oldPanel, 681 newHeader: data.newHeader, 682 newContent: data.newPanel 683 }); 684 } else if ( type === "activate" ) { 685 ret = _trigger.call( this, "change", event, { 686 oldHeader: data.oldHeader, 687 oldContent: data.oldPanel, 688 newHeader: data.newHeader, 689 newContent: data.newPanel 690 }); 691 } 692 return ret; 693 }; 694 }( jQuery, jQuery.ui.accordion.prototype ) ); 695 696 // animated option 697 // NOTE: this only provides support for "slide", "bounceslide", and easings 698 // not the full $.ui.accordion.animations API 699 (function( $, prototype ) { 700 $.extend( prototype.options, { 701 animate: null, 702 animated: "slide" 703 }); 704 705 var _create = prototype._create; 706 prototype._create = function() { 707 var options = this.options; 708 if ( options.animate === null ) { 709 if ( !options.animated ) { 710 options.animate = false; 711 } else if ( options.animated === "slide" ) { 712 options.animate = 300; 713 } else if ( options.animated === "bounceslide" ) { 714 options.animate = { 715 duration: 200, 716 down: { 717 easing: "easeOutBounce", 718 duration: 1000 719 } 720 }; 721 } else { 722 options.animate = options.animated; 723 } 724 } 725 726 _create.call( this ); 727 }; 728 }( jQuery, jQuery.ui.accordion.prototype ) ); 729 } 730 731 })( jQuery );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |