Switch DIV content using only Javascript - javascript

Why is it not working after I added this code below? As you can see on snippet. Container #1 is not working when click. I've added title and content on it but it is not showing.
Is there anything that I can use instead of getElementsByTagName?
function showDiv(idInfo) {
var sel = document.getElementById('divLinks').getElementsByTagName('div');
for (var i = 0; i < sel.length; i++) {
sel[i].style.display = 'none';
}
document.getElementById('container' + idInfo).style.display = 'block';
}
#container1,
#container2,
#container3,
#container4 {
display: none;
border: 3px solid blue;
height: 200px;
overflow: hidden;
}
<div id="linkDiv">
Home
link 1
link 2
link 3
link 4
</div>
<div id="container">
The container I want all content divs to load into... and by default, to show the first container content
</div>
<div id="divLinks">
<div id="container1">Container #1
<div>Title</div>
<div>Content:</div>
<p>Whole bunch of text 1</p>
</div>
<div id="container2">
Container #2
<p>Whole bunch of text 2</p>
</div>
<div id="container3">
Container #3
<p>Whole bunch of text 3</p>
</div>
<div id="container4">
Container #4
<p>Whole bunch of text 4</p>
</div>
</div>

You can use querySelectorAll to target the direct children of divLinks only.
function showDiv(idInfo) {
const sel = document.querySelectorAll('#divLinks > div');
sel.forEach(item => {
item.style.display = item.id === `container${idInfo}` ? 'block' : 'none';
});
}
#container1,
#container2,
#container3,
#container4 {
display: none;
border: 3px solid blue;
height: 200px;
overflow: hidden;
}
<div id="linkDiv">
Home
link 1
link 2
link 3
link 4
</div>
<div id="container">
The container I want all content divs to load into... and by default, to show the first container content
</div>
<div id="divLinks">
<div id="container1">Container #1
<div>Title</div>
<div>Content:</div>
<p>Whole bunch of text 1</p>
</div>
<div id="container2">
Container #2
<p>Whole bunch of text 2</p>
</div>
<div id="container3">
Container #3
<p>Whole bunch of text 3</p>
</div>
<div id="container4">
Container #4
<p>Whole bunch of text 4</p>
</div>
</div>

You just only need to get Parent children not nested child.
Just modify
var sel = document.getElementById('divLinks').getElementsByTagName('div');
with
sel = document.querySelector('#divLinks').children;

Related

Need to display a hidden text when i click on image

