refactoring a code with inline JavaScript - javascript

I'm trying to refactor this w3schools for a toggleable tabs code because all of us know that using inline JavaScript is a very bad practice so I'm trying to sepearte them as much as possible so I selected the tablinks and I added an event listener but I'm struggling with the city names (take a look to their code and you'll understand what I'm talking about)
any help please and thank you in advance
HTML
<!-- Tab links -->
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'London')">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<!-- Tab content -->
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
CSS
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons that are used to open the tab content */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
JavaScript
function openCity(evt, cityName) {
// Declare all variables
var i, tabcontent, tablinks;
// Get all elements with class="tabcontent" and hide them
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Get all elements with class="tablinks" and remove the class "active"
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(cityName).style.display = "block";
evt.currentTarget.className += " active";
}

w3schools is a very good source of bad practice, because they often take many shortcuts while trying to highlight the one small example they are giving.
In practice, you would solve this situation by using a data- attribute. If you don't recognize some of the calls, please refer to some of these articles:
https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes
https://developer.mozilla.org/en-US/docs/Glossary/IIFE
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
// Wrap our code in an IIFE in order to avoid polluting the global namespace
// and to facilitate faster garbage collection
(function(){
// Preload queries for later use
const tabs = document.querySelectorAll('.tablinks');
const content = document.querySelectorAll('.tabcontent');
// iterate tab to create content interaction
tabs.forEach(f => // f will be the tab element in this loop
// Assign click event to each tab
f.addEventListener('click',function(){
// Locate any previously marked active tab element
const prevActive = document.querySelector('.tablinks.active');
// If a previously marked element exists set its classname to default
if(prevActive) prevActive.className = 'tablinks';
// Assign the currently clicked tab element the active class
f.className = 'tablinks active';
// Iterate through the content to look for the data-attribute we used earlier
content.forEach(c => { // c will be the content element in this loop
// if the id of the element matches the data attribute from the tab then show the content
c.style.display = c.id == f.getAttribute("data-city") ? "block" : "none" ;
})
})
);
})();
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons that are used to open the tab content */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
<div class="tab">
<button class="tablinks" data-city="London">London</button>
<button class="tablinks" data-city="Paris">Paris</button>
<button class="tablinks" data-city="Tokyo">Tokyo</button>
</div>
<!-- Tab content -->
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>

<button id="London" class="tablinks">London</button>
var btns = document.querySelectorAll('.tab button')
btns.forEach((btn)=>{
btn.addEventListener('click', (event)=>{
openCity(event, btn.id, btn)
})
})
Give each button an id with the city name, then pass the id to the openCity function
You can pass the btn to your openCity function too

Related

How to un-toggle tabs

I'm using the w3schools how-to on tabs. (https://www.w3schools.com/howto/howto_js_tabs.asp) I noticed that their example does not allow for tabs to be untoggled and hide the text when pressed again. Can someone briefly explain how I would be able to integrate that into my code if I'm following theirs? Thanks.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {font-family: Arial;}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons inside the tab */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
</style>
</head>
<body>
<h2>Tabs</h2>
<p>Click on the buttons inside the tabbed menu:</p>
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'London')">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
<script>
function openCity(evt, cityName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(cityName).style.display = "block";
evt.currentTarget.className += " active";
}
</script>
</body>
</html>
Not sure if I understand correctly, but what you describe is not the "expected" behaviour of a tabbed interface. Why would you want content to be hidden? In a tabbed interface (think navigation), there is usually always one tab active, showing it's content, so clicking the active tab should simply do nothing and not hide the content (at least in conventional tabbed interfaces). Maybe you are looking more for an accordion-like behaviour?
In other words, the behaviour of the (notoriously crappy) example from W3Schools is not how a tabbed interface is supposed to work, when initialized, no content is shown, the user needs to click a tab first to see something, that's not good UX... the first tab should already be active!
But if you really want to go for this behaviour, it could be done like this:
function openCity(evt, cityName) {
// Declare all variables
var i, tabcontent, tablinks;
if ( evt.currentTarget.classList.contains('active') ) {
document.getElementById(cityName).style.display = "none";
evt.currentTarget.classList.remove('active');
} else {
// Get all elements with class="tabcontent" and hide them
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Get all elements with class="tablinks" and remove the class "active"
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(cityName).style.display = "block";
evt.currentTarget.className += " active";
}
}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons that are used to open the tab content */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
<!-- Tab links -->
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'London')">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<!-- Tab content -->
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
There are different approaches that you could take. You could use if else statements to check whether an element in the for loops contains a specific CSS style or class name so in this case active. Then you may disable it by changing its style through JS when the condition is met.

