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