javascript function to selectively show and hide contents by Id - javascript

I am working on a project where I want to show page contents selectively.
Have buttons "next" and "previous"
contents are id-ed in a serial manner.
what I want to achieve is
at the first page loading, show the first content(id='item-0') and only show the "next" button since there is no previous content, and when click on "next" button, hide currently showing contents(id='item-0') and show all the contents that are in (id='item-1') and so forth, and do not show the "next" button when it's the last content.
this is what I got so far,
on the page I first load every contents with display: none; so, nothing's showing up of course. but I want to be able to show the first content(id="item-0") by changing the style display to inline-block. and then update the "which" that's in the "next" button onclick action to the next id which is id="item-1" and dynamically update this "which" whenever either "next" or "previous" buttons clicked.
// page when first loaded.
<div class="container p-0 m-0" id="item-0" style="display:none;">
<p>example data</p>
<img src="example.com/img.png">
<video src="abc.com/abc/def.mp4"></video>
</div>
<div class="container p-0 m-0" id="item-1" style="display:none;">
<img src="example.com/img-5.png">
<video src="abc.com/abc/def.mp4"></video>
<div class="row"><h1>ABCD</h1></div>
</div>
<div class="container p-0 m-0" id="item-2" style="display:none;">
<p>example data</p>
<p>example data 2</p>
</div>
<a class="btn" onclick="nextBtn('item-0','item-1')">Next</a>
<a class="btn" onclick="prevBtn('item-0',null)" style="display:none;">Prev</a>
So far I worked on:
function show_item(which) {
var element = document.getElementById(which)
element.style.display='inline-block';
}
function hide_item(which) {
var element = document.getElementById(which)
element.style.display='none';
}
function nextBtn(current_which, next_which) {
// e.g. current_which = "item-0", next_which = "item-1"
hide_item(current_which);
show_item(next_which);
}
function prevBtn(current_which, prev_which) {
// e.g. current_which = "item-1", prev_which = "item-0"
hide_item(current_which);
show_item(prev_which);
}
what I haven't figured out are:
how to update the current_which and next_which that go in to the "Next" and "Prev" buttons.
how to not show "Prev" button when the page is showing the first content, and how to now show "Next" button when the page is showing the last content.

I have prepared something for you. If it is not exactly what you are looking for, I hope it'll you give some general idea on how to achieve what you want.
var next = document.querySelector('.next');
var prev = document.querySelector('.prev');
var elements = document.getElementsByClassName('container')
//get the currentDiv ID
var currentDiv = 0;
//when next is clicked
next.addEventListener('click',function(){
//we first check if the viewed div is not the last one
if(currentDiv < 2){
//if not we remove the .active class
removeActive(currentDiv);
//increment the ID of the current ID
currentDiv += 1;
//and add .active class to the next DIV
addActive(currentDiv)
}
})
prev.addEventListener('click',function(){
//same thing with prev, we first test if the current div is not the first one
if(currentDiv > 0){
//if not we remove the .active class
removeActive(currentDiv);
//decrement the selected div
currentDiv -= 1;
//and add the .active class
addActive(currentDiv);
}
})
//below are 2 functions that handles the addActive & removeActive if the conditions are passed
function removeActive(currentDiv){
document.getElementById('item-'+currentDiv).classList.remove('active');
}
function addActive(currentDiv){
document.getElementById('item-'+currentDiv).classList.add('active');
}
.container.hide {
display: none;
}
.active {
display: block !important;
}
.btn {
cursor: pointer;
}
<div class="container active hide p-0 m-0" id="item-0">
<p>example data</p>
<h3>Image For Div 1</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Smart-Watch.jpg" width="100px" height="100px"/>
</div>
<div class="container hide p-0 m-0" id="item-1">
<p>example data</p>
<h3>Image For Div 2</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Wireless-Phone-Chargers.jpg" width="100px" height="100px"/>
</div>
<div class="container hide p-0 m-0" id="item-2">
<p>example data</p>
<h3>Image For Div 3</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Phone-Lenses.jpg" width="100px" height="100px"/>
</div>
<br/><br/><br/>
<a class="btn prev">Prev</a>
<a class="btn next">Next</a>

