1;(function ( $, window, undefined ) { 2 3 /** Default settings */ 4 var defaults = { 5 active: null, 6 event: 'click', 7 disabled: [], 8 collapsible: 'accordion', 9 startCollapsed: 'none', 10 rotate: false, 11 setHash: false, 12 animation: 'default', 13 animationQueue: false, 14 duration: 500, 15 fluidHeight: true, 16 scrollToAccordion: true, 17 scrollToAccordionOnLoad: false, 18 scrollToAccordionOffset: 0, 19 accordionTabElement: '<div></div>', 20 accordionAnchorHTML: '', 21 closeCurrent: true, 22 breakpoint: 767, 23 click: function(){}, 24 activate: function(){}, 25 deactivate: function(){}, 26 load: function(){}, 27 activateState: function(){}, 28 classes: { 29 stateDefault: 'r-tabs-state-default', 30 stateActive: 'r-tabs-state-active', 31 stateDisabled: 'r-tabs-state-disabled', 32 stateExcluded: 'r-tabs-state-excluded', 33 container: 'r-tabs', 34 ul: 'r-tabs-nav', 35 tab: 'r-tabs-tab', 36 anchor: 'r-tabs-anchor', 37 panel: 'r-tabs-panel', 38 accordionTitle: 'r-tabs-accordion-title', 39 elements: '.ue-element', 40 activeElements: '.ue-element.active', 41 containerPanel: '.tab-container' 42 } 43 }; 44 45 /** 46 * Responsive Tabs 47 * @constructor 48 * @param {object} element - The HTML element the validator should be bound to 49 * @param {object} options - An option map 50 */ 51 function ResponsiveContentTabs(element, options) { 52 this.element = element; // Selected DOM element 53 this.$element = $(element); // Selected jQuery element 54 55 this.tabs = []; // Create tabs array 56 this.state = ''; // Define the plugin state (tabs/accordion) 57 this.rotateInterval = 0; // Define rotate interval 58 this.$queue = $({}); 59 60 // Extend the defaults with the passed options 61 this.options = $.extend( {}, defaults, options); 62 63 this.init(); 64 } 65 66 67 /** 68 * This function initializes the tab plugin 69 */ 70 ResponsiveContentTabs.prototype.init = function () { 71 var _this = this; 72 73 // Load all the elements 74 this.tabs = this._loadElements(); 75 this._loadClasses(); 76 this._loadEvents(); 77 78 // Window resize bind to check state 79 $(window).on('resize', function(e) { 80 _this._setState(e); 81 if(_this.options.fluidHeight !== true) { 82 _this._equaliseHeights(); 83 } 84 }); 85 86 // Hashchange event 87 $(window).on('hashchange', function(e) { 88 var tabRef = _this._getTabRefBySelector(window.location.hash); 89 var oTab = _this._getTab(tabRef); 90 91 // Check if a tab is found that matches the hash 92 if(tabRef >= 0 && !oTab._ignoreHashChange && !oTab.disabled) { 93 94 //close other tabs 95 96 97 // If so, open the tab and auto close the current one 98 _this._openTab(e, _this._getTab(tabRef), true); 99 100 } 101 102 103 }); 104 105 // Start rotate event if rotate option is defined 106 if(this.options.rotate !== false) { 107 this.startRotation(); 108 } 109 110 // Set fluid height 111 if(this.options.fluidHeight !== true) { 112 _this._equaliseHeights(); 113 } 114 115 // -------------------- 116 // Define plugin events 117 // 118 119 // Activate: this event is called when a tab is selected 120 this.$element.bind('tabs-click', function(e, oTab) { 121 _this.options.click.call(this, e, oTab); 122 }); 123 124 // Activate: this event is called when a tab is selected 125 this.$element.bind('tabs-activate', function(e, oTab) { 126 _this.options.activate.call(this, e, oTab); 127 }); 128 // Deactivate: this event is called when a tab is closed 129 this.$element.bind('tabs-deactivate', function(e, oTab) { 130 _this.options.deactivate.call(this, e, oTab); 131 }); 132 // Activate State: this event is called when the plugin switches states 133 this.$element.bind('tabs-activate-state', function(e, state) { 134 _this.options.activateState.call(this, e, state); 135 }); 136 137 // Load: this event is called when the plugin has been loaded 138 this.$element.bind('tabs-load', function(e) { 139 var startTab; 140 141 _this._setState(e); // Set state 142 143 var isDesktopBeakpoint = window.matchMedia("(min-width: " + _this.options.breakpoint + "px)"); 144 145 function openFirstItem(){ 146 147 startTab = _this._getStartTab(); 148 149 // Open the initial tab 150 _this._openTab(e, startTab); // Open first tab 151 152 // Call the callback function 153 _this.options.load.call(this, e, startTab); // Call the load callback 154 } 155 156 // Check if the panel should be collapsed on load 157 if(_this.options.startCollapsed == 'none' && !(_this.options.startCollapsed === 'accordion' && _this.state === 'accordion')) 158 openFirstItem(); 159 160 // Check if the panel should be collapsed on load 161 if(_this.options.startCollapsed == 'mobile' && !(_this.options.startCollapsed === 'accordion' && _this.state === 'accordion')) { 162 163 if(isDesktopBeakpoint.matches == true) 164 openFirstItem(); 165 166 } 167 168 if(window.location.hash && _this.options.startCollapsed != 'none' && _this.options.setHash == true){ 169 170 var tabRef = _this._getTabRefBySelector(window.location.hash); 171 startTab = _this._getTab(tabRef); 172 173 if(tabRef >= 0 && !startTab.disabled) 174 openFirstItem(); 175 } 176 177 }); 178 // Trigger loaded event 179 this.$element.trigger('tabs-load'); 180 }; 181 182 // 183 // PRIVATE FUNCTIONS 184 // 185 186 /** 187 * This function loads the tab elements and stores them in an array 188 * @returns {Array} Array of tab elements 189 */ 190 ResponsiveContentTabs.prototype._loadElements = function() { 191 var _this = this; 192 var $ul = this.$element.children('ul:first'); 193 var tabs = []; 194 var id = 0; 195 196 // Add the classes to the basic html elements 197 this.$element.addClass(_this.options.classes.container); // Tab container 198 $ul.addClass(_this.options.classes.ul); // List container 199 200 // Get tab buttons and store their data in an array 201 $('li', $ul).each(function() { 202 var $tab = $(this);
203 var isExcluded = $tab.hasClass(_this.options.classes.stateExcluded); 204 var $anchor, $panel, $accordionTab, $accordionAnchor, panelSelector; 205 206 // Check if the tab should be excluded 207 if(!isExcluded) { 208 209 $anchor = $('a', $tab); 210 panelSelector = $anchor.attr('data-content-id'); 211 panelSelectorId = $anchor.attr('id'); 212 $panel = $("#"+panelSelector); 213 $accordionTab = $(_this.options.accordionTabElement).insertBefore($panel); 214 $accordionAnchor = $('<a></a>').attr('href', panelSelector).attr("rel", "nofollow").html("<div class='uc-tabs-accordion-title'>" +$anchor.html()+"</div>").appendTo($accordionTab); 215 216 if(_this.options.accordionAnchorHTML) 217 $accordionAnchor.append(_this.options.accordionAnchorHTML); 218 219 var oTab = { 220 _ignoreHashChange: false, 221 id: id, 222 disabled: ($.inArray(id, _this.options.disabled) !== -1), 223 tab: $(this), 224 anchor: $('a', $tab), 225 panel: $panel, 226 selector: panelSelectorId, 227 accordionTab: $accordionTab, 228 accordionAnchor: $accordionAnchor, 229 active: false 230 }; 231 232 // 1up the ID 233 id++; 234 // Add to tab array 235 tabs.push(oTab); 236 } 237 }); 238 return tabs; 239 }; 240 241 242 /** 243 * This function adds classes to the tab elements based on the options 244 */ 245 ResponsiveContentTabs.prototype._loadClasses = function() { 246 for (var i=0; i<this.tabs.length; i++) { 247 this.tabs[i].tab.addClass(this.options.classes.stateDefault).addClass(this.options.classes.tab); 248 this.tabs[i].anchor.addClass(this.options.classes.anchor); 249 this.tabs[i].panel.addClass(this.options.classes.stateDefault).addClass(this.options.classes.panel); 250 this.tabs[i].accordionTab.addClass(this.options.classes.accordionTitle); 251 this.tabs[i].accordionAnchor.addClass(this.options.classes.anchor); 252 if(this.tabs[i].disabled) { 253 this.tabs[i].tab.removeClass(this.options.classes.stateDefault).addClass(this.options.classes.stateDisabled); 254 this.tabs[i].accordionTab.removeClass(this.options.classes.stateDefault).addClass(this.options.classes.stateDisabled); 255 } 256 } 257 }; 258 259 /** 260 * This function adds events to the tab elements 261 */ 262 ResponsiveContentTabs.prototype._loadEvents = function() { 263 var _this = this; 264 265 // Define activate event on a tab element 266 var fActivate = function(e) { 267 var current = _this._getCurrentTab(); // Fetch current tab 268 var activatedTab = e.data.tab; 269 e.preventDefault(); 270 271 // Trigger click event for whenever a tab is clicked/touched even if the tab is disabled 272 activatedTab.tab.trigger('tabs-click', activatedTab); 273 274 // Make sure this tab isn't disabled 275 if(!activatedTab.disabled) { 276 277 // Check if hash has to be set in the URL location 278 if(_this.options.setHash) { 279 // Set the hash using the history api if available to tackle Chromes repaint bug on hash change 280 if(history.pushState) { 281 history.pushState(null, null, window.location.origin + window.location.pathname + window.location.search + activatedTab.selector); 282 } else { 283 // Otherwise fallback to the hash update for sites that don't support the history api 284 window.location.hash = activatedTab.selector; 285 } 286 } 287 288 e.data.tab._ignoreHashChange = true; 289 290 // Check if the activated tab isnt the current one or if its collapsible. If not, do nothing 291 if(current !== activatedTab || _this._isCollapisble()) { 292 // The activated tab is either another tab of the current one. If it's the current tab it is collapsible 293 // Either way, the current tab can be closed 294 295 if(current == activatedTab && _this.options.closeCurrent == true){ 296 _this._closeTab(e, current); 297 } 298
299 if(current != activatedTab || _this.getState() === 'accordion'){ 300 _this._closeTab(e, current); 301 } 302 303 // Check if the activated tab isnt the current one or if it isnt collapsible 304 if(current !== activatedTab || !_this._isCollapisble()) { 305 _this._openTab(e, activatedTab, false, true); 306 } 307 } 308 } 309 }; 310 311 // Loop tabs 312 for (var i=0; i<this.tabs.length; i++) { 313 // Add activate function to the tab and accordion selection element 314 this.tabs[i].anchor.on(_this.options.event, {tab: _this.tabs[i]}, fActivate); 315 this.tabs[i].accordionAnchor.on(_this.options.event, {tab: _this.tabs[i]}, fActivate); 316 317 this.tabs[i].anchor.on("ucclick", {tab: _this.tabs[i]}, fActivate); 318 this.tabs[i].accordionAnchor.on("ucclick", {tab: _this.tabs[i]}, fActivate); 319 320 } 321 }; 322 323 /** 324 * This function gets the tab that should be opened at start 325 * @returns {Object} Tab object 326 */ 327 ResponsiveContentTabs.prototype._getStartTab = function() { 328 var tabRef = this._getTabRefBySelector(window.location.hash); 329 var startTab; 330 331 // Check if the page has a hash set that is linked to a tab 332 if(tabRef >= 0 && !this._getTab(tabRef).disabled) { 333 // If so, set the current tab to the linked tab 334 startTab = this._getTab(tabRef); 335 } else if(this.options.active > 0 && !this._getTab(this.options.active).disabled) { 336 startTab = this._getTab(this.options.active); 337 } else { 338 // If not, just get the first one 339 startTab = this._getTab(0); 340 } 341 342 return startTab; 343 }; 344 345 /** 346 * This function sets the current state of the plugin 347 * @param {Event} e - The event that triggers the state change 348 */ 349 ResponsiveContentTabs.prototype._setState = function(e) { 350 var $ul = $('ul:first', this.$element); 351 var oldState = this.state; 352 var startCollapsedIsState = (typeof this.options.startCollapsed === 'string'); 353 var startTab; 354 355 // The state is based on the visibility of the tabs list 356 if($ul.is(':visible')){ 357 // Tab list is visible, so the state is 'tabs' 358 this.state = 'tabs'; 359 } else { 360 // Tab list is invisible, so the state is 'accordion' 361 362 this.state = 'accordion'; 363 } 364 365 // If the new state is different from the old state 366 if(this.state !== oldState) { 367 // If so, the state activate trigger must be called 368 this.$element.trigger('tabs-activate-state', {oldState: oldState, newState: this.state}); 369 370 // Check if the state switch should open a tab 371 if(oldState && startCollapsedIsState && this.options.startCollapsed !== this.state && this._getCurrentTab() === undefined) { 372 // Get initial tab 373 startTab = this._getStartTab(e); 374 // Open the initial tab 375 this._openTab(e, startTab); // Open first tab 376 } 377 } 378 }; 379 380 /** 381 * This function opens a tab 382 * @param {Event} e - The event that triggers the tab opening 383 * @param {Object} oTab - The tab object that should be opened 384 * @param {Boolean} closeCurrent - Defines if the current tab should be closed 385 * @param {Boolean} stopRotation - Defines if the tab rotation loop should be stopped 386 */ 387 ResponsiveContentTabs.prototype._openTab = function(e, oTab, closeCurrent, stopRotation) { 388 389 //protection from synced parent invisible elementor container 390 var objHiddenParentDesktop = jQuery(oTab.accordionTab).parents('.elementor-hidden-desktop'); 391 var objHiddenParentTablet = jQuery(oTab.accordionTab).parents('.elementor-hidden-tablet'); 392 var objHiddenParentMobile = jQuery(oTab.accordionTab).parents('.elementor-hidden-mobile'); 393 394 if(objHiddenParentDesktop.length >= 1 && objHiddenParentDesktop.is(':visible') == false) 395 return(false); 396 397 if(objHiddenParentTablet.length >= 1 && objHiddenParentTablet.is(':visible') == false) 398 return(false); 399 400 if(objHiddenParentTablet.length >= 1 &&objHiddenParentMobile.is(':visible') == false) 401 return(false); 402 403 var _this = this; 404 var scrollOffset; 405 406 // Check if the current tab has to be closed 407 408 if(_this.options.closeCurrent == true) { 409 this._closeTab(e, this._getCurrentTab()); 410 } 411 412 // Check if the rotation has to be stopped when activated 413 if(stopRotation && this.rotateInterval > 0) { 414 this.stopRotation(); 415 } 416 417 if(oTab == undefined) 418 return(false) 419 420 // Set this tab to active 421 oTab.active = true; 422 // Set active classes to the tab button and accordion tab button 423
424 if(_this.getState() === 'tabs'){ 425 oTab.tab.removeClass(_this.options.classes.stateDefault).addClass(_this.options.classes.stateActive); 426 } 427 428 if(_this.getState() === 'accordion'){ 429 oTab.accordionTab.removeClass(_this.options.classes.stateDefault).addClass(_this.options.classes.stateActive); 430 } 431 432 // Run panel transiton 433 _this._doTransition(oTab.panel, _this.options.animation, 'open', function() { 434 var scrollOnLoad = (e.type !== 'tabs-load' || _this.options.scrollToAccordionOnLoad); 435 436 // When finished, set active class to the panel 437 oTab.panel.removeClass(_this.options.classes.stateDefault).addClass(_this.options.classes.stateActive); 438 439 // And if enabled and state is accordion, scroll to the accordion tab 440 if(_this.getState() === 'accordion' && _this.options.scrollToAccordion && (!_this._isInView(oTab.accordionTab) || _this.options.animation !== 'default') && scrollOnLoad) { 441 442 // Add offset element's height to scroll position 443 scrollOffset = oTab.accordionTab.offset().top - _this.options.scrollToAccordionOffset; 444 445 // Check if the animation option is enabled, and if the duration isn't 0 446 if(_this.options.animation !== 'default' && _this.options.duration > 0) { 447 // If so, set scrollTop with animate and use the 'animation' duration 448 $('html, body').animate({ 449 scrollTop: scrollOffset 450 }, _this.options.duration); 451 } else { 452 // If not, just set scrollTop 453 $('html, body').scrollTop(scrollOffset); 454 } 455 } 456 }); 457 458 this.$element.trigger('tabs-activate', oTab); 459 460 // show/hide elements by id 461 462 var elements = defaults.classes.elements; 463 464 if(jQuery(elements).length < 0){ 465 return true 466 } 467 468 var objTabs = this.$element; 469 var container = defaults.classes.containerPanel; 470 var parentElement = jQuery(elements).parents(container); 471 var elementParentIndex; 472 var elementParentArray = []; 473 474 parentElement.each(function(){ 475 elementParentIndex = Math.floor(jQuery(this).index() / 2); 476 elementParentArray.push(elementParentIndex); 477 }); 478 479 // hide container when tab with elements to show is clicked 480 481 function hideContainer(){ 482 jQuery(elements).parents(container).hide(); 483 } 484 485 if(elementParentIndex == 0){ 486 hideContainer(); 487 } 488 489 var elementsId; 490 var currentTabIndex = jQuery(oTab.tab[0]).index(); 491 492 // hide all elements 493 494 jQuery(elements).each(function(){ 495 496 elementsId = jQuery(this).data('id'); 497 var elementsIdArray = elementsId.split(','); 498 499 elementsIdArray.forEach(function(value){ 500 var element = jQuery("#" + value); 501 element.hide(); 502 503 // show elements if in editor and debug mode is true 504 505 var dataDebug = _this.$element.data("debug"); 506 var dataEditor = _this.$element.data("editor"); 507 508 if(dataEditor == "yes" && dataDebug == true){ 509 element.show(); 510 element.css({"border": "3px solid red"}); 511 }else{ 512 element.css({"border": "none"}); 513 } 514 }); 515 }); 516 517 // find active elements 518 objTabs.find(container).find(elements).removeClass('active'); 519 objTabs.find(container).eq(currentTabIndex).find(elements).addClass('active'); 520 521 var activeElements = jQuery(defaults.classes.activeElements); 522 523 // show active elements 524 525 jQuery(activeElements).each(function(){ 526 527 elementsId = jQuery(this).data('id'); 528 var elementsIdArray = elementsId.split(','); 529 530 elementsIdArray.forEach(function(value){ 531 var element = jQuery("#" + value); 532 533 elementParentArray.forEach(function(index, value){ 534 535 if(currentTabIndex == index){ 536 element.show(); 537 hideContainer(); 538 } 539 }); 540 }); 541 }); 542 }; 543 544 /** 545 * This function closes a tab 546 * @param {Event} e - The event that is triggered when a tab is closed 547 * @param {Object} oTab - The tab object that should be closed 548 */ 549 ResponsiveContentTabs.prototype._closeTab = function(e, oTab) { 550 var _this = this; 551 var doQueueOnState = typeof _this.options.animationQueue === 'string'; 552 var doQueue; 553 554 if(oTab !== undefined) {
555 if(doQueueOnState && _this.getState() === _this.options.animationQueue) { 556 doQueue = true; 557 } else if(doQueueOnState) { 558 doQueue = false; 559 } else { 560 doQueue = _this.options.animationQueue; 561 } 562 563 // Deactivate tab 564 oTab.active = false; 565 // Set default class to the tab button 566 if(_this.getState() === 'tabs'){ 567 oTab.tab.removeClass(_this.options.classes.stateActive).addClass(_this.options.classes.stateDefault); 568 } 569 570 if(_this.getState() === 'accordion'){ 571 oTab.accordionTab.removeClass(_this.options.classes.stateActive).addClass(_this.options.classes.stateDefault); 572 } 573 574 // Run panel transition 575 _this._doTransition(oTab.panel, _this.options.animation, 'close', function() { 576 // Set default class to the accordion tab button and tab panel 577 oTab.accordionTab.removeClass(_this.options.classes.stateActive).addClass(_this.options.classes.stateDefault); 578 oTab.panel.removeClass(_this.options.classes.stateActive).addClass(_this.options.classes.stateDefault); 579 }, !doQueue); 580 581 this.$element.trigger('tabs-deactivate', oTab); 582 } 583 }; 584 585 /** 586 * This function runs an effect on a panel 587 * @param {Element} panel - The HTML element of the tab panel 588 * @param {String} method - The transition method reference 589 * @param {String} state - The state (open/closed) that the panel should transition to 590 * @param {Function} callback - The callback function that is called after the transition 591 * @param {Boolean} dequeue - Defines if the event queue should be dequeued after the transition 592 */ 593 ResponsiveContentTabs.prototype._doTransition = function(panel, method, state, callback, dequeue) { 594 var effect; 595 var _this = this; 596 597 // Get effect based on method 598 switch(method) { 599 case 'slide': 600 effect = (state === 'open') ? 'slideDown' : 'slideUp'; 601 break; 602 case 'fade': 603 effect = (state === 'open') ? 'fadeIn' : 'fadeOut'; 604 break; 605 default: 606 effect = (state === 'open') ? 'show' : 'hide'; 607 // When default is used, set the duration to 0 608 _this.options.duration = 0; 609 break; 610 } 611 612 // Add the transition to a custom queue 613 this.$queue.queue('responsive-tabs',function(next){ 614 // Run the transition on the panel 615 panel[effect]({ 616 duration: _this.options.duration, 617 complete: function() { 618 // Call the callback function 619 callback.call(panel, method, state); 620 // Run the next function in the queue 621 next(); 622 } 623 }); 624 }); 625 626 // When the panel is openend, dequeue everything so the animation starts 627 if(state === 'open' || dequeue) { 628 this.$queue.dequeue('responsive-tabs'); 629 } 630 631 }; 632 633 /** 634 * This function returns the collapsibility of the tab in this state 635 * @returns {Boolean} The collapsibility of the tab 636 */ 637 ResponsiveContentTabs.prototype._isCollapisble = function() { 638 return (typeof this.options.collapsible === 'boolean' && this.options.collapsible) || (typeof this.options.collapsible === 'string' && this.options.collapsible === this.getState()); 639 }; 640 641 /** 642 * This function returns a tab by numeric reference 643 * @param {Integer} numRef - Numeric tab reference 644 * @returns {Object} Tab object 645 */ 646 ResponsiveContentTabs.prototype._getTab = function(numRef) { 647 return this.tabs[numRef]; 648 }; 649 650 /** 651 * This function returns the numeric tab reference based on a hash selector 652 * @param {String} selector - Hash selector 653 * @returns {Integer} Numeric tab reference 654 */ 655 ResponsiveContentTabs.prototype._getTabRefBySelector = function(selector) { 656 // Loop all tabs 657 658 for (var i=0; i<this.tabs.length; i++) { 659 // Check if the hash selector is equal to the tab selector 660 if(this.tabs[i].selector === selector) { 661 return i; 662 } 663 } 664 // If none is found return a negative index 665 return -1; 666 }; 667 668 /** 669 * This function returns the current tab element 670 * @returns {Object} Current tab element 671 */ 672 ResponsiveContentTabs.prototype._getCurrentTab = function() { 673 return this._getTab(this._getCurrentTabRef()); 674 }; 675 676 /** 677 * This function returns the next tab's numeric reference 678 * @param {Integer} currentTabRef - Current numeric tab reference 679 * @returns {Integer} Numeric tab reference 680 */ 681 ResponsiveContentTabs.prototype._getNextTabRef = function(currentTabRef) { 682 var tabRef = (currentTabRef || this._getCurrentTabRef()); 683 var nextTabRef = (tabRef === this.tabs.length - 1) ? 0 : tabRef + 1; 684 return (this._getTab(nextTabRef).disabled) ? this._getNextTabRef(nextTabRef) : nextTabRef; 685 }; 686 687 /** 688 * This function returns the previous tab's numeric reference 689 * @returns {Integer} Numeric tab reference 690 */ 691 ResponsiveContentTabs.prototype._getPreviousTabRef = function() { 692 return (this._getCurrentTabRef() === 0) ? this.tabs.length - 1 : this._getCurrentTabRef() - 1; 693 }; 694 695 /** 696 * This function returns the current tab's numeric reference 697 * @returns {Integer} Numeric tab reference 698 */ 699 ResponsiveContentTabs.prototype._getCurrentTabRef = function() { 700 // Loop all tabs 701 for (var i=0; i<this.tabs.length; i++) { 702 // If this tab is active, return it 703 if(this.tabs[i].active) { 704 return i; 705 } 706 } 707 // No tabs have been found, return negative index 708 return -1; 709 }; 710 711 /** 712 * This function gets the tallest tab and applied the height to all tabs 713 */ 714 ResponsiveContentTabs.prototype._equaliseHeights = function() { 715 var maxHeight = 0; 716 717 $.each($.map(this.tabs, function(tab) { 718 maxHeight = Math.max(maxHeight, tab.panel.css('minHeight', '').height()); 719 return tab.panel; 720 }), function() { 721 this.css('minHeight', maxHeight); 722 }); 723 }; 724 725 // 726 // HELPER FUNCTIONS 727 // 728 729 ResponsiveContentTabs.prototype._isInView = function($element) { 730 var docViewTop = $(window).scrollTop(), 731 docViewBottom = docViewTop + $(window).height(), 732 elemTop = $element.offset().top, 733 elemBottom = elemTop + $element.height(); 734 return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); 735 }; 736 737 // 738 // PUBLIC FUNCTIONS 739 // 740 741 /** 742 * This function activates a tab 743 * @param {Integer} tabRef - Numeric tab reference 744 * @param {Boolean} stopRotation - Defines if the tab rotation should stop after activation 745 */ 746 ResponsiveContentTabs.prototype.activate = function(tabRef, stopRotation) { 747 var e = jQuery.Event('tabs-activate'); 748 var oTab = this._getTab(tabRef); 749 750 if(!oTab.disabled) { 751 this._openTab(e, oTab, true, stopRotation || true); 752 } 753 }; 754 755 /** 756 * This function deactivates a tab 757 * @param {Integer} tabRef - Numeric tab reference 758 */ 759 ResponsiveContentTabs.prototype.deactivate = function(tabRef) { 760 var e = jQuery.Event('tabs-dectivate'); 761 var oTab = this._getTab(tabRef); 762 if(!oTab.disabled) { 763 this._closeTab(e, oTab); 764 } 765 }; 766 767 /** 768 * This function enables a tab 769 * @param {Integer} tabRef - Numeric tab reference 770 */ 771 ResponsiveContentTabs.prototype.enable = function(tabRef) { 772 var oTab = this._getTab(tabRef); 773 if(oTab){ 774 oTab.disabled = false;
775 oTab.tab.addClass(this.options.classes.stateDefault).removeClass(this.options.classes.stateDisabled); 776 oTab.accordionTab.addClass(this.options.classes.stateDefault).removeClass(this.options.classes.stateDisabled); 777 } 778 }; 779 780 /** 781 * This function disable a tab 782 * @param {Integer} tabRef - Numeric tab reference 783 */ 784 ResponsiveContentTabs.prototype.disable = function(tabRef) { 785 var oTab = this._getTab(tabRef); 786 if(oTab){ 787 oTab.disabled = true; 788 oTab.tab.removeClass(this.options.classes.stateDefault).addClass(this.options.classes.stateDisabled); 789 oTab.accordionTab.removeClass(this.options.classes.stateDefault).addClass(this.options.classes.stateDisabled); 790 } 791 }; 792 793 /** 794 * This function gets the current state of the plugin 795 * @returns {String} State of the plugin 796 */ 797 ResponsiveContentTabs.prototype.getState = function() { 798 return this.state; 799 }; 800 801 /** 802 * This function starts the rotation of the tabs 803 * @param {Integer} speed - The speed of the rotation 804 */ 805 ResponsiveContentTabs.prototype.startRotation = function(speed) { 806 var _this = this; 807 // Make sure not all tabs are disabled 808 if(this.tabs.length > this.options.disabled.length) { 809 this.rotateInterval = setInterval(function(){ 810 var e = jQuery.Event('rotate'); 811 _this._openTab(e, _this._getTab(_this._getNextTabRef()), true); 812 }, speed || (($.isNumeric(_this.options.rotate)) ? _this.options.rotate : 4000) ); 813 } else { 814 throw new Error("Rotation is not possible if all tabs are disabled"); 815 } 816 }; 817 818 /** 819 * This function stops the rotation of the tabs 820 */ 821 ResponsiveContentTabs.prototype.stopRotation = function() { 822 window.clearInterval(this.rotateInterval); 823 this.rotateInterval = 0; 824 }; 825 826 /** 827 * This function can be used to get/set options 828 * @return {any} Option value 829 */ 830 ResponsiveContentTabs.prototype.option = function(key, value) { 831 if(value) { 832 this.options[key] = value; 833 } 834 return this.options[key]; 835 }; 836 837 /** jQuery wrapper */ 838 $.fn.responsiveContentTabs = function ( event, options ) { 839 var args = arguments; 840 var instance; 841 842 if(event == 'init'){ 843 844 if (options === undefined || typeof options === 'object') { 845 return this.each(function () { 846 if (!$.data(this, 'responsivecontenttabs')) { 847 $.data(this, 'responsivecontenttabs', new ResponsiveContentTabs( this, options )); 848 } 849 }); 850 } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') { 851 instance = $.data(this[0], 'responsivecontenttabs'); 852 853 // Allow instances to be destroyed via the 'destroy' method 854 if (options === 'destroy') { 855 // TODO: destroy instance classes, etc 856 $.data(this, 'responsivecontenttabs', null); 857 } 858 859 if (instance instanceof ResponsiveContentTabs && typeof instance[options] === 'function') { 860 return instance[options].apply( instance, Array.prototype.slice.call( args, 1 ) ); 861 } else { 862 return this; 863 } 864 } 865 866 } 867 868 if(event == 'reinit'){ 869 870 if (options === undefined || typeof options === 'object') { 871 872 if (!$.data(this, 'responsivecontenttabs')) { 873 $.data(this, 'responsivecontenttabs', new ResponsiveContentTabs( this, options )); 874 } 875 876 } 877 878 } 879 880 881 }; 882 883}(jQuery, window));
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.