[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 /*! 2 * jQuery UI Accordion 1.13.3 3 * https://jqueryui.com 4 * 5 * Copyright OpenJS Foundation and other contributors 6 * Released under the MIT license. 7 * https://jquery.org/license 8 */ 9 10 //>>label: Accordion 11 //>>group: Widgets 12 /* eslint-disable max-len */ 13 //>>description: Displays collapsible content panels for presenting information in a limited amount of space. 14 /* eslint-enable max-len */ 15 //>>docs: https://api.jqueryui.com/accordion/ 16 //>>demos: https://jqueryui.com/accordion/ 17 //>>css.structure: ../../themes/base/core.css 18 //>>css.structure: ../../themes/base/accordion.css 19 //>>css.theme: ../../themes/base/theme.css 20 21 ( function( factory ) { 22 "use strict"; 23 24 if ( typeof define === "function" && define.amd ) { 25 26 // AMD. Register as an anonymous module. 27 define( [ 28 "jquery", 29 "../version", 30 "../keycode", 31 "../unique-id", 32 "../widget" 33 ], factory ); 34 } else { 35 36 // Browser globals 37 factory( jQuery ); 38 } 39 } )( function( $ ) { 40 "use strict"; 41 42 return $.widget( "ui.accordion", { 43 version: "1.13.3", 44 options: { 45 active: 0, 46 animate: {}, 47 classes: { 48 "ui-accordion-header": "ui-corner-top", 49 "ui-accordion-header-collapsed": "ui-corner-all", 50 "ui-accordion-content": "ui-corner-bottom" 51 }, 52 collapsible: false, 53 event: "click", 54 header: function( elem ) { 55 return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() ); 56 }, 57 heightStyle: "auto", 58 icons: { 59 activeHeader: "ui-icon-triangle-1-s", 60 header: "ui-icon-triangle-1-e" 61 }, 62 63 // Callbacks 64 activate: null, 65 beforeActivate: null 66 }, 67 68 hideProps: { 69 borderTopWidth: "hide", 70 borderBottomWidth: "hide", 71 paddingTop: "hide", 72 paddingBottom: "hide", 73 height: "hide" 74 }, 75 76 showProps: { 77 borderTopWidth: "show", 78 borderBottomWidth: "show", 79 paddingTop: "show", 80 paddingBottom: "show", 81 height: "show" 82 }, 83 84 _create: function() { 85 var options = this.options; 86 87 this.prevShow = this.prevHide = $(); 88 this._addClass( "ui-accordion", "ui-widget ui-helper-reset" ); 89 this.element.attr( "role", "tablist" ); 90 91 // Don't allow collapsible: false and active: false / null 92 if ( !options.collapsible && ( options.active === false || options.active == null ) ) { 93 options.active = 0; 94 } 95 96 this._processPanels(); 97 98 // handle negative values 99 if ( options.active < 0 ) { 100 options.active += this.headers.length; 101 } 102 this._refresh(); 103 }, 104 105 _getCreateEventData: function() { 106 return { 107 header: this.active, 108 panel: !this.active.length ? $() : this.active.next() 109 }; 110 }, 111 112 _createIcons: function() { 113 var icon, children, 114 icons = this.options.icons; 115 116 if ( icons ) { 117 icon = $( "<span>" ); 118 this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header ); 119 icon.prependTo( this.headers ); 120 children = this.active.children( ".ui-accordion-header-icon" ); 121 this._removeClass( children, icons.header ) 122 ._addClass( children, null, icons.activeHeader ) 123 ._addClass( this.headers, "ui-accordion-icons" ); 124 } 125 }, 126 127 _destroyIcons: function() { 128 this._removeClass( this.headers, "ui-accordion-icons" ); 129 this.headers.children( ".ui-accordion-header-icon" ).remove(); 130 }, 131 132 _destroy: function() { 133 var contents; 134 135 // Clean up main element 136 this.element.removeAttr( "role" ); 137 138 // Clean up headers 139 this.headers 140 .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" ) 141 .removeUniqueId(); 142 143 this._destroyIcons(); 144 145 // Clean up content panels 146 contents = this.headers.next() 147 .css( "display", "" ) 148 .removeAttr( "role aria-hidden aria-labelledby" ) 149 .removeUniqueId(); 150 151 if ( this.options.heightStyle !== "content" ) { 152 contents.css( "height", "" ); 153 } 154 }, 155 156 _setOption: function( key, value ) { 157 if ( key === "active" ) { 158 159 // _activate() will handle invalid values and update this.options 160 this._activate( value ); 161 return; 162 } 163 164 if ( key === "event" ) { 165 if ( this.options.event ) { 166 this._off( this.headers, this.options.event ); 167 } 168 this._setupEvents( value ); 169 } 170 171 this._super( key, value ); 172 173 // Setting collapsible: false while collapsed; open first panel 174 if ( key === "collapsible" && !value && this.options.active === false ) { 175 this._activate( 0 ); 176 } 177 178 if ( key === "icons" ) { 179 this._destroyIcons(); 180 if ( value ) { 181 this._createIcons(); 182 } 183 } 184 }, 185 186 _setOptionDisabled: function( value ) { 187 this._super( value ); 188 189 this.element.attr( "aria-disabled", value ); 190 191 // Support: IE8 Only 192 // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE 193 // so we need to add the disabled class to the headers and panels 194 this._toggleClass( null, "ui-state-disabled", !!value ); 195 this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled", 196 !!value ); 197 }, 198 199 _keydown: function( event ) { 200 if ( event.altKey || event.ctrlKey ) { 201 return; 202 } 203 204 var keyCode = $.ui.keyCode, 205 length = this.headers.length, 206 currentIndex = this.headers.index( event.target ), 207 toFocus = false; 208 209 switch ( event.keyCode ) { 210 case keyCode.RIGHT: 211 case keyCode.DOWN: 212 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 213 break; 214 case keyCode.LEFT: 215 case keyCode.UP: 216 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 217 break; 218 case keyCode.SPACE: 219 case keyCode.ENTER: 220 this._eventHandler( event ); 221 break; 222 case keyCode.HOME: 223 toFocus = this.headers[ 0 ]; 224 break; 225 case keyCode.END: 226 toFocus = this.headers[ length - 1 ]; 227 break; 228 } 229 230 if ( toFocus ) { 231 $( event.target ).attr( "tabIndex", -1 ); 232 $( toFocus ).attr( "tabIndex", 0 ); 233 $( toFocus ).trigger( "focus" ); 234 event.preventDefault(); 235 } 236 }, 237 238 _panelKeyDown: function( event ) { 239 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 240 $( event.currentTarget ).prev().trigger( "focus" ); 241 } 242 }, 243 244 refresh: function() { 245 var options = this.options; 246 this._processPanels(); 247 248 // Was collapsed or no panel 249 if ( ( options.active === false && options.collapsible === true ) || 250 !this.headers.length ) { 251 options.active = false; 252 this.active = $(); 253 254 // active false only when collapsible is true 255 } else if ( options.active === false ) { 256 this._activate( 0 ); 257 258 // was active, but active panel is gone 259 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 260 261 // all remaining panel are disabled 262 if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) { 263 options.active = false; 264 this.active = $(); 265 266 // activate previous panel 267 } else { 268 this._activate( Math.max( 0, options.active - 1 ) ); 269 } 270 271 // was active, active panel still exists 272 } else { 273 274 // make sure active index is correct 275 options.active = this.headers.index( this.active ); 276 } 277 278 this._destroyIcons(); 279 280 this._refresh(); 281 }, 282 283 _processPanels: function() { 284 var prevHeaders = this.headers, 285 prevPanels = this.panels; 286 287 if ( typeof this.options.header === "function" ) { 288 this.headers = this.options.header( this.element ); 289 } else { 290 this.headers = this.element.find( this.options.header ); 291 } 292 this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed", 293 "ui-state-default" ); 294 295 this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide(); 296 this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" ); 297 298 // Avoid memory leaks (#10056) 299 if ( prevPanels ) { 300 this._off( prevHeaders.not( this.headers ) ); 301 this._off( prevPanels.not( this.panels ) ); 302 } 303 }, 304 305 _refresh: function() { 306 var maxHeight, 307 options = this.options, 308 heightStyle = options.heightStyle, 309 parent = this.element.parent(); 310 311 this.active = this._findActive( options.active ); 312 this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" ) 313 ._removeClass( this.active, "ui-accordion-header-collapsed" ); 314 this._addClass( this.active.next(), "ui-accordion-content-active" ); 315 this.active.next().show(); 316 317 this.headers 318 .attr( "role", "tab" ) 319 .each( function() { 320 var header = $( this ), 321 headerId = header.uniqueId().attr( "id" ), 322 panel = header.next(), 323 panelId = panel.uniqueId().attr( "id" ); 324 header.attr( "aria-controls", panelId ); 325 panel.attr( "aria-labelledby", headerId ); 326 } ) 327 .next() 328 .attr( "role", "tabpanel" ); 329 330 this.headers 331 .not( this.active ) 332 .attr( { 333 "aria-selected": "false", 334 "aria-expanded": "false", 335 tabIndex: -1 336 } ) 337 .next() 338 .attr( { 339 "aria-hidden": "true" 340 } ) 341 .hide(); 342 343 // Make sure at least one header is in the tab order 344 if ( !this.active.length ) { 345 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 346 } else { 347 this.active.attr( { 348 "aria-selected": "true", 349 "aria-expanded": "true", 350 tabIndex: 0 351 } ) 352 .next() 353 .attr( { 354 "aria-hidden": "false" 355 } ); 356 } 357 358 this._createIcons(); 359 360 this._setupEvents( options.event ); 361 362 if ( heightStyle === "fill" ) { 363 maxHeight = parent.height(); 364 this.element.siblings( ":visible" ).each( function() { 365 var elem = $( this ), 366 position = elem.css( "position" ); 367 368 if ( position === "absolute" || position === "fixed" ) { 369 return; 370 } 371 maxHeight -= elem.outerHeight( true ); 372 } ); 373 374 this.headers.each( function() { 375 maxHeight -= $( this ).outerHeight( true ); 376 } ); 377 378 this.headers.next() 379 .each( function() { 380 $( this ).height( Math.max( 0, maxHeight - 381 $( this ).innerHeight() + $( this ).height() ) ); 382 } ) 383 .css( "overflow", "auto" ); 384 } else if ( heightStyle === "auto" ) { 385 maxHeight = 0; 386 this.headers.next() 387 .each( function() { 388 var isVisible = $( this ).is( ":visible" ); 389 if ( !isVisible ) { 390 $( this ).show(); 391 } 392 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 393 if ( !isVisible ) { 394 $( this ).hide(); 395 } 396 } ) 397 .height( maxHeight ); 398 } 399 }, 400 401 _activate: function( index ) { 402 var active = this._findActive( index )[ 0 ]; 403 404 // Trying to activate the already active panel 405 if ( active === this.active[ 0 ] ) { 406 return; 407 } 408 409 // Trying to collapse, simulate a click on the currently active header 410 active = active || this.active[ 0 ]; 411 412 this._eventHandler( { 413 target: active, 414 currentTarget: active, 415 preventDefault: $.noop 416 } ); 417 }, 418 419 _findActive: function( selector ) { 420 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 421 }, 422 423 _setupEvents: function( event ) { 424 var events = { 425 keydown: "_keydown" 426 }; 427 if ( event ) { 428 $.each( event.split( " " ), function( index, eventName ) { 429 events[ eventName ] = "_eventHandler"; 430 } ); 431 } 432 433 this._off( this.headers.add( this.headers.next() ) ); 434 this._on( this.headers, events ); 435 this._on( this.headers.next(), { keydown: "_panelKeyDown" } ); 436 this._hoverable( this.headers ); 437 this._focusable( this.headers ); 438 }, 439 440 _eventHandler: function( event ) { 441 var activeChildren, clickedChildren, 442 options = this.options, 443 active = this.active, 444 clicked = $( event.currentTarget ), 445 clickedIsActive = clicked[ 0 ] === active[ 0 ], 446 collapsing = clickedIsActive && options.collapsible, 447 toShow = collapsing ? $() : clicked.next(), 448 toHide = active.next(), 449 eventData = { 450 oldHeader: active, 451 oldPanel: toHide, 452 newHeader: collapsing ? $() : clicked, 453 newPanel: toShow 454 }; 455 456 event.preventDefault(); 457 458 if ( 459 460 // click on active header, but not collapsible 461 ( clickedIsActive && !options.collapsible ) || 462 463 // allow canceling activation 464 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 465 return; 466 } 467 468 options.active = collapsing ? false : this.headers.index( clicked ); 469 470 // When the call to ._toggle() comes after the class changes 471 // it causes a very odd bug in IE 8 (see #6720) 472 this.active = clickedIsActive ? $() : clicked; 473 this._toggle( eventData ); 474 475 // Switch classes 476 // corner classes on the previously active header stay after the animation 477 this._removeClass( active, "ui-accordion-header-active", "ui-state-active" ); 478 if ( options.icons ) { 479 activeChildren = active.children( ".ui-accordion-header-icon" ); 480 this._removeClass( activeChildren, null, options.icons.activeHeader ) 481 ._addClass( activeChildren, null, options.icons.header ); 482 } 483 484 if ( !clickedIsActive ) { 485 this._removeClass( clicked, "ui-accordion-header-collapsed" ) 486 ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" ); 487 if ( options.icons ) { 488 clickedChildren = clicked.children( ".ui-accordion-header-icon" ); 489 this._removeClass( clickedChildren, null, options.icons.header ) 490 ._addClass( clickedChildren, null, options.icons.activeHeader ); 491 } 492 493 this._addClass( clicked.next(), "ui-accordion-content-active" ); 494 } 495 }, 496 497 _toggle: function( data ) { 498 var toShow = data.newPanel, 499 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 500 501 // Handle activating a panel during the animation for another activation 502 this.prevShow.add( this.prevHide ).stop( true, true ); 503 this.prevShow = toShow; 504 this.prevHide = toHide; 505 506 if ( this.options.animate ) { 507 this._animate( toShow, toHide, data ); 508 } else { 509 toHide.hide(); 510 toShow.show(); 511 this._toggleComplete( data ); 512 } 513 514 toHide.attr( { 515 "aria-hidden": "true" 516 } ); 517 toHide.prev().attr( { 518 "aria-selected": "false", 519 "aria-expanded": "false" 520 } ); 521 522 // if we're switching panels, remove the old header from the tab order 523 // if we're opening from collapsed state, remove the previous header from the tab order 524 // if we're collapsing, then keep the collapsing header in the tab order 525 if ( toShow.length && toHide.length ) { 526 toHide.prev().attr( { 527 "tabIndex": -1, 528 "aria-expanded": "false" 529 } ); 530 } else if ( toShow.length ) { 531 this.headers.filter( function() { 532 return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; 533 } ) 534 .attr( "tabIndex", -1 ); 535 } 536 537 toShow 538 .attr( "aria-hidden", "false" ) 539 .prev() 540 .attr( { 541 "aria-selected": "true", 542 "aria-expanded": "true", 543 tabIndex: 0 544 } ); 545 }, 546 547 _animate: function( toShow, toHide, data ) { 548 var total, easing, duration, 549 that = this, 550 adjust = 0, 551 boxSizing = toShow.css( "box-sizing" ), 552 down = toShow.length && 553 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 554 animate = this.options.animate || {}, 555 options = down && animate.down || animate, 556 complete = function() { 557 that._toggleComplete( data ); 558 }; 559 560 if ( typeof options === "number" ) { 561 duration = options; 562 } 563 if ( typeof options === "string" ) { 564 easing = options; 565 } 566 567 // fall back from options to animation in case of partial down settings 568 easing = easing || options.easing || animate.easing; 569 duration = duration || options.duration || animate.duration; 570 571 if ( !toHide.length ) { 572 return toShow.animate( this.showProps, duration, easing, complete ); 573 } 574 if ( !toShow.length ) { 575 return toHide.animate( this.hideProps, duration, easing, complete ); 576 } 577 578 total = toShow.show().outerHeight(); 579 toHide.animate( this.hideProps, { 580 duration: duration, 581 easing: easing, 582 step: function( now, fx ) { 583 fx.now = Math.round( now ); 584 } 585 } ); 586 toShow 587 .hide() 588 .animate( this.showProps, { 589 duration: duration, 590 easing: easing, 591 complete: complete, 592 step: function( now, fx ) { 593 fx.now = Math.round( now ); 594 if ( fx.prop !== "height" ) { 595 if ( boxSizing === "content-box" ) { 596 adjust += fx.now; 597 } 598 } else if ( that.options.heightStyle !== "content" ) { 599 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 600 adjust = 0; 601 } 602 } 603 } ); 604 }, 605 606 _toggleComplete: function( data ) { 607 var toHide = data.oldPanel, 608 prev = toHide.prev(); 609 610 this._removeClass( toHide, "ui-accordion-content-active" ); 611 this._removeClass( prev, "ui-accordion-header-active" ) 612 ._addClass( prev, "ui-accordion-header-collapsed" ); 613 614 // Work around for rendering bug in IE (#5421) 615 if ( toHide.length ) { 616 toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className; 617 } 618 this._trigger( "activate", null, data ); 619 } 620 } ); 621 622 } );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Sat Nov 23 08:20:01 2024 | Cross-referenced by PHPXref |