1(function (window, document) { 2 var modules = window.EditorumPublicationDetailModules = window.EditorumPublicationDetailModules || {}; 3 var shared = modules.shared || {}; 4 var journal = modules.journal = modules.journal || {}; 5 6 var queryAll = shared.queryAll; 7 var parseQuery = shared.parseQuery; 8 var getQueryParam = shared.getQueryParam; 9 var getHashId = shared.getHashId; 10 var getHashIdFromHref = shared.getHashIdFromHref; 11 var updateUrlState = shared.updateUrlState; 12 13 function initJournalTabs(options) { 14 var settings = options || {}; 15 var tabRoot = document.querySelector(settings.rootSelector || '.journal-tabs-bar__nav'); 16 var tabs = tabRoot ? queryAll(settings.linkSelector || '.journal-tabs-bar__link', tabRoot) : []; 17 var panels = queryAll(settings.panelSelector || '.journal-page .journal-tab-panel'); 18 var queryParam = settings.queryParam || 'section'; 19 var aliases = settings.aliases || {}; 20 var defaultSection = settings.defaultSection || 'fresh'; 21 var initialSection = settings.initialSection || defaultSection; 22 var knownSections = {}; 23 24 function normalizeSection(sectionId) { 25 if (!sectionId) { 26 return ''; 27 } 28 29 return aliases[sectionId] || sectionId; 30 } 31 32 function getSectionFromHref(href) { 33 var value = href || ''; 34 var hashIndex = value.indexOf('#'); 35 var queryIndex = value.indexOf('?'); 36 var queryValue = null; 37 var query; 38 39 if (queryIndex !== -1) { 40 query = value.slice(queryIndex, hashIndex === -1 ? value.length : hashIndex); 41 queryValue = parseQuery(query)[queryParam] || null; 42 } 43 44 // The default section's link carries no ?section=, like the page URL it opens. 45 return normalizeSection(queryValue || getHashIdFromHref(value)) || defaultSection; 46 } 47 48 function resolveRequestedSection() { 49 var requestedSection = normalizeSection(getQueryParam(queryParam) || getHashId(window.location.hash) || initialSection || defaultSection); 50 51 if (requestedSection && knownSections[requestedSection]) { 52 return requestedSection; 53 } 54 55 if (knownSections[defaultSection]) { 56 return defaultSection; 57 } 58 59 return ''; 60 } 61 62 function getPanelBySection(sectionId) { 63 var normalizedSection = normalizeSection(sectionId); 64 var match = null; 65 66 panels.some(function (panel) { 67 if (normalizeSection(panel.getAttribute('data-section-panel')) === normalizedSection) { 68 match = panel; 69 return true; 70 } 71 72 return false; 73 }); 74 75 return match; 76 } 77 78 function panelHasRenderedContent(sectionId) { 79 var panel = getPanelBySection(sectionId); 80 81 if (!panel) { 82 return false; 83 } 84 85 return Array.prototype.some.call(panel.childNodes, function (node) { 86 if (node.nodeType === 1) { 87 return true; 88 } 89 90 return node.nodeType === 3 && node.textContent.trim().length > 0; 91 }); 92 } 93 94 function activateSection(sectionId, writeUrl) { 95 var normalizedSection = normalizeSection(sectionId) || defaultSection; 96
97 tabs.forEach(function (tab) { 98 var tabSection = getSectionFromHref(tab.getAttribute('href') || ''); 99 var isActive = tabSection === normalizedSection; 100 101 tab.classList.toggle('active', isActive); 102 tab.setAttribute('aria-selected', isActive ? 'true' : 'false'); 103 }); 104 105 panels.forEach(function (panel) { 106 var isActive = panel.getAttribute('data-section-panel') === normalizedSection; 107 108 panel.classList.toggle('is-active', isActive); 109 panel.setAttribute('aria-hidden', isActive ? 'false' : 'true'); 110 panel.hidden = !isActive; 111 }); 112 113 if (writeUrl) { 114 updateUrlState((function () { 115 var state = {}; 116 117 state[queryParam] = normalizedSection; 118 119 return state; 120 })(), '', false); 121 } 122 123 return true; 124 } 125 126 if (!tabs.length) { 127 return false; 128 } 129
130 tabs.forEach(function (tab) { 131 var section = getSectionFromHref(tab.getAttribute('href') || ''); 132 133 if (section) { 134 knownSections[section] = true; 135 } 136 }); 137 138 panels.forEach(function (panel) { 139 var section = normalizeSection(panel.getAttribute('data-section-panel')); 140 141 if (section) { 142 knownSections[section] = true; 143 } 144 }); 145 146 // A fragment naming another section was already turned into ?section= by the journal page 147 // <head>; reloading from here would show the default section first. 148 var initialResolvedSection = resolveRequestedSection(); 149 var queryValue = getQueryParam(queryParam); 150 151 if (queryValue !== null && !knownSections[normalizeSection(queryValue)]) { 152 updateUrlState((function () { 153 var state = {}; 154 155 state[queryParam] = ''; 156 157 return state; 158 })(), undefined, true); 159 } 160 161 activateSection(initialResolvedSection, false); 162 163 if (window.location.hash) { 164 var normalizedHashSection = normalizeSection(getHashId(window.location.hash)); 165 166 if (normalizedHashSection && knownSections[normalizedHashSection]) { 167 updateUrlState((function () { 168 var state = {}; 169 170 state[queryParam] = initialResolvedSection || defaultSection; 171 172 return state; 173 })(), '', true); 174 } 175 } 176
177 tabs.forEach(function (tab) { 178 tab.addEventListener('click', function (event) { 179 var targetSection = getSectionFromHref(tab.getAttribute('href') || ''); 180 181 if (!panelHasRenderedContent(targetSection)) { 182 return; 183 } 184 185 event.preventDefault(); 186 activateSection(targetSection, true); 187 }); 188 }); 189 190 window.addEventListener('popstate', function () { 191 activateSection(resolveRequestedSection(), false); 192 }); 193 194 return true; 195 } 196 197 journal.initJournalTabs = initJournalTabs; 198})(window, document);
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.