1/* ---------------- 2ResponsiveTabs.js 3Author: Pete Love | www.petelove.com 4Version: 1.10 5------------------- */ 6 7var RESPONSIVEUI = {}; 8 9(function($) { 10 11 RESPONSIVEUI.responsiveTabs = function () { 12 var $tabSets = $('.responsive-tabs'); 13 14 if (!$tabSets.hasClass('responsive-tabs--enabled')) { // if we haven't already called this function and enabled tabs 15 $tabSets.addClass('responsive-tabs--enabled'); 16 17 //loop through all sets of tabs on the page 18 var tablistcount = 1; 19 20 $tabSets.each(function() { 21 22 var $tabs = $(this); 23 24 // add tab heading and tab panel classes 25 $tabs.children(':header').addClass('responsive-tabs__heading'); 26 $tabs.children('div').addClass('responsive-tabs__panel'); 27 28 // determine if markup already identifies the active tab panel for this set of tabs 29 // if not then set first heading and tab to be the active one 30 var $activePanel = $tabs.find('.responsive-tabs__panel--active'); 31 if(!$activePanel.length) { 32 $activePanel = $tabs.find('.responsive-tabs__panel').first().addClass('responsive-tabs__panel--active'); 33 } 34 35 $tabs.find('.responsive-tabs__panel').not('.responsive-tabs__panel--active').hide().attr('aria-hidden','true'); //hide all except active panel 36 $activePanel.attr('aria-hidden', 'false'); 37 /* make active tab panel hidden for mobile */ 38 $activePanel.addClass('responsive-tabs__panel--closed-accordion-only'); 39 40 // wrap tabs in container - to be dynamically resized to help prevent page jump 41 var $tabsWrapper = $('<div/>', {'class': 'responsive-tabs-wrapper' }); 42 $tabs.wrap($tabsWrapper); 43 44 var highestHeight = 0; 45 46 // determine height of tallest tab panel. Used later to prevent page jump when tabs are clicked 47 $tabs.find('.responsive-tabs__panel').each(function() { 48 var tabHeight = $(this).height(); 49 if (tabHeight > highestHeight) { 50 highestHeight = tabHeight; 51 } 52 }); 53 54 //create the tab list 55 var $tabList = $('<ul/>', { 'class': 'responsive-tabs__list', 'role': 'tablist' }); 56 57 //loop through each heading in set 58 var tabcount = 1; 59 $tabs.find('.responsive-tabs__heading').each(function() { 60 61 var $tabHeading = $(this); 62 var $tabPanel = $(this).next(); 63 64 $tabHeading.attr('tabindex', 0); 65 66 // CREATE TAB ITEMS (VISIBLE ON DESKTOP) 67 //create tab list item from heading 68 //associate tab list item with tab panel 69 var $tabListItem = $('<li/>', { 70 'class': 'responsive-tabs__list__item', 71 id: 'tablist' + tablistcount + '-tab' + tabcount, 72 'aria-controls': 'tablist' + tablistcount +'-panel' + tabcount, 73 'role': 'tab', 74 tabindex: 0, 75 text: $tabHeading.text(), 76 keydown: function (objEvent) { 77 if (objEvent.keyCode === 13) { // if user presses 'enter' 78 $tabListItem.click(); 79 } 80 }, 81 click: function() { 82 //Show associated panel 83 84 //set height of tab container to highest panel height to avoid page jump 85 $tabsWrapper.css('height', highestHeight); 86 87 // remove hidden mobile class from any other panel as we'll want that panel to be open at mobile size 88 $tabs.find('.responsive-tabs__panel--closed-accordion-only').removeClass('responsive-tabs__panel--closed-accordion-only'); 89 90 // close current panel and remove active state from its (hidden on desktop) heading 91 $tabs.find('.responsive-tabs__panel--active').toggle().removeClass('responsive-tabs__panel--active').attr('aria-hidden','true').prev().removeClass('responsive-tabs__heading--active'); 92 93 //make this tab panel active 94 $tabPanel.toggle().addClass('responsive-tabs__panel--active').attr('aria-hidden','false'); 95 96 //make the hidden heading active 97 $tabHeading.addClass('responsive-tabs__heading--active'); 98 99 //remove active state from currently active tab list item 100 $tabList.find('.responsive-tabs__list__item--active').removeClass('responsive-tabs__list__item--active'); 101 102 //make this tab active 103 $tabListItem.addClass('responsive-tabs__list__item--active'); 104 105 //reset height of tab panels to auto 106 $tabsWrapper.css('height', 'auto'); 107 } 108 }); 109 110 //associate tab panel with tab list item 111 $tabPanel.attr({ 112 'role': 'tabpanel', 113 'aria-labelledby': $tabListItem.attr('id'), 114 id: 'tablist' + tablistcount + '-panel' + tabcount 115 }); 116 117 // if this is the active panel then make it the active tab item 118 if($tabPanel.hasClass('responsive-tabs__panel--active')) { 119 $tabListItem.addClass('responsive-tabs__list__item--active'); 120 } 121 122 // add tab item 123 $tabList.append($tabListItem); 124 125 126 // TAB HEADINGS (VISIBLE ON MOBILE) 127 // if user presses 'enter' on tab heading trigger the click event 128 $tabHeading.keydown(function(objEvent) { 129 if (objEvent.keyCode === 13) { 130 $tabHeading.click(); 131 } 132 }); 133 134 //toggle tab panel if click heading (on mobile) 135 $tabHeading.click(function() { 136 137 // remove any hidden mobile class 138 $tabs.find('.responsive-tabs__panel--closed-accordion-only').removeClass('responsive-tabs__panel--closed-accordion-only'); 139 140 // if this isn't currently active 141 if (!$tabHeading.hasClass('responsive-tabs__heading--active')){ 142 143 var oldActivePos, 144 $activeHeading = $tabs.find('.responsive-tabs__heading--active'); 145 146 // if there is an active heading, get its position 147 if($activeHeading.length) { 148 oldActivePos = $activeHeading.offset().top; 149 } 150 151 // close currently active panel and remove active state from any hidden heading 152 $tabs.find('.responsive-tabs__panel--active').slideToggle().removeClass('responsive-tabs__panel--active').prev().removeClass('responsive-tabs__heading--active'); 153 154 //close all tabs 155 $tabs.find('.responsive-tabs__panel').hide().attr('aria-hidden','true'); 156 157 //open this panel 158 $tabPanel.slideToggle().addClass('responsive-tabs__panel--active').attr('aria-hidden','false'); 159 160 // make this heading active 161 $tabHeading.addClass('responsive-tabs__heading--active'); 162 163 var $currentActive = $tabs.find('.responsive-tabs__list__item--active'); 164 165 //set the active tab list item (for desktop) 166 $currentActive.removeClass('responsive-tabs__list__item--active'); 167 var panelId = $tabPanel.attr('id'); 168 var tabId = panelId.replace('panel','tab'); 169 $('#' + tabId).addClass('responsive-tabs__list__item--active'); 170 171 //scroll to active heading only if it is below previous one 172 var tabsPos = $tabs.offset().top; 173 var newActivePos = ($tabHeading.offset().top) - 15; 174 if(oldActivePos < newActivePos) { 175 $('html, body').animate({ scrollTop: tabsPos }, 0).animate({ scrollTop: newActivePos }, 400); 176 } 177 178 } 179 180 // if this tab panel is already active 181 else { 182 183 // hide panel but give it special responsive-tabs__panel--closed-accordion-only class so that it can be visible at desktop size 184 $tabPanel.removeClass('responsive-tabs__panel--active').slideToggle(function () { $(this).addClass('responsive-tabs__panel--closed-accordion-only'); }); 185 186 //remove active heading class 187 $tabHeading.removeClass('responsive-tabs__heading--active'); 188 189 //don't alter classes on tabs as we want it active if put back to desktop size 190 } 191 192 }); 193 194 tabcount ++; 195 196 }); 197 198 // add finished tab list to its container 199 $tabs.prepend($tabList); 200 201 // next set of tabs on page 202 tablistcount ++; 203 }); 204 } 205 }; 206})(jQuery);
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.