TL;DR
I'd like to drag & drop spans from one container div to a target div and back but not being the draggable spans valid drop targets themselves.
Description
I'm bulding an interactive tournament bracket app and I do struggle with setting the elements valid drop targets. I have a bordered div with #team-container on the right where all the draggable team spans (.draggable-team) are placed (screen snippet).
I used this tutorial and managed to get it working perfectly but there is also an unintended behaviour.
The valid drop targets are indicated by .drop-target and I add event listeners to all of these via
const dropTargets = document.querySelectorAll(".drop-target");
dropTargets.forEach(dropTarget => {
// dropTarget.addEventListener(...);
});
Unfortunately, the items I like to place via drag & drop are also set as valid drop targets (see here). I think that is due to the querySelectorAll I use as the #team-container is a .drop-target too, so the teams can be returned there when necessary. The returned NodeList object does contain the #team-container with its childNodes containing the draggable teams which might be the cause of trouble.
Any idea how to prevent the childs (the teams I like to drag & drop) from being a valid drop target just by being placed into a div that also is a valid drop target? Every help much appreciated! Thanks!
Edit 1
Removed First version with the issue. Possible nesting of draggable team spans is undesirable.
I have kind of solved my problem with if clauses checking if the drop target also is a draggable-team or contains .name. Is there a more elegant way of preventing the draggable team spans from being selectable as drop target?
Edit 2
Added first version snippet here and removed links to jsfiddle.net
addDragListeners();
const dropTargets = document.querySelectorAll('.drop-target');
dropTargets.forEach((dropTarget) => {
dropTarget.addEventListener('dragenter', dragEnter);
dropTarget.addEventListener('dragover', dragOver);
dropTarget.addEventListener('dragleave', dragLeave);
dropTarget.addEventListener('drop', drop);
});
function addDragListeners() {
let items = document.querySelectorAll('.draggable-team');
items.forEach((item) => {
item.addEventListener('dragstart', dragStart);
});
}
function dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
setTimeout(() => {
e.target.classList.add('hide');
}, 0);
}
function dragEnter(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
function dragOver(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
function dragLeave(e) {
e.target.classList.remove('drag-over');
}
function drop(e) {
let dropTarget = e.target;
dropTarget.classList.remove('drag-over');
let id = e.dataTransfer.getData('text/plain');
let draggable = document.getElementById(id);
if (dropTarget.id === 'team-container') {
draggable.classList.remove('dragged-team');
} else {
draggable.classList.add('dragged-team');
}
dropTarget.appendChild(draggable);
draggable.classList.remove('hide');
}
/* ==================== GLOBAL ==================== */
:root {
--text-white: #aaaaaa;
--text-pale: #505050;
--team-background: #1e1e1e;
--background: #303030;
--blue: #003865;
--bracket-line: 4px solid #ffffff;
}
html {
font-size: 14px;
}
body {
margin: 0;
font-family: sans-serif;
background-color: var(--background);
}
* {
box-sizing: border-box;
}
/* ==================== BRACKET ==================== */
.bracket-container {
display: flex;
flex-direction: row;
column-gap: 0.5rem;
margin-left: 1rem;
}
/* ----- MATCHES ----- */
.match-column {
display: flex;
flex-direction: column;
justify-content: space-around;
}
.match {
display: flex;
margin: 1rem 0;
}
.team-names {
display: flex;
flex-direction: column;
width: 100%;
}
.match-number {
height: 100%;
display: flex;
align-items: center;
margin-right: 0.5rem;
color: var(--text-white);
}
.top-number,
.top-name {
border-bottom: 1px solid var(--text-pale);
}
.number {
padding: 0.5rem 0.5rem;
min-width: 2.1rem;
color: var(--team-background);
background-color: var(--text-white);
justify-content: center;
display: flex;
}
.name {
padding: 0.5rem 1rem;
color: var(--text-white);
background-color: var(--team-background);
display: block;
height: 50%;
min-width: 10rem;
}
/* ==================== DRAG & DROP ==================== */
#team-container {
position: absolute;
display: flex;
flex-direction: column;
right: 10px;
top: 10px;
height: 50vh;
padding: 1rem 2rem;
border: 3px solid #000000;
}
#team-container>span {
margin: 1rem 0;
text-align: center;
max-height: 2.5rem;
}
.draggable-team {
cursor: move;
}
.dragged-team {
padding: 0;
height: 100%;
}
.hide {
display: none;
}
.drag-over {
background-color: var(--blue);
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<article class="bracket-container">
<div class="match-column">
<div class="match">
<span class="seed-number">
<span class="number top-number">1</span>
<span class="number bottom-number">4</span>
</span>
<span class="team-names">
<span class="drop-target name top-name"></span>
<span class="drop-target name bottom-name"></span>
</span>
</div>
<div class="match">
<span class="seed-number">
<span class="number top-number">2</span>
<span class="number bottom-number">3</span>
</span>
<span class="team-names">
<span class="drop-target name top-name"></span>
<span class="drop-target name bottom-name"></span>
</span>
</div>
</div>
<div class="match-column">
<div class="match">
<span class="seed-number">
<span class="number top-number">1</span>
<span class="number bottom-number">2</span>
</span>
<span class="team-names">
<span class="drop-target name top-name"></span>
<span class="drop-target name bottom-name"></span>
</span>
</div>
</div>
</article>
<div id="team-container" class="drop-target">
<span class="draggable-team name" id="team1" draggable="true">Team1</span>
<span class="draggable-team name" id="team2" draggable="true">Team2</span>
<span class="draggable-team name" id="team3" draggable="true">Team3</span>
<span class="draggable-team name" id="team4" draggable="true">Team4</span>
</div>
<script src="script.js"></script>
</body>
</html>
Added second snippet with improved version here
addDragListeners();
const dropTargets = document.querySelectorAll(".drop-target");
dropTargets.forEach(dropTarget => {
dropTarget.addEventListener("dragenter", dragEnter);
dropTarget.addEventListener("dragover", dragOver);
dropTarget.addEventListener("dragleave", dragLeave);
dropTarget.addEventListener("drop", drop);
});
function addDragListeners() {
let items = document.querySelectorAll(".draggable-team");
items.forEach(item => {
item.addEventListener("dragstart", dragStart);
});
}
function dragStart(e) {
e.dataTransfer.setData("text/plain", e.target.id);
setTimeout(() => {
e.target.classList.add("hide");
}, 0);
}
function dragEnter(e) {
e.preventDefault();
e.target.classList.add("drag-over");
}
function dragOver(e) {
e.preventDefault();
e.target.classList.add("drag-over");
}
function dragLeave(e) {
e.target.classList.remove("drag-over");
}
function drop(e) {
let dropTarget = e.target;
dropTarget.classList.remove("drag-over");
let id = e.dataTransfer.getData("text/plain");
let draggable = document.getElementById(id);
// Move draggable back to tem-container if dropTarget is not empty
if (dropTarget.textContent != "") {
resetToTeamContainer(e);
} else {
// Remove class dragged-team when put back to team-container
if (dropTarget.id === "team-container") {
draggable.classList.remove("dragged-team");
} else {
draggable.classList.add("dragged-team");
}
// If dropped in draggable team, place back in team-container and remove
// class dragged-team
if (dropTarget.classList.contains("draggable-team")) {
resetToTeamContainer(e);
} else {
dropTarget.appendChild(draggable);
}
}
// display the draggable element
draggable.classList.remove("hide");
}
function resetToTeamContainer(e) {
let id = e.dataTransfer.getData("text/plain");
let draggable = document.getElementById(id);
draggable.classList.remove("dragged-team");
document.querySelector("#team-container").appendChild(draggable);
}
/* ==================== GLOBAL ==================== */
:root {
--text-white: #aaaaaa;
--text-pale: #505050;
--team-background: #1e1e1e;
--background: #303030;
--blue: #003865;
--bracket-line: 4px solid #ffffff;
}
html {
font-size: 14px;
}
body {
margin: 0;
font-family: sans-serif;
background-color: var(--background);
}
* {
box-sizing: border-box;
}
/* ==================== BRACKET ==================== */
.bracket-container {
display: flex;
flex-direction: row;
column-gap: 0.5rem;
margin-left: 1rem;
}
/* ----- MATCHES ----- */
.match-column {
display: flex;
flex-direction: column;
justify-content: space-around;
}
.match {
display: flex;
margin: 1rem 0;
}
.team-names {
display: flex;
flex-direction: column;
width: 100%;
}
.match-number {
height: 100%;
display: flex;
align-items: center;
margin-right: 0.5rem;
color: var(--text-white);
}
.top-number,
.top-name {
border-bottom: 1px solid var(--text-pale);
}
.number {
padding: 0.5rem 0.5rem;
min-width: 2.1rem;
color: var(--team-background);
background-color: var(--text-white);
justify-content: center;
display: flex;
}
.name {
padding: 0.5rem 1rem;
color: var(--text-white);
background-color: var(--team-background);
display: block;
height: 50%;
min-width: 10rem;
}
/* ==================== DRAG & DROP ==================== */
#team-container {
position: absolute;
display: flex;
flex-direction: column;
right: 10px;
top: 10px;
height: 50vh;
padding: 1rem 2rem;
border: 3px solid #000000;
}
#team-container>span {
margin: 1rem 0;
text-align: center;
max-height: 2.5rem;
}
.draggable-team {
cursor: move;
}
.dragged-team {
padding: 0;
height: 100%;
}
.hide {
display: none;
}
.drag-over {
background-color: var(--blue);
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<article class="bracket-container">
<div class="match-column">
<div class="match">
<span class="seed-number">
<span class="number top-number">1</span>
<span class="number bottom-number">4</span>
</span>
<span class="team-names">
<span class="drop-target name top-name"></span>
<span class="drop-target name bottom-name"></span>
</span>
</div>
<div class="match">
<span class="seed-number">
<span class="number top-number">2</span>
<span class="number bottom-number">3</span>
</span>
<span class="team-names">
<span class="drop-target name top-name"></span>
<span class="drop-target name bottom-name"></span>
</span>
</div>
</div>
<div class="match-column">
<div class="match">
<span class="seed-number">
<span class="number top-number">1</span>
<span class="number bottom-number">2</span>
</span>
<span class="team-names">
<span class="drop-target name top-name"></span>
<span class="drop-target name bottom-name"></span>
</span>
</div>
</div>
</article>
<div id="team-container" class="drop-target">
<span class="draggable-team name" id="team1" draggable="true">Team1</span>
<span class="draggable-team name" id="team2" draggable="true">Team2</span>
<span class="draggable-team name" id="team3" draggable="true">Team3</span>
<span class="draggable-team name" id="team4" draggable="true">Team4</span>
</div>
<script src="script.js"></script>
</body>
</html>
Remaining question:
Is there a way to prevent the draggable spans from being a valid drop target?
The blue F turns into an actual amount of weight when you enter a number into the input field above.
The Two Functions Kg() and Lbs() are changing the class .dynamic which is where Kg or Lbs is being appended to the 8 divs that have the .dynamic class. Now that's exactly what isn't happening. When I select the divs with the .dynamic class, It adds Kg or Lbs (whatever button I press) to the first element with the .dynamic class.
How do I make it so that it appends that to all of the elements with the .dynamic class?
//Variables
const mercury = document.getElementById("mercury");
const venus = document.getElementById("venus");
const earth = document.getElementById("earth");
const mars = document.getElementById("mars");
const jupiter = document.getElementById("jupiter");
const saturn = document.getElementById("saturn");
const uranus = document.getElementById("uranus");
const neptune = document.getElementById("neptune");
const weight = document.getElementById("weight");
weight.addEventListener("input", Calc);
function Calc() {
if (weight.value > 99999) {
alert("Max Amount Of Numbers is 99999");
weight.value = "";
} else {
var val = weight.value;
console.log(val);
var calculate = val * 0.38;
calculate = Math.round(calculate);
mercury.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 0.9;
calculate = Math.round(calculate);
venus.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 1;
calculate = Math.round(calculate);
earth.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 0.38;
calculate = Math.round(calculate);
mars.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 2.36;
calculate = Math.round(calculate);
jupiter.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 0.92;
calculate = Math.round(calculate);
saturn.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 0.89;
calculate = Math.round(calculate);
uranus.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 1.12;
calculate = Math.round(calculate);
neptune.innerHTML = calculate;
console.log(calculate);
}
}
function lbs() {
let unit = document.getElementById("unit");
if (unit == null) {
let newElement = document.createElement("h3");
newElement.setAttribute("class", "value");
newElement.setAttribute("id", "unit");
newElement.textContent = "Lbs";
document.querySelector(".dynamic").appendChild(newElement);
} else {
if (unit.innerHTML == "Kg") {
unit.innerHTML = "Lbs";
}
}
}
function kg() {
let unit = document.getElementById("unit");
if (unit == null) {
let newElement = document.createElement("h3");
newElement.setAttribute("class", "value");
newElement.setAttribute("id", "unit");
newElement.textContent = "Kg";
document.querySelector(".dynamic").appendChild(newElement);
} else {
if (unit.innerHTML == "Lbs") {
unit.innerHTML = "Kg";
}
}
}
#import url("https://fonts.googleapis.com/css2?family=Montserrat:ital,wght#0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
#font-face {
font-family: SpaceQuest;
src: url(https://raw.githubusercontent.com/Lemirq/WODP/master/Fonts/SpaceQuest-yOY3.woff);
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
}
::-webkit-scrollbar {
width: 10px;
}
/* Track */
::-webkit-scrollbar-track {
background: url(./dario-bronnimann-hNQwIirOseE-unsplash.jpg);
}
/* Handle */
::-webkit-scrollbar-thumb {
background: rgba(59, 59, 59, 0.741);
border-radius: 200px;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: rgb(255, 255, 255);
}
* {
--c-light: #f4f4f4;
--c-dark: #141414;
--c-blue: rgb(10, 132, 255);
--f-body: "Montserrat", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
--trans-ease-in-out: all 0.2s ease-in-out;
color: var(--c-light);
}
body {
background-image: url(https://raw.githubusercontent.com/Lemirq/WODP/master/images/dario-bronnimann-hNQwIirOseE-unsplash.jpg);
margin: 0;
inset: 50px;
font-family: var(--f-body);
}
a {
color: var(--c-light);
text-decoration: none;
}
/***** NAVBAR *****/
.nav-item {
transition: var(--trans-ease-in-out);
}
.ext-link {
cursor: alias;
}
.nav-item:hover {
color: var(--c-dark);
background-color: var(--c-light);
}
.nav-item:hover li {
color: var(--c-dark);
}
.nav-item.icon-link:hover i {
color: var(--c-dark);
}
.nav-item:not(:last-child) {
margin-right: 20px;
}
navbar {
display: flex;
flex-direction: row;
justify-content: end;
align-items: center;
padding: 20px;
}
.nav-item-container {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
margin: 0;
padding: 0;
}
.nav-item {
display: inline-block;
list-style: none;
padding: 10px;
font-size: 20px;
border-radius: 10px;
}
.gh-icon {
font-size: 30px;
}
/***** End NAVBAR *****/
/***** Main *****/
#wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
h1 {
font-family: SpaceQuest, sans-serif;
font-size: 3.5rem;
}
.input-group {
border: 2px var(--c-light) solid;
border-radius: 10px;
/* max-width: 400px; */
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
margin-top: 50px;
}
[type="number"]:focus {
outline: none;
}
[type="number"] {
font-size: 20px;
padding: 5px;
background-color: rgba(217, 217, 217, 0.2);
border: none;
font-family: var(--f-body);
min-width: 280px;
}
.btn-form {
font-size: 20px;
padding: 5px;
background-color: rgba(217, 217, 217, 0.2);
border: none;
transition: var(--trans-ease-in-out);
cursor: pointer;
font-family: var(--f-body);
}
.btn-form:hover {
background-color: rgba(217, 217, 217, 0.4);
}
.btn-form:first {
border-right: var(--c-light) 1px solid;
}
.input-group-text {
background-color: rgba(217, 217, 217, 0.2);
font-size: 17px;
padding: 7px;
}
/***** End Main *****/
/***** CARDS *****/
.card-container {
margin: 50px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
align-items: center;
grid-gap: 10px;
width: calc(100vw - 200px);
}
.card {
background-color: #141414;
width: auto;
height: auto;
border-radius: 10px;
padding: 30px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175);
}
.planet-info {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.planet {
font-size: 50px;
margin: 0;
text-transform: capitalize;
}
.planet-img {
width: 80px;
height: auto;
margin-right: 30px;
}
[src="./images/planets/Saturn.png"] {
height: 79.25px;
width: auto;
}
.weight {
margin-top: 10px;
text-transform: capitalize;
font-size: 20px;
}
.weight::after {
content: ":";
}
.divider {
height: 1px;
width: 100%;
margin: 20px 0;
background-color: var(--c-light);
}
.value {
font-size: 60px;
color: var(--c-blue);
}
.dynamic>.value:nth-child(2) {
margin-left: 10px;
}
.dynamic {
display: flex;
flex-direction: row;
justify-content: space-between;
}
/***** End CARDS *****/
.input-error {
outline: 1px solid red;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.8.3/font/bootstrap-icons.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<navbar>
<ul class="nav-item-container">
<a target="_blank" class="nav-item ext-link" href="https://lemirq.github.io">
<li>Website</li>
</a>
<a target="_blank" class="nav-item icon-link ext-link" href="https://github.com/Lemirq">
<li><i class="bi bi-github gh-icon"></i></li>
</a>
</ul>
</navbar>
<div id="wrapper">
<h1 id="vs-h1">Your Weight On Different Planets</h1>
<div class="input-group">
<input id="weight" placeholder="Enter your Weight" type="number">
<button id="kg" onclick="kg()" class="btn-form" type="button">Kg</button>
<button id="lbs" onclick="lbs()" class="btn-form" type="button">Lbs</button>
</div>
<div class="card-container">
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Mercury.png" alt="EARTH">
<h3 class="planet">mercury</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="mercury" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Venus.png" alt="EARTH">
<h3 class="planet">venus</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="venus" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Earth.png" alt="EARTH">
<h3 class="planet">earth</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="earth" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Mars.png" alt="EARTH">
<h3 class="planet">mars</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="mars" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Jupiter.png" alt="EARTH">
<h3 class="planet">jupiter</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="jupiter" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Saturn.png" alt="EARTH">
<h3 class="planet">saturn</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="saturn" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Uranus.png" alt="EARTH">
<h3 class="planet">uranus</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="uranus" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Neptune.png" alt="EARTH">
<h3 class="planet">neptune</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="neptune" class="value">F</h3>
</div>
</div>
</div>
</div>
Select all elements with the .dynamic class by using querySelectorAll
Iterate through the NodeList and append desired child to each node
let dynamics = document.querySelectorAll(".dynamic")
dynamics.forEach((ele) => {
let newElement = document.createElement("h3");
ele.appendChild(newElement);
}
Minor Problems
There's no such HTML element <navbar>, there's <nav>.
There's a block code hard-coded 8 times with the only difference between them is a number. Whenever code needs to repeat itself, we use some sort of iteration such as a for loop or an array method and the numbers would be passed as a single variable passed with every iteration.
const gforce = [0.38, 0.9, 1, 0.38, 2.36, 0.92, 0.89, 1.12];
for (let i=0; i < 8; i++) {
var val = weight.value;
console.log(val);
var calculate = val * gforce[i];//<== that should be a variable
calculate = Math.round(calculate);
venus.innerHTML = calculate;
console.log(calculate);
}
Also, the <input> that's supposed to calculate lbs and kg doesn't appear to convert kg to lbs or vice-versa.
Details are commented in example
// An array of objects - each object represents a planet
const data = [{
planet: 'Mercury',
gforce: 0.38,
img: `https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Mercury_in_true_color.jpg/440px-Mercury_in_true_color.jpg`
},
{
planet: 'Venus',
gforce: 0.9,
img: `https://upload.wikimedia.org/wikipedia/commons/thumb/0/08/Venus_from_Mariner_10.jpg/440px-Venus_from_Mariner_10.jpg`
},
{
planet: 'Earth',
gforce: 1,
img: `https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/The_Blue_Marble_%28remastered%29.jpg/440px-The_Blue_Marble_%28remastered%29.jpg`
},
{
planet: 'Mars',
gforce: 0.38,
img: `https://upload.wikimedia.org/wikipedia/commons/thumb/0/02/OSIRIS_Mars_true_color.jpg/440px-OSIRIS_Mars_true_color.jpg`
},
{
planet: 'Jupiter',
gforce: 2.36,
img: `https://upload.wikimedia.org/wikipedia/commons/thumb/2/2b/Jupiter_and_its_shrunken_Great_Red_Spot.jpg/440px-Jupiter_and_its_shrunken_Great_Red_Spot.jpg`
},
{
planet: 'Saturn',
gforce: 0.92,
img: `https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Saturn_during_Equinox.jpg/600px-Saturn_during_Equinox.jpg`
},
{
planet: 'Uranus',
gforce: 0.89,
img: `https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Uranus_as_seen_by_NASA%27s_Voyager_2_%28remastered%29.png/440px-Uranus_as_seen_by_NASA%27s_Voyager_2_%28remastered%29.png`
},
{
planet: 'Neptune',
gforce: 1.12,
img: `https://upload.wikimedia.org/wikipedia/commons/thumb/6/63/Neptune_-_Voyager_2_%2829347980845%29_flatten_crop.jpg/440px-Neptune_-_Voyager_2_%2829347980845%29_flatten_crop.jpg`
}
];
// Reference <form> and all form controls
const conv = document.forms.converter;
const IO = conv.elements;
/*
Collect all tags with [name='planet'] and convert it into an array...
...iterate through array and define a htmlString and interpolate planet
name and <img> url...
...render htmlString into current <output>
*/
[...IO.planet].forEach((output, index) => {
const html = `
<h3>${data[index].planet}</h3>
<img src='${data[index].img}'>
<h4></h4>`;
output.insertAdjacentHTML('beforeend', html)
});
// Bind the "input" event to <form>
conv.oninput = IWC;
/*
Event handler passes Event Object by default
Reference all form controls
Reference the tag the user interacted with
If the user typed into [name='weight']...
...if that tag was also #lbs...
...#kg value is the value of >origin< times 0.45359237...
...otherwise #lbs value is the value of >origin< times 2.20462...
*/
/*
Collect all [name='planet'] into an array and iterate with .forEach()...
...clear out the last tag of current <output> (<h4>)...
...display the calculated totals for lbs. and kg of each planet
*/
function IWC(e) {
const IO = this.elements;
const origin = e.target;
if (origin.name === 'weight') {
if (origin.id === 'lbs') {
IO.kg.value = +origin.value * 0.45359237;
} else {
IO.lbs.value = +origin.value * 2.20462;
}
[...IO.planet].forEach((output, index) => {
output.lastElementChild.innerHTML = '';
output.lastElementChild.insertAdjacentHTML('beforeend',
`lbs. ${Math.round(data[index].gforce * IO.lbs.value)}<br>
kg ${Math.round(data[index].gforce * IO.kg.value)}`);
});
}
}
#import url('https://fonts.googleapis.com/css2?family=Oswald:wght#300&family=Raleway:wght#300&display=swap');
html {
font: 300 2ch/1 Oswald;
}
body {
width: 100%;
overflow-x: hidden;
background: #aaa
}
h1 {
color: gold
}
h1,
h2,
h3,
h4 {
margin: 0;
font-family: Raleway;
}
h3,
h4 {
position: absolute;
z-index: 1;
}
h3 {
margin: 0 auto;
}
h4 {
bottom: 0
}
form {
margin: 0 0 0 -15px;
}
fieldset {
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: center;
max-width: 90%;
margin: 15px
}
fieldset+fieldset {
background: #222
}
fieldset+fieldset legend {
color: gold
}
output {
position: relative;
display: inline-flex;
width: 24%;
min-height: 8rem;
margin-top: 15px;
padding: 2px;
background: black;
color: cyan
}
input {
font: inherit;
width: 10rem;
margin: 10px;
text-align: center;
}
img {
width: 100%;
}
<form id='converter'>
<fieldset>
<legend>
<h1>Interplanetary<br>Weight Converter</h1>
</legend>
<input id="lbs" name='weight' placeholder=" Weight in lbs." type="number" min='0' max='99999'><label for='lbs'>lbs.</label>
<input id="kg" name='weight' placeholder="Weight in kg." type="number" min='0' max='99999'><label for='kg'>kg</label>
</fieldset>
<fieldset>
<legend>
<h2>The Solar System</h2>
</legend>
<output name='planet'></output>
<output name='planet'></output>
<output name='planet'></output>
<output name='planet'></output>
<output name='planet'></output>
<output name='planet'></output>
<output name='planet'></output>
<output name='planet'></output>
</fieldset>
</form>
The script must look something like this:
<script>
let elements = document.querySelectorAll(".dynamic")
elements.forEach(el=>{
let child = document.createElement('div')
el.appendChild(child)
})
</script>
This can be simplified quite a bit, the buttons' innerHTML values match what you want in the new unit elements.
<button id="kg" class="btn-form" type="button">Kg</button>
<button id="lbs" class="btn-form" type="button">Lbs</button>
Use JavaScript to add an event listener to both unit buttons that call the same function which will update the innerHTML of the unit headings to match the clicked button. When initializing the unit heading elements you should not give them all the same id but rather a common class and you must also append a cloned copy of the element or it will just move the element form one spot to the next:
document.querySelectorAll('#kg, #lbs').forEach(ub => ub.addEventListener('click', units));
function units(e) {
let units = document.querySelectorAll(".value.unit");
if (units.length == 0) {
let newElement = document.createElement("h3");
newElement.setAttribute("class", "value unit");
document.querySelectorAll(".dynamic").forEach((dyn) => {
// append a cloned copy to each, not the same newElement
dyn.appendChild(newElement.cloneNode())
});
// re-run the query to find the newly added nodes
units = document.querySelectorAll(".value.unit");
}
// set the content
units.forEach(unit => unit.innerHTML = e.target.innerHTML);
}
//Variables
const mercury = document.getElementById("mercury");
const venus = document.getElementById("venus");
const earth = document.getElementById("earth");
const mars = document.getElementById("mars");
const jupiter = document.getElementById("jupiter");
const saturn = document.getElementById("saturn");
const uranus = document.getElementById("uranus");
const neptune = document.getElementById("neptune");
const weight = document.getElementById("weight");
weight.addEventListener("input", Calc);
function Calc() {
if (weight.value > 99999) {
alert("Max Amount Of Numbers is 99999");
weight.value = "";
} else {
var val = weight.value;
console.log(val);
var calculate = val * 0.38;
calculate = Math.round(calculate);
mercury.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 0.9;
calculate = Math.round(calculate);
venus.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 1;
calculate = Math.round(calculate);
earth.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 0.38;
calculate = Math.round(calculate);
mars.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 2.36;
calculate = Math.round(calculate);
jupiter.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 0.92;
calculate = Math.round(calculate);
saturn.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 0.89;
calculate = Math.round(calculate);
uranus.innerHTML = calculate;
console.log(calculate);
var val = weight.value;
console.log(val);
var calculate = val * 1.12;
calculate = Math.round(calculate);
neptune.innerHTML = calculate;
console.log(calculate);
}
}
document.querySelectorAll('#kg, #lbs').forEach(ub => ub.addEventListener('click', units));
function units(e) {
let units = document.querySelectorAll(".value.unit");
if (units.length == 0) {
let newElement = document.createElement("h3");
newElement.setAttribute("class", "value unit");
document.querySelectorAll(".dynamic").forEach((dyn) => {
// append a cloned copy to each, not the same newElement
dyn.appendChild(newElement.cloneNode())
});
// re-run the query to find the newly added nodes
units = document.querySelectorAll(".value.unit");
}
// set the content
units.forEach(unit => unit.innerHTML = e.target.innerHTML);
}
#import url("https://fonts.googleapis.com/css2?family=Montserrat:ital,wght#0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
#font-face {
font-family: SpaceQuest;
src: url(https://raw.githubusercontent.com/Lemirq/WODP/master/Fonts/SpaceQuest-yOY3.woff);
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
}
::-webkit-scrollbar {
width: 10px;
}
/* Track */
::-webkit-scrollbar-track {
background: url(./dario-bronnimann-hNQwIirOseE-unsplash.jpg);
}
/* Handle */
::-webkit-scrollbar-thumb {
background: rgba(59, 59, 59, 0.741);
border-radius: 200px;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: rgb(255, 255, 255);
}
* {
--c-light: #f4f4f4;
--c-dark: #141414;
--c-blue: rgb(10, 132, 255);
--f-body: "Montserrat", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
--trans-ease-in-out: all 0.2s ease-in-out;
color: var(--c-light);
}
body {
background-image: url(https://raw.githubusercontent.com/Lemirq/WODP/master/images/dario-bronnimann-hNQwIirOseE-unsplash.jpg);
margin: 0;
inset: 50px;
font-family: var(--f-body);
}
a {
color: var(--c-light);
text-decoration: none;
}
/***** NAVBAR *****/
.nav-item {
transition: var(--trans-ease-in-out);
}
.ext-link {
cursor: alias;
}
.nav-item:hover {
color: var(--c-dark);
background-color: var(--c-light);
}
.nav-item:hover li {
color: var(--c-dark);
}
.nav-item.icon-link:hover i {
color: var(--c-dark);
}
.nav-item:not(:last-child) {
margin-right: 20px;
}
navbar {
display: flex;
flex-direction: row;
justify-content: end;
align-items: center;
padding: 20px;
}
.nav-item-container {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
margin: 0;
padding: 0;
}
.nav-item {
display: inline-block;
list-style: none;
padding: 10px;
font-size: 20px;
border-radius: 10px;
}
.gh-icon {
font-size: 30px;
}
/***** End NAVBAR *****/
/***** Main *****/
#wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
h1 {
font-family: SpaceQuest, sans-serif;
font-size: 3.5rem;
}
.input-group {
border: 2px var(--c-light) solid;
border-radius: 10px;
/* max-width: 400px; */
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
margin-top: 50px;
}
[type="number"]:focus {
outline: none;
}
[type="number"] {
font-size: 20px;
padding: 5px;
background-color: rgba(217, 217, 217, 0.2);
border: none;
font-family: var(--f-body);
min-width: 280px;
}
.btn-form {
font-size: 20px;
padding: 5px;
background-color: rgba(217, 217, 217, 0.2);
border: none;
transition: var(--trans-ease-in-out);
cursor: pointer;
font-family: var(--f-body);
}
.btn-form:hover {
background-color: rgba(217, 217, 217, 0.4);
}
.btn-form:first {
border-right: var(--c-light) 1px solid;
}
.input-group-text {
background-color: rgba(217, 217, 217, 0.2);
font-size: 17px;
padding: 7px;
}
/***** End Main *****/
/***** CARDS *****/
.card-container {
margin: 50px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
align-items: center;
grid-gap: 10px;
width: calc(100vw - 200px);
}
.card {
background-color: #141414;
width: auto;
height: auto;
border-radius: 10px;
padding: 30px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175);
}
.planet-info {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.planet {
font-size: 50px;
margin: 0;
text-transform: capitalize;
}
.planet-img {
width: 80px;
height: auto;
margin-right: 30px;
}
[src="./images/planets/Saturn.png"] {
height: 79.25px;
width: auto;
}
.weight {
margin-top: 10px;
text-transform: capitalize;
font-size: 20px;
}
.weight::after {
content: ":";
}
.divider {
height: 1px;
width: 100%;
margin: 20px 0;
background-color: var(--c-light);
}
.value {
font-size: 60px;
color: var(--c-blue);
}
.dynamic>.value:nth-child(2) {
margin-left: 10px;
}
.dynamic {
display: flex;
flex-direction: row;
justify-content: space-between;
}
/***** End CARDS *****/
.input-error {
outline: 1px solid red;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.8.3/font/bootstrap-icons.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<navbar>
<ul class="nav-item-container">
<a target="_blank" class="nav-item ext-link" href="https://lemirq.github.io">
<li>Website</li>
</a>
<a target="_blank" class="nav-item icon-link ext-link" href="https://github.com/Lemirq">
<li><i class="bi bi-github gh-icon"></i></li>
</a>
</ul>
</navbar>
<div id="wrapper">
<h1 id="vs-h1">Your Weight On Different Planets</h1>
<div class="input-group">
<input id="weight" placeholder="Enter your Weight" type="number">
<button id="kg" class="btn-form" type="button">Kg</button>
<button id="lbs" class="btn-form" type="button">Lbs</button>
</div>
<div class="card-container">
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Mercury.png" alt="EARTH">
<h3 class="planet">mercury</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="mercury" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Venus.png" alt="EARTH">
<h3 class="planet">venus</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="venus" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Earth.png" alt="EARTH">
<h3 class="planet">earth</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="earth" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Mars.png" alt="EARTH">
<h3 class="planet">mars</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="mars" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Jupiter.png" alt="EARTH">
<h3 class="planet">jupiter</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="jupiter" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Saturn.png" alt="EARTH">
<h3 class="planet">saturn</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="saturn" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Uranus.png" alt="EARTH">
<h3 class="planet">uranus</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="uranus" class="value">F</h3>
</div>
</div>
<div class="card">
<div class="planet-info">
<img class="planet-img" src="./images/planets/Neptune.png" alt="EARTH">
<h3 class="planet">neptune</h3>
</div>
<div class="divider"></div>
<h4 class="weight">weight</h4>
<div class="dynamic">
<h3 id="neptune" class="value">F</h3>
</div>
</div>
</div>
</div>
I'm creating a website for sociology info. It's similar to yourlogicalfallacyis.com so when you hover over the icons, the name and description of each icon is displayed. Each icon has a different description. However, I can't seem to find a way to display the correct information for each icon.
The lorem ipsum text is just a placeholder for the description of each icon. Here is my code. Is there a way I can show the description of each image when I hover over them?
// Labeling each variable
const conceptNameDisplay = document.getElementById('conceptNameDisplay');
const conceptInfoDisplay = document.getElementById('conceptInfoDisplay');
// Labeling each description
const socioDefinition = document.getElementById('socioDefinition');
const socioTheories = document.getElementById('socioTheories');
const interactionist = document.getElementById('interactionist');
const conflict = document.getElementById('conflict');
const functionalist = document.getElementById('functionalist');
const formsSocialization = document.getElementById('formsSocialization');
const exchange = document.getElementById('exchange');
const learning = document.getElementById('learning');
const labeling = document.getElementById('labeling');
const feminism = document.getElementById('feminism');
const strain = document.getElementById('strain');
const game = document.getElementById('game');
const sociobiology = document.getElementById('sociobiology');
const chaos = document.getElementById('chaos');
const phenomonology = document.getElementById('phenomonology');
const disengagement = document.getElementById('disengagement');
const macro = document.getElementById('macro');
const comte = document.getElementById('comte');
const marx = document.getElementById('marx');
const durkheim = document.getElementById('durkheim');
const weber = document.getElementById('weber');
const spencer = document.getElementById('spencer');
// Selecting all images
const icons = document.querySelectorAll('img');
// function for when images are clicked, applicable to all images
icons.forEach(icon => icon.addEventListener("mouseover", (e) => {
conceptName = e.target.alt
conceptNameDisplay.innerHTML = conceptName
displayInfo()
}))
// function to display respective information for each icon
function displayInfo() {
if (document.getElementById('whatIsSociologyIcon').onmouseover == true) {
conceptInfoDisplay.innerHTML = 'Sociology is the study of human social relationships and institutions. Sociology’s subject matter is diverse, ranging from crime to religion, from the family to the state, from the divisions of race and social class to the shared beliefs of a common culture, and from social stability to radical change in whole societies.';
} else if (document.getElementById('socioTheoriesIcon').onmouseover == true) {
conceptInfoDisplay.innerHTML = 'A sociological theory is a supposition that intends to consider, analyze, and/or explain objects of social reality from a sociological perspective, drawing connections between individual concepts in order to organize and substantiate sociological knowledge.';
} else if (document.getElementById('interactionistIcon').onmouseover == true) {
conceptInfoDisplay.innerHTML = 'Interactionist Perspective Information';
}
}
#import url('https://fonts.googleapis.com/css2?family=Merriweather:ital,wght#0,300;0,400;0,700;0,900;1,900&display=swap');
:root {
--mainbgcolor: #FDFBEC;
--logo: #F4C553;
--green: #E1EEDD;
--greentext: #153A1E;
--orange: #EE9F4A;
}
html, body {
margin: 0 auto;
padding: 0;
height: 100vh;
display: flex;
flex-direction: column;
font-family: 'Merriweather', serif;
background-color: var(--mainbgcolor);
box-sizing: border-box;
}
header {
display: flex;
align-items: center;
justify-content: space-between;
background-color: var(--mainbgcolor);
color: var(--logo);
padding: 0px 20px;
font-size: small;
}
#logo {
font-weight: 900;
}
header a, li {
text-decoration: none;
list-style: none;
color: var(--orange);
font-weight: 700;
}
ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
gap: 16px
}
main {
margin: 0px;
padding: 0px;
display: flex;
flex-direction: column;
}
.icon-container {
padding: 10px 20px;
display: grid;
gap: 15px;
grid-template-columns: auto auto auto auto auto;
justify-content: center;
}
.info-icons-container {
padding: 5px 20px;
text-align: center;
}
#conceptName {
font-weight: 700;
font-size: 2rem;
margin: 5px 0px 10px 0px;
}
.conceptInfo {
font-size: 0.8rem;
}
footer {
background-color: var(--orange);
color: var(--mainbgcolor);
text-align: center;
margin-top: auto;
}
.icon img {
width: 55px;
height: auto;
cursor: pointer;
}
.icon img:hover {
box-shadow: 0 0 5px 5px var(--orange);
}
#media only screen
and (min-width: 1024px)
and (max-height: 1366px)
and (-webkit-min-device-pixel-ratio: 1.5) {
header {
font-size: medium;
padding: 0 30px;
}
.icon-container {
gap: 30px;
}
.icon img {
width: 80px;
height: auto;
}
#conceptName {
font-size: 3rem;
}
#conceptInfo {
font-size: 1rem;
margin: 0 30px;
}
}
#media only screen
and (min-device-width: 768px)
and (max-device-width: 1190px)
and (orientation: portrait)
and (-webkit-min-device-pixel-ratio: 1) {
header {
font-size: medium;
padding: 0 30px;
}
.icon-container {
gap: 30px;
}
.icon img {
width: 100px;
height: auto;
}
#conceptName {
font-size: 3rem;
}
#conceptInfo {
font-size: 1rem;
margin: 0 30px;
}
}
#media (min-width:1200px) {
header {
font-size: medium;
padding: 0 30px;
}
.icon-container {
gap: 50px;
}
.info-icons-container {
margin-bottom: 20px;
}
.icon img {
width: 100px;
height: auto;
}
#conceptName {
font-size: 3rem;
}
#conceptInfo {
font-size: 1rem;
margin: 0 30px;
}
footer {
width: 100%;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pop Sociology</title>
</head>
<body>
<header>
<div class="left">
<h1 id="logo">Pop Sociology!</h1>
</div>
<div class="right">
<ul>
<li>Home</li>
<li>About</li>
</ul>
</div>
</header>
<main>
<div class="icon-container">
<div class="icon">
<img src="whatissocio2.png" alt="What is Sociology?" id="whatIsSociologyIcon">
</div>
<div class="icon">
<img src="sociotheory2.png" alt="Sociological Theories" id="socioTheoriesIcon">
</div>
<div class="icon">
<img src="interactionist2.png" alt="Interactionist Perspective" id="interactionistIcon">
</div>
<div class="icon">
<img src="conflict2.png" alt="Conflict Perspective" id="conflictIcon">
</div>
<div class="icon">
<img src="functionalist2.png" alt="Functionalist Perspective" id="functionalistIcon">
</div>
<div class="icon">
<img src="socialization2.PNG" alt="Socialization" id="socialization">
</div>
<div class="icon">
<img src="formssocializatin2.png" alt="Forms of Socialization" id="formsSocializationIcon">
</div>
<div class="icon">
<img src="exchange2.png" alt="Social Exchange Theory" id="exchangeIcon">
</div>
<div class="icon">
<img src="sociallearning2.png" alt="Social Learning Theory" id="learningIcon">
</div>
<div class="icon">
<img src="labeling2.PNG" alt="Labeling Theory" id="labelingIcon">
</div>
<div class="icon">
<img src="feminism2.png" alt="Feminist Theory" id="feminismIcon">
</div>
<div class="icon">
<img src="critical2.PNG" alt="Critical Theory" id="criticalIcon">
</div>
<div class="icon">
<img src="strain2.png" alt="Social Strain Theory" id="strainIcon">
</div>
<div class="icon">
<img src="rational2.png" alt="Rational Theory" id="rationalIcon">
</div>
<div class="icon">
<img src="game2.PNG" alt="Game Theory" id="gameIcon">
</div>
<div class="icon">
<img src="sociobiology2.PNG" alt="Sociobiology" id="sociobiologyIcon">
</div>
<div class="icon">
<img src="chaos2.png" alt="Chaos Theory" id="chaosIcon">
</div>
<div class="icon">
<img src="gears2.PNG" alt="Social Phenomenology" id="phenomonologyIcon">
</div>
<div class="icon">
<img src="disengagement2.png" alt="Disengagement Theory" id="disengagementIcon">
</div>
<div class="icon">
<img src="macro2.PNG" alt="Macro Theory" id="macroIcon">
</div>
<div class="icon">
<img src="comte2.PNG" alt="August Comte" id="comteIcon">
</div>
<div class="icon">
<img src="marx2.PNG" alt="Karl Marx" id="marxIcon">
</div>
<div class="icon">
<img src="durkheim2.png" alt="Emile Durkheim" id="durkheimIcon">
</div>
<div class="icon">
<img src="weber2.PNG" alt="Max Weber" id="weberIcon">
</div>
<div class="icon">
<img src="spencer2.PNG" alt="Herbert Spencer" id="spencerIcon">
</div>
</div>
<div class="info-icons-container">
<h3 id="conceptName"><span id="conceptNameDisplay">Name of Concept</h3></span>
<p><span id="conceptInfoDisplay">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Odio voluptatibus saepe sequi dolores quod ab enim excepturi non unde dolorem!</span></p></span>
</div>
</main>
<footer>
<p>Created by Me</p>
</footer>
<script src="script.js"></script>
</body>
</html>
This will work as you intended.
And I use event delegation, which is more effective than putting eventListner to all icons.
const iconContainer = document.querySelector(".icon-container");
const icons = document.querySelectorAll(".icon > img");
// function for when images are clicked, applicable to all images
iconContainer.addEventListener("mouseover", (e) => {
const img = e.target.closest(".icon > img");
if (!img) return;
conceptNameDisplay.innerHTML = img.alt;
displayInfo(img.id);
});
// function to display respective information for each icon
function displayInfo(id) {
const selectedIcon = [...icons].find((icon) => icon.id === id);
if (id === "whatIsSociologyIcon") {
conceptInfoDisplay.innerHTML =
"Sociology is the study of human social relationships and institutions. Sociology’s subject matter is diverse, ranging from crime to religion, from the family to the state, from the divisions of race and social class to the shared beliefs of a common culture, and from social stability to radical change in whole societies.";
} else if (id === "socioTheoriesIcon") {
conceptInfoDisplay.innerHTML =
"A sociological theory is a supposition that intends to consider, analyze, and/or explain objects of social reality from a sociological perspective, drawing connections between individual concepts in order to organize and substantiate sociological knowledge.";
} else if (id === "interactionistIcon") {
conceptInfoDisplay.innerHTML = "Interactionist Perspective Information";
}
}
See code snippet.
// Labeling each variable
const conceptNameDisplay = document.getElementById("conceptNameDisplay");
const conceptInfoDisplay = document.getElementById("conceptInfoDisplay");
// Labeling each description
const socioDefinition = document.getElementById("socioDefinition");
const socioTheories = document.getElementById("socioTheories");
const interactionist = document.getElementById("interactionist");
const conflict = document.getElementById("conflict");
const functionalist = document.getElementById("functionalist");
const formsSocialization = document.getElementById("formsSocialization");
const exchange = document.getElementById("exchange");
const learning = document.getElementById("learning");
const labeling = document.getElementById("labeling");
const feminism = document.getElementById("feminism");
const strain = document.getElementById("strain");
const game = document.getElementById("game");
const sociobiology = document.getElementById("sociobiology");
const chaos = document.getElementById("chaos");
const phenomonology = document.getElementById("phenomonology");
const disengagement = document.getElementById("disengagement");
const macro = document.getElementById("macro");
const comte = document.getElementById("comte");
const marx = document.getElementById("marx");
const durkheim = document.getElementById("durkheim");
const weber = document.getElementById("weber");
const spencer = document.getElementById("spencer");
const iconContainer = document.querySelector(".icon-container");
const icons = document.querySelectorAll(".icon > img");
// function for when images are clicked, applicable to all images
iconContainer.addEventListener("mouseover", (e) => {
const img = e.target.closest(".icon > img");
if (!img) return;
conceptNameDisplay.innerHTML = img.alt;
displayInfo(img.id);
});
// function to display respective information for each icon
function displayInfo(id) {
const selectedIcon = [...icons].find((icon) => icon.id === id);
if (id === "whatIsSociologyIcon") {
conceptInfoDisplay.innerHTML =
"Sociology is the study of human social relationships and institutions. Sociology’s subject matter is diverse, ranging from crime to religion, from the family to the state, from the divisions of race and social class to the shared beliefs of a common culture, and from social stability to radical change in whole societies.";
} else if (id === "socioTheoriesIcon") {
conceptInfoDisplay.innerHTML =
"A sociological theory is a supposition that intends to consider, analyze, and/or explain objects of social reality from a sociological perspective, drawing connections between individual concepts in order to organize and substantiate sociological knowledge.";
} else if (id === "interactionistIcon") {
conceptInfoDisplay.innerHTML = "Interactionist Perspective Information";
}
}
#import url("https://fonts.googleapis.com/css2?family=Merriweather:ital,wght#0,300;0,400;0,700;0,900;1,900&display=swap");
:root {
--mainbgcolor: #fdfbec;
--logo: #f4c553;
--green: #e1eedd;
--greentext: #153a1e;
--orange: #ee9f4a;
}
html,
body {
margin: 0 auto;
padding: 0;
height: 100vh;
display: flex;
flex-direction: column;
font-family: "Merriweather", serif;
background-color: var(--mainbgcolor);
box-sizing: border-box;
}
header {
display: flex;
align-items: center;
justify-content: space-between;
background-color: var(--mainbgcolor);
color: var(--logo);
padding: 0px 20px;
font-size: small;
}
#logo {
font-weight: 900;
}
header a,
li {
text-decoration: none;
list-style: none;
color: var(--orange);
font-weight: 700;
}
ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
gap: 16px;
}
main {
margin: 0px;
padding: 0px;
display: flex;
flex-direction: column;
}
.icon-container {
padding: 10px 20px;
display: grid;
gap: 15px;
grid-template-columns: auto auto auto auto auto;
justify-content: center;
}
.info-icons-container {
padding: 5px 20px;
text-align: center;
}
#conceptName {
font-weight: 700;
font-size: 2rem;
margin: 5px 0px 10px 0px;
}
.conceptInfo {
font-size: 0.8rem;
}
footer {
background-color: var(--orange);
color: var(--mainbgcolor);
text-align: center;
margin-top: auto;
}
.icon img {
width: 55px;
height: auto;
cursor: pointer;
}
.icon img:hover {
box-shadow: 0 0 5px 5px var(--orange);
}
#media only screen and (min-width: 1024px) and (max-height: 1366px) and (-webkit-min-device-pixel-ratio: 1.5) {
header {
font-size: medium;
padding: 0 30px;
}
.icon-container {
gap: 30px;
}
.icon img {
width: 80px;
height: auto;
}
#conceptName {
font-size: 3rem;
}
#conceptInfo {
font-size: 1rem;
margin: 0 30px;
}
}
#media only screen and (min-device-width: 768px) and (max-device-width: 1190px) and (orientation: portrait) and (-webkit-min-device-pixel-ratio: 1) {
header {
font-size: medium;
padding: 0 30px;
}
.icon-container {
gap: 30px;
}
.icon img {
width: 100px;
height: auto;
}
#conceptName {
font-size: 3rem;
}
#conceptInfo {
font-size: 1rem;
margin: 0 30px;
}
}
#media (min-width: 1200px) {
header {
font-size: medium;
padding: 0 30px;
}
.icon-container {
gap: 50px;
}
.info-icons-container {
margin-bottom: 20px;
}
.icon img {
width: 100px;
height: auto;
}
#conceptName {
font-size: 3rem;
}
#conceptInfo {
font-size: 1rem;
margin: 0 30px;
}
footer {
width: 100%;
}
}
<header>
<div class="left">
<h1 id="logo">Pop Sociology!</h1>
</div>
<div class="right">
<ul>
<li>Home</li>
<li>About</li>
</ul>
</div>
</header>
<main>
<div class="icon-container">
<div class="icon">
<img src="whatissocio2.png" alt="What is Sociology?" id="whatIsSociologyIcon">
</div>
<div class="icon">
<img src="sociotheory2.png" alt="Sociological Theories" id="socioTheoriesIcon">
</div>
<div class="icon">
<img src="interactionist2.png" alt="Interactionist Perspective" id="interactionistIcon">
</div>
<div class="icon">
<img src="conflict2.png" alt="Conflict Perspective" id="conflictIcon">
</div>
<div class="icon">
<img src="functionalist2.png" alt="Functionalist Perspective" id="functionalistIcon">
</div>
<div class="icon">
<img src="socialization2.PNG" alt="Socialization" id="socialization">
</div>
<div class="icon">
<img src="formssocializatin2.png" alt="Forms of Socialization" id="formsSocializationIcon">
</div>
<div class="icon">
<img src="exchange2.png" alt="Social Exchange Theory" id="exchangeIcon">
</div>
<div class="icon">
<img src="sociallearning2.png" alt="Social Learning Theory" id="learningIcon">
</div>
<div class="icon">
<img src="labeling2.PNG" alt="Labeling Theory" id="labelingIcon">
</div>
<div class="icon">
<img src="feminism2.png" alt="Feminist Theory" id="feminismIcon">
</div>
<div class="icon">
<img src="critical2.PNG" alt="Critical Theory" id="criticalIcon">
</div>
<div class="icon">
<img src="strain2.png" alt="Social Strain Theory" id="strainIcon">
</div>
<div class="icon">
<img src="rational2.png" alt="Rational Theory" id="rationalIcon">
</div>
<div class="icon">
<img src="game2.PNG" alt="Game Theory" id="gameIcon">
</div>
<div class="icon">
<img src="sociobiology2.PNG" alt="Sociobiology" id="sociobiologyIcon">
</div>
<div class="icon">
<img src="chaos2.png" alt="Chaos Theory" id="chaosIcon">
</div>
<div class="icon">
<img src="gears2.PNG" alt="Social Phenomenology" id="phenomonologyIcon">
</div>
<div class="icon">
<img src="disengagement2.png" alt="Disengagement Theory" id="disengagementIcon">
</div>
<div class="icon">
<img src="macro2.PNG" alt="Macro Theory" id="macroIcon">
</div>
<div class="icon">
<img src="comte2.PNG" alt="August Comte" id="comteIcon">
</div>
<div class="icon">
<img src="marx2.PNG" alt="Karl Marx" id="marxIcon">
</div>
<div class="icon">
<img src="durkheim2.png" alt="Emile Durkheim" id="durkheimIcon">
</div>
<div class="icon">
<img src="weber2.PNG" alt="Max Weber" id="weberIcon">
</div>
<div class="icon">
<img src="spencer2.PNG" alt="Herbert Spencer" id="spencerIcon">
</div>
</div>
<div class="info-icons-container">
<h3 id="conceptName"><span id="conceptNameDisplay">Name of Concept</h3></span>
<p><span id="conceptInfoDisplay">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Odio voluptatibus saepe sequi dolores quod ab enim excepturi non unde dolorem!</span></p></span>
</div>
</main>
<footer>
<p>Created by Me</p>
</footer>
One thing you can do is to keep all your descriptions in an array in javascript. Then use for loop instead of forEach loop on icons array. Then map each element of icon with the appropriate element of description array yourself, like here shown in the code below.
// Labeling each variable
const conceptNameDisplay = document.getElementById('conceptNameDisplay');
const conceptInfoDisplay = document.getElementById('conceptInfoDisplay');
// Selecting all images
const icons = document.querySelectorAll('img');
// Description array
const descriptions = ['Sociology is the study of human social relationships and institutions. Sociology’s subject matter is diverse, ranging from crime to religion, from the family to the state, from the divisions of race and social class to the shared beliefs of a common culture, and from social stability to radical change in whole societies.','A sociological theory is a supposition that intends to consider, analyze, and/or explain objects of social reality from a sociological perspective, drawing connections between individual concepts in order to organize and substantiate sociological knowledge.','Interactionist Perspective Information', 'des4', 'des5', 'des6', 'des7', 'des8', 'des9', 'des10', 'des11', 'des12', 'des13', 'des14', 'des15', 'des16', 'des17', 'des18', 'des19', 'des20', 'des21', 'des22', 'des23', 'des24', 'des25'];
// function for when images are clicked, applicable to all images
for (let i = 0, n=icons.length; i < n; i++) {
icons[i].addEventListener("mouseover", (e) => {
conceptName = e.target.alt
conceptNameDisplay.innerHTML = conceptName;
conceptInfoDisplay.innerHTML = descriptions[i];
});
}
I have accordion block.
When you click on an inactive item, it becomes active.
The active class is removed from the previous item.
It all works.
But now I needed to make it so that when you click on the active item again, it becomes inactive again.
I also have a function so that hiding / opening items happens without jerks.
But it doesn't work with the current JS code:
function setHeight() {
if (content.offsetHeight) {
content.style.height = 0;
} else {
content.style.height = accordText.offsetHeight + 'px';
};
};
How can I do that?
const accordItems = document.querySelectorAll('.accordion__item');
accordItems.forEach(item => {
const accordText = item.querySelector('.accordion__text');
const content = item.querySelector('.accordion__content');
item.addEventListener('click', (event) => {
accordItems.forEach(item => {
item.classList.remove('active');
});
item.classList.add('active');
});
});
#import url("https://fonts.googleapis.com/css2?family=Lora&display=swap");
#import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
body {
margin: 0;
padding: 0;
box-sizing: border-box;
color: #1f1f1f;
background: #f2f2f2; }
html {
font-size: 62.5%; }
h5 {
margin: 0; }
p {
margin: 0; }
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: auto;
max-width: 140rem; }
.section-accordion {
display: flex;
align-items: center;
max-width: 134rem;
margin: auto; }
.accordion-image {
width: 630px;
height: 450px;
background: url("https://eternel.maitreart.com/wp-content/uploads/2021/07/creat-home-1.jpg");
background-repeat: no-repeat;
background-size: cover; }
.accordion {
width: 63rem;
height: auto;
margin-left: 8rem; }
.accordion__item {
border-top: 1px solid #a8a6a4;
overflow: hidden;
transition: height .5s;
padding-bottom: 1rem; }
.accordion__item.active {
height: 100%; }
.accordion__item:last-child {
border-bottom: 1px solid #a8a6a4; }
.accordion__header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 2rem 1rem 1rem 1rem;
cursor: pointer; }
.accordion__title {
font-family: 'Lora';
font-size: 2.4rem;
line-height: 1.2;
font-weight: 400;
text-transform: uppercase; }
.accordion__icon {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 2rem;
height: 2rem;
transition: transform .5s ease; }
.accordion__icon span:first-child {
transform: rotate(90deg) translateX(1px);
width: 1.4rem;
height: .1rem;
background: currentColor; }
.accordion__icon span {
display: block;
width: 1.4rem;
height: .1rem;
background: currentColor;
cursor: pointer; }
.accordion__content {
font-family: 'Roboto', sans-serif;
font-size: 1.6rem;
line-height: 1.62;
font-weight: 400;
padding: 0 1rem 0 1rem;
height: 0;
overflow: hidden;
transition: height .5s; }
.accordion__item.active > .accordion__header .accordion__icon {
transform: rotate(45deg); }
.accordion__item.active > .accordion__content {
margin-bottom: 1.2rem;
height: 100%; }
<div class="container">
<section class="section-accordion">
<div class="accordion-image"></div>
<div class="accordion">
<div class="accordion__item active">
<div class="accordion__header">
<h5 class="accordion__title">Visual direction</h5>
<div class="accordion__icon">
<span></span>
<span></span>
</div>
</div>
<div class="accordion__content">
<p class="accordion__text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course.
Assistance travelling so especially do prosperous appearance mr no celebrated.
Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
<div class="accordion__item">
<div class="accordion__header">
<h5 class="accordion__title">Event production</h5>
<div class="accordion__icon">
<span></span>
<span></span>
</div>
</div>
<div class="accordion__content">
<p class="accordion__text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course.
Assistance travelling so especially do prosperous appearance mr no celebrated.
Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
<div class="accordion__item">
<div class="accordion__header">
<h5 class="accordion__title">Brand creation</h5>
<div class="accordion__icon">
<span></span>
<span></span>
</div>
</div>
<div class="accordion__content">
<p class="accordion__text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course.
Assistance travelling so especially do prosperous appearance mr no celebrated.
Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
<div class="accordion__item">
<div class="accordion__header">
<h5 class="accordion__title">Design concept</h5>
<div class="accordion__icon">
<span></span>
<span></span>
</div>
</div>
<div class="accordion__content">
<p class="accordion__text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course.
Assistance travelling so especially do prosperous appearance mr no celebrated.
Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
</div>
</div>
</section>
</div>
Can you do something like this?
accordItems.forEach(item => {
const accordText = item.querySelector('.accordion__text');
const content = item.querySelector('.accordion__content');
item.addEventListener('click', (event) => {
const wasActive = item.classList.contains('active');
accordItems.forEach(item => {
item.classList.remove('active');
});
if (!wasActive) {
item.classList.add('active');
}
});
});
This makes a clicked item active only if it wasn't active when the click occurred. Toggling is another option, if you are okay with more than one item being active at the same time:
accordItems.forEach(item => {
const accordText = item.querySelector('.accordion__text');
const content = item.querySelector('.accordion__content');
item.addEventListener('click', (event) => {
item.classList.toggle('active');
});
});
Instead of adding and removing class you can use a shorthand syntax toggle it makes things easier.
It remove the class if the class is present vice versa
Here's the code for it
item.classList.toggle('active')
const accordItems = document.querySelectorAll('.accordion__item');
accordItems.forEach(item => {
const accordText = item.querySelector('.accordion__text');
const content = item.querySelector('.accordion__content');
item.addEventListener('click', (event) => {
accordItems.forEach(item => {
item.classList.toggle('active');
});
item.classList.add('active');
});
});
I've coded a simple image slideshow using Vanilla JS which unfortunately isn't working. It's structured in a 'section', within a 'container'. The overflow of the container is hidden, and there are relative 'span' circles below it which I want to use to control the slideshow.
Here is my code so far:
// Variables
let i;
let image = document.getElementsByClassName("image");
let slideIndex = 1;
let dots = document.getElementsByClassName("dots");
// Functions
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showImage(n) {
if (n > image.length) {
slideIndex = 1;
}
if (n < 1) {
slideIndex = image.length;
}
for (i = 0; i < image.length; i++) {
image[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace("active", "");
}
image[slideIndex-1].style.display = "block";
dots[slideIndex-1].classList.add("active");
}
showImage(slideIndex);
body {
margin: 0;
padding: 0;
font-family: Helvetica;
}
.image-section {
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: space-around;
flex-direction: column;
background-color: #303960;
}
.image-container {
height: 600px;
width: 900px;
overflow: hidden;
background-color: #f9f9f9;
}
.image {
height: 600px;
width: 900px;
}
.image-controller {
height: 10vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.dots {
height: 30px;
width: 30px;
border-radius: 100%;
background-color: #fff;
margin: 0 10px;
cursor: pointer;
}
.active {
background-color: #f96d80;
}
<section class="image-section">
<div class="image-container">
<div class="image" style="background-color: black">
</div>
<div class="image" style="background-color: red">
</div>
<div class="image" style="background-color: blue">
</div>
<div class="image" style="background-color: orange">
</div>
<div class="image" style="background-color: purple">
</div>
<div class="image" style="background-color: brown">
</div>
</div>
<div class="image-controller">
<span class="dots active" onclick="currentSlide(1)"></span>
<span class="dots" onclick="currentSlide(2)"></span>
<span class="dots" onclick="currentSlide(3)"></span>
<span class="dots" onclick="currentSlide(4)"></span>
<span class="dots" onclick="currentSlide(5)"></span>
<span class="dots" onclick="currentSlide(6)"></span>
</div>
</section>
I'm assuming it's a problem with my for loop, but I could be wrong. Any advice would be great!
Was this something you had in mind? You made the code a bit too complex.
I changed everything in your javascript code, because nothing really worked with all your different method names and how they were called. Thought it was easier for me to just type a few lines of code to show a different way of thinking.
Your images (it should be called "images", not "image" because there are several of them) and dots arrays start at position 0, so use that. Start by adding 0 as a parameter in your onclick method on your first dot element.
Then just keep track of the previous index (prevSelection) and remove the .active class from the previously selected image and dot, while adding .active to the newly selected image and dot. I added CSS style for .active for .image.
If you want to add a sliding animation, this is not the way to go, however.
// Variables
let images = document.getElementsByClassName("image");
let dots = document.getElementsByClassName("dots");
var prevSelection = 0;
function showSlides(slidePosition) {
removeClass('active', prevSelection);
addClass('active', slidePosition);
prevSelection = slidePosition;
}
function removeClass(className, slidePosition) {
dots [slidePosition].classList.remove(className);
images[slidePosition].classList.remove(className);
}
function addClass(className, slidePosition) {
dots [slidePosition].classList.add(className);
images[slidePosition].classList.add(className);
}
body {
margin: 0;
padding: 0;
font-family: Helvetica;
}
.image-section {
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: space-around;
flex-direction: column;
background-color: #303960;
}
.image-container {
height: 600px;
width: 900px;
overflow: hidden;
background-color: #f9f9f9;
}
.image {
display: none;
height: 600px;
width: 900px;
}
.image.active { /* added this */
display: block;
}
.image-controller {
height: 10vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.dots {
height: 30px;
width: 30px;
border-radius: 100%;
background-color: #fff;
margin: 0 10px;
cursor: pointer;
}
.dots.active { /* added .dots for better clarity */
background-color: #f96d80;
}
<section class="image-section">
<div class="image-container">
<div class="active image" style="background-color: black">
</div>
<div class="image" style="background-color: red">
</div>
<div class="image" style="background-color: blue">
</div>
<div class="image" style="background-color: orange">
</div>
<div class="image" style="background-color: purple">
</div>
<div class="image" style="background-color: brown">
</div>
</div>
<div class="image-controller">
<span class="active dots" onclick="showSlides(0)"></span>
<span class="dots" onclick="showSlides(1)"></span>
<span class="dots" onclick="showSlides(2)"></span>
<span class="dots" onclick="showSlides(3)"></span>
<span class="dots" onclick="showSlides(4)"></span>
<span class="dots" onclick="showSlides(5)"></span>
</div>
</section>