I'm working on a website which have multiply images. The user can click on this images and then it will show a tiny text under this one. My idea was to get the ID of the images and then show the text who correspond to this one.
Let me show you my code
function SOE() {
let bSOE = document.getElementById("bSOE");
let Soe = document.getElementById("SOE");
if (getComputedStyle(Soe).display != "none") {
Soe.style.display = "none";
} else {
var elements = document.getElementsByClassName("secret");
for (var i = 0; i < elements.length; i++) {
if (elements[i].id != "SOE") {
elements[i].style.display = "none";
}
}
Soe.style.display = "block";
}
}
<div class="mn_bo3">
<div class="map" id="bSOE" onclick="SOE()" style="background-image: url('source/Soe.png')"></div>
<div class="map" id="bTG" style="background-image: url('source/tg.png')"></div>
<div class="map" id="bDER" style="background-image: url('source/Der.png')"></div>
<div class="map" id="bZNS" style="background-image: url('source/Zns.png')"></div>
<div class="map" id="bGK" style="background-image: url('source/Gk.png')"></div>
</div>
<!--Tiny hidden text -->
<div class="secret" id="SOE" style="display:none;">
<p>Here are the list of the easter eggs of Shadow of Evil map :</p>
</div>
So I created a function but it's working only for one and it's not using this ID. I need some help or this code will be very DRY.
Thanks a lot for read that!
Check up on this code to see if it solve your issue.
function SOE(selector) {
$('p').fadeOut(500)
$('#'+selector+' > p').fadeIn(500)
}
.mn_bo3 {
height: 100vh;
display: flex;
justify-content: space-between;
}
.map {
height: 100px;
width: 100px;
background-repeat: no-repeat;
background-size: contain;
position: relative;
}
p {
position: absolute;
bottom: -2em;
left: 0;
right: 0;
text-align: center;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mn_bo3">
<div class="map" id="bSOE" onclick="SOE('bSOE')" style="background-image: url('1.png')">
<p>Text image 1</p>
</div>
<div class="map" id="bTG" onclick="SOE('bTG')" style="background-image: url('2.png')">
<p>Text image 2</p>
</div>
<div class="map" id="bDER" onclick="SOE('bDER')" style="background-image: url('3.png')">
<p>Text image 3</p>
</div>
<div class="map" id="bZNS" onclick="SOE('bZNS')" style="background-image: url('4.png')">
<p>Text image 4</p>
</div>
<div class="map" id="bGK" onclick="SOE('bGK')" style="background-image: url('1.png')">
<p>Text image 5</p>
</div>
</div>
You could pass the id of each div in the onClick function call, like this:
JS:
function SOE(id){
let bSOE = document.getElementById(id);
...
}
HTML:
<div class="map" id="bSOE" onclick="SOE('bSOE')" style="background-image: url('source/Soe.png')" ></div>
Or if its guaranteed, that every object has an ID you could get the id via the 'this' object (js stays the same):
<div class="map" id="bSOE" onclick="SOE(this.id)" style="background-image: url('source/Soe.png')" ></div>
After that you can create a object, which saves the image id with the text id:
var elements = { "BSOE": "SOE" }
And then display the corresponding text for each image:
function SOE (id) {
var elem = document.getElementById(elements[id]);
elem.style.display = "block";
You can create a common click handler for all images and show hidden text with receptive image.
So in this case your code structure will be as below
<div class="map" id="bSOE" onclick="onElementClick(this)" style="background-image: url(https://picsum.photos/200)"></div>
<div class="secret" id="bSOE_text">
<p>Here are the list of the easter eggs of Shadow of Evil map :</p>
</div>
Working Code
function onElementClick(event){
//Before showing div hide other's one
[...document.querySelectorAll('div.secret')].forEach(el => el.style.display = 'none');
//To show the repective div
document.querySelector('div#' + event.id + '_text').style.display = 'block';
}
.map {
height: 100px;
width: 100px;
background-size: cover;
order: 1px solid;
margin: 10px;
}
.secret {
display: none;
}
<div class="mn_bo3">
<div class="map" id="bSOE" onclick="onElementClick(this)" style="background-image: url(https://picsum.photos/200)" ></div>
<div class="secret" id="bSOE_text">
<p>Here are the list of the easter eggs of Shadow of Evil map :</p>
</div>
<div class="map" id="bTG" style="background-image: url(https://picsum.photos/200
)" onclick="onElementClick(this)"></div>
<div class="secret" id="bTG_text">
<p>Here are the list of the easter eggs of Shadow of Evil map :</p>
</div>
<div class="map" id="bDER" style="background-image: url(https://picsum.photos/200)" onclick="onElementClick(this)"></div>
<div class="secret" id="bDER_text">
<p>Here are the list of the easter eggs of Shadow of Evil map :</p>
</div>
<div class="map" id="bZNS" style="background-image: url(https://picsum.photos/200)" onclick="onElementClick(this)"></div>
<div class="secret" id="bZNS_text">
<p>Here are the list of the easter eggs of Shadow of Evil map :</p>
</div>
<div class="map" id="bGK" style="background-image: url(https://picsum.photos/200)" onclick="onElementClick(this)"></div>
<div class="secret" id="bGK_text">
<p>Here are the list of the easter eggs of Shadow of Evil map :</p>
</div>
</div>
When you insist on using Javascript functionality for other purposes regarding users clicking on your images, I suggest you check the other answers and take your pick.
When you are looking for a straightforward solution, you might want to investigate using a <details><summary> construction as these elements by default incorporate a click-an-show mechanism without the need for Javascript.
Have a look at this simple snippet:
/* [OPTIONAL], but makes sense in this case */
summary { list-style-type: none }
/* just extra eye-candy */
body { padding: 1rem; margin: 0; cursor: default }
summary { cursor: pointer }
<details>
<summary><img src="https://picsum.photos/360?random=1"></summary>
<p>some tiny text when the image gets clicked</p>
</details>

classList.toggle() only works one time

I am trying to implement a different pop-up window when I click different divs. Here's an example:
<div class="column" onclick="togglePopup('popup', 2)">Residential cleaning</div> <!--Function used here. -->
<div id="overlay">
<div class="popup">
<div class="popup_content">
<div class="close_btn" onclick="closePopup('popup',2)">×</div>
<h1>Some heading</h1>
<p>SOME TEXT</p>
<img src="assets/some_image.jpg" alt="image" width="249">
</div>
</div> <!--END of the popup window -->
</div>
When I click on the div of class column, I should see the popup div, however it only works with the very first one. Here's the JavaScript:
function togglePopup(popup_class, div_num){
overlay.style.display="flex";
let all_divs = document.getElementsByClassName(popup_class);
let my_div = all_divs[div_num-1];
my_div.classList.toggle("active");
console.log(my_div)
}
function closePopup(popup_class, div_num){
overlay.style.display="none";
let all_divs = document.getElementsByClassName(popup_class);
let my_div = all_divs[div_num-1];
my_div.classList.toggle("active");
console.log(my_div)
}
The function saves all the divs of class popup in the let all_divs, then it uses the parameter div_num to select a specific div and finally toggle the class "active" (CSS will be below). But like I said it only works one time. By the way the id overlay is originally hidden.
CSS:
.popup.active .popup_content {
transition:all 300ms ease-in-out;
transform:translate(-50%,-50%) scale(1);
}
#overlay {
position:fixed;
top:0px;
left:0px;
width:100%;
height:100%;
background-color:rgba(0,0,0,0.7);
z-index:1;
display:none;
}
I really don't know why this happens, it works as intended only with the first element of the list "all_divs". Is there a way around this? I already tried many things and realized it only works on the first element of the list. I did not include the first div in the code, (the one that works) because it's the exact same thing, except instead of a 1 in onclick="togglePopup('popup', 1)" it has a 2.
You're attempting to access a HTMLCollection by an index that does not exist. e.g.
let all_divs = document.getElementsByClassName('popup');
let my_div = all_divs[2]; // undefined
Instead you should add data to the open button to explicitly describe which popup it should open by its unique id.
Also, you should:
use querySelectorAll to addEventListener to each of the relevant buttons
use html buttons instead of divs
const openBtns = document.querySelectorAll('.open_btn')
const closeBtns = document.querySelectorAll('.close_btn')
openBtns.forEach(openBtn => openBtn.addEventListener('click', (e) => {
const popupIdToOpen = e.currentTarget.dataset.popup;
const popupToOpen = document.querySelector(`#${popupIdToOpen}`)
if (popupToOpen) {
popupToOpen.classList.add('active')
}
}))
closeBtns.forEach(closeBtn => closeBtn.addEventListener('click', (e) => {
const popupToClose = e.currentTarget.closest(".overlay")
if (popupToClose) {
popupToClose.classList.remove('active')
}
}))
.overlay {
color: white;
position: fixed;
top: 0;
background-color: #000;
display: none;
}
.active {
display: block;
}
<button class="open_btn" data-popup="popup1">Popup 1</button>
<div class="overlay" id="popup1">
<button class="close_btn">×</button >
<h1>Popup 1 heading</h1>
<p>Popup 1 Content</p>
</div>
<button class="open_btn" data-popup="popup2">Popup 2</button>
<div class="overlay" id="popup2">
<button class="close_btn">×</button >
<h1>Popup 2 heading</h1>
<p>Popup 2 Content</p>
</div>
<button class="open_btn" data-popup="popup3">Popup 3</button>
<div class="overlay" id="popup3">
<button class="close_btn">×</button >
<h1>Popup 3 heading</h1>
<p>Popup 3 Content</p>
</div>