Force div inside tab navigation to appear on top of all other page content

I'm working with templates, so I can only edit so much of the environment. I have a tabbed navigation set up. Within one of the tabs, I have a div that I want to have a fixed position that is outside/on top of everything else on the page.
This isn't the actual code I'm working with, but it's similar enough that I can use it as an example. The "outsidediv" div is placed in the "London" div. But I want to make it so you see outsidediv even if you click into the Paris or Tokyo tabs.
I've tried using z-index and every kind of position property I can think of to get this to work. I cannot move the outsidediv from where it is.
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
.tab button:hover {
background-color: #ddd;
}
.tab button.active {
background-color: #ccc;
}
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
#outsidediv {
position: fixed;
top: 80px;
right: 50px;
background: pink;
}
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'London')">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
<div id="outsidediv">This div should appear no matter which tab is selected.</div>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
<script>
function openCity(evt, cityName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(cityName).style.display = "block";
evt.currentTarget.className += " active";
}
</script>
I don't know that there is any other way to do this other than to move the div so that it's outside of the tab, and give it a very high z-index because once you hide a tab with display:none the entire tab (and its descendants) won't be rendered.
If you can't modify the HTML template structure, you could use JavaScript to move it with this one line:
document.body.appendChild(document.getElementById("outsidediv"));
I've also modified/updated your existing JavaScript code so that you aren't using .getElementsByClassName() or using inline HTML event attributes, which makes the code much more efficient and more in line with modern development methodologies. See the comments in the code for details.
/* Just add this class when you want to hide something
and remove when you want to show */
.hidden { display:none; }
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
.tab button:hover {
background-color: #ddd;
}
.tab button.active {
background-color: #ccc;
}
.tabcontent {
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
#outsidediv {
position: fixed;
z-index:9999;
top: 80px;
right: 50px;
background: pink;
}
<div class="tab">
<!-- Don't use inline HTML event attributes. Do your JavaScript in JavaScript-->
<button class="tablinks">London</button>
<button class="tablinks">Paris</button>
<button class="tablinks">Tokyo</button>
</div>
<div id="London" class="tabcontent hidden">
<h3>London</h3>
<p>London is the capital city of England.</p>
<div id="outsidediv">This div should appear no matter which tab is selected.</div>
</div>
<div id="Paris" class="tabcontent hidden">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent hidden">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
<script>
// Move the div that should stay on top to just after the tab divs
document.body.appendChild(document.getElementById("outsidediv"));
// Just set your event up at the parent of the buttons
// and use event delegation to leverage event bubbling
document.querySelector(".tab").addEventListener("click", openCity);
function openCity(event) {
// Never, never, never use `getElementsByClassName()`
// and instead, use `.querySelectorAll()`. You can
// then loop through the resulting collection with
// `.forEach()`, which makes looping without indexes
// possible
// Hide all the tab conttent
document.querySelectorAll(".tabcontent").forEach(function(tab){
// Avoid inline styles when possible and just apply/remove classes
tab.classList.add("hidden");
});
// Remove the active tab
document.querySelectorAll(".tablinks").forEach(function(tabLink){
tabLink.classList.remove("active");
});
// Loop over the content again
document.querySelectorAll(".tabcontent").forEach(function(tab){
// If the text of the clicked button matches the text of the tab header...
if(event.target.textContent === tab.querySelector("h3").textContent){
tab.classList.remove("hidden"); // Unhide the tabcontent
event.target.classList.add("active"); // Make the tab active
}
});
}
</script>
You can make an additional function to add the outsidediv. Before adding the element, first check if it exists on the page and if so remove it, then add it to the current active tab element.
Check below:
function openCity(evt, cityName) {
var i, tabcontent, tablinks;
var div = document.getElementById("outsidediv");
if(div !== null) { // if outsidediv exists on the page, remove it
div.remove();
}
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
let cityDiv = document.getElementById(cityName); // made cityDiv variable
cityDiv.style.display = "block";
evt.currentTarget.className += " active";
cityDiv.append( makeOutsideDiv() ); // add the outsidediv to the active element
}
function makeOutsideDiv() {
let div = document.createElement("div");
div.innerHTML = "This div should appear no matter which tab is selected.";
div.id = "outsidediv";
return div;
}
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
.tab button:hover {
background-color: #ddd;
}
.tab button.active {
background-color: #ccc;
}
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
#outsidediv {
position: fixed;
top: 80px;
right: 50px;
background: pink;
}
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'London')">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
<div id="outsidediv">This div should appear no matter which tab is selected.</div>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
I used visibility instead of display, and each inactive tab I am setting position:fixed and sending it way above the rendered area of the page (out of sight and out of mind). Then when the tab is clicked again I'm setting it back to position:relative with no offset.
Here's the fiddle: https://jsfiddle.net/tm1wyax6/1/
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'London')">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
<div id="outsidediv">This div should appear no matter which tab is selected.</div>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
<script>
function openCity(evt, cityName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.visibility = "hidden";
tabcontent[i].style.position = "fixed";
tabcontent[i].style.top = "-1000px";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(cityName).style.visibility = "visible";
document.getElementById(cityName).style.position = "relative";
document.getElementById(cityName).style.top = "0";
evt.currentTarget.className += " active";
}
</script>
CSS:
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
.tab button:hover {
background-color: #ddd;
}
.tab button.active {
background-color: #ccc;
}
.tabcontent {
visibility: hidden;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
#outsidediv {
position: fixed;
top: 80px;
right: 50px;
background: pink;
visibility: visible;
}

