I have a website with three sections containing tabbed areas. I had an older version of this which worked fine, and showed all sections correctly at all times, however as I was changing to a new layout the tabbed sections stopped functioning, I then changed them to some new code and ended up preferring this instead. I then noticed that my content would only show in one section at a time, so some sections do not show up when the page is loaded, unless the tab link is active/clicked.
I recall finding a way to fix this before but I've looked online and can't find anything, and didn't save a version of my old JS code to refer back to. I was hoping someone could help me remember why this happens and how to fix it.
I should note that I have unique IDs for my code and I have not reflected this in my code, as I had that issue the first time round. The unique IDs do not help fix the issue unfortunately.
function openPage(pageName, elmnt, color) {
// Hide all elements with class="tabcontent" by default */
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Remove the background color of all tablinks/buttons
tablinks = document.getElementsByClassName("tablink");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].style.backgroundColor = "";
}
// Show the specific tab content
document.getElementById(pageName).style.display = "block";
// Add the specific color to the button used to open the tab content
elmnt.style.backgroundColor = color;
}
// Get the element with id="defaultOpen" and click on it
document.getElementById("defaultOpen").click();
h3 {
font-size: 15px;
word-spacing: 2px;
font-weight: 100;
letter-spacing: 1px;
text-transform: uppercase;
font-family: 'IBM Plex Mono', sans-serif;
}
h2 {
font-size: 40px;
color: white;
word-spacing: 2px;
margin-bottom: 15px;
font-weight: 700;
letter-spacing: 1px;
font-family: 'IBM Plex Serif', sans-serif;
}
p {
font-weight: 300;
font-size: 15px;
color: white;
text-align: justify;
line-height: 1.5;
}
.new-section__black {
padding: 5%;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
position: relative;
transition: .5s ease;
background-color: #000;
height: 100%;
}
/* Style tab links */
.tablink {
float: left;
outline: none;
cursor: pointer;
margin: 0 1%;
padding: 5px 5px;
font-size: 17px;
width: 10%;
}
.link-black {
background-color: #fff;
color: #000;
border: 1px solid #000;
}
.link-white {
background-color: #000;
color: #fff;
}
.tablink:first-of-type {
margin-left: 5%;
}
.tablink:last-of-type {
margin-right: 5%;
}
.link-black:active,
.link-black:hover {
background-color: #000;
color: #fff;
box-shadow: 2px 2px 10px #555;
}
.link-white:active,
.link-white:hover {
background-color: #fff;
color: #000;
}
/* Style the tab content (and add height:100% for full page content) */
.tabcontent {
width: 100%;
display: none;
margin-top: 1%;
padding: 100px 20px;
height: 100%;
}
.content-black {
color: #000;
}
.content-white {
color: #fff;
}
.tabcontent .col:first-of-type {
margin-left: 0;
}
#defaultOpen {
display: block;
}
<section class="card new-section__black new_section">
<button class="tablink link-white" onclick="openPage('Tab1', this)" id="defaultOpen">
<h3>Tab1</h3>
</button>
<button class="tablink link-white" onclick="openPage('Tab2', this)">
<h3>Tab2</h3>
</button>
<button class="tablink link-white" onclick="openPage('Tab3', this)">
<h3>Tab3</h3>
</button>
<button class="tablink link-white" onclick="openPage('Tab4', this)">
<h3>Tab4</h3>
</button>
<div id="Tab1" class="tabcontent content-white">
<div class="col span-2-of-2">
<h2>Tab1</h2>
<p>Text</p>
</div>
</div>
<div id="Tab2" class="tabcontent content-white">
<div class="col span-2-of-2">
<h2>Tab2</h2>
<p>Text</p>
</div>
</div>
<div id="Tab3" class="tabcontent content-white">
<div class="col span-2-of-2">
<h2>Tab3</h2>
<p>Text</p>
</div>
</div>
<div id="Tab4" class="tabcontent content-white">
<div class="col span-2-of-2">
<h2>Tab4</h2>
<p>Text</p>
</div>
</div>
</section>
Here is a CodePen example of what I have.
If you have multiple sets of "tabs" on the page, you need to scope your interactions to that specific <section>.
function openPage(pageName, elmnt, color) {
// Get the parent node, make all DOM selections based on this
var section = elmnt.parentElement;
// Hide all elements with class="tabcontent" by default */
var i, tabcontent, tablinks;
tabcontent = section.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Remove the background color of all tablinks/buttons
tablinks = section.getElementsByClassName("tablink");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].style.backgroundColor = "";
}
// Show the specific tab content
section.getElementById(pageName).style.display = "block";
// Add the specific color to the button used to open the tab content
elmnt.style.backgroundColor = color;
}
// Get the element with id="defaultOpen" and click on it
document.getElementById("defaultOpen").click();
Also, you repeat element id values everywhere, this is not proper HTML and will lead to unexpected behavior. Each id should be unique. (you currently have multiple "defaultOpen" elements, you have multiple "Tab1", "Tab2", etc... rename them with no repeated values)
Related
Novice -
I am building a page in a TinyMCE wysiwyg and want to be able to show and hide divs when a link/button is clicked. The way things are structured, it appears I can't add javascript into the html section, so I am identifying the links with javascript.
From examples I was able to create the following code, which toggles a single div when clicking on any button marked with the toggleLink class. Is there a good way to target individual elements to show 1 div and hide the rest? I think getElementById might be heading in the right direction, but I am not sure how to apply the eventListeners individually
var togg = document.getElementsByClassName("toggleLink");
var i;
for (i = 0; i < togg.length; i++) {
togg[i].addEventListener("click", function() {
this.classList.toggle("active");
var openDiv = document.getElementById("myDIV1");
if (openDiv.style.display === "none"){
openDiv.style.display = "block";
} else {
openDiv.style.display = "none";
}
});
}
.demoLinks {
background-color: #fff;
height: 200px;
width: 15%;
font-size: 14pt;
color: #ffffff;
background-color: #3156f3;
padding: 20px 0px 20px 20px;
font-family: 'Lato', sans-serif;
float: left;
position: sticky; top: 100px;
}
.demoLinks p {
margin-bottom: 2px;
padding-left: 15px;
color: #ffffff;
}
.demoLinks p a {
color: #ffffff;
}
.toggleLink {
color: #ffffff;
cursor:pointer;
}
.demoVideos {
background-color: #fff;
width: 75%;
padding: 0px 0px 20px 20px;
font-family: 'Lato', sans-serif;
float: right;"
}
<div>
<div class="demoLinks">
<p style="margin-bottom: 8px; color: #ffffff; font-weight: bold;">Products:</p>
<p><a class="toggleLink">This Link</a></p>
<p><a class="toggleLink"> ThatLink</a></p>
</div>
<div class="demoVideos">
<div id="myDIV1" style="display: block;">
<p style="margin-bottom: 0.25em;"><span style="font-family: 'Lato', sans-serif; color: #2b28bc; margin-bottom: 0.5em;"><strong><span style="font-size: 24pt;">Product Demo 1</span></strong></span></p>
<div style="height:585px; width:1034px; background-color:#333333;"></div>
</div>
<div id="myDIV2" style="display: none;">
<p style="margin-bottom: 0.25em;"><span style="font-family: 'Lato', sans-serif; color: #2b28bc; margin-bottom: 0.5em;"><strong><span style="font-size: 24pt;">Product Demo 2</span></strong></span></p>
<div style="height:585px; width:1034px; background-color:#333333;"></div>
</div>
</div>
</div>
Thanks for any assistance!
You can correlate your links with your targets using a suffix on the 'id' property. So, for instance, you can give your first link an id of 'link1', which you can then relate to 'myDIV1' by replacing the text 'link' with 'myDIV'. And the same logic then for all link-div associations.
Once you have that, you should know that the function you pass to an event listener accepts a parameter which is the event that ultimately calls it. You can use this to get the id of the link that was clicked (e.target.id);
With that you can show the target div you're interested in, and hide the rest.
Below is a very simplified version of your code, along with my recommended logic. I should let you know that querySelectorAll has similar purposes to getElement(s)By..., but lets you select using css selectors. Also, the syntax 'test ? trueResult : falseResult' can be replaced by an if/then statement if you desire.
var links = document.querySelectorAll('.toggleLink');
var demos = document.querySelectorAll('.demoVideos > div');
for (var l = 0; l < links.length; l++) {
links[l].addEventListener("click", function(e) {
var linkDivId = e.target.id;
var targetDivId = linkDivId.replace('link', 'myDIV');
for (var d = 0; d < demos.length; d++)
demos[d].style.display = demos[d].id == targetDivId ? 'block' : 'none';
});
}
<div class="demoLinks">
<a id='link1' class="toggleLink">Demo 1 Link</a><br/>
<a id='link2' class="toggleLink">Demo 2 Link</a>
</div>
<br/>
<div class="demoVideos">
<div id="myDIV1" style="display: none;">
Product Demo 1
</div>
<div id="myDIV2" style="display: none;">
Product Demo 2
</div>
</div>
First off, forgive me a bit I took some liberties with your markup and CSS to make it easier for me to visualize the task at hand - toggle of visibility.
Rather than use an element id, I would suggest a class but here, I put in a data-linktarget on each of the links so you can simply put a selector in there and use either an id, class or whatever you choose which should give your task some flexibility.
Next, I used a hidden class to toggle the visibility of the target - this can be done several ways but I used this to help make intent clear. I also toggle the "active" class but did not do anything with it other than facilities what you had started.
Rather than a complex set of event handlers on multiple id's, I used a class to target the toggleLink class.
I made the code somewhat simple but enough to illustrate what it is doing.
function handleEvent(event) {
let videos = document.querySelector(".demo-videos");
let hideMe = videos.querySelectorAll(".demo-thing:not(.hidden)");
hideMe.forEach(function(el) {
el.classList.toggle("hidden", true);
el.classList.toggle("active", false);
});
let vSelected = videos.querySelector(this.dataset.linktarget);
vSelected.classList.toggle("hidden", false);
vSelected.classList.toggle("active", true);
}
Array.prototype.filter.call(document.getElementsByClassName("toggleLink"), function(testElement) {
testElement.addEventListener("click", handleEvent);
});
.hidden {
display: none;
}
.demo-container {
font-family: 'Lato', sans-serif;
}
.demoLinks {
height: 200px;
width: 15%;
font-size: 14pt;
background-color: #3156f3;
padding: 20px 0px 20px 20px;
float: left;
position: sticky;
top: 100px;
font-weight: bold;
}
.demo-links-title-text {
font-size: 1.2em;
color: #FFFF00;
}
.demoLinks .demo-link {
margin-bottom: 8px;
font-weight: bold;
margin-bottom: 2px;
padding-left: 15px;
}
.toggleLink {
color: #FFFF88;
cursor: pointer;
}
.demo-videos {
background-color: #fff;
width: 75%;
padding: 0px 0px 20px 20px;
float: right;
}
.demo-videos .header-part {
margin-bottom: 0.25em;
}
.demo-videos .header-part .header-part-text {
color: #2b28bc;
margin-bottom: 0.5em;
font-size: 24pt;
font-weight: bold;
/* put back <strong> tags if desired instead */
}
.demo-videos .block-part {
height: 585px;
width: 1034px;
background-color: #333333;
color: cyan;
}
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Lato&display=swap" rel="stylesheet">
<div class="demo-container">
<div class="demoLinks">
<p class="demo-links-title-text">Products:</p>
<p class="demo-link"><a class="toggleLink" data-linktarget="#myDIV1" href="#">This Link</a></p>
<p class="demo-link"><a class="toggleLink" data-linktarget=".demo-thing:nth-child(2)" href="#">ThatLink</a></p>
<p class="demo-link"><a class="toggleLink" data-linktarget=".demo-thing:nth-child(3)" href="#">That new Link</a></p>
</div>
<div class="demo-videos">
<div id="myDIV1" class="demo-thing active">
<p class="header-part"><span class="header-part-text"><span>Product Demo 1</span></span>
</p>
<div class="block-part">I am first</div>
</div>
<div id="myDIV2" class="demo-thing hidden">
<p class="header-part"><span class="header-part-text"><span>Product Demo 2</span></span>
</p>
<div class="block-part">Happy Day</div>
</div>
<div id="another-id" class="demo-thing hidden">
<p class="header-part"><span class="header-part-text"><span>Product Demo New</span></span>
</p>
<div class="block-part">Wonderful news</div>
</div>
</div>
</div>
I'm looking to move some content on a page, into a set of tabs higher on the page via javascript or any other means. I can't edit WHERE on the page this code exists, but I can set Pre/Post HTML on the fields and thus give it a class or an ID to mess with.
I built it out here to play with
If you don't want to go there, here's the code:
function openTab(evt, tabName) {
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(tabName).style.display = "block";
evt.currentTarget.className += " active";
}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f9f9f9;
}
/* 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: #0090bf;
color: #fff;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
```
<!-- I can edit this section as needed. -->
<section class="panel panel-persondetails">
<div class="tab">
<button class="tablinks active" onclick="openTab(event, 'tab1')">Tab Name 1</button>
<button class="tablinks" onclick="openTab(event, 'tab2')">Tab Name 2</button>
<button class="tablinks" onclick="openTab(event, 'tab3')">Tab Name 3</button>
</div>
<div id="tab1" class="tabcontent" style="display: block;">
<div>
replace me with stuff 1
</div>
</div>
<div id="tab2" class="tabcontent">
<div>
replace me with stuff 2
</div>
</div>
<div id="tab3" class="tabcontent">
<div>
replace me with stuff 3
</div>
</div>
</section>
<!-- The following is elsewhere on the page and I can't move it. I can add pre/post HTML which is how I'd wrap it in a div and give it an ID or class to hopefully use js to show it in the tabs above instead. -->
<div id="content-tab-1">I want this in tab1.</div>
<div id="content-tab-2">I want this in tab2.</div>
<div id="content-tab-3">I want this in tab3.</div>
Where are the JS experts locked in quarantine and itching for a problem to solve? Thanks all!
You could do something like
var newContent = $("#content-tab-1]").detach();
$("#tab1").find("div").first().html(newContent);
Obviously you'll have to put that wherever you need it, and expand for tabs 2 and 3.
I edited your JSFiddle and I think that I did the thing that you were asking. Initially, the content below the tabs is set to the contents of the element that said, "I want this in tab1". After that, the program simply gets the corresponding content each time you switch to a different tab. Here's the link to the JSFiddle:
Tab Switching Demo
// START WITH THE CONTENT AS THE FIRST TAB ITEM
var contents = document.getElementById("content-tab1").innerHTML;
document.getElementById("tabcontent").innerHTML = contents;
function openTab(evt, tabName) {
var i, tabcontent, tablinks;
// MAKE ALL OF THE TABS LOOK INACTIVE
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
//CHANGE THE DISPLAY AND CSS PROPERTIES OF THE CLICKED TAB
var contents = document.getElementById("content-" + tabName).innerHTML;
console.log(contents);
document.getElementById("tabcontent").innerHTML = contents;
evt.currentTarget.className += " active";
console.log(evt.currentTarget.id);
}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f9f9f9;
}
/* 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: #0090bf;
color: #fff;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
<!-- I can edit this section as needed. -->
<section class="panel panel-persondetails">
<div class="tab">
<button id="tab1" class="tablinks active" onclick="openTab(event, 'tab1')">Tab Name 1</button>
<button id="tab2" class="tablinks" onclick="openTab(event, 'tab2')">Tab Name 2</button>
<button id="tab3" class="tablinks" onclick="openTab(event, 'tab3')">Tab Name 3</button>
</div>
<div class="tabcontent" style="display: block;">
<div id="tabcontent">
replace me with stuff 1
</div>
</div>
</section>
<br>
<!-- The following is elsewhere on the page and I can't move it. I can add pre/post HTML which is how I'd wrap it in a div and give it an ID or class to hopefully use js to show it in the tabs above instead. -->
<div id="content-tab1">I want this in tab1.</div>
<div id="content-tab2">I want this in tab2.</div>
<div id="content-tab3">I want this in tab3.</div>
var tabcontent = document.getElementsByClassName("tabcontent");
var tablinks = document.getElementsByClassName("tablinks");
insertToTab(1);
console.log('tablinks ', tablinks);
for (let i = 0; i < tablinks.length; i++) {
tablinks[i].addEventListener('click', bindClick2(i))
}
function bindClick2(i) {
return function() {
insertToTab(i + 1);
for (j = 0; j < tabcontent.length; j++) {
tabcontent[j].style.display = "none";
}
for (j = 0; j < tablinks.length; j++) {
tablinks[j].className = tablinks[j].className.replace(" active", "");
}
var tabName = 'tab' + (+i + 1);
document.getElementById(tabName).style.display = "block";
this.className += " active";
}
}
function insertToTab(i) {
var currContentTab = document.getElementById("content-tab-" + i);
var currTabcontent = document.getElementById("tab" + i)
currTabcontent.innerText = currContentTab.innerText;
}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f9f9f9;
}
/* 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: #0090bf;
color: #fff;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
<section class="panel panel-persondetails">
<div class="tab">
<button class="tablinks active">Tab Name 1</button>
<button class="tablinks">Tab Name 2</button>
<button class="tablinks">Tab Name 3</button>
</div>
<div id="tab1" class="tabcontent" style="display: block;">
<div>
replace me with stuff 1
</div>
</div>
<div id="tab2" class="tabcontent">
<div>
replace me with stuff 2
</div>
</div>
<div id="tab3" class="tabcontent">
<div>
replace me with stuff 3
</div>
</div>
</section>
<div id="content-tab-1">I want this in tab1.</div>
<div id="content-tab-2">I want this in tab2.</div>
<div id="content-tab-3">I want this in tab3.</div>
I have a page with an initial description, followed by 2 buttons, where the user can choose typeA or typeB. They work by "target": when the user clicks typeA comes the content relative to typeA, bellow the buttons; same to typeB.
typeA is the most common selection, then, when the page loads, a javascript emulates the click to typeA and opens respective content. To avoid hidden the initial description, there is another javascript to put the page at the top. Worked on Chrome and Edge, not on Firefox.
I would like to repeat the same process when the user clicks: opens the respective content, but positioning the page at the top, or, at least, showing the buttons. I thought event onClick calling the same js backToTop would worked - but not.
I put an alert on js and enters there but not execute: always keeps the content of the button selected in its better visibility.
I tried:
window.location.href = '#top';
window.scrollBy(0, -500);
document.html.scrollTop = document.documentElement.scrollTop = 0;
without success.
What am I doing wrong?
<head>
<meta charset="UTF-8">
<title>TOP PAGE TEST</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body,html {margin-left:auto; margin-right:auto;width:70%; font-family:verdana; font-size:1.2em;}
.menuFAQ {background:#aaa; font-size:2em; width:100%;}
.menuFAQ ul {list-style-type:none; position:relative; margin-left:-40px; /* to avoid user agent chrome */}
.menuFAQ li {display:inline-block; margin-top:10px; margin-bottom:10px; width:49%; background:#fff; text-align:center; box-shadow:2px 3px 4px 0px rgba(170,170,170,1); font-weight:400; line-height:80px;}
.menuFAQ li a {display:block; color:#020062; background:#fff; font-weight:400; text-decoration:none;}
.menuFAQ li .active,.menuFAQ li:hover a {color:#fff; font-weight:400; background-image:linear-gradient(#165686, #0f3a5a); }
:target {color:#fff;font-size:1em;}
div.items>div:not(:target) {display:none}
div.items>div:target {display:block; margin-left:auto; margin-right:auto; color:#000; border:1px solid #aaa;}
</style>
</head>
<body>
<div id="top">Top Page</div>
<br>textExp1<br>textExp2<br>textExp3<br>textExp4<br>textExp5
<div class="menuFAQ">
<ul>
<li><a id="preferedFAQ" onclick="backToTop()" class="target" href="#typeA">TypeA</a></li>
<li><a onclick="backToTop()" class="target" href="#typeB">TypeB</a></li>
</ul>
</div>
<div class="items">
<div id="typeA">
<nav>
A long and variable text size to explain TypeA <br>text1A<br>text2A<br>text3A<br>text4A<br>text5A<br>text6A<br>text7A<br>text8A<br>text9A<br>textAA<br>textBA<br>textCA<br>textDA
<br>[...]
</nav>
</div>
</div>
<div class="items">
<div id="typeB">
<nav>
A long and variable text size to explain TypeB
<p>text1B</p><p>text2B</p><p>text3B</p>
<br>[...]
</nav>
</div>
</div>
<script>
const allTargetLinks = document.querySelectorAll('.target')
allTargetLinks.forEach(targetLink => {
targetLink.addEventListener('click', () => {
allTargetLinks.forEach(targetLink => {
targetLink.classList.remove('active')
})
targetLink.classList.add('active')
})
})
window.onload = function() {assignPreferedFAQ()};
function assignPreferedFAQ() {
document.getElementById("preferedFAQ").click();
backToTop();
};
function backToTop() {
//document.html.scrollTop = document.documentElement.scrollTop = 0;
//document.body.scrollTop = document.documentElement.scrollTop = 0;
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
};
</script>
You had a real mess there regarding how you process click events and href attribute, i.e:
You had onclick attribute on your links, and you were adding yet another listener to them in JS
You didn't event.preventDefault() in your function, and default browser behavior when you click on a link is to get you to its href path
I've cleaned up a bit and changed some things. Since we need to prevent default behavior :target selector will no longer work, so instead I did what you've already been doing with links, and added an active class to your content. clickHandler() will now remove and add class active as necessary. At the end just scroll to the top. Here's the snippet:
document.querySelectorAll('.target').forEach(targetLink => targetLink.addEventListener('click', clickHandler, false));
function clickHandler(ev) {
ev.preventDefault(); // prevent browser from automatically scrolling to href pos
if (!ev.currentTarget.classList.contains('active')) {
// disable active elements
document.querySelector('.target.active').classList.remove('active');
document.querySelector('.items div.active').classList.remove('active');
// add class to the clicked on button and its corresponding content tab
ev.currentTarget.classList.add('active');
// to prevent pointless string slicing below, you'd have to store ids somewhere else i.e in the data-id attribute
const id = ev.currentTarget.href.slice(ev.currentTarget.href.lastIndexOf('#') + 1);
document.getElementById(id).classList.add('active');
}
window.scrollTo(0,0);
}
* {
font-family: verdana;
font-size: 1em;
}
.menuFAQ {
background: #aaa;
font-size: 2em;
width: 100%;
}
.menuFAQ ul {
list-style-type: none;
text-align: center;
padding: 0;
/* to avoid user agent chrome */
}
.menuFAQ li {
display: inline-block;
width: 48%;
margin-top: 10px;
margin-bottom: 10px;
background: #fff;
text-align: center;
box-shadow: 2px 3px 4px 0px rgba(170, 170, 170, 1);
font-weight: 400;
line-height: 80px;
}
.menuFAQ li a {
display: block;
color: #020062;
background: #fff;
font-weight: 400;
text-decoration: none;
}
.menuFAQ li .active,
.menuFAQ li:hover a {
color: #fff;
font-weight: 400;
background-image: linear-gradient(#165686, #0f3a5a);
}
div.items>div {
display: none;
}
div.items>div.active {
display: block;
margin-left: auto;
margin-right: auto;
color: #000;
border: 1px solid #aaa;
}
<div id="top">Top Page</div>
<br>textExp1<br>textExp2<br>textExp3<br>textExp4<br>textExp5
<div class="menuFAQ">
<ul>
<li><a class="target active" href="#typeA">TypeA</a></li>
<li><a class="target" href="#typeB">TypeB</a></li>
</ul>
</div>
<div class="items">
<div class="active" id="typeA">
<nav>
A long and variable text size to explain TypeA <br>text1A<br>text2A<br>text3A<br>text4A<br>text5A<br>text6A<br>text7A<br>text8A<br>text9A<br>textAA<br>textBA<br>textCA<br>textDA
<br>[...]
</nav>
</div>
</div>
<div class="items">
<div id="typeB">
<nav>
A long and variable text size to explain TypeB
<p>text1B</p>
<p>text2B</p>
<p>text3B</p>
<br>[...]
</nav>
</div>
</div>
Note that instead of artificially clicking at the page load, now your content just loads with class active.
Hope this help you.
< script >
window.onload = function() {
document.getElementById("preferedFAQ").click();
backToTop();
};
function backToTop() {
document.documentElement.scrollTop = document.body.scrollTop = 0;
//alert("enter backToTop");
var elmnt = document.getElementById("top");
var x = elmnt.scrollLeft;
var y = elmnt.scrollTop;
}; <
/script>
body,
html {
margin-left: auto;
margin-right: auto;
width: 70%;
font-family: verdana;
font-size: 1.2em;
}
.menuFAQ {
background: #aaa;
font-size: 2em;
width: 100%;
}
.menuFAQ ul {
list-style-type: none;
position: relative;
margin-left: -40px;
/* to avoid user agent chrome */
}
.menuFAQ li {
display: inline-block;
margin-top: 10px;
margin-bottom: 10px;
width: 49%;
background: #fff;
text-align: center;
box-shadow: 2px 3px 4px 0px rgba(170, 170, 170, 1);
font-weight: 400;
line-height: 80px;
}
.menuFAQ li a {
display: block;
color: #020062;
background: #fff;
font-weight: 400;
text-decoration: none;
}
.menuFAQ li .active,
.menuFAQ li:hover a {
color: #fff;
font-weight: 400;
background-image: linear-gradient(#165686, #0f3a5a);
}
:target {
color: #fff;
font-size: 1em;
}
div.items>div:not(:target) {
display: none
}
div.items>div:target {
display: block;
margin-left: auto;
margin-right: auto;
color: #000;
border: 1px solid #aaa;
}
<div id="top">Top Page</div> <br>textExp1<br>textExp2<br>textExp3<br>textExp4<br>textExp5<br>textExp6<br>textExp7<br>textExp8<br>textExp9<br>textExpA<br>textExpB<br>textExpC<br>textExpD
<br>textExpE
<div class="menuFAQ">
<ul>
<li><a id="preferedFAQ" onclick="backToTop()" class="target" href="#typeA">TypeA</a></li>
<li><a onclick="backToTop()" class="target" href="#typeB">TypeB</a></li>
</ul>
</div>
<div class="items">
<div id="typeA">
<nav>
A long and variable text size to explain TypeA <br>text1A<br>text2A<br>text3A<br>text4A<br>text5A<br>text6A<br>text7A<br>text8A<br>text9A<br>textAA<br>textBA<br>textCA<br>textDA
<br>[...]
</nav>
</div>
</div>
<div class="items">
<div id="typeB">
<nav>
A long and variable text size to explain TypeB
<p>text1B</p>
<p>text2B</p>
<p>text3B</p>
<br>[...]
</nav>
</div>
</di
I know that this question has been asked many times before:
Javascript: Fade In images on page load; one after the other?
Fade in divs one after another
jQuery .fadeIn() on page load?
But I've tried all of the suggested techniques and none of them worked. I'm trying to get three lines of text (the words are wrapped in divs), to appear one after the other when the page loads. Here is what I have:
HTML:
<div class="row"><!--second row-->
<div class="col-lg-12 center">
<div id="tagline-wrapper">
<div class="center-text hidden1">Responsive</div>
<div class="between-lines">
<div class="line"></div>
<div class="clean hidden2">Clean</div>
<div class="line"></div>
</div>
<div class="center-text hidden3">Powerful</div>
</div>
</div>
</div><!--end row-->
CSS:
.center {
text-align: center;
display: flex;
color: #ffffff;
font-family: 'proxima_nova_ltsemibold';
text-transform: uppercase;
font-size: 52px;
}
#tagline-wrapper {
margin-top: 150px;
margin-left: auto;
margin-right: auto;
}
.center-text {
text-align: center;
font-family: 'proxima_nova_ltsemibold';
font-size: 52px;
text-transform: uppercase;
color: #ffffff;
}
.between-lines {
display: flex;
align-items: center;
}
.line {
border-bottom: 2px solid #ffffff;
display: block;
flex-grow: 1;
height: 0;
}
.clean {
padding: 0 1.5rem;
text-align: center;
font-family: 'proxima_nova_ltsemibold';
font-size: 52px;
text-transform: uppercase;
color: #ffffff;
}
/*hide elements initially*/
.hidden1 {
display: none;
}
.hidden2 {
display: none;
}
.hidden3 {
display: none;
}
JavaScript
$(document).ready(function(){
var elements = [ 'hidden1, hidden2, hidden3' ];
for (var i = 0; i < elements.length; i++) {
setTimeout(function() {
elements[i].style.opacity = 1;
}, 1250 * i);
}
});
The above is the JS technique that was suggested in the first linked article.
JSFiddle attempt with the first technique here: https://jsfiddle.net/b184reyv/1/
JSFiddle attempt with the second technique here: https://jsfiddle.net/b184reyv/2/
JSFiddle attempt with the third technique here: https://jsfiddle.net/4w7kxLxf/
Thank you.
So there are a handful of issues here that I'll try to document for you:
1. for loops in JavaScript often scope a bit unexpectedly. You can read here for a great explanation of them. In your example, using i in a setTimeout would result in the last iteration of the loop being grabbed each time, as i is declared globally.
2. You're modifying the opacity of your hidden elements, but their original state is display: none;. An item with display: none; will never be shown, regardless of opacity. Instead of display: none;, use opacity: 0; You can also add a transition: opacity 1s to make them fade-in instead of just "appear".
3. Your array is not syntactically correct. Each item should be within quotes and split with a comma, whereas yours is currently one large string with commas in it.
var elements = ['hidden1', 'hidden2', 'hidden3'];
4. You're using .style on each item in the elements array, but they are simply strings. At no point to you convert these strings into elements, so trying to use .style will throw an error. You'll need to implement them into a selector.
Putting all of this information together, you may be looking for something like this instead. See the comments in the JavaScript for explanation.
var elements = ['hidden1', 'hidden2', 'hidden3'];
for (let i = 0; i < elements.length; i++) {
var thisElement = $("." + elements[i]); //Get the current element based on class
fadeInElement(thisElement, i); //Call our "Fade in" function
}
function fadeInElement(elem, time) { //Fade-in function that takes the element to fade-in, and the time it should wait
setTimeout(function() {
elem.css("opacity", "1"); //Set our element's opacity to 1
}, 1250 * time); //Set the time it should wait
}
body {
background-color: black;
}
.center {
text-align: center;
display: flex;
color: #ffffff;
font-family: 'proxima_nova_ltsemibold';
text-transform: uppercase;
font-size: 52px;
}
#tagline-wrapper {
margin-top: 150px;
margin-left: auto;
margin-right: auto;
}
.center-text {
text-align: center;
font-family: 'proxima_nova_ltsemibold';
font-size: 52px;
text-transform: uppercase;
color: #ffffff;
}
.between-lines {
display: flex;
align-items: center;
}
.line {
border-bottom: 2px solid #ffffff;
display: block;
flex-grow: 1;
height: 0;
}
.clean {
padding: 0 1.5rem;
text-align: center;
font-family: 'proxima_nova_ltsemibold';
font-size: 52px;
text-transform: uppercase;
color: #ffffff;
}
/*hide elements initially*/
.hidden1, .hidden2, .hidden3 {
opacity: 0;
transition: opacity 1s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<!--second row-->
<div class="col-lg-12 center">
<div id="tagline-wrapper">
<div class="center-text hidden1">Responsive</div>
<div class="between-lines">
<div class="line"></div>
<div class="clean hidden2">Clean</div>
<div class="line"></div>
</div>
<div class="center-text hidden3">Powerful</div>
</div>
</div>
</div>
<!--end row-->
Oh so here my custom answer for what I understand of your problem :)
$(window).load(function() {
var $word1 = $(".word1");
var $word2 = $(".word2");
var $word3 = $(".word3");
$word1.fadeIn(1000, function() {
$word2.fadeIn(1000, function() {
$word3.fadeIn(1000);
});
});
});
.word {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="word word1">
this
</div>
<div class="word word2">
is
</div>
<div class="word word3">
working
</div>
I have the following code for a tab I am trying to create.
<style>
nav.tab {
margin: 0;
padding: 0;
display: block;
width: 150px;
overflow: hidden;
border: 1px solid #ccc;
background-color: black;
float: left;
}
#static {
margin-left: 200px;
}
/* Float the list items side by side*/
section.tab {float: left;}
/* Style the links inside the list items*/
nav.tab a {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
transition: 0.3s;
font-size: 17px;
font-family: Segoe UI;
}
/*Change background color of links on hover */
nav.tab a:hover {
background-color: purple;
color: white;
}
/* Create an active/current tablink class */
nav.tab a:focus, .active {
background-color: white;
color: purple;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border-top: none;
height: 700px;
width: 600px;
}
</style>
<nav class="tab">
Profile
Password
Tokyo
</nav>
<div id="static" class="container">
<div id="Profile" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Password" class="tabcontent">
<h4 style="font-family: Segoe UI; color: purple; padding: 15px 0 15px 0;">Change Password</h4>
<p id="label">Enter OLD Password</p><input type="password" id="field" size="25" name="oldpassword" required="required"><br/><br/>
<p id="label">Enter NEW Password</p><input type="password" id="field" size="25" name="newpassword" required="required"><br/><br/>
<p id="label">Enter NEW Password AGAIN</p><input type="password" id="field" size="25" name="newpassword2" required="required"><br/><br/>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
</div>
<script>
function openSetting(evt, settingName) {
var i, tabcontent, tablinks;
$('.tabcontent a:first').tab('show');
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(settingName).style.display = "block";
evt.currentTarget.className += " active";
}
</script>
I am trying to make the first tab show by default.
As of now, when the page loads none of the content for the tabs can be seen because of a 'display: none;' css value. But i need the first page to show on load.
Help me out please.
As I understand you need only to set class ".active" to the first tab.
Profile
And in js, when you handle click on tab do something like this:
$(nav.tab>a).removeClass('active');
Maybe you want to use jqueryui? Tabs are included there.
also bootstrap provides nice tabs:
http://www.w3schools.com/bootstrap/tryit.asp?filename=trybs_ref_js_tab&stacked=h
Try this solution --> https://css-tricks.com/css3-tabs/
Also try make a new class, for example class selected, and manage the selected tab (also the default selected tab) with that class and then, with JS add or remove that class.
See also this --> http://www.menucool.com/tabbed-content
See u!
Just fire that function with the desired params on document.ready:
openSetting(event, 'Profile');
openSetting(event, 'Profile');
function openSetting(evt, settingName) {
var i, tabcontent, tablinks;
//$('.tabcontent a:first').show();
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(settingName).style.display = "block";
evt.currentTarget.className += " active";
}
nav.tab {
margin: 0;
padding: 0;
display: block;
width: 150px;
overflow: hidden;
border: 1px solid #ccc;
background-color: black;
float: left;
}
#static {
margin-left: 200px;
}
/* Float the list items side by side*/
section.tab {
float: left;
}
/* Style the links inside the list items*/
nav.tab a {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
transition: 0.3s;
font-size: 17px;
font-family: Segoe UI;
}
/*Change background color of links on hover */
nav.tab a:hover {
background-color: purple;
color: white;
}
/* Create an active/current tablink class */
nav.tab a:focus,
.active {
background-color: white;
color: purple;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border-top: none;
height: 700px;
width: 600px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<nav class="tab">
Profile
Password
Tokyo
</nav>
<div id="static" class="container">
<div id="Profile" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Password" class="tabcontent">
<h4 style="font-family: Segoe UI; color: purple; padding: 15px 0 15px 0;">Change Password</h4>
<p id="label">Enter OLD Password</p>
<input type="password" id="field" size="25" name="oldpassword" required="required">
<br/>
<br/>
<p id="label">Enter NEW Password</p>
<input type="password" id="field" size="25" name="newpassword" required="required">
<br/>
<br/>
<p id="label">Enter NEW Password AGAIN</p>
<input type="password" id="field" size="25" name="newpassword2" required="required">
<br/>
<br/>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
</div>
Assuming first tab to be shown as the default tab.
These are the changes
Profile
add this line after closing bracket of function openSetting.
document.getElementById("defaultOpen").click();