Here is a slightly more condensed version of a working script:
const btn = document.querySelectorAll('.btn'), // btn[0]: Prev, btn[1]: Next
divs = document.querySelectorAll('.container');
function render(n){
[n,n!==divs.length-1].forEach((c,i)=>btn[i].style.visibility=c?null:"hidden"); // show/hide buttons
divs.forEach((d,i)=>d.classList.toggle("hide",i!==n)); // show/hide divs
}
render(divs.curr=1); // define the starting div
btn.forEach(b => b.onclick = () => {
render( divs.curr += (b.textContent==="Next" ? 1 : -1) );
});
.hide { display: none; }
.btn { cursor: pointer; }
<div class="container hide p-0 m-0" id="item-0">
<p>example data</p>
<h3>Image For Div 1</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Smart-Watch.jpg" width="100px" height="100px" />
</div>
<div class="container hide p-0 m-0" id="item-1">
<p>example data</p>
<h3>Image For Div 2</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Wireless-Phone-Chargers.jpg" width="100px" height="100px" />
</div>
<div class="container hide p-0 m-0" id="item-2">
<p>example data</p>
<h3>Image For Div 3</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Phone-Lenses.jpg" width="100px" height="100px" />
</div>
<div class="container hide p-0 m-0" id="item-3">
<p>example data</p>
<h3>Image For Div 4</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Thumb-224.jpg" height="100px" />
</div>
<div class="container hide p-0 m-0" id="item-4">
<p>example data</p>
<h3>Image For Div 5</h3>
<img src="https://www.cloudways.com/blog/wp-content/uploads/Thumb-221.jpg" height="100px" />
</div>
<br/><br/><br/>
<a class="btn prev">Prev</a>
<a class="btn next">Next</a>
I designed the script to have a small footprint, i. e. only a few global variables - or better - constants: btn and divs. In divs.curr you will find the index of the currently "active" div.
This script is also open for changes to the markup: The number of divs can change to any number.

Related

Is there a way target an element without it's class or id

I have a show more button I want to expand a div with it, I can put the button in the div and target it's parent but I don't want it to be on top of the div which I want to expand and if I put it in the end the button hides with the text, I am gonna have more than one div, and I can keep the button outside the div and target the div using it's class but the reason I am gonna have more than one div the first div will expand not matter which button I click, and I don't wanna give each div an unique class or Id and I don't want to place the button in the div I already mentioned the reason, so is there a way to directly target the div or to place button in the div and still have it to be shown on the bottom without it being hidden
CODE
<div class="ccontainer" id="ccontainer">
<p id="context"> content </p>
<div class="img" id="cntimgcon">
<img src="images\image2.jpg" id="cntimgp1">
</div>
<p id="context"> content </p>
</div>
<button id="showmore" onclick=" this.parentElement.style.maxHeight = 'none'"> show more </button>
Someone told me to target the show more button from its Id then target it's upper sibling but it doesn't work.
At very first you named the Button opening tag with camelcase (first letter uppercase), the closing tag is lowercase.
Second I changed the "showmore" id to class. And please see the script what I made for you.
You can remove the class of the buttons also if you using getElementsByTag("button").
const buttons = document.getElementsByClassName("showmore");
console.log(buttons);
Array.from(buttons).forEach(button => button.addEventListener("click", (e)=> {
e.preventDefault();
const collapse = button.previousElementSibling; //https://www.w3schools.com/jsref/prop_node_previoussibling.asp
collapse.style.maxHeight = collapse.style.maxHeight == '0px' ? '200px' : '0px';
}));
<div class="ccontainer" id="ccontainer">
<p id="context"> content </p>
<div class="img" id="cntimgcon" >
<img src="images\image2.jpg" id="cntimgp1">
</div>
<p id="context"> content
</p>
</div>
<button class="showmore"> show more </button>
<div class="ccontainer" id="ccontainer">
<p id="context"> content </p>
<div class="img" id="cntimgcon" >
<img src="images\image2.jpg" id="cntimgp1">
</div>
<p id="context"> content
</p>
</div>
<button class="showmore"> show more </button>
<div class="ccontainer" id="ccontainer">
<p id="context"> content </p>
<div class="img" id="cntimgcon" >
<img src="images\image2.jpg" id="cntimgp1">
</div>
<p id="context"> content
</p>
</div>
<button class="showmore"> show more </button>