How can I avoid using inline JavaScript for clickable tabs?

I need to create tabs that reveal content when clicked. I have found some code that provides the functionality I need from this W3Schools Tutorial, although I want to avoid using the inline JavaScript to call the openCity() function. In the original code, each tab button was defined like so:
<button class="tablinks" onclick="openCity(event, 'London')">London</button>
This works fine, but I would much rather avoid using JavaScript like this in any code if I can. It looks like the event.currentTarget property is one of the most important parts here for adding the .active class to the tabs when clicked, although I was wondering if there was another way to carry out the same process.
I have tried several different solutions but still have not been able to find the best one. In previous attempts I had a few errors such as an Uncaught TypeError for not being able to access the property of an undefined value. Now, no errors arise, but the page is just stuck on the first tab and the others do not work.
In the latest attempt, I tried looping through each tab and added an event listener to call the function on them individually, but am still new to using JavaScript and am unsure on what else to do. Please excuse any silly mistakes!
Please find the code below (HTML, CSS, and JavaScript).
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: Arial;
}
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
.tab button:hover {
background-color: #ddd;
}
.tab button.active {
background-color: #ccc;
}
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
</style>
</head>
<body>
<div class="tab">
<button class="tablinks">London</button>
<button class="tablinks">Paris</button>
<button class="tablinks">Tokyo</button>
</div>
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
<script>
var i, tabcontent, tablinks;
tablinks = document.getElementsByClassName("tablinks");
for (var i = 0; i < tablinks.length; i++) {
var name = tablinks[i].innerHTML;
console.log(name);
tablinks[i].addEventListener('click', openCity(name));
}
function openCity(cityName) {
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(cityName).style.display = "block";
this.className += ' active';
// event.currentTarget.className += " active";
}
</body>
I had other ideas without using data attributes, but i think it's a correct way.
Probably code can looks like that:
let handleClick = e => {
Array.from(document.querySelectorAll(".active"), e => e.classList.remove("active")); // remove `active` class from every elements which contains him.
e.target.classList.add("active");
document.querySelector(`div.tabcontent[data-id*="${e.target.dataset.id}"]`).classList.add("active");
};
Array.from(document.getElementsByClassName("tablinks"), btn => btn.addEventListener('click', handleClick, false));
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
.tab button:hover {
background-color: #ddd;
}
.tab button.active {
background-color: #ccc;
}
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
.active {
display: block;
}
<div class="tab">
<button class="tablinks" data-id="1">London</button>
<button class="tablinks" data-id="2">Paris</button>
<button class="tablinks" data-id="3">Tokyo</button>
</div>
<div data-id="1" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div data-id="2" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div data-id="3" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>

