Only show the content of a clicked header and hide others - javascript

I have a page with four headers with id of heading-1, heading-2, heading-3 and heading-4. These headers have contents in div containers with the ids of content-1, content-2, content-3 and content-4 respectively.
The four headings are shown by default but only the contents of "content-1" div is shown while the remaining three containers "content-2", "content-3", and "content-4" are hidden and not displayed.
To NOT display these contents by default, I set their "display" property to "none". To display "content-1", I added class name of "active" which set the "display" property to block.
To give the "heading-1" a green color, I added class name of "active" which set the color to green
The contents of any container "content-1, content-2, content-3 and content-4 should ONLY SHOW when their corresponding headings "heading-1", "heading-2", "heading-3" and "heading-4" is clicked. On clicking it, only the clicked header and its corresponding content container should be given the class names "active" for the color and display styles to be applied respectively.
Only one content and header can be active at a time. If a new header is clicked, the class name "active" should be removed on any header and content that has it and added to the clicked one.
I already wrote out the code for this but it is not scalable and can really get overwhelming when you have lots of headers and contents.
What is the best way/method/code to achieve this solution?
Note: The code should be in VANILLA JavaScript and NOT Jquery.
Thanks.
const headingOne = document.getElementById("heading-1");
const headingTwo = document.getElementById("heading-2");
const headingThree = document.getElementById("heading-3");
const headingFour = document.getElementById("heading-4");
const contentOne = document.getElementById("content-1");
const contentTwo = document.getElementById("content-2");
const contentThree = document.getElementById("content-3");
const contentFour = document.getElementById("content-4");
document.addEventListener("click", function(event) {
if (event.target === headingOne) {
headingOne.classList.add("active");
headingTwo.classList.remove("active");
headingThree.classList.remove("active");
headingFour.classList.remove("active");
contentOne.classList.add("active");
contentTwo.classList.remove("active");
contentThree.classList.remove("active");
contentFour.classList.remove("active");
} else if (event.target === headingTwo) {
headingTwo.classList.add("active");
headingOne.classList.remove("active");
headingThree.classList.remove("active");
headingFour.classList.remove("active");
contentTwo.classList.add("active");
contentOne.classList.remove("active");
contentThree.classList.remove("active");
contentFour.classList.remove("active");
} else if (event.target === headingThree) {
headingThree.classList.add("active");
headingOne.classList.remove("active");
headingTwo.classList.remove("active");
headingFour.classList.remove("active");
contentThree.classList.add("active");
contentOne.classList.remove("active");
contentTwo.classList.remove("active");
contentFour.classList.remove("active");
} else if (event.target === headingFour) {
headingFour.classList.add("active");
headingOne.classList.remove("active");
headingThree.classList.remove("active");
headingTwo.classList.remove("active");
contentFour.classList.add("active");
contentOne.classList.remove("active");
contentThree.classList.remove("active");
contentTwo.classList.remove("active");
}
})
.container {
display: flex;
max-width: 1000px;
margin: 0 auto;
background: whitesmoke;
border: 1px solid #ccc;
border-radius: 10px;
padding: 50px;
}
.heading {
font-size: 28px;
line-height: 140%;
cursor: pointer;
}
.heading.active {
color: green;
}
.box {
width: 50%;
}
.content {
font-size: 18px;
line-height: 25px;
display: none;
}
.content.active {
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Headers/Contents</title>
</head>
<body>
<div class="container">
<div class="box box-1">
<h2 class="heading active" id="heading-1">Heading One</h2>
<h2 class="heading" id="heading-2"> Heading Two</h2>
<h2 class="heading" id="heading-3">Heading Three</h2>
<h2 class="heading" id="heading-4">Heading Four</h2>
</div>
<div class="box box-2">
<div class="content active" id="content-1">
<p>Content One</p>
</div>
<div class="content" id="content-2">
<p>Content Two</p>
</div>
<div class="content" id="content-3">
<p>Content Three</p>
</div>
<div class="content" id="content-4">
<p>Content Four</p>
</div>
</div>
</div>
<script src="app.js"></script>
</body>
</html>

Here is another approach to shorten the code , using a common class for heading and content without requiring to set an id.
let H2 = document.querySelectorAll(".box-1 h2.heading");
let AllSet = document.querySelectorAll( ".box-2 > div.content,.box-1 h2.heading ");
for (let e of H2) {
e.addEventListener("click", function() {
let linkedClass = this.classList.item(1);
toggleActive(linkedClass);
});
}
function toggleActive(linkedClass) {
for (let i = 0; i < AllSet.length; i++) {
AllSet[i].classList.remove("active");
if (AllSet[i].classList.item(1) == linkedClass) {
AllSet[i].classList.add("active");
}
}
}
.container {
display: flex;
max-width: 1000px;
margin: 0 auto;
background: whitesmoke;
border: 1px solid #ccc;
border-radius: 10px;
padding: 50px;
}
.heading {
font-size: 28px;
line-height: 140%;
cursor: pointer;
margin:0;
}
.heading.active {
color: green;
}
.box {
flex:1;
display:flex;
flex-direction:column;
}
.content:nth-child(even){background:#bee}
.content {
font-size: 18px;
line-height: 25px;
display: none;
flex:1;
background:#eeb
}
.content.active {
display: block;
}
<div class="container">
<div class="box box-1">
<h2 class="heading heading-1 active">Heading One</h2>
<h2 class="heading heading-2"> Heading Two</h2>
<h2 class="heading heading-3">Heading Three</h2>
<h2 class="heading heading-4">Heading Four</h2>
<h2 class="heading heading-5">Heading Five</h2>
</div>
<div class="box box-2">
<div class="content heading-1 active">
<p>Content One</p>
</div>
<div class="content heading-2">
<p>Content Two</p>
</div>
<div class="content heading-3">
<p>Content Three</p>
</div>
<div class="content heading-4">
<p>Content Four</p>
</div>
<div class="content heading-5">
<p>Content Five</p>
</div>
</div>
</div>

You could do something along these lines:
const headings = document.querySelectorAll(".heading");
const contents = document.querySelectorAll(".content");
document.addEventListener("click", function(event) {
// If we just clicked on a heading
if (event.target.classList.contains('heading')) {
// Extract the number from the id
const id = parseInt(event.target.id.match(/\d+/)[0], 10);
// Only add the active class on the current heading
for (let i = 0; i < headings.length; i++) {
const heading = headings[i];
heading.classList[heading === event.target ? 'add' : 'remove']('active');
}
// Only add the active class on the current content
for (let i = 0; i < contents.length; i++) {
const content = contents[i];
content.classList[content.id === `content-${id}` ? 'add' : 'remove']('active');
}
}
})
.container{display:flex;max-width:1000px;margin:0 auto;background:#f5f5f5;border:1px solid #ccc;border-radius:10px;padding:50px}.heading{font-size:28px;line-height:140%;cursor:pointer}.heading.active{color:green}.box{width:50%}.content{font-size:18px;line-height:25px;display:none}.content.active{display:block}
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="style.css"> <title>Headers/Contents</title></head><body> <div class="container"> <div class="box box-1"> <h2 class="heading active" id="heading-1">Heading One</h2> <h2 class="heading" id="heading-2"> Heading Two</h2> <h2 class="heading" id="heading-3">Heading Three</h2> <h2 class="heading" id="heading-4">Heading Four</h2> </div><div class="box box-2"> <div class="content active" id="content-1"> <p>Content One</p></div><div class="content" id="content-2"> <p>Content Two</p></div><div class="content" id="content-3"> <p>Content Three</p></div><div class="content" id="content-4"> <p>Content Four</p></div></div></div><script src="app.js"></script></body></html>

Related

How To Create A Client-Sided Search Bar Using Javascript

I'm trying to create a client-sided search bar using javascript and I'm not sure how to do that and get it to function properly. I'm trying to create one without using PHP since I have no experience with server-sided programming. How would you create one that works with the client-side? Do you need an index for the search results and an API as well? And how would you use an index and an API? The goal of the search bar is to find terms or words that are present on the webpage is what I'm trying to achieve with it. It's to give the user a chance to search for the name of an article present in the webpage. Here is my current code if you want to see it: https://jsfiddle.net/snt87eg9/1/
<div class="topnav">
<a class="active" href="#home">Home</a>
News
Contact
About
<div class="search-container">
<form action="/action_page.php">
<input type="text" placeholder="Search.." name="search">
<button type="submit"><i class="fa fa-search"></i></button>
</form>
</div>
</div>
<div class="header">
<div id ="header">
<h2 style="text-indent: 1em; font-family: Helvetica; color: blue;">Articles</h2>
</div></div><br>
<div class="row">
<div class="leftcolumn">
<div class="card">
<div id="Title">
<h2>Article 1</h2>
<h5>Date</h5>
<p>Some text over there.,.. </p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="card">
<div id="Title2">
<h2>Article 2</h2>
<h5>Date</h5>
<p> Some text over here..... </p>
</div>
</div>
</div>
```
You need a way to select the searchbar, articles and article titles,
lets say you give classes article and article-title and give the searchbar id="searchbar"
Document should look like this:
<div class="topnav">
<a class="active" href="#home">Home</a>
News
Contact
About
<div class="search-container">
<form action="/action_page.php">
<input type="text" placeholder="Search.." name="search" id="searchbar">
<button type="submit"><i class="fa fa-search"></i></button>
</form>
</div>
</div>
<div class="header">
<div id="header">
<h2 style="text-indent: 1em; font-family: Helvetica; color: blue;">Articles</h2>
</div>
</div><br>
<div class="row article">
<div class="leftcolumn">
<div class="card">
<div id="Title">
<a href="#">
<h2 class="article-title">Article 1</h2>
</a>
<h5>Date</h5>
<p>Some text over there.,.. </p>
</div>
</div>
</div>
</div>
<div class="row article">
<div class="card">
<div id="Title2">
<a href="#">
<h2 class="article-title">Article 2</h2>
</a>
<h5>Date</h5>
<p> Some text over here..... </p>
</div>
</div>
</div>
Here's the way to filter out what you wrote in the searchbar:
<script>
$('#searchbar').keyup(function(){
let articles = $('.article'); //get all elements with class="article"
let keyword = $(this).val().toLowerCase(); //get the content of the searchbar
if(keyword == "") //show all elements if searchbar is empty
articles.show();
else{ //else loop through articles and check if the keyword is in the title div
articles.each(function(element) {
let title = $(this).find('.article-title').text().toLowerCase();
(title.indexOf(keyword) >= 0) ? $(this).show() : $(this).hide();
});
}
});
</script>
The script uses jQuery , you can put this before the script if you don't have it already imported :
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
I just took the time to make a client-side search javascript function. But if you are not too familiar with javascript try to learn a little bit more before implementing this type of things.
$(document).ready(function() {
$("#header").hide().fadeIn(2000);
});
$(document).ready(function() {
$("#title").hide().fadeIn(2000);
});
$(document).ready(function() {
$("#footer").hide().fadeIn(2000);
});
function searchInArticles(word) {
const articles = document.querySelectorAll(".card");
articles.forEach(article => {
if (article.innerHTML.includes(word)) {
article.style.display = "block";
article.scrollIntoView();
} else {
article.style.display = "none";
}
})
}
searchInArticles("Yes");
//searchInArticles("Some");
/* Add a gray background color with some padding */
body {
font-family: Arial;
padding: 20px;
background: #32cd32;
}
/* Header/Blog Title */
.header {
padding: 30px;
font-size: 40px;
text-align: center;
background: #7df9ff;
}
/* Create two unequal columns that floats next to each other */
/* Left column */
.leftcolumn {
float: left;
width: 100%;
}
/* Add a card effect for articles */
.card {
background-color: #87ceeb;
padding: 20px;
margin-top: 20px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* Footer */
.footer {
padding: 20px;
text-align: center;
background: #00bfff;
margin-top: 20px;
}
.topnav {
overflow: hidden;
background-color: #333;
}
.topnav a {
float: left;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.topnav a.active {
background-color: #04AA6D;
color: white;
}
/* Responsive layout - when the screen is less than 800px wide, make the two columns stack on top of each other instead of next to each other */
#media screen and (max-width: 800px) {
.leftcolumn,
.rightcolumn {
width: 100%;
padding: 0;
}
}
.topnav .search-container {
float: right;
}
.topnav input[type=text] {
padding: 6px;
margin-top: 8px;
font-size: 17px;
border: none;
}
.topnav .search-container button {
float: right;
padding: 6px 10px;
margin-top: 8px;
margin-right: 16px;
background: #ddd;
font-size: 17px;
border: none;
cursor: pointer;
}
.topnav .search-container button:hover {
background: #ccc;
}
#media screen and (max-width: 600px) {
.topnav .search-container {
float: none;
}
.topnav a,
.topnav input[type=text],
.topnav .search-container button {
float: none;
display: block;
text-align: left;
width: 100%;
margin: 0;
padding: 14px;
}
.topnav input[type=text] {
border: 1px solid #ccc;
}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<!-- My link -->
<div class="topnav">
<a class="active" href="#home">Home</a>
News
Contact
About
<div class="search-container">
<form action="/action_page.php">
<input type="text" placeholder="Search.." name="search">
<button type="submit"><i class="fa fa-search"></i></button>
</form>
</div>
</div>
<div class="header">
<div id="header">
<h2 style="text-indent: 1em; font-family: Helvetica; color: blue;">Articles</h2>
</div>
</div><br>
<div class="row">
<div class="leftcolumn">
<div class="card">
<div id="Title">
<a href="#">
<h2>Article 1</h2>
</a>
<h5>Date</h5>
<p>Yes text over there.,.. </p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="card">
<div id="Title2">
<a href="#">
<h2>Article 2</h2>
</a>
<h5>Date</h5>
<p> Some text over here..... </p>
</div>
</div>
</div>
<div class="row">
<div class="card">
<div id="Title2">
<a href="#">
<h2>Article 2</h2>
</a>
<h5>Date</h5>
<p> Some text over here..... </p>
</div>
</div>
</div>
<div class="row">
<div class="card">
<div id="Title2">
<a href="#">
<h2>Article 2</h2>
</a>
<h5>Date</h5>
<p> Yes text over here..... </p>
</div>
</div>
</div>
<div class="row">
<div class="card">
<div id="Title2">
<a href="#">
<h2>Article 2</h2>
</a>
<h5>Date</h5>
<p> Some text over here..... </p>
</div>
</div>
</div>
<div class="row">
<div class="card">
<div id="Title2">
<a href="#">
<h2>Article 2</h2>
</a>
<h5>Date</h5>
<p> Some text over here..... </p>
</div>
</div>
</div>
<div class="row">
<div class="card">
<div id="Title2">
<a href="#">
<h2>Article 2</h2>
</a>
<h5>Date</h5>
<p> Some text over here..... </p>
</div>
</div>
</div>
<div class="footer">
<div id="footer">
</div>
</div>
</body>
</html>

HTML JS CSS Value not showing in Column Cards

I'm a bit new to technology.
i"m trying to build a dashboard. But when I pass the attribute id to the cards. it's not displaying the values.
Sometimes I'm only getting value for the 1st card only. do I have to add additional div? or any other ways?
how to resolve these?.
window.onload = function() {
getCovidStats();
}
function getCovidStats() {
fetch('https://coronavirus-tracker-api.herokuapp.com/v2/locations/225')
.then(function(resp) { return resp.json() })
.then(function(data) {
let population = data.location.country_population;
let update = data.location.last_updated;
let confirmedCases = data.location.latest.confirmed;
let deaths = data.location.latest.deaths;
document.getElementById('population').innerHTML = population.toLocaleString('en');
document.getElementById('update').innerHTML = update.substr(0, 10);
document.getElementById('cases').innerHTML = confirmedCases.toLocaleString('en');
document.getElementById('deaths').innerHTML = deaths.toLocaleString('en');
document.getElementById('percent').innerHTML = ((Number(deaths)/Number(confirmedCases))*100).toLocaleString("en", {minimumFractionDigits: 2, maximumFractionDigits: 2}) + "%";
})
.catch(function() {
console.log("error");
})
setTimeout(getCovidStats, 43200000) // update every 12 hours
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>* {box-sizing: border-box;
}
body {
font-family: Arial, Helvetica, sans-serif;
}
h1{
font-size: smaller;
}
/* Float four columns side by side */
.column {
float: left;
width: 25%;
padding: 0 10px;
}
/* Remove extra left and right margins, due to padding */
.row {
margin: 0 -5px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* Responsive columns */
#media screen and (max-width: 600px) {
.column {
width: 100%;
display: block;
margin-bottom: 20px;
}
}
/* Style the counter cards */
.card {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
padding: 16px;
text-align: center;
background-color: #f1f1f1;
}
</style>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<h2>Responsive Column Cards</h2>
<p>Resize the browser window to see the effect.</p>
<div class="row">
<div class="column">
<div class="card">
<h3>Card 1</h3>
<h4>Cases</h4>
<h1 id="population"></h1>
</div>
</div>
<div class="column">
<div class="card">
<h3>Card 2</h3>
<h4>Cases</h4>
<h1 id="cases"></h1>
</div>
</div>
<div class="column">
<div class="card">
<h3>Card 3</h3>
<h4>Cases</h4>
<h1 id="deaths"></h1>
</div>
</div>
<div class="column">
<div class="card">
<h3>Card 4</h3>
<h4>Cases</h4>
<h1 id="percent"></h1>
</div>
</div>
</div>
</body>
</html>
above is how I'm getting. I need to display the values in the red boxed areas.
This happend because this line
document.getElementById('update').innerHTML = update.substr(0, 10);
you don't have an element with the id update. And JS crash in that line. You need to comment that line or add a validator to check if that element exist.
window.onload = function() {
getCovidStats();
}
function getCovidStats() {
fetch('https://coronavirus-tracker-api.herokuapp.com/v2/locations/225')
.then(function(resp) { return resp.json() })
.then(function(data) {
let population = data.location.country_population;
let update = data.location.last_updated;
let confirmedCases = data.location.latest.confirmed;
let deaths = data.location.latest.deaths;
document.getElementById('population').innerHTML = population.toLocaleString('en');
document.getElementById('cases').innerHTML = confirmedCases.toLocaleString('en');
document.getElementById('deaths').innerHTML = deaths.toLocaleString('en');
document.getElementById('percent').innerHTML = ((Number(deaths)/Number(confirmedCases))*100).toLocaleString("en", {minimumFractionDigits: 2, maximumFractionDigits: 2}) + "%";
})
.catch(function() {
console.log("error");
})
setTimeout(getCovidStats, 43200000) // update every 12 hours
}
* {box-sizing: border-box;
}
body {
font-family: Arial, Helvetica, sans-serif;
}
h1{
font-size: smaller;
}
/* Float four columns side by side */
.column {
float: left;
width: 25%;
padding: 0 10px;
}
/* Remove extra left and right margins, due to padding */
.row {
margin: 0 -5px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* Responsive columns */
#media screen and (max-width: 600px) {
.column {
width: 100%;
display: block;
margin-bottom: 20px;
}
}
/* Style the counter cards */
.card {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
padding: 16px;
text-align: center;
background-color: #f1f1f1;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h2>Responsive Column Cards</h2>
<p>Resize the browser window to see the effect.</p>
<div class="row">
<div class="column">
<div class="card">
<h3>Card 1</h3>
<h4>Cases</h4>
<h1 id="population"></h1>
</div>
</div>
<div class="column">
<div class="card">
<h3>Card 2</h3>
<h4>Cases</h4>
<h1 id="cases"></h1>
</div>
</div>
<div class="column">
<div class="card">
<h3>Card 3</h3>
<h4>Cases</h4>
<h1 id="deaths"></h1>
</div>
</div>
<div class="column">
<div class="card">
<h3>Card 4</h3>
<h4>Cases</h4>
<h1 id="percent"></h1>
</div>
</div>
</div>
</body>
</html>
You are missing an HTML block. Add this to your HTML below the population data:
<div class="column">
<div class="card">
<h3>Card</h3>
<h4>Cases</h4>
<h1 id="update"></h1>
</div>
</div>
Just a quick tips, you can put your CSS styles in an external file and the access it so that your HTML file won't get messy. Create a new file (style.css) and copy all your CSS and paste into the style.css. Then add <link rel="stylesheet" type="text/css" href="style.css"> to the head of HTML.

Vanilla Javascript Accordion Functionality

I need help with closing other panels once I open a click on a different panel. I have been trying to get my head around it for the past week but I'm just not able to.
I don't want to use a jquery library, I want to be able to code this code directly into my website.
I think the javascript code needed is simple in concept but hard to write for someone like me. I still don't exactly understand how javascript commands, functions, etc. work.
Any help or guidance is greatly appreciated!
Here is my code:
HTML
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="accordion.css">
</head>
<body>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<script src="accordion.js"></script>
</body>
</html>
CSS
.accordion {
background-color: #2364aa;
color: #ffffff;
cursor: pointer;
padding: 18px;
border: none;
text-align: left;
outline: none;
font-size: 21px;
transition: 0.4s;
}
.open, .accordion:hover {
background-color: #205A99;
}
.accordion:after {
content: '\f067';
font-family: "Font Awesome 5 Free";
color: #ffffff;
float: right;
font-size: 1.25em;
line-height: 25px;
}
.open:after {
content: "\2212";
}
.panel {
max-height: 0;
overflow: hidden;
transition: 0.2s ease-out;
}
.panel-body {
padding: 18px 0;
}
#media only screen and (min-width: 960px) {
.container {
display: table;
box-sizing: border-box;
}
.row .col {
margin: 10px 0;
}
.col {
display: table-cell;
}
.col.middle {
vertical-align: middle;
}
.col-2 {
width: 50%;
padding-right: 72px;
}
.col-4 {
width: 33.33333333333333333%;
padding-right: 72px;
}
}
Javascript
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
Event Delegation
Wrap everything in a block element.
var main = document.querySelector(`main`)
Add an EventListener to that "parent" element
main.addEventListener('click', ....
Now if main or any descendants of main are clicked, a callback function will be invoked. So we have only one EventListener listening for a click event on the behalf of each .accordion. We determine which .accordion was actually clicked by using an if condition and the event.target property.
The rule of mutual exclusivity applies to how an accordion works:
Only one .accordion + .panel combo can have the .active class.
Whenever it's time to change (in this case, e.target (the clicked element) has been clicked), all .accordions will remove the .active class (whether they actually had it or not).
After there are no element with the .active class, you then give it to e.target.
Changes
.accordion + .panel.active instead of .accordion.active.
.style.maxHeight replaced by class .active:
.panel.active {
max-height: 2000px;
height:auto;
overflow: hidden;
transition: 0.2s ease-out;
}
Demo
Details are commented in Demo
// Reference the parent of all .accordion
var main = document.querySelector('main');
/* Register main to click events...
|| when main or any of its descendant elements are clicked...
*/
main.addEventListener("click", function(e) {
/* Collect all .accordion into a NodeList and convert it into
|| an array.
*/
var acc = Array.from(document.querySelectorAll(".accordion"));
/* Loop thru each .accordion to remove the .active class
|| from each .panel
*/
for (let a = 0; a < acc.length; a++) {
var panel = acc[a].nextElementSibling;
panel.classList.remove('active');
}
/* After nothing has class .active, assign .active to the
|| .panel of the clicked element (e.target)
*/
if (e.target !== e.currentTarget) {
var tgt = e.target.nextElementSibling;
tgt.classList.add("active");
}
});
.accordion {
background-color: #2364aa;
color: #ffffff;
cursor: pointer;
padding: 18px;
border: none;
text-align: left;
outline: none;
font-size: 21px;
transition: 0.4s;
}
.open,
.accordion:hover {
background-color: #205A99;
}
.accordion:after {
content: '\f067';
font-family: "Font Awesome 5 Free";
color: #ffffff;
float: right;
font-size: 1.25em;
line-height: 25px;
}
.open:after {
content: "\2212";
}
.panel {
max-height: 0;
overflow: hidden;
transition: 0.2s ease-out;
}
.panel.active {
max-height: 2000px;
height:auto;
overflow: hidden;
transition: 0.2s ease-out;
}
#media only screen and (min-width: 960px) {
.container {
display: table;
box-sizing: border-box;
}
.row .col {
margin: 10px 0;
}
.col {
display: table-cell;
}
.col.middle {
vertical-align: middle;
}
.col-2 {
width: 50%;
padding-right: 72px;
}
.col-4 {
width: 33.33333333333333333%;
padding-right: 72px;
}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<main>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
</main>
</body>
</html>
I hope this function helps you
function closeAll() {
var accs = document.querySelectorAll('.accordion');
for(var i = 0; i < accs.length; i ++) {
accs[i].classList.remove('active');
var panel = accs[i].nextElementSibling;
panel.style.maxHeight = null;
}
}
Update We can skip closing clicked element by adding this condition to closeAll function:
if (accs[i] == tar) {
continue;
}
Full code here
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function(ev) {
closeAll(ev.target);
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
function closeAll(tar) {
var accs = document.querySelectorAll('.accordion');
for (var i = 0; i < accs.length; i++) {
if (accs[i] == tar) {
continue;
}
accs[i].classList.remove('active');
var panel = accs[i].nextElementSibling;
panel.style.maxHeight = null;
}
}
.accordion {
background-color: #2364aa;
color: #ffffff;
cursor: pointer;
padding: 18px;
border: none;
text-align: left;
outline: none;
font-size: 21px;
transition: 0.4s;
}
.open,
.accordion:hover {
background-color: #205A99;
}
.accordion:after {
content: '\f067';
font-family: "Font Awesome 5 Free";
color: #ffffff;
float: right;
font-size: 1.25em;
line-height: 25px;
}
.open:after {
content: "\2212";
}
.panel {
max-height: 0;
overflow: hidden;
transition: 0.2s ease-out;
}
.panel-body {
padding: 18px 0;
}
#media only screen and (min-width: 960px) {
.container {
display: table;
box-sizing: border-box;
}
.row .col {
margin: 10px 0;
}
.col {
display: table-cell;
}
.col.middle {
vertical-align: middle;
}
.col-2 {
width: 50%;
padding-right: 72px;
}
.col-4 {
width: 33.33333333333333333%;
padding-right: 72px;
}
}
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="accordion.css">
</head>
<body>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<script src="accordion.js"></script>
</body>
</html>
This is a class called Accordion in Vanilla js. It mostly shows the functionality in javascript , style is not good :)
class Accordion {
constructor(AccordionData) {
// State
this.data = AccordionData;
// View Layer
this.mainContainer = document.querySelector('.container');
this.allAccordionDetailsElements = [];
this.init();
}
init() {
this.createAccordions();
this.bindEvents();
}
createAccordions() {
this.data.forEach(acc => {
let accordionHTML = this.generateHTML(acc);
this.mainContainer.appendChild(accordionHTML);
});
this.allAccordionDetailsElements = document.querySelectorAll('.accordion-details');
}
checkIfCurrentTarget(targetEl, detailsEl) {
return detailsEl.dataset.target === targetEl.id;
}
getDisplayStatus(element) {
return element.style.display;
}
toggleDetailsVisibility(detailsEl) {
const isVisible = this.getDisplayStatus(detailsEl) === 'block';
if (!isVisible) {
detailsEl.style.display = 'block';
} else {
detailsEl.style.display = 'none';
}
}
hideAllDetails() {
this.allAccordionDetailsElements.forEach(detailsSection => {
detailsSection.style.display = 'none';
});
}
bindEvents() {
this.mainContainer.addEventListener('click', (e) => {
if (typeof e === 'undefined') return;
const targetEl = e.target;
const isAccordionHeader = targetEl.classList.contains('accordion-header');
if (isAccordionHeader) {
this.hideAllDetails();
this.allAccordionDetailsElements.forEach(detailsSection => {
if (this.checkIfCurrentTarget(targetEl, detailsSection)) {
this.toggleDetailsVisibility(detailsSection)
}
});
}
});
}
generateHTML(accordionElData) {
const { id, headerText, detailsText } = accordionElData;
const sectionEl = document.createElement('section');
sectionEl.className = 'accordion-container';
const headerEl = document.createElement('button');
headerEl.type = 'button';
headerEl.className = 'accordion-header';
headerEl.textContent = headerText;
headerEl.id = id;
const articleEl = document.createElement('article');
articleEl.className = 'accordion-details';
articleEl.textContent = detailsText;
articleEl.dataset.target = id;
sectionEl.appendChild(headerEl);
sectionEl.appendChild(articleEl);
return sectionEl;
}
}
const AccordionData = [
{
id: 'acc-1',
headerText: 'Section 1',
detailsText: 'This is dummy Text for Section 1'
},
{
id: 'acc-2',
headerText: 'Section 2',
detailsText: 'This is dummy Text for Section 2'
},
{
id: 'acc-3',
headerText: 'Section 3',
detailsText: 'This is dummy Text for Section 3'
}
];
window.addEventListener('DOMContentLoaded', () => {
const accordion = new Accordion(AccordionData);
});
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.accordion-details {
display: none;
}
<main class="container"></main>

JS: Iterate through divs

I have 5 div elements, all with class='item'.
Im catching them with: var x = document.getElementsByClassName("item");
Now I want to make disappear that div, which was mouseovered.
https://jsfiddle.net/LqsLbrco/1/
But it doesn't work as it supposed to do. Because all elements are disappearing, not only this which was hovered.
Edit: My point is that the modal div appear (the pink box) when the item div is hovered. Check out the new jsfiddle: https://jsfiddle.net/LqsLbrco/10/
There's a div behind the blue boxes, I want him to appear when the user hovers the blue box.
If you do it in jQuery, you could just do this.
Modified the markup to accommodate the requirements.
$(function() {
$(".container .item").bind("mouseover", function(event) {
$(event.target).find(".modal").show();
});
$(".container .modal").bind("mouseleave", function(event) {
$(event.target).hide();
})
});
.item {
height: 100px;
width: 100px;
background-color: blue;
display: inline-block;
margin: 5px;
}
.container {
display: inline-block;
}
.modal {
height: 100px;
width: 100px;
background-color: pink;
display: inline-block;
margin: 0px;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item">
<div class="modal"></div>
</div>
</div>
<div class="container">
<div class="item">
<div class="modal"></div>
</div>
</div>
<div class="container">
<div class="item">
<div class="modal"></div>
</div>
</div>
<div class="container">
<div class="item">
<div class="modal"></div>
</div>
</div>
<div class="container">
<div class="item">
<div class="modal"></div>
</div>

My JS is not working with my html/css. Not sure why. (Console error 'ReferenceError: $ is not defined')

I am trying to create a content slider, and am having difficulties with it functioning appropriately. Specifically when testing locally the aspect that is not working is: (When you click the arrows left or right the current-slide fades out and fades back in but the slide content does not switch to the next block of content.)
Here is my HTML:
<!DOCTYPE html>
<html>
<head>
<html lang="en-US">
<meta charset="UTF-8">
<title>PLACEHOLDER</title>
<meta name"keywords" content="PLACEHOLDER" />
<meta name"description" content="PLACEHOLDER" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script src="code.js"></script>
<link type="text/css" rel="stylesheet" href="style2.css" />
</head>
<body>
<div class="slider">
<div class="slide active-slide">
<div class="container">
<div class="row">
<div class="slide-copy col-xs-5">
<h1 id="welcome">FIRST SLIDE HEADER</h1>
<div id="img1">
<img src="######.png" width="450" height="250" />
</div>
<div id="intro">
<p>FIRST SLIDE CONTENT</p </div>
</div>
</div>
</div>
<div class="slide slide-feature">
<div class="container">
<div class="row">
<div class="col-xs-12">
<h1>Slide2</h1>
<p>Slide 2 stuff.</p>
</div>
</div>
</div>
</div>
<div class="slide">
<div class="container">
<div class="row">
<div class="slide-copy col-xs-5">
<h1>Slide 3</h1>
<h2>Slide3</h2>
<p>Slide3 content</p>
</div>
</div>
</div>
</div>
<div class="slide">
<div class="container">
<div class="row">
<div class="slide-copy col-xs-5">
<h1>Slide 4</h1>
<p>slide 4 content</p>
</div>
</div>
</div>
</div>
</div>
<div class="slider-nav">
<a href="#" class="arrow-prev">
<img src="ARROW LEFT IMAGE">
</a>
<ul class="slider-dots">
<li class="dot active-dot">•</li>
<li class="dot">•</li>
<li class="dot">•</li>
<li class="dot">•</li>
</ul>
<a href="#" class="arrow-next">
<img src="ARROW RIGHT IMAGE">
</a>
</div>
Here is my JS:
var main = function () {
$('.arrow-next').click(function () {
var currentSlide = $('.active-slide');
var nextSlide = currentSlide.next();
var currentDot = $('.active-dot');
var nextDot = currentDot.next()
if (nextSlide.length === 0) {
nextSlide = $('.slide').first();
nextDot = $('.dot').first();
}
currentSlide.fadeOut(600).removeClass('active-slide');
nextSlide.fadeIn(600).addClass('active-slide');
currentDot.removeClass('active-dot');
nextDot.addClass('active-dot');
});
$('.arrow-prev').click(function()
{
var currentSlide = $('.active-slide');
var prevSlide = currentSlide.prev();
var currentDot = $('.active-dot');
var prevDot = currentDot.prev()
if(prevSlide.length == 0)
{
prevSlide = $('.slide').last();
prevDot = $('.dot').last();
}
currentSlide.fadeOut(600).removeClass('active-slide');
prevSlide.fadeIn(600).addClass('active-slide');
currentDot.removeClass('active-dot');
prevDot.addClass('active-dot');
});
};
$(document).ready(main);
HERE IS MY CSS(Just to tie it all together):
.slider {
position: relative;
width: 50%;
height: 470px;
margin-left: 25%;
border-bottom: 1px solid #ddd;
margin-top: -8%;
}
.slide {
background: transparent url('http://s3.amazonaws.com/codecademy-content/courses/ltp2/img/flipboard/feature-gradient-transparent.png') center center no-repeat;
background-size: cover;
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.active-slide {
display: block;
}
.slide-copy h1 {
color: #363636;
font-family: 'Oswald', sans-serif;
font-weight: 400;
font-size: 40px;
margin-top: 105px;
margin-bottom: 0px;
}
.slide-copy h2 {
color: #b7b7b7;
font-family: 'Oswald', sans-serif;
font-weight: 400;
font-size: 40px;
margin: 5px;
}
.slide-copy p {
color: #959595;
font-family: Georgia, "Times New Roman", serif;
font-size: 1.15em;
line-height: 1.75em;
margin-bottom: 15px;
margin-top: 16px;
}
.slide-img {
text-align: right;
}
/* Slide feature */
.slide-feature {
text-align: center;
background-image: url('http://s3.amazonaws.com/codecademy-content/courses/ltp2/img/flipboard/ac.png');
height: 470px;
}
.slide-feature img {
margin-top: 112px;
margin-bottom: 28px;
}
.slide-feature a {
display: block;
color: #6fc5e0;
font-family: "HelveticaNeueMdCn", Helvetica, sans-serif;
font-family: 'Oswald', sans-serif;
font-weight: 400;
font-size: 20px;
}
.slider-nav {
text-align: center;
margin-top: 20px;
margin-top: 30%;
}
.arrow-prev {
margin-right: 45px;
display: inline-block;
vertical-align: top;
margin-top: 9px;
}
.arrow-next {
margin-left: 45px;
display: inline-block;
vertical-align: top;
margin-top: 9px;
}
.slider-dots {
list-style: none;
display: inline-block;
padding-left: 0;
margin-bottom: 0;
}
.slider-dots li {
color: #bbbcbc;
display: inline;
font-size: 30px;
margin-right: 5px;
}
.slider-dots li.active-dot {
color: #363636;
}
NOTE: I only put the sections of html/js/css that matter for this case. And I used placeholders for some text and images. On my local machine those placeholders are replaced with correct content.
if you look at the HTML closely, you'll see that the slider div's are not positioned properly. all the other div's with the class '.slide' are enclosed inside <div class="slide active-slide"> whereas they should be independent of each other.
the javascript code is not able to find the next() slide since they're all contained in one single parent which is the 'active-slide'
you need to update your HTML to the following
<div class="slider">
<div class="slide active-slide">
<div class="container">
<div class="row">
<div class="slide-copy col-xs-5">
<h1 id="welcome">FIRST SLIDE HEADER</h1>
<div id="img1">
<img src="######.png" width="450" height="250" />
</div>
<div id="intro">
<p>FIRST SLIDE CONTENT</p </div>
</div>
</div>
</div>
</div>
</div>
<div class="slide slide-feature">
<div class="container">
<div class="row">
<div class="col-xs-12">
<h1>Slide2</h1>
<p>Slide 2 stuff.</p>
</div>
</div>
</div>
</div>
<div class="slide">
<div class="container">
<div class="row">
<div class="slide-copy col-xs-5">
<h1>Slide 3</h1>
<h2>Slide3</h2>
<p>Slide3 content</p>
</div>
</div>
</div>
</div>
<div class="slide">
<div class="container">
<div class="row">
<div class="slide-copy col-xs-5">
<h1>Slide 4</h1>
<p>slide 4 content</p>
</div>
</div>
</div>
</div>
</div>
<div class="slider-nav">
<a href="#" class="arrow-prev">
<img src="ARROW LEFT IMAGE">
</a>
<ul class="slider-dots">
<li class="dot active-dot">•</li>
<li class="dot">•</li>
<li class="dot">•</li>
<li class="dot">•</li>
</ul>
<a href="#" class="arrow-next">
<img src="ARROW RIGHT IMAGE">
</a>
</div>
here's a working JSFIDDLE for the same. hope this helps
You just need to include the jQuery library from here: http://jquery.com/download/
You will get this error if you haven't included jquery file or you are getting conflicts in jquery.
ReferenceError: $ is not defined
Add following in Head section of your code:
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>

Categories

Resources