JavaScript show/hide divs on button click - multiple per page

I am trying to develop a page where there would be multiple divs, each of these divs have a button of which would show a "dropdown" style div below it when clicked.
Currently I have some code which when one button is clicked, it shows all of the "dropdown" styled divs on the page instead of just the one in the same container as the button.
I would like this to be done in pure JavaScript without jquery, any help would be appreciated, thank you!
HTML
<div class="fullResultsContainer">
<div class="resultContainer">
<div class="resultRow">
<!-- This has multiple divs but this is the only one relevant to the issue-->
<div class="resultMenu">
<button class="mobileShowActivityFeedBtn" onclick="mobileActivityLog()"> Show activity feed </button>
</div>
</div>
<div class="mobileDropDown">
<p> This is the content I want to show on button click</p>
</div>
</div>
<div class="resultContainer">
<div class="resultRow">
<!-- This has multiple divs but this is the only one relevant to the issue-->
<div class="resultMenu">
<button class="mobileShowActivityFeedBtn" onclick="mobileActivityLog()"> Show activity feed </button>
</div>
</div>
<div class="mobileDropDown">
<p> This is the content I want to show on button click</p>
</div>
</div>
</div>
JS
function mobileActivityLog() {
var btn = document.getElementsByClassName("mobileShowActivityFeedBtn");
var activity = document.getElementsByClassName("mobileDropDown");
for(var i=0; i<btn.length; i++) {
for(var j=0; i<activity.length; j++) {
if(activity[j].style.display == "none") {
activity[j].style.display = "flex"
} else {
activity[j].style.display = "none"
}
}
}
}
I think the easiest way is to send a parameter to the method and getElementById with a concatenated string with the parameter.
<div class="fullResultsContainer">
<div class="resultContainer">
<div class="resultRow">
<div class="resultMenu">
<button onclick="mobileActivityLog(1)"> Show activity feed </button>
</div>
</div>
<div class="mobileDropDown-1">
<p> This is the content I want to show on button click</p>
</div>
</div>
<div class="resultContainer">
<div class="resultRow">
<div class="resultMenu">
<button onclick="mobileActivityLog(2)"> Show activity feed </button>
</div>
</div>
<div id="mobileDropDown-2">
<p> This is the content I want to show on button click</p>
</div>
</div>
</div>
JS
function mobileActivityLog(index) {
var activity = document.getElementsById("mobileDropDown-" + index);
if(activity.style.display == "none") {
activity.style.display = "flex"
} else {
activity.style.display = "none"
}
}
One of the best possible ways to achieve this is to pass the current context using 'call' in the HTML. Use this context to target the required result container(here 'mobileDropDown' container).
function mobileActivityLog () {
var _this = this;
var activity = _this.closest('.resultContainer').querySelector(".mobileDropDown");
activity.classList.toggle('hide');
}
.hide {
display: none;
}
<div class="fullResultsContainer">
<div class="resultContainer">
<div class="resultRow">
<!-- This has multiple divs but this is the only one relevant to the issue-->
<div class="resultMenu">
<button class="mobileShowActivityFeedBtn" onclick="mobileActivityLog.call(this)"> Show activity feed </button>
</div>
</div>
<div class="mobileDropDown">
<p> This is the content I want to show on button click</p>
</div>
</div>
<div class="resultContainer">
<div class="resultRow">
<!-- This has multiple divs but this is the only one relevant to the issue-->
<div class="resultMenu">
<button class="mobileShowActivityFeedBtn" onclick="mobileActivityLog.call(this)"> Show activity feed </button>
</div>
</div>
<div class="mobileDropDown">
<p> This is the content I want to show on button click</p>
</div>
</div>
</div>