Javascript Div class default tab

I am trying to use tablinks in my program using the w3school article
how to js tabs
CSS
function openCity(evt, cityName) {
// Declare all variables
var i, tabcontent, tablinks;
// Get all elements with class="tabcontent" and hide them
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Get all elements with class="tablinks" and remove the class "active"
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(cityName).style.display = "block";
evt.currentTarget.className += " active";
}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons that are used to open the tab content */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
<!-- Tab links -->
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'London')">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<!-- Tab content -->
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
Below is the code to make one tab as "Active" one.
<button class="tablinks" onclick="openCity(event, 'London')" id="defaultOpen">London</button>
<script>
// Get the element with id="defaultOpen" and click on it
document.getElementById("defaultOpen").click();
</script>
When i click on one tab i need to make it as default, so that next time when i open the page, the latest page should be the default.
I have few pages like sales, costs,expenses etc.
When the user makes an entry in costs, it will redirect to another jsp page and inserts the record to db and then redirect back to the home.jsp page where we have all these tabs. So when we redirect it should open the costs tab as default.
forgive me if my english is rude or badly formatted . english is not my mother tongue .
Thank you very much.. any help will be highly appreciated.
Based on the article you linked, looks like css is governing which tab is showing.
This excerpt is from their example page later on.
document.getElementById(cityName).style.display = "block";
evt.currentTarget.className += " active";
So if you want to manage which tab and page is active, you will need to manage that active class using Javascript just like they are doing with the function on their example page.
Using their example, i was able to change the tab that displays by just calling:
document.getElementById("Tokyo").style.display = "block";
var tokyo = document.getElementsByClassName("tablinks")
tokyo[2].className += " active";

by default it's blank I want first tab as default

as you can see when the page reloads the section under these tabs are empty (maybe using wrong word) need to click this to see content
All I want is when page the loads content on the first tab show by default
Click Here
hope you undersatnd me
Do these 2 things to achieve the desired result:
1.
Use style="display:block;" on the first tab because the logic of your javascript code works like this.
So on page load the 1st tab content will alwyas be visible and on tab change it will work accordingly.
Add class="tablinks active" to the first tab link to make it active.
<!DOCTYPE html>
<html>
<head>
<style>
body {font-family: "Lato", sans-serif;}
/* Style the tab */
div.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons inside the tab */
div.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
/* Change background color of buttons on hover */
div.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
div.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
</style>
</head>
<body>
<p>Click on the buttons inside the tabbed menu:</p>
<div class="tab">
<button class="tablinks active" onclick="openCity(event, 'London')">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris')">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<div id="London" class="tabcontent" style="display:block;">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
<script>
function openCity(evt, cityName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(cityName).style.display = "block";
evt.currentTarget.className += " active";
}
</script>
</body>
</html>
All of your .tabcontent tabs have their display property set to none. Change the display property of your first tab to block and it will show by default.
You can use jquery for this and then put this in script
$('.tablinks').eq(0).click();
Working example

Categories