How do I toggle the background colors within a list of divs?

From a list of items, each in separate divs, the user can select and click only one. The background color should change on the selected one. If the user changes their mind, they can select another one, and the background color should change to the selected color and all the other divs on the list should change back to the default background color.
It's basically the same logic as a radio button on a form. Only one can be selected at a time.
How do I achieve this?
I have attempted to use the element.classList.toggle property. But it only handles each individually. Are there a javascript command(s) to handle this?
<style>
.teamSelected{
background-color: red;
border-radius: 4px;
}
</style>
<div onclick="toggleBackground(team1)">
<div id="team1">
</div>
</div>
<div onclick="toggleBackground(team2)">
<div id="team2">
</div>
</div>
<div onclick="toggleBackground(team3)">
<div id="team3">
</div>
</div>
<script>
function toggleBackground(teamnumber) {
var element = document.getElementById(teamnumber);
if (element) {
element.classList.toggle("teamSelected");
}
}
</script>
Thanks!
You are passing variables to the function, which don't exist. You need to put them in quotes, because the function is expecting strings.
const allDivs = document.querySelectorAll('.div');
function toggleBackground(teamnumber) {
var element = document.getElementById(teamnumber);
if (element) {
allDivs.forEach(function(el){
el.classList.remove('teamSelected');
});
element.classList.add("teamSelected");
}
}
.toggle > div {
width: 100px;
height: 100px;
border: 1px solid #000;
}
.teamSelected {
background-color: red;
border-radius: 4px;
}
<div onclick="toggleBackground('team1')" class="toggle">
<div id="team1" class="div">
</div>
</div>
<div onclick="toggleBackground('team2')" class="toggle">
<div id="team2" class="div">
</div>
</div>
<div onclick="toggleBackground('team3')" class="toggle">
<div id="team3" class="div">
</div>
</div>
seems like this is something you want?
let x = ('.something');
$(x).on('click', function(){
$(x).css('background','blue');
$(this).css('background', 'green');
});
.something{
width: 100px;
height: 100px;
background: yellow
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div class="something">
<div id="team1">
</div>
</div>
<div class="something">
<div id="team2">
</div>
</div>
<div class="something">
<div id="team3">
</div>
</div>

Reorder divs with CSS? Insert parent 1 between children of parent 2

This is what I have:
<div class="container>
<div class="parent1"></div>
<div class="parent2">
<div class="child1"></div>
<div class="child2"></div>
</div>
</div>
This is what I want:
<div class="container>
<div class="parent2">
<div class="child1"></div>
<div class="parent1"></div>
<div class="child2"></div>
</div>
</div>
Is this possible with only CSS or JavaScript (no jQuery)?
Even if the HTML doesn't move, as long as they appear in that order on the page that would be perfect.
You can do it with Javascript: document.querySelector('.child1').appendChild(document.querySelector('.parent1'));
Demo:
function reorder() {
document.querySelector('.child1').appendChild(document.querySelector('.parent1'));
}
.container * {
display: block;
border: 2px solid lightgrey;
color: lightgrey;
padding: 5px;
margin: 15px;
}
.parent1 {
color: red;
border-color: red;
}
.child1 {
color: blue;
border-color: blue;
}
<div class="container">
<div class="parent1">I'm parent 1!</div>
<div class="parent2">
I'm parent 2!
<div class="child1 ">I'm child 1!</div>
<div class="child2 ">I'm child 2!</div>
</div>
</div>
<button onclick='reorder();'>Reorder!</button>
Note: Css is only for better looks
With Javascript:
//Remove the parent 1 div from the container div
document.getElementsByClassName('container')[0].removeChild(document.getElementsByClassName('parent1')[0]);
//Insert into div between children
const parent2 = document.getElementsByClassName('parent2')[0];
let divEle = document.createElement('div');
divEle.className = 'parent1';
parent2.insertBefore(divEle, parent2.querySelector('.child2'));
To make this work, I would advise that you remove the div.parent2 around the child classes.
Therefore the code becomes
<div class="container parent">
<div clas="parent1"></div>
<div class="child1"></div>
<div class="child2></div>
</div>
then you can use flexbox to do this
.parent{display: flex};
.child1{order:1}
.parent1{order:2}

How to make multiple divs slidetoggle with changing arrow

I'm very new to javascript and jQuery and has now got completely stuck despite trying various options. I'm trying to create a expand/collapse section with multiple divs. I would like each div to open and close seperately, with an arrow at the side pointing up or down, depending whether the content is expanded or collapsed.
From the code I have written below, only the first div works correctly. The only thing which happen When you click on the two other divs, is that the arrow in the first div change.
Any help will be greatly appreciated.
Following is the CSS:
#header_background {
background-image: url(header-background.png);
width:748px;
height:43px;
margin-left: -17px;}
#expand_arrow {
display: inline-block;
width: 17px;
height: 18px;
float:left;
margin-left:20px;
padding-left:0px;
padding-top:11px;
background-repeat:no-repeat; }
.sub_header {
color:#204187;
font-weight:bold;
font-size:16px;
vertical-align:middle;
padding-left:4px;
padding-top:12px;
float:left;
text-decoration:none;
}
Here's the attempted javascript and jQuery:
function chngimg() {
var img = document.getElementById('expand_arrow').src;
if (img.indexOf('expand-arrow.png')!=-1) {
document.getElementById('expand_arrow').src = 'images/collapse-arrow.png';
}
else {
document.getElementById('expand_arrow').src = 'images/expand-arrow.png';
}
}
$(document).ready(function(){
$("#header_background").click(function(){
$("#section").slideToggle("slow");
});
});
And here's the HTML
<div id="header_background" >
<img id="expand_arrow" alt="" src="images/collapse-arrow.png" onclick="chngimg()">
<div class="sub_header" onclick="chngimg()">header 1</div>
</div>
<div id="section" style="display:none">
text 1
</div>
<div id="header_background" >
<img id="expand_arrow" alt="" src="images/collapse-arrow.png" onclick="chngimg()">
<div class="sub_header" onclick="chngimg()">header 2</div>
</div>
<div id="section" style="display:none">
text 2
</div>
<div id="header_background" >
<img id="expand_arrow" alt="" src="images/collapse-arrow.png" onclick="chngimg()">
<div class="sub_header" onclick="chngimg()">header 3</div>
</div>
<div id="section" style="display:none">
text 3
</div>
It's only working for the first set of elements because you're using IDs, and IDs have to be unique within the document (page). You could change to using classes and perform some simple DOM traversal to get the corresponding section based on the header that was clicked. Something like this:
$(document).ready(function() {
$('.header_background').click(function(e) {
$(this).next('.section').slideToggle('slow');
var img = $(this).find('img.expand_arrow')[0]; // the actual DOM element for the image
if (img.src.indexOf('expand-arrow.png') != -1) {
img.src = 'images/collapse-arrow.png';
}
else {
img.src = 'images/expand-arrow.png';
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="header_background" >
<img class="expand_arrow" alt="" src="images/collapse-arrow.png">
<div class="sub_header">header 1</div>
</div>
<div class="section" style="display:none">
text 1
</div>
<div class="header_background" >
<img class="expand_arrow" alt="" src="images/collapse-arrow.png">
<div class="sub_header">header 2</div>
</div>
<div class="section" style="display:none">
text 2
</div>
<div class="header_background" >
<img class="expand_arrow" alt="" src="images/collapse-arrow.png">
<div class="sub_header">header 3</div>
</div>
<div class="section" style="display:none">
text 3
</div>
Look for your next section of the header clicked like so. And change your id for class because ID need to be unique
$(".header_background").click(function(){
$(this).nextAll(".section:first").slideToggle("slow");
});

Categories

Resources