Accessing multiple elements by getElementsByClassName() with JS

I am trying to create multiple popups on one page that would appear after clicking a button corresponding to them. I currently have them under the same class, as in here:
<div>
<!-- Popup -->
<div class="popup">
<div class="popup-content">
Some text here
</div>
</div>
<!-- Button -->
<img src="button.png" class="popup-button"/>
</div>
The problem is that I am struggling to access individual elements with my javascript code. I am not sure what to replace the manual array accessing ( [0] right now ) with.
<script>
// Get the popup
var popup = document.getElementsByClassName("popup")[0];
// Get the button that opens the popup
var btn = document.getElementsByClassName("popup-button")[0];
// When the user clicks the button, open the popup (hidden by default)
btn.onclick = function() {
popup.style.display = "block";
}
</script>
Now, I could create multiple scripts and access the arrays manually for each element but of course I am trying to automate it, so that script would run depending on which button was clicked. Say, if 5th button was clicked, 5th popup appears. Thank you!
Best way to link multiple elements in Javascript is using an id through the dataset of the elements.
// Get the popup's btn list
var popupsBtn = document.getElementsByClassName("popup-btn");
// Go through the popup's btn list
for (var i = 0; i < popupsBtn.length; i++) {
// Define the onclick event on popup's btn
popupsBtn[i].onclick = function() {
// Get the popup associated to the btn with the data-popup-id
var popup = document.getElementById("popup-" + this.dataset.popupId);
// Use a class to toggle popup visible or not
popup.classList.toggle("visible");
}
}
.popup {
display: none;
}
.popup.visible {
display: block;
}
<!DOCUMENT html>
<html>
<head></head>
<body>
<div>
<div id="popup-1" class="popup">popup 1 here</div>
<img src="button.png" class="popup-btn" data-popup-id="1" />
</div>
<div>
<div id="popup-2" class="popup">popup 2 here</div>
<img src="button.png" class="popup-btn" data-popup-id="2" />
</div>
<div>
<div id="popup-3" class="popup">popup 3 here</div>
<img src="button.png" class="popup-btn" data-popup-id="3" />
</div>
</body>
</html>
Given your HTML, it would probably be easiest to just access the previous sibling of the clicked button to get to the .popup, and then change its style:
document.querySelectorAll('.popup-button').forEach(button => {
button.onclick = () => {
button.previousElementSibling.style.display = 'block';
};
});
.popup {
display: none;
}
<div>
<div class="popup">
<div class="popup-content">
Some text here1
</div>
</div>
<img src="button.png" class="popup-button" />
</div>
<div>
<div class="popup">
<div class="popup-content">
Some text here2
</div>
</div>
<img src="button.png" class="popup-button" />
</div>
<div>
<div class="popup">
<div class="popup-content">
Some text here3
</div>
</div>
<img src="button.png" class="popup-button" />
</div>
You can use other attributes to identify the button. You could not rely on the className alone.
You can use data-id attribute and pass it in the method. using this.
Depending on your HTML structure, there are multiple possibilities.
Anyway, I suggest you to use .querySelectorAll() to get your elements, and then use a .forEach() to execute your code.
I tried to use much of your code to make it work correctly.
With a parent div
// Get all the buttons that opens the popups
var btns = document.querySelectorAll(".popup-button");
btns.forEach(function(btn, index) {
// When the user clicks the button, open the popup that is in the same parent div
btn.onclick = function() {
btn.closest('div').querySelector('.popup').style.display = "block";
}
});
.popup {
display: none;
}
<div>
<div class="popup">
<div class="popup-content">Pop-up 1</div>
</div>
<img src="button.png" class="popup-button" />1
</div>
<div>
<div class="popup">
<div class="popup-content">Pop-up 2</div>
</div>
<img src="button.png" class="popup-button" />2
</div>
<div>
<div class="popup">
<div class="popup-content">Pop-up 3</div>
</div>
<img src="button.png" class="popup-button" />3
</div>
Without a parent div
// Get the popups
var popups = document.querySelectorAll(".popup");
// Get the buttons that opens the popups
var btns = document.querySelectorAll(".popup-button");
btns.forEach(function(btn, index) {
// When the user clicks the button, open the popup (hidden by default)
btn.onclick = function() {
popups[index].style.display = "block";
}
});
.popup {
display: none;
}
<div class="popup">
<div class="popup-content">Pop-up 1</div>
</div>
<img src="button.png" class="popup-button" />
<br>
<br>
<div class="popup">
<div class="popup-content">Pop-up 2</div>
</div>
<img src="button.png" class="popup-button" />
<br>
<br>
<div class="popup">
<div class="popup-content">Pop-up 3</div>
</div>
<img src="button.png" class="popup-button" />
This solution withour parent div will work even if the popups and the buttons are not next to each other. But the order (and index) of the elements need to be the same. See it here:
// Get the popups
var popups = document.querySelectorAll(".popup");
// Get the buttons that opens the popups
var btns = document.querySelectorAll(".popup-button");
btns.forEach(function(btn, index) {
// When the user clicks the button, open the popup (hidden by default)
btn.onclick = function() {
popups[index].style.display = "block";
}
});
.popup {
display: none;
}
<img src="button.png" class="popup-button" />1
<img src="button.png" class="popup-button" />2
<img src="button.png" class="popup-button" />3
<div class="popup">
<div class="popup-content">Pop-up 1</div>
</div>
<div class="popup">
<div class="popup-content">Pop-up 2</div>
</div>
<div class="popup">
<div class="popup-content">Pop-up 3</div>
</div>
Hope it helps.

