PageSourceSearch

https://eternal-landscapes.co.uk/wp-content/uploads/ac_assets/uc_c…/jquery.responsiveContentTabs.js?ver=2.0.21

js eternal-landscapes.co.uk collected 2026-10-02 08:41:16 UTC 30,380 bytes, 883 lines download raw bytes

1;(function ( $, window, undefined ) {
2  
3  /** Default settings */
4  var defaults = {
5    active: null,
6    event: 'click',
7    disabled: [],
8    collapsible: 'accordion',
9    startCollapsed: false,
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    click: function(){},
22    activate: function(){},
23    deactivate: function(){},
24    load: function(){},
25    activateState: function(){},
26    classes: {
27      stateDefault: 'r-tabs-state-default',
28      stateActive: 'r-tabs-state-active',
29      stateDisabled: 'r-tabs-state-disabled',
30      stateExcluded: 'r-tabs-state-excluded',
31      container: 'r-tabs',
32      ul: 'r-tabs-nav',
33      tab: 'r-tabs-tab',
34      anchor: 'r-tabs-anchor',
35      panel: 'r-tabs-panel',
36      accordionTitle: 'r-tabs-accordion-title',
37      elements: '.ue-element',
38      activeElements: '.ue-element.active',
39      containerPanel: '.tab-container'
40    }
41  };
42  
43  /**
44  * Responsive Tabs
45  * @constructor
46  * @param {object} element - The HTML element the validator should be bound to
47  * @param {object} options - An option map
48  */
49  function ResponsiveContentTabs(element, options) {
50    this.element = element; // Selected DOM element
51    this.$element = $(element); // Selected jQuery element
52    
53    this.tabs = []; // Create tabs array
54    this.state = ''; // Define the plugin state (tabs/accordion)
55    this.rotateInterval = 0; // Define rotate interval
56    this.$queue = $({});
57    
58    // Extend the defaults with the passed options
59    this.options = $.extend( {}, defaults, options);
60    
61    this.init();
62  }
63  
64  
65  /**
66  * This function initializes the tab plugin
67  */
68  ResponsiveContentTabs.prototype.init = function () {
69    var _this = this;
70    
71    // Load all the elements
72    this.tabs = this._loadElements();
73    this._loadClasses();
74    this._loadEvents();
75    
76    // Window resize bind to check state
77    $(window).on('resize', function(e) {
78      _this._setState(e);
79      if(_this.options.fluidHeight !== true) {
80        _this._equaliseHeights();
81      }
82    });
83    
84    // Hashchange event
85    $(window).on('hashchange', function(e) {
86      setTimeout(function() {
87        var tabRef = _this._getTabRefBySelector(window.location.hash);
88        var oTab = _this._getTab(tabRef);
89        if(tabRef >= 0 && !oTab._ignoreHashChange && !oTab.disabled) {                  
90          _this._openTab(e, _this._getTab(tabRef), true);        
91        }
92        if(oTab) oTab._ignoreHashChange = false; // Reset it
93      }, 20);
94    });
95    
96    // Start rotate event if rotate option is defined
97    if(this.options.rotate !== false) {
98      this.startRotation();
99    }
100    
101    // Set fluid height
102    if(this.options.fluidHeight !== true) {
103      _this._equaliseHeights();
104    }
105    
106    // --------------------
107    // Define plugin events
108    //
109    
110    // Activate: this event is called when a tab is selected
111    this.$element.bind('tabs-click', function(e, oTab) {     
112      _this.options.click.call(this, e, oTab);
113    });
114    
115    // Activate: this event is called when a tab is selected
116    this.$element.bind('tabs-activate', function(e, oTab) {
117      _this.options.activate.call(this, e, oTab);
118      
119      //add active class to tab if it wasn't added
120      if(oTab.tab.hasClass(_this.options.classes.stateActive) == false){
121        oTab.tab.addClass(_this.options.classes.stateActive);
122      }
123    });
124    
125    // Deactivate: this event is called when a tab is closed
126    this.$element.bind('tabs-deactivate', function(e, oTab) {
127      _this.options.deactivate.call(this, e, oTab);
128      
129      //remove active class from tab if it wasn't removed
130      if(oTab.tab.hasClass(_this.options.classes.stateActive) == true){
131        oTab.tab.removeClass(_this.options.classes.stateActive);
132      }
133    });
134    // Activate State: this event is called when the plugin switches states
135    this.$element.bind('tabs-activate-state', function(e, state) {
136      _this.options.activateState.call(this, e, state);
137    });
138    
139    // Load: this event is called when the plugin has been loaded
140    this.$element.bind('tabs-load', function(e) {
141      var startTab;
142      
143      _this._setState(e); // Set state
144      
145      var isDesktopBeakpoint = window.matchMedia("(min-width: " + _this.options.breakpoint + "px)");
146      
147      function openFirstItem(){
148        
149        startTab = _this._getStartTab();
150        
151        // Open the initial tab
152        _this._openTab(e, startTab); // Open first tab
153        
154        // Call the callback function
155        _this.options.load.call(this, e, startTab); // Call the load callback
156      }
157      
158      // Check if the panel should be collapsed on load
159      if(_this.options.startCollapsed == 'none' && !(_this.options.startCollapsed === 'accordion' && _this.state === 'accordion'))
160        openFirstItem();
161      
162      // Check if the panel should be collapsed on load
163      if(_this.options.startCollapsed == 'mobile' && !(_this.options.startCollapsed === 'accordion' && _this.state === 'accordion')) {
164        
165        if(isDesktopBeakpoint.matches == true)
166          openFirstItem();
167        
168      }
169      
170      if(window.location.hash && _this.options.startCollapsed != 'none' && _this.options.setHash == true){
171        
172        var tabRef = _this._getTabRefBySelector(window.location.hash);
173        startTab = _this._getTab(tabRef);
174        
175        if(tabRef >= 0 && !startTab.disabled)
176          openFirstItem();
177      }
178      
179    });
180    // Trigger loaded event
181    this.$element.trigger('tabs-load');
182  };
183  
184  //
185  // PRIVATE FUNCTIONS
186  //
187  
188  /**
189  * This function loads the tab elements and stores them in an array
190  * @returns {Array} Array of tab elements
191  */
192  ResponsiveContentTabs.prototype._loadElements = function() {
193    var _this = this;
194    var $ul = this.$element.children('ul:first');
195    var tabs = [];
196    var id = 0;
197    
198    // Add the classes to the basic html elements
199    this.$element.addClass(_this.options.classes.container); // Tab container
200    $ul.addClass(_this.options.classes.ul); // List container
201    
202    // Get tab buttons and store their data in an array
203    $('li', $ul).each(function() {
204      var $tab = $(this);
205      var isExcluded = $tab.hasClass(_this.options.classes.stateExcluded);
206      var $anchor, $panel, $accordionTab, $accordionAnchor, panelSelector;
207      
208      // Check if the tab should be excluded
209      if(!isExcluded) {
210        
211        $anchor = $('a', $tab);
212        panelSelector = $anchor.attr('data-content-id');
213        panelSelectorId = $anchor.attr('data-hash-id');
214        $panel = $("#"+panelSelector);
215        $accordionTab = $(_this.options.accordionTabElement).insertBefore($panel);
216        $accordionAnchor = $('<a></a>').attr('href', panelSelector).attr("data-e-disable-page-transition", true).attr("rel", "nofollow").html("<div class='uc-tabs-accordion-title'>" +$anchor.html()+"</div>").appendTo($accordionTab);
217        
218        if(_this.options.accordionAnchorHTML)
219          $accordionAnchor.append(_this.options.accordionAnchorHTML);				
220        
221        var oTab = {
222          _ignoreHashChange: false,
223          id: id,
224          disabled: ($.inArray(id, _this.options.disabled) !== -1),
225          tab: $(this),
226          anchor: $('a', $tab),
227          panel: $panel,
228          selector: panelSelectorId,
229          accordionTab: $accordionTab,
230          accordionAnchor: $accordionAnchor,
231          active: false
232        };
233        
234        // 1up the ID
235        id++;
236        // Add to tab array
237        tabs.push(oTab);
238      }
239    });
240    return tabs;
241  };
242  
243  
244  /**
245  * This function adds classes to the tab elements based on the options
246  */
247  ResponsiveContentTabs.prototype._loadClasses = function() {
248    for (var i=0; i<this.tabs.length; i++) {
249      this.tabs[i].tab.addClass(this.options.classes.stateDefault).addClass(this.options.classes.tab);
250      this.tabs[i].anchor.addClass(this.options.classes.anchor);
251      this.tabs[i].panel.addClass(this.options.classes.stateDefault).addClass(this.options.classes.panel);
252      this.tabs[i].accordionTab.addClass(this.options.classes.accordionTitle);
253      this.tabs[i].accordionAnchor.addClass(this.options.classes.anchor);
254      if(this.tabs[i].disabled) {
255        this.tabs[i].tab.removeClass(this.options.classes.stateDefault).addClass(this.options.classes.stateDisabled);
256        this.tabs[i].accordionTab.removeClass(this.options.classes.stateDefault).addClass(this.options.classes.stateDisabled);
257      }
258    }
259  };
260  
261  /**
262  * This function adds events to the tab elements
263  */
264  ResponsiveContentTabs.prototype._loadEvents = function() {
265    var _this = this;
266    
267    // Define activate event on a tab element
268    var fActivate = function(e) {
269      var current = _this._getCurrentTab(); // Fetch current tab
270      var activatedTab = e.data.tab;
271      e.preventDefault();
272      
273      // Trigger click event for whenever a tab is clicked/touched even if the tab is disabled
274      activatedTab.tab.trigger('tabs-click', activatedTab);
275      
276      // Make sure this tab isn't disabled
277      if(!activatedTab.disabled) {
278        
279        // Check if hash has to be set in the URL location
280        if(_this.options.setHash) {
281          // Set the hash using the history api if available to tackle Chromes repaint bug on hash change
282          if(history.pushState) {
283            history.pushState(null, null, window.location.origin + window.location.pathname + window.location.search + activatedTab.selector);
284          } else {
285            // Otherwise fallback to the hash update for sites that don't support the history api
286            window.location.hash = activatedTab.selector;
287          }
288        }
289        
290        e.data.tab._ignoreHashChange = true;
291        
292        // Check if the activated tab isnt the current one or if its collapsible. If not, do nothing
293        if(current !== activatedTab || _this._isCollapisble()) {
294          // The activated tab is either another tab of the current one. If it's the current tab it is collapsible
295          // Either way, the current tab can be closed
296          //if closeCurrent is false, state is tabs and current == activatedTab do not close
297          if(_this.options.closeCurrent === false && _this.getState() === 'tabs' && current === activatedTab) {
298          }else
299            _this._closeTab(e, current);
300          
301          // Check if the activated tab isnt the current one or if it isnt collapsible
302          if(current !== activatedTab || !_this._isCollapisble()) {
303            _this._openTab(e, activatedTab, false, true);
304          }
305        }
306      }
307    };
308    
309    // Loop tabs
310    for (var i=0; i<this.tabs.length; i++) {
311      // Add activate function to the tab and accordion selection element
312      this.tabs[i].anchor.on(_this.options.event, {tab: _this.tabs[i]}, fActivate);
313      this.tabs[i].accordionAnchor.on(_this.options.event, {tab: _this.tabs[i]}, fActivate);
314      
315      this.tabs[i].anchor.on("ucclick", {tab: _this.tabs[i]}, fActivate);
316      this.tabs[i].accordionAnchor.on("ucclick", {tab: _this.tabs[i]}, fActivate);
317      
318    }
319  };
320  
321  /**
322  * This function gets the tab that should be opened at start
323  * @returns {Object} Tab object
324  */
325  ResponsiveContentTabs.prototype._getStartTab = function() {
326    var tabRef = this._getTabRefBySelector(window.location.hash);
327    var startTab;
328    
329    // Check if the page has a hash set that is linked to a tab
330    if(tabRef >= 0 && !this._getTab(tabRef).disabled) {
331      // If so, set the current tab to the linked tab
332      startTab = this._getTab(tabRef);
333    } else if(this.options.active > 0 && !this._getTab(this.options.active).disabled) {
334      startTab = this._getTab(this.options.active);
335    } else {
336      // If not, just get the first one
337      startTab = this._getTab(0);
338    }
339    
340    return startTab;
341  };
342  
343  /**
344  * This function sets the current state of the plugin
345  * @param {Event} e - The event that triggers the state change
346  */
347  ResponsiveContentTabs.prototype._setState = function(e) {
348    var $ul = $('ul:first', this.$element);
349    var oldState = this.state;
350    var startCollapsedIsState = (typeof this.options.startCollapsed === 'string');
351    var startTab;
352    
353    // The state is based on the visibility of the tabs list
354    if($ul.is(':visible')){
355      // Tab list is visible, so the state is 'tabs'
356      this.state = 'tabs';
357      
358    } else { 
359      // Tab list is invisible, so the state is 'accordion' 
360      
361      this.state = 'accordion';
362      
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  /**
382  * This function opens a tab
383  * @param {Event} e - The event that triggers the tab opening
384  * @param {Object} oTab - The tab object that should be opened
385  * @param {Boolean} closeCurrent - Defines if the current tab should be closed
386  * @param {Boolean} stopRotation - Defines if the tab rotation loop should be stopped
387  */
388  ResponsiveContentTabs.prototype._openTab = function(e, oTab, closeCurrent, stopRotation) {
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    var dataDeviceMode = jQuery('body').attr("data-elementor-device-mode");
394    
395    // if(objHiddenParentDesktop.length >= 1 && objHiddenParentDesktop.is(':visible') == false && dataDeviceMode == 'desktop')
396    //   return(false);
397    
398    // if(objHiddenParentTablet.length >= 1 && objHiddenParentTablet.is(':visible') == false && dataDeviceMode == 'tablet')
399    //   return(false);
400    
401    // if(objHiddenParentTablet.length >= 1 && objHiddenParentMobile.is(':visible') == false && dataDeviceMode == 'mobile')
402    //   return(false);  
403    
404    var _this = this;
405    var scrollOffset;
406    // Check if the current tab has to be closed
407    if(closeCurrent || _this.options.closeCurrent === true) {
408      this._closeTab(e, this._getCurrentTab());
409    }
410    
411    // Check if the rotation has to be stopped when activated
412    if(stopRotation && this.rotateInterval > 0) {
413      this.stopRotation();
414    }
415    
416    if(oTab == undefined)
417      return(false)
418    
419    // Set this tab to active
420    oTab.active = true;
421    // Set active classes to the tab button and accordion tab button
422    
423    if(_this.getState() === 'tabs'){
424      oTab.tab.removeClass(_this.options.classes.stateDefault).addClass(_this.options.classes.stateActive);     
425    }
426    
427    if(_this.getState() === 'accordion'){
428      oTab.accordionTab.removeClass(_this.options.classes.stateDefault).addClass(_this.options.classes.stateActive);    
429    }
430    
431    // Run panel transiton
432    _this._doTransition(oTab.panel, _this.options.animation, 'open', function() {
433      var scrollOnLoad = (e.type !== 'tabs-load' || _this.options.scrollToAccordionOnLoad);
434      
435      // When finished, set active class to the panel
436      oTab.panel.removeClass(_this.options.classes.stateDefault).addClass(_this.options.classes.stateActive);
437      
438      // And if enabled and state is accordion, scroll to the accordion tab
439      if(_this.getState() === 'accordion' && _this.options.scrollToAccordion && (!_this._isInView(oTab.accordionTab) || _this.options.animation !== 'default') && scrollOnLoad) {
440        
441        // Add offset element's height to scroll position
442        scrollOffset = oTab.accordionTab.offset().top - _this.options.scrollToAccordionOffset;
443        
444        // Check if the animation option is enabled, and if the duration isn't 0
445        if(_this.options.animation !== 'default' && _this.options.duration > 0) {
446          // If so, set scrollTop with animate and use the 'animation' duration
447          $('html, body').animate({
448            scrollTop: scrollOffset
449          }, _this.options.duration);
450        } else {
451          //  If not, just set scrollTop
452          $('html, body').scrollTop(scrollOffset);
453        }
454      }
455    });
456    
457    this.$element.trigger('tabs-activate', oTab);
458    
459    // show/hide elements by id
460    
461    var elements = defaults.classes.elements;
462    
463    if(jQuery(elements).length < 0){
464      return true
465    }
466    
467    var objTabs = this.$element;
468    var container = defaults.classes.containerPanel;
469    var parentElement = jQuery(elements).parents(container);
470    var elementParentIndex;
471    var elementParentArray = [];
472    
473    parentElement.each(function(){
474      elementParentIndex = Math.floor(jQuery(this).index() / 2);
475      elementParentArray.push(elementParentIndex);
476    });
477    
478    // hide container when tab with elements to show is clicked
479    
480    function hideContainer(){
481      jQuery(elements).parents(container).hide();
482    }
483    
484    if(elementParentIndex == 0){
485      hideContainer();
486    }
487    
488    var elementsId;
489    var currentTabIndex = jQuery(oTab.tab[0]).index();
490    
491    // hide all elements
492    
493    jQuery(elements).each(function(){
494      
495      elementsId = jQuery(this).data('id');
496      var elementsIdArray = elementsId.split(',');
497      
498      elementsIdArray.forEach(function(value){
499        var element = jQuery("#" + value);
500        element.hide();
501        
502        // show elements if in editor and debug mode is true
503        
504        var dataDebug = _this.$element.data("debug");
505        var dataEditor = _this.$element.data("editor");
506        
507        if(dataEditor == "yes" && dataDebug == true){
508          element.show();
509          element.css({"border": "3px solid red"});
510        }else{
511          element.css({"border": "none"});
512        }
513      });
514    });
515    
516    // find active elements     
517    objTabs.find(container).find(elements).removeClass('active');
518    objTabs.find(container).eq(currentTabIndex).find(elements).addClass('active');
519    
520    var activeElements = jQuery(defaults.classes.activeElements);
521    
522    // show active elements
523    
524    jQuery(activeElements).each(function(){
525      
526      elementsId = jQuery(this).data('id');
527      var elementsIdArray = elementsId.split(',');
528      
529      elementsIdArray.forEach(function(value){
530        var element = jQuery("#" + value);
531        
532        elementParentArray.forEach(function(index, value){
533          
534          if(currentTabIndex == index){
535            element.show();
536            hideContainer();
537          }
538        });
539      });
540    });
541  };
542  
543  /**
544  * This function closes a tab
545  * @param {Event} e - The event that is triggered when a tab is closed
546  * @param {Object} oTab - The tab object that should be closed
547  */
548  ResponsiveContentTabs.prototype._closeTab = function(e, oTab) {
549    
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.