[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 /*! 2 * jQuery UI Tabs 1.12.1 3 * http://jqueryui.com 4 * 5 * Copyright jQuery Foundation and other contributors 6 * Released under the MIT license. 7 * http://jquery.org/license 8 */ 9 10 //>>label: Tabs 11 //>>group: Widgets 12 //>>description: Transforms a set of container elements into a tab structure. 13 //>>docs: http://api.jqueryui.com/tabs/ 14 //>>demos: http://jqueryui.com/tabs/ 15 //>>css.structure: ../../themes/base/core.css 16 //>>css.structure: ../../themes/base/tabs.css 17 //>>css.theme: ../../themes/base/theme.css 18 19 ( function( factory ) { 20 if ( typeof define === "function" && define.amd ) { 21 22 // AMD. Register as an anonymous module. 23 define( [ 24 "jquery", 25 "./core" 26 ], factory ); 27 } else { 28 29 // Browser globals 30 factory( jQuery ); 31 } 32 }( function( $ ) { 33 34 $.widget( "ui.tabs", { 35 version: "1.12.1", 36 delay: 300, 37 options: { 38 active: null, 39 classes: { 40 "ui-tabs": "ui-corner-all", 41 "ui-tabs-nav": "ui-corner-all", 42 "ui-tabs-panel": "ui-corner-bottom", 43 "ui-tabs-tab": "ui-corner-top" 44 }, 45 collapsible: false, 46 event: "click", 47 heightStyle: "content", 48 hide: null, 49 show: null, 50 51 // Callbacks 52 activate: null, 53 beforeActivate: null, 54 beforeLoad: null, 55 load: null 56 }, 57 58 _isLocal: ( function() { 59 var rhash = /#.*$/; 60 61 return function( anchor ) { 62 var anchorUrl, locationUrl; 63 64 anchorUrl = anchor.href.replace( rhash, "" ); 65 locationUrl = location.href.replace( rhash, "" ); 66 67 // Decoding may throw an error if the URL isn't UTF-8 (#9518) 68 try { 69 anchorUrl = decodeURIComponent( anchorUrl ); 70 } catch ( error ) {} 71 try { 72 locationUrl = decodeURIComponent( locationUrl ); 73 } catch ( error ) {} 74 75 return anchor.hash.length > 1 && anchorUrl === locationUrl; 76 }; 77 } )(), 78 79 _create: function() { 80 var that = this, 81 options = this.options; 82 83 this.running = false; 84 85 this._addClass( "ui-tabs", "ui-widget ui-widget-content" ); 86 this._toggleClass( "ui-tabs-collapsible", null, options.collapsible ); 87 88 this._processTabs(); 89 options.active = this._initialActive(); 90 91 // Take disabling tabs via class attribute from HTML 92 // into account and update option properly. 93 if ( $.isArray( options.disabled ) ) { 94 options.disabled = $.unique( options.disabled.concat( 95 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 96 return that.tabs.index( li ); 97 } ) 98 ) ).sort(); 99 } 100 101 // Check for length avoids error when initializing empty list 102 if ( this.options.active !== false && this.anchors.length ) { 103 this.active = this._findActive( options.active ); 104 } else { 105 this.active = $(); 106 } 107 108 this._refresh(); 109 110 if ( this.active.length ) { 111 this.load( options.active ); 112 } 113 }, 114 115 _initialActive: function() { 116 var active = this.options.active, 117 collapsible = this.options.collapsible, 118 locationHash = location.hash.substring( 1 ); 119 120 if ( active === null ) { 121 122 // check the fragment identifier in the URL 123 if ( locationHash ) { 124 this.tabs.each( function( i, tab ) { 125 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { 126 active = i; 127 return false; 128 } 129 } ); 130 } 131 132 // Check for a tab marked active via a class 133 if ( active === null ) { 134 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 135 } 136 137 // No active tab, set to false 138 if ( active === null || active === -1 ) { 139 active = this.tabs.length ? 0 : false; 140 } 141 } 142 143 // Handle numbers: negative, out of range 144 if ( active !== false ) { 145 active = this.tabs.index( this.tabs.eq( active ) ); 146 if ( active === -1 ) { 147 active = collapsible ? false : 0; 148 } 149 } 150 151 // Don't allow collapsible: false and active: false 152 if ( !collapsible && active === false && this.anchors.length ) { 153 active = 0; 154 } 155 156 return active; 157 }, 158 159 _getCreateEventData: function() { 160 return { 161 tab: this.active, 162 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 163 }; 164 }, 165 166 _tabKeydown: function( event ) { 167 var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ), 168 selectedIndex = this.tabs.index( focusedTab ), 169 goingForward = true; 170 171 if ( this._handlePageNav( event ) ) { 172 return; 173 } 174 175 switch ( event.keyCode ) { 176 case $.ui.keyCode.RIGHT: 177 case $.ui.keyCode.DOWN: 178 selectedIndex++; 179 break; 180 case $.ui.keyCode.UP: 181 case $.ui.keyCode.LEFT: 182 goingForward = false; 183 selectedIndex--; 184 break; 185 case $.ui.keyCode.END: 186 selectedIndex = this.anchors.length - 1; 187 break; 188 case $.ui.keyCode.HOME: 189 selectedIndex = 0; 190 break; 191 case $.ui.keyCode.SPACE: 192 193 // Activate only, no collapsing 194 event.preventDefault(); 195 clearTimeout( this.activating ); 196 this._activate( selectedIndex ); 197 return; 198 case $.ui.keyCode.ENTER: 199 200 // Toggle (cancel delayed activation, allow collapsing) 201 event.preventDefault(); 202 clearTimeout( this.activating ); 203 204 // Determine if we should collapse or activate 205 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 206 return; 207 default: 208 return; 209 } 210 211 // Focus the appropriate tab, based on which key was pressed 212 event.preventDefault(); 213 clearTimeout( this.activating ); 214 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 215 216 // Navigating with control/command key will prevent automatic activation 217 if ( !event.ctrlKey && !event.metaKey ) { 218 219 // Update aria-selected immediately so that AT think the tab is already selected. 220 // Otherwise AT may confuse the user by stating that they need to activate the tab, 221 // but the tab will already be activated by the time the announcement finishes. 222 focusedTab.attr( "aria-selected", "false" ); 223 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 224 225 this.activating = this._delay( function() { 226 this.option( "active", selectedIndex ); 227 }, this.delay ); 228 } 229 }, 230 231 _panelKeydown: function( event ) { 232 if ( this._handlePageNav( event ) ) { 233 return; 234 } 235 236 // Ctrl+up moves focus to the current tab 237 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 238 event.preventDefault(); 239 this.active.trigger( "focus" ); 240 } 241 }, 242 243 // Alt+page up/down moves focus to the previous/next tab (and activates) 244 _handlePageNav: function( event ) { 245 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 246 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 247 return true; 248 } 249 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 250 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 251 return true; 252 } 253 }, 254 255 _findNextTab: function( index, goingForward ) { 256 var lastTabIndex = this.tabs.length - 1; 257 258 function constrain() { 259 if ( index > lastTabIndex ) { 260 index = 0; 261 } 262 if ( index < 0 ) { 263 index = lastTabIndex; 264 } 265 return index; 266 } 267 268 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 269 index = goingForward ? index + 1 : index - 1; 270 } 271 272 return index; 273 }, 274 275 _focusNextTab: function( index, goingForward ) { 276 index = this._findNextTab( index, goingForward ); 277 this.tabs.eq( index ).trigger( "focus" ); 278 return index; 279 }, 280 281 _setOption: function( key, value ) { 282 if ( key === "active" ) { 283 284 // _activate() will handle invalid values and update this.options 285 this._activate( value ); 286 return; 287 } 288 289 this._super( key, value ); 290 291 if ( key === "collapsible" ) { 292 this._toggleClass( "ui-tabs-collapsible", null, value ); 293 294 // Setting collapsible: false while collapsed; open first panel 295 if ( !value && this.options.active === false ) { 296 this._activate( 0 ); 297 } 298 } 299 300 if ( key === "event" ) { 301 this._setupEvents( value ); 302 } 303 304 if ( key === "heightStyle" ) { 305 this._setupHeightStyle( value ); 306 } 307 }, 308 309 _sanitizeSelector: function( hash ) { 310 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; 311 }, 312 313 refresh: function() { 314 var options = this.options, 315 lis = this.tablist.children( ":has(a[href])" ); 316 317 // Get disabled tabs from class attribute from HTML 318 // this will get converted to a boolean if needed in _refresh() 319 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 320 return lis.index( tab ); 321 } ); 322 323 this._processTabs(); 324 325 // Was collapsed or no tabs 326 if ( options.active === false || !this.anchors.length ) { 327 options.active = false; 328 this.active = $(); 329 330 // was active, but active tab is gone 331 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 332 333 // all remaining tabs are disabled 334 if ( this.tabs.length === options.disabled.length ) { 335 options.active = false; 336 this.active = $(); 337 338 // activate previous tab 339 } else { 340 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 341 } 342 343 // was active, active tab still exists 344 } else { 345 346 // make sure active index is correct 347 options.active = this.tabs.index( this.active ); 348 } 349 350 this._refresh(); 351 }, 352 353 _refresh: function() { 354 this._setOptionDisabled( this.options.disabled ); 355 this._setupEvents( this.options.event ); 356 this._setupHeightStyle( this.options.heightStyle ); 357 358 this.tabs.not( this.active ).attr( { 359 "aria-selected": "false", 360 "aria-expanded": "false", 361 tabIndex: -1 362 } ); 363 this.panels.not( this._getPanelForTab( this.active ) ) 364 .hide() 365 .attr( { 366 "aria-hidden": "true" 367 } ); 368 369 // Make sure one tab is in the tab order 370 if ( !this.active.length ) { 371 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 372 } else { 373 this.active 374 .attr( { 375 "aria-selected": "true", 376 "aria-expanded": "true", 377 tabIndex: 0 378 } ); 379 this._addClass( this.active, "ui-tabs-active", "ui-state-active" ); 380 this._getPanelForTab( this.active ) 381 .show() 382 .attr( { 383 "aria-hidden": "false" 384 } ); 385 } 386 }, 387 388 _processTabs: function() { 389 var that = this, 390 prevTabs = this.tabs, 391 prevAnchors = this.anchors, 392 prevPanels = this.panels; 393 394 this.tablist = this._getList().attr( "role", "tablist" ); 395 this._addClass( this.tablist, "ui-tabs-nav", 396 "ui-helper-reset ui-helper-clearfix ui-widget-header" ); 397 398 // Prevent users from focusing disabled tabs via click 399 this.tablist 400 .on( "mousedown" + this.eventNamespace, "> li", function( event ) { 401 if ( $( this ).is( ".ui-state-disabled" ) ) { 402 event.preventDefault(); 403 } 404 } ) 405 406 // Support: IE <9 407 // Preventing the default action in mousedown doesn't prevent IE 408 // from focusing the element, so if the anchor gets focused, blur. 409 // We don't have to worry about focusing the previously focused 410 // element since clicking on a non-focusable element should focus 411 // the body anyway. 412 .on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() { 413 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { 414 this.blur(); 415 } 416 } ); 417 418 this.tabs = this.tablist.find( "> li:has(a[href])" ) 419 .attr( { 420 role: "tab", 421 tabIndex: -1 422 } ); 423 this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" ); 424 425 this.anchors = this.tabs.map( function() { 426 return $( "a", this )[ 0 ]; 427 } ) 428 .attr( { 429 role: "presentation", 430 tabIndex: -1 431 } ); 432 this._addClass( this.anchors, "ui-tabs-anchor" ); 433 434 this.panels = $(); 435 436 this.anchors.each( function( i, anchor ) { 437 var selector, panel, panelId, 438 anchorId = $( anchor ).uniqueId().attr( "id" ), 439 tab = $( anchor ).closest( "li" ), 440 originalAriaControls = tab.attr( "aria-controls" ); 441 442 // Inline tab 443 if ( that._isLocal( anchor ) ) { 444 selector = anchor.hash; 445 panelId = selector.substring( 1 ); 446 panel = that.element.find( that._sanitizeSelector( selector ) ); 447 448 // remote tab 449 } else { 450 451 // If the tab doesn't already have aria-controls, 452 // generate an id by using a throw-away element 453 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; 454 selector = "#" + panelId; 455 panel = that.element.find( selector ); 456 if ( !panel.length ) { 457 panel = that._createPanel( panelId ); 458 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 459 } 460 panel.attr( "aria-live", "polite" ); 461 } 462 463 if ( panel.length ) { 464 that.panels = that.panels.add( panel ); 465 } 466 if ( originalAriaControls ) { 467 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 468 } 469 tab.attr( { 470 "aria-controls": panelId, 471 "aria-labelledby": anchorId 472 } ); 473 panel.attr( "aria-labelledby", anchorId ); 474 } ); 475 476 this.panels.attr( "role", "tabpanel" ); 477 this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" ); 478 479 // Avoid memory leaks (#10056) 480 if ( prevTabs ) { 481 this._off( prevTabs.not( this.tabs ) ); 482 this._off( prevAnchors.not( this.anchors ) ); 483 this._off( prevPanels.not( this.panels ) ); 484 } 485 }, 486 487 // Allow overriding how to find the list for rare usage scenarios (#7715) 488 _getList: function() { 489 return this.tablist || this.element.find( "ol, ul" ).eq( 0 ); 490 }, 491 492 _createPanel: function( id ) { 493 return $( "<div>" ) 494 .attr( "id", id ) 495 .data( "ui-tabs-destroy", true ); 496 }, 497 498 _setOptionDisabled: function( disabled ) { 499 var currentItem, li, i; 500 501 if ( $.isArray( disabled ) ) { 502 if ( !disabled.length ) { 503 disabled = false; 504 } else if ( disabled.length === this.anchors.length ) { 505 disabled = true; 506 } 507 } 508 509 // Disable tabs 510 for ( i = 0; ( li = this.tabs[ i ] ); i++ ) { 511 currentItem = $( li ); 512 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 513 currentItem.attr( "aria-disabled", "true" ); 514 this._addClass( currentItem, null, "ui-state-disabled" ); 515 } else { 516 currentItem.removeAttr( "aria-disabled" ); 517 this._removeClass( currentItem, null, "ui-state-disabled" ); 518 } 519 } 520 521 this.options.disabled = disabled; 522 523 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, 524 disabled === true ); 525 }, 526 527 _setupEvents: function( event ) { 528 var events = {}; 529 if ( event ) { 530 $.each( event.split( " " ), function( index, eventName ) { 531 events[ eventName ] = "_eventHandler"; 532 } ); 533 } 534 535 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 536 537 // Always prevent the default action, even when disabled 538 this._on( true, this.anchors, { 539 click: function( event ) { 540 event.preventDefault(); 541 } 542 } ); 543 this._on( this.anchors, events ); 544 this._on( this.tabs, { keydown: "_tabKeydown" } ); 545 this._on( this.panels, { keydown: "_panelKeydown" } ); 546 547 this._focusable( this.tabs ); 548 this._hoverable( this.tabs ); 549 }, 550 551 _setupHeightStyle: function( heightStyle ) { 552 var maxHeight, 553 parent = this.element.parent(); 554 555 if ( heightStyle === "fill" ) { 556 maxHeight = parent.height(); 557 maxHeight -= this.element.outerHeight() - this.element.height(); 558 559 this.element.siblings( ":visible" ).each( function() { 560 var elem = $( this ), 561 position = elem.css( "position" ); 562 563 if ( position === "absolute" || position === "fixed" ) { 564 return; 565 } 566 maxHeight -= elem.outerHeight( true ); 567 } ); 568 569 this.element.children().not( this.panels ).each( function() { 570 maxHeight -= $( this ).outerHeight( true ); 571 } ); 572 573 this.panels.each( function() { 574 $( this ).height( Math.max( 0, maxHeight - 575 $( this ).innerHeight() + $( this ).height() ) ); 576 } ) 577 .css( "overflow", "auto" ); 578 } else if ( heightStyle === "auto" ) { 579 maxHeight = 0; 580 this.panels.each( function() { 581 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 582 } ).height( maxHeight ); 583 } 584 }, 585 586 _eventHandler: function( event ) { 587 var options = this.options, 588 active = this.active, 589 anchor = $( event.currentTarget ), 590 tab = anchor.closest( "li" ), 591 clickedIsActive = tab[ 0 ] === active[ 0 ], 592 collapsing = clickedIsActive && options.collapsible, 593 toShow = collapsing ? $() : this._getPanelForTab( tab ), 594 toHide = !active.length ? $() : this._getPanelForTab( active ), 595 eventData = { 596 oldTab: active, 597 oldPanel: toHide, 598 newTab: collapsing ? $() : tab, 599 newPanel: toShow 600 }; 601 602 event.preventDefault(); 603 604 if ( tab.hasClass( "ui-state-disabled" ) || 605 606 // tab is already loading 607 tab.hasClass( "ui-tabs-loading" ) || 608 609 // can't switch durning an animation 610 this.running || 611 612 // click on active header, but not collapsible 613 ( clickedIsActive && !options.collapsible ) || 614 615 // allow canceling activation 616 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 617 return; 618 } 619 620 options.active = collapsing ? false : this.tabs.index( tab ); 621 622 this.active = clickedIsActive ? $() : tab; 623 if ( this.xhr ) { 624 this.xhr.abort(); 625 } 626 627 if ( !toHide.length && !toShow.length ) { 628 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 629 } 630 631 if ( toShow.length ) { 632 this.load( this.tabs.index( tab ), event ); 633 } 634 this._toggle( event, eventData ); 635 }, 636 637 // Handles show/hide for selecting tabs 638 _toggle: function( event, eventData ) { 639 var that = this, 640 toShow = eventData.newPanel, 641 toHide = eventData.oldPanel; 642 643 this.running = true; 644 645 function complete() { 646 that.running = false; 647 that._trigger( "activate", event, eventData ); 648 } 649 650 function show() { 651 that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" ); 652 653 if ( toShow.length && that.options.show ) { 654 that._show( toShow, that.options.show, complete ); 655 } else { 656 toShow.show(); 657 complete(); 658 } 659 } 660 661 // Start out by hiding, then showing, then completing 662 if ( toHide.length && this.options.hide ) { 663 this._hide( toHide, this.options.hide, function() { 664 that._removeClass( eventData.oldTab.closest( "li" ), 665 "ui-tabs-active", "ui-state-active" ); 666 show(); 667 } ); 668 } else { 669 this._removeClass( eventData.oldTab.closest( "li" ), 670 "ui-tabs-active", "ui-state-active" ); 671 toHide.hide(); 672 show(); 673 } 674 675 toHide.attr( "aria-hidden", "true" ); 676 eventData.oldTab.attr( { 677 "aria-selected": "false", 678 "aria-expanded": "false" 679 } ); 680 681 // If we're switching tabs, remove the old tab from the tab order. 682 // If we're opening from collapsed state, remove the previous tab from the tab order. 683 // If we're collapsing, then keep the collapsing tab in the tab order. 684 if ( toShow.length && toHide.length ) { 685 eventData.oldTab.attr( "tabIndex", -1 ); 686 } else if ( toShow.length ) { 687 this.tabs.filter( function() { 688 return $( this ).attr( "tabIndex" ) === 0; 689 } ) 690 .attr( "tabIndex", -1 ); 691 } 692 693 toShow.attr( "aria-hidden", "false" ); 694 eventData.newTab.attr( { 695 "aria-selected": "true", 696 "aria-expanded": "true", 697 tabIndex: 0 698 } ); 699 }, 700 701 _activate: function( index ) { 702 var anchor, 703 active = this._findActive( index ); 704 705 // Trying to activate the already active panel 706 if ( active[ 0 ] === this.active[ 0 ] ) { 707 return; 708 } 709 710 // Trying to collapse, simulate a click on the current active header 711 if ( !active.length ) { 712 active = this.active; 713 } 714 715 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 716 this._eventHandler( { 717 target: anchor, 718 currentTarget: anchor, 719 preventDefault: $.noop 720 } ); 721 }, 722 723 _findActive: function( index ) { 724 return index === false ? $() : this.tabs.eq( index ); 725 }, 726 727 _getIndex: function( index ) { 728 729 // meta-function to give users option to provide a href string instead of a numerical index. 730 if ( typeof index === "string" ) { 731 index = this.anchors.index( this.anchors.filter( "[href$='" + 732 $.ui.escapeSelector( index ) + "']" ) ); 733 } 734 735 return index; 736 }, 737 738 _destroy: function() { 739 if ( this.xhr ) { 740 this.xhr.abort(); 741 } 742 743 this.tablist 744 .removeAttr( "role" ) 745 .off( this.eventNamespace ); 746 747 this.anchors 748 .removeAttr( "role tabIndex" ) 749 .removeUniqueId(); 750 751 this.tabs.add( this.panels ).each( function() { 752 if ( $.data( this, "ui-tabs-destroy" ) ) { 753 $( this ).remove(); 754 } else { 755 $( this ).removeAttr( "role tabIndex " + 756 "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" ); 757 } 758 } ); 759 760 this.tabs.each( function() { 761 var li = $( this ), 762 prev = li.data( "ui-tabs-aria-controls" ); 763 if ( prev ) { 764 li 765 .attr( "aria-controls", prev ) 766 .removeData( "ui-tabs-aria-controls" ); 767 } else { 768 li.removeAttr( "aria-controls" ); 769 } 770 } ); 771 772 this.panels.show(); 773 774 if ( this.options.heightStyle !== "content" ) { 775 this.panels.css( "height", "" ); 776 } 777 }, 778 779 enable: function( index ) { 780 var disabled = this.options.disabled; 781 if ( disabled === false ) { 782 return; 783 } 784 785 if ( index === undefined ) { 786 disabled = false; 787 } else { 788 index = this._getIndex( index ); 789 if ( $.isArray( disabled ) ) { 790 disabled = $.map( disabled, function( num ) { 791 return num !== index ? num : null; 792 } ); 793 } else { 794 disabled = $.map( this.tabs, function( li, num ) { 795 return num !== index ? num : null; 796 } ); 797 } 798 } 799 this._setOptionDisabled( disabled ); 800 }, 801 802 disable: function( index ) { 803 var disabled = this.options.disabled; 804 if ( disabled === true ) { 805 return; 806 } 807 808 if ( index === undefined ) { 809 disabled = true; 810 } else { 811 index = this._getIndex( index ); 812 if ( $.inArray( index, disabled ) !== -1 ) { 813 return; 814 } 815 if ( $.isArray( disabled ) ) { 816 disabled = $.merge( [ index ], disabled ).sort(); 817 } else { 818 disabled = [ index ]; 819 } 820 } 821 this._setOptionDisabled( disabled ); 822 }, 823 824 load: function( index, event ) { 825 index = this._getIndex( index ); 826 var that = this, 827 tab = this.tabs.eq( index ), 828 anchor = tab.find( ".ui-tabs-anchor" ), 829 panel = this._getPanelForTab( tab ), 830 eventData = { 831 tab: tab, 832 panel: panel 833 }, 834 complete = function( jqXHR, status ) { 835 if ( status === "abort" ) { 836 that.panels.stop( false, true ); 837 } 838 839 that._removeClass( tab, "ui-tabs-loading" ); 840 panel.removeAttr( "aria-busy" ); 841 842 if ( jqXHR === that.xhr ) { 843 delete that.xhr; 844 } 845 }; 846 847 // Not remote 848 if ( this._isLocal( anchor[ 0 ] ) ) { 849 return; 850 } 851 852 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 853 854 // Support: jQuery <1.8 855 // jQuery <1.8 returns false if the request is canceled in beforeSend, 856 // but as of 1.8, $.ajax() always returns a jqXHR object. 857 if ( this.xhr && this.xhr.statusText !== "canceled" ) { 858 this._addClass( tab, "ui-tabs-loading" ); 859 panel.attr( "aria-busy", "true" ); 860 861 this.xhr 862 .done( function( response, status, jqXHR ) { 863 864 // support: jQuery <1.8 865 // http://bugs.jquery.com/ticket/11778 866 setTimeout( function() { 867 panel.html( response ); 868 that._trigger( "load", event, eventData ); 869 870 complete( jqXHR, status ); 871 }, 1 ); 872 } ) 873 .fail( function( jqXHR, status ) { 874 875 // support: jQuery <1.8 876 // http://bugs.jquery.com/ticket/11778 877 setTimeout( function() { 878 complete( jqXHR, status ); 879 }, 1 ); 880 } ); 881 } 882 }, 883 884 _ajaxSettings: function( anchor, event, eventData ) { 885 var that = this; 886 return { 887 888 // Support: IE <11 only 889 // Strip any hash that exists to prevent errors with the Ajax request 890 url: anchor.attr( "href" ).replace( /#.*$/, "" ), 891 beforeSend: function( jqXHR, settings ) { 892 return that._trigger( "beforeLoad", event, 893 $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) ); 894 } 895 }; 896 }, 897 898 _getPanelForTab: function( tab ) { 899 var id = $( tab ).attr( "aria-controls" ); 900 return this.element.find( this._sanitizeSelector( "#" + id ) ); 901 } 902 } ); 903 904 // DEPRECATED 905 // TODO: Switch return back to widget declaration at top of file when this is removed 906 if ( $.uiBackCompat !== false ) { 907 908 // Backcompat for ui-tab class (now ui-tabs-tab) 909 $.widget( "ui.tabs", $.ui.tabs, { 910 _processTabs: function() { 911 this._superApply( arguments ); 912 this._addClass( this.tabs, "ui-tab" ); 913 } 914 } ); 915 } 916 917 return $.ui.tabs; 918 919 } ) );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Mar 1 01:00:03 2021 | Cross-referenced by PHPXref 0.7.1 |