Can anyone help me out with saving the last tab state in the event someone leaves the page and returns ... thanks in advance <div class="container"> <div class="bar blue"> <button class="bar-item button tablink red" onclick="openTab(event,'Summary')">Summary</button> <button class="bar-item button tablink" onclick="openTab(event,'Finance')">Finance</button> <button class="bar-item button tablink" onclick="openTab(event,'Enquire')">Enquire</button> <button class="bar-item button tablink" onclick="openTab(event,'Save')">Save</button> </div> <div id="Summary" class="container border vehTab"> SUMMARY IMNFO HERE </div> <div id="Finance" class="container border vehTab" style="display:none"> FINANCE INFO HERE </div> <div id="Enquire" class="container border vehTab" style="display:none"> ENQUIRY CONTENT HERE </div> <div id="Save" class="container border vehTab" style="display:none"> SAVE DETAILS HERE </div> </div> HTML: JAVASCRIPT: function openTab(evt, tabName) { var i, x, tablinks; x = document.getElementsByClassName("vehTab"); for (i = 0; i < x.length; i++) { x[i].style.display = "none"; } tablinks = document.getElementsByClassName("tablink"); for (i = 0; i < x.length; i++) { tablinks[i].className = tablinks[i].className.replace("red", ""); } document.getElementById(tabName).style.display = "block"; evt.currentTarget.className += " red"; } Code (JavaScript):
I set up a demo at https://codepen.io/itamer/pen/jOZPWMb with this code (I changed a few things)... It saves the value and then retrieves it as a demo, normally the retrieve would be somewhere else. <div class="container"> <div class="bar blue"> <button class="bar-item button tablink red" data-label='Summary'>Summary</button> <button class="bar-item button tablink" data-label='Finance'>Finance</button> <button class="bar-item button tablink" data-label='Enquire'>Enquire</button> <button class="bar-item button tablink" data-label='Save'>Save</button> </div> <div id="Summary" class="container border vehTab"> SUMMARY INFO HERE </div> <div id="Finance" class="container border vehTab" style="display:none"> FINANCE INFO HERE </div> <div id="Enquire" class="container border vehTab" style="display:none"> ENQUIRY CONTENT HERE </div> <div id="Save" class="container border vehTab" style="display:none"> SAVE DETAILS HERE </div> </div> <div>The saved tab is: <span id='saved' class='red'></saved> HTML: const allTabs = document.querySelectorAll(".tablink"); console.log(allTabs, allTabs.length); for (var i = 0; i < allTabs.length; i++) { allTabs[i].addEventListener("click", openTab); } function openTab() { const tabName = this.dataset.label; for (let i = 0; i < allTabs.length; i++) { if (allTabs[i].dataset.label === tabName) { allTabs[i].className += " red"; document.getElementById(tabName).style.display = "block"; } else { allTabs[i].className = allTabs[i].className.replace("red", ""); let label = allTabs[i].dataset.label; let infoBlock = document.getElementById(label); infoBlock.style.display = "none"; } } // can we access localstorage? if yes, save the value if (typeof window !== "undefined") { window.localStorage.setItem("activeTab", tabName); } // demo on retrieving the value back again. let savedDemoField = document.getElementById("saved"); savedDemoField.innerHTML = getActiveTab(); } function getActiveTab() { if (typeof window === "undefined") { return "Summary"; } try { // Get from local storage by key return window.localStorage.getItem("activeTab"); // Parse stored json or if none return initialValue } catch (error) { console.log(error); return "Summary"; } } Code (JavaScript):
That's a demo of storage and retrieval. When the page opens you need to do the retrieval bit. when they click you do the storage bit.
Stunning example of how NOT to do... any of this. 1) let CSS do your heavy lifting. That means don't use buttons and scripting only functionality for your tabs. LABEL pointing at INPUT type="radio" using the adjacent sibling selector would work wonders. 2) NEVER piss "onevent" attributes into the markup, especially if they're calling functions as that means you're polluting the global namespace. Concepts like "separation of concerns" exists for a reason people! 99% of the time you see something like onclick="" in the HTML, you're looking at ignorance, incompetence, and ineptitude by people unqualified to write client-side code. Much the same can be said of aria-bloat BS like data-label... Remember ARIA roles mostly mean that you're using the wrong markup. You know what's better than going full re-re halfwit pissing more code into the page so you can use the wrong HTML? Using the RIGHT HTML, that's what! And of course don't even get me STARTED about the mental-huffing migetry of presentational classes such as "red" or "blue", much less going full gungan with class="button" on a freaking button tag. Yewza wents full Gungan. Meesa says yewsa nevah goes FULL Gungan. So first, let's clean up the markup and set it up for scriptless tabs. <div class="tabbedSections"> <input type="radio" name="tabSection" id="tab_summary" checked hidden> <input type="radio" name="tabSection" id="tab_finance" hidden> <input type="radio" name="tabSection" id="tab_enquire" hidden> <input type="radio" name="tabSection" id="tab_save" hidden> <ul hidden> <li><label for="tab_summary">Summary</lable></ll> <li><label for="tab_finance">Finance</lable></ll> <li><label for="tab_enquire">Enquire</lable></ll> <li><label for="tab_save">Save</lable></ll> </ul> <section> SUMMARY INFO HERE </section> <section> FINANCE INFO HERE </section> <section> ENQUIRY CONTENT HERE </section> <section> SAVE DETAILS HERE </section> <!-- .tabbedSections --></div> Code (markup): The use of "hidden" is so that we do not negatively impact screen readers, likewise we do NOT hide the individual sections by default with display:none or inlined style or any other BS since we don't want non-visual ua's (screen readers, braille readers, search engines) ignoring your content! Basically we don't want such UA's ignoring the SECTION, but we do want them ignoring the input and tab menu since those mean exactly two things to them... and Jack left town. Remember the basic rule, write your base HTML as if CSS, default appearance of tags, and your final desired appearance does not even exist FIRST. Then when you add media specific elements and behaviors, filter them out with hidden or via other techniques. That way you're not pissing on accessibility. Then implement tabs in CSS. I set it up to support up to nine tabs. You need more than nine tabs on a website you might be doing something wrong. .tabbedSections > ul { display:flex; list-style:none; padding:0; margin:0 0 -0.0625rem; border-left:0.0625rem solid #999; } .tabbedSections > ul > li { background:#CCC; border:0.0625rem solid #999; border-left:0; } .tabbedSections > ul > li:first-child { border-radius:0.5rem 0 0; } .tabbedSections > ul > li:last-child { border-radius:0 0.5rem 0 0; } .tabbedSections > ul label { cursor:pointer; display:block; padding:0.25rem 0.5rem; } .tabbedSections > * { /* Some older browsers won't let us change the input when "hidden", and somme non-visual UA's wond read display:none text so hide them off-screen instead. */ display:block; position:fixed; bottom:-100vh; left:-100vh; } .tabbedSections > section { padding:1rem; background:#EEE; border:0.0625rem solid #999; border-radius:0 0 0.5rem 0.5rem; } .tabbedSections > ul, .tabbedSections > input:nth-of-type(1):checked ~ section:nth-of-type(1), .tabbedSections > input:nth-of-type(2):checked ~ section:nth-of-type(2), .tabbedSections > input:nth-of-type(3):checked ~ section:nth-of-type(3), .tabbedSections > input:nth-of-type(4):checked ~ section:nth-of-type(4), .tabbedSections > input:nth-of-type(5):checked ~ section:nth-of-type(5), .tabbedSections > input:nth-of-type(6):checked ~ section:nth-of-type(6), .tabbedSections > input:nth-of-type(7):checked ~ section:nth-of-type(7), .tabbedSections > input:nth-of-type(8):checked ~ section:nth-of-type(8), .tabbedSections > input:nth-of-type(9):checked ~ section:nth-of-type(9) { position:static; /* ignore positioning */ } .tabbedSections > input:nth-of-type(1):checked ~ ul > li:nth-of-type(1), .tabbedSections > input:nth-of-type(2):checked ~ ul > li:nth-of-type(2), .tabbedSections > input:nth-of-type(3):checked ~ ul > li:nth-of-type(3), .tabbedSections > input:nth-of-type(4):checked ~ ul > li:nth-of-type(4), .tabbedSections > input:nth-of-type(5):checked ~ ul > li:nth-of-type(5), .tabbedSections > input:nth-of-type(6):checked ~ ul > li:nth-of-type(6), .tabbedSections > input:nth-of-type(7):checked ~ ul > li:nth-of-type(7), .tabbedSections > input:nth-of-type(8):checked ~ ul > li:nth-of-type(8), .tabbedSections > input:nth-of-type(9):checked ~ ul > li:nth-of-type(9) { background:#EEE; border-bottom-color:#EEE; } Code (markup): Now that we have working tabs without JS, we can enhance them with scripting to remember the last set one. { const tabChangeEvent = (event) => { localStorage.setItem(event.currentTarget.name, event.currentTarget.id); }; for (let radio of document.querySelectorAll(".tabbedSections > input")) { let storageId = localStorage.getItem(radio.name); if (storageId) radio.checked = storageId === radio.id; radio.addEventListener("change", tabChangeEvent); } } Code (markup): The outer {} isolates scope so we're not pissing on the global namespace. We set up the function handler first since it's applied multiple times. Then we loop through all our radio input grabbed via querySelectorAll. IF the name of the radio button exists in localstorage we set the radio.checked to if the id stored in LS matches the one on the input. Then we just hook in our tabChangeEvent PROPERLY using addEventListener. Easy-peasy, lemon squeezy. Codepen live of this here: https://codepen.io/jason-knight/pen/YzeXRQV Hope that helps. Also this is written to allow multiple tab areas on a page. Just change the name on all the radio INPUT and the ID's for the for/id associations, and you're good to go.
and there I was feeling bad for meddling as much as I did! @energylevels - take heed of all that - it's like a masterclass for the specific problem you have!