Is it possible to toggle different divs by clicking on different elements using the same function?

Say I have 50 div, like this:
<div class="btn1"></div> //Toggles the first container to appear
<div class="btn2"></div> //Toggles the second container to appear
<div class="btn3"></div> //Toggles the third container to appear
And another 50 div that contain information, like this:
<div class="container-1"><h1>This is the first container</h1></div>
<div class="container-2"><h1>This is the second container</h1></div>
<div class="container-3"><h1>This is the third container</h1></div>
Is it possible to make the corresponding div toggle when each button is clicked with just one function? I have read a little about delegation and operating on parents/siblings but it only seems to work on multiple buttons opening the same container, rather than each button opening each container.
Somehow I don't think writing a function for every div is the way to go.
yes it is possible. Basically you need to add a reference to clicked object so click event will know what to show/hide
$(function() {
$('.btn').on('click', function(e) {
var $dataTarget = $($(this).data('target'));
$dataTarget.show().siblings('.container').hide();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn btn1" data-target=".container-1"></div> //Toggles the first container to appear
<div class="btn btn2" data-target=".container-2"></div> //Toggles the second container to appear
<div class="btn btn3" data-target=".container-3"></div> //Toggles the third container to appear
<div class="container container-1">
<h1>This is the first container</h1>
</div>
<div class="container container-2">
<h1>This is the second container</h1>
</div>
<div class="container container-3">
<h1>This is the third container</h1>
</div>
This will show the container targeted, then will hide other containers.
Use starts with selector ^ Document here
Use data-* to store corresponding div on button.
Select the data-* then use as selector to show
$('div[class^=container]').hide();
$('div[class^=btn]').click(function() {
$('div[class^=container]').hide();
var thisclass = $(this).attr("data-class")
$('.' + thisclass).show();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn1" data-class="container-1">1</div>
<div class="btn2" data-class="container-2">2</div>
<div class="btn3" data-class="container-3">3</div>
<div class="container-1">
<h1>This is the first container</h1>
</div>
<div class="container-2">
<h1>This is the second container</h1>
</div>
<div class="container-3">
<h1>This is the third container</h1>
</div>
You can use index and eq to do this
$("[class*='btn']").click(function(){
$("[class*='container-']").eq($(this).index()-1).toggle();
})
[class*="btn"]{
width:150px;
height:20px;
border:2px solid #000;
display:inline-block;
cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="btn1"></div>
<div class="btn2"></div>
<div class="btn3"></div>
<div class="container-1">
<h1>This is the first container</h1>
</div>
<div class="container-2">
<h1>This is the second container</h1>
</div>
<div class="container-3">
<h1>This is the third container</h1>
</div>
you can use something like this
$(document).ready(function() {
$("div[class^='btn']").each(function() {
$(this).click(function() {
var str = $(this)[0].className;
$(".container-" + str.substring(3, str.length)).toggle();
});
});
});
Find all the class which starts with btn and apply a click event to it..
and based on the number hide the corresponding container class.
Here is the full code:
$(document).ready(function() {
$("div[class^='btn']").each(function() {
$(this).click(function() {
var str = $(this)[0].className;
$(".container-" + str.substring(3, str.length)).toggle();
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="btn1">aaaa</div> //Toggles the first container to appear
<div class="btn2">bbbb</div> //Toggles the second container to appear
<div class="btn3">cccc</div> //Toggles the third container to appear
<div class="container-1">
<h1>This is the first container</h1>
</div>
<div class="container-2">
<h1>This is the second container</h1>
</div>
<div class="container-3">
<h1>This is the third container</h1>
</div>
(Source: fiddle https://jsfiddle.net/fxabnk4o/17/)

DOM traversing using jQuery

I am trying to create a comparison overlay that shows items selected by users when they 'add to compare' link.(like one in flipkart that appears on top when you hit add to compare). Here is my code:
<div class="college-list-container">
<div class = "individual-college-container" id="text1">
<div class="image-header"><h3>text1</h3>
</div>
<div class="dark-overlay">
<div class="overlay-links" style=" float:left;"> <div class="absolute-center ">Details</div></div>
<a href=""> <div class="overlay-links" style=" float:right; border-right:none;"> <div class="absolute-center comparison" id="comparison">Add to compare</div>
</div></a>
</div>
</div>
<div class = "individual-college-container">
<div class="image-header"><h3>text2</h3>
</div>
<div class="dark-overlay">
<div class="overlay-links" style=" float:left;"> <div class="absolute-center ">Details</div></div>
<a href=""> <div class="overlay-links" style=" float:right; border-right:none;"> <div class="absolute-center comparison">Add to compare</div>
</div></a>
</div>
</div>
<div class = "individual-college-container" id="itm">
<div class="image-header" ><h3>text3</h3>
</div>
<div class="dark-overlay">
<div class="overlay-links" style=" float:left;"> <div class="absolute-center ">Details</div></div>
<a href=""> <div class="overlay-links" style=" float:right; border-right:none;"> <div class="absolute-center comparison">Add to compare</div>
</div></a>
</div>
Javascript
/show overlay when one checkbox is checked and add its name/image to the empty space
$('.comparison').click(function(e){
var clgId = $(this).parentsUntil('.individual-clg-container').find('.image-header').text();
e.preventDefault();
var clg = $("<li></li>")
clg.text(clgId);
var removeLink = $("<a href=''>(Remove)</a>");
clg.append(removeLink)
$('.comparison-colleges').append(clg);
$('.add-to-compare-overlay').show("slide", { direction: "up" }, 300);
});
I want the text in the div containing class 'image-header' to be assigned to the variable clgId. The problem that i am facing with my code is that it is adding the text of all the divs containing class 'image-header'. Ex i want the value text1 to be assigned on clicking add to compare of the div with id text1. However it assigns 'text1 text2 text3' to clgId.
Please help
I've created a JSFiddle with what I think is your desired functionality (I included a console log output in the script of the clgId variable):
http://jsfiddle.net/py38kuvv/
I replaced the parentsUntil function with the closest function (and replaced the individual-clg-container class selector):
var clgId = $(e.target).closest('.individual-college-container').find('.image-header').text();
and also updated your click handler:
$('.comparison').on( "click", function(e) {
In order to get a quicker response in future, posting a JSFiddle of what you have so far makes it easier for others to help :)
It is adding all of them because
var clgId = $(this).parentsUntil('.individual-clg-container').find('.image-header').text();
should be
var clgId = $(this).parentsUntil('.individual-college-container').find('.image-header').text();

Categories

Resources