Closing spoiler when clicking another spoiler - javascript

I have the following problem, I would like to create a few spoilers. This has worked so far, but I would like that if a spoiler is open and one clicks on another, the opened again closes.
<button title="Click to show/hide content" type="button" onclick="if(document.getElementById('spoiler') .style.display=='none') {document.getElementById('spoiler') .style.display=''}else{document.getElementById('spoiler') .style.display='none'}">Show/hide</button>
<div id="spoiler" style="display:none">
Content
</div>
<br><br>
<button title="Click to show/hide content" type="button" onclick="if(document.getElementById('spoiler2') .style.display=='none') {document.getElementById('spoiler2') .style.display=''}else{document.getElementById('spoiler2') .style.display='none'}">Show/hide</button>
<div id="spoiler2" style="display:none">
Content2
</div>

Assign a common class to all spoilers and on click hide the contents of all the spoilers using the class name and simply show only the one you want to show:
I have created a function for this like so:
<script>
function showSpoiler(spoilerId)
{
var spoilers = document.getElementsByClassName('spoilers');
for(var i=0;i<spoilers.length; i++)
{
spoilers[i].style.display = "none";
}
document.getElementById(spoilerId).style.display = "block";
}
</script>
<button title="Click to show/hide content" type="button" onclick="showSpoiler('spoiler');">Show/hide</button>
<div id="spoiler" class="spoilers" style="display:none">
Content
</div>
<br><br>
<button title="Click to show/hide content" type="button" onclick="showSpoiler('spoiler2');">Show/hide</button>
<div id="spoiler2" class="spoilers" style="display:none">
Content2
</div>
spoilers is the common class which needs to be hidden before showing the specific one.
Remember
getElementsByClassName() gives out an array that is why the for loop is in place.

To make it easier for you to start, I'll give you an example made for Event Listener for Radio buttons.
code:
document.getElementById("type_test").addEventListener("click", functio_test);
document.getElementById("type_test1").addEventListener("click", functio_test);
function functio_test(){
var x = document.querySelector('input[name="type_test"]:checked').value;
//var x = document.forms[0].elements.type_test.value;
if(x == "ola"){
alert("Ola José");
document.getElementById('disp_0').style.display = 'block';
document.getElementById('disp_1').style.display = 'none';
}
else if(x == "adeus"){
alert("Adeus José");
document.getElementById('disp_1').style.display = 'block';
document.getElementById('disp_0').style.display = 'none';
}
else {
alert("Continua José");
}
}
<div id="select_0">
<br> <input id = "type_test" type="radio" name="type_test" value="ola"> ola
<input id = "type_test1" type="radio" name="type_test" value="adeus"> adeus <br/> <br><br/>
</div>
<div id="disp_0" style="display:none">
<input type="text" name="lastname" value="ola Jose" ><br><br/>
</div>
<div id="disp_1" style="display:none">
<input type="text" name="lastname1" value="Adeus Jose" ><br><br/>
</div>
I hope the post helps you.

you can use classes to accomplish this (class="spoilers")
<button title="Click to show/hide content" type="button" onclick="toggleSpoiler('spoiler')"> Show/hide </button>
<div id="spoiler" style="display:none" class="spoilers">
Content
</div>
<br><br>
<button title="Click to show/hide content" type="button" onclick="toggleSpoiler('spoiler2')"> Show/hide </button>
<div id="spoiler2" style="display:none" class="spoilers">
Content2
</div>
<script>
function toggleSpoiler(id) {
var spoilers = document.getElementsByClassName("spoilers");
for(var i = 0; i < spoilers.length; i++) {
if (spoilers[i].id != id) {
spoilers[i].style.display = "none";
}
}
if(document.getElementById(id).style.display=='none') {
document.getElementById(id).style.display='';
} else {
document.getElementById(id).style.display='none';
}
}
</script>

The way I would do this would be to create two additional classes and add an additional div to use the parent/child association to determine which spoiler (in relation to the button) needs to be displayed.
Starting off with the classes, let's call them
.spoiler
and
.active
The idea is to make the .spoiler class hide and the .active class show, like so:
.spoiler {
display:none;
}
.spoiler.active {
display:block;
}
All spoiler elements would have .spoiler as a class and only the currently active spoiler would have the .active class, now let's create our new div which will bundle the spoilers and their buttons to have a common parent.
<div class="spoiler-item">
<button title="Click to show/hide content">
Show/Hide
</button>
<div class="spoiler">
Content
</div>
</div>
<div class="spoiler-item">
<button title="Click to show/hide content">
Show/Hide
</button>
<div class="spoiler">
Content2
</div>
</div>
Now we can use the relative "spoiler-item" class when a button is pressed to determine which spoiler is related to the button being pressed and also remove the "active" class from all other "spoiler" elements to make sure only one spoiler is shown at a time.
I recommend using jQuery for this, due to time constraints I'm not going to be able to do it in pure JS.
$(document).ready(function() {
$('.spoiler-item button').click(function(e) {
if($(this).parent('.spoiler-item').find('.spoiler').hasClass('active')) { // If the item we've selected is already active
$(this).parent('.spoiler-item').find('.spoiler').removeClass('active');
return;
}
$('.spoiler.active').removeClass('active'); // Close all open spoilers
$(this).parent('.spoiler-item').find('.spoiler').addClass('active'); // Open relative spoiler
});
});
See JSFiddle for working answer: https://jsfiddle.net/vvm4xe0m

Related

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>

How do I toggle hide/show between three divs; using three buttons (each belongs to one div) dynamically?

lets say, I have
<div class = "buttons">
<button onclick= "toggleFirst()"> Show me Hide me 1</button>
<button onclick= "toggleSecond()"> Show me Hide me 2</button>
<button onclick= "toggleThird();"> Show me Hide me 3</button>
</div>
<div style="display: none" id="one" > Random Content1 < /div>
<div style="display: none" id="two" > Random Content 2< /div>
<div style="display: none" id="three" > Random Content 3< /div>
How can I write a JavaScript function or functions (no jquery please) that will toggle on and off content dynamically based on each button? if i click button 1, I want content in div id one to show, if i click it again, I want content in div id one to hide and or when i click button 2 , I want only content in dive id two to show and hide other stuff...so same patter and logic for all of them.
You've already started by giving each of those buttons a function to execute onClick. Just define those functions and check the display property of the style property of your divs.
I went ahead and made a simpler toggleId function as well to limit how much code is duplicated.
It's also worth noting that < /div> is invalid. You don't put a space in the front of a closing HTML tag. You can put one at the end, but there's no reason to. Just use </div>.
function toggleFirst()
{
toggleId("one");
}
function toggleSecond()
{
toggleId("two");
}
function toggleThird()
{
toggleId("three");
}
function toggleId(id)
{
var div = document.getElementById(id);
if(div.style.display == "none")
div.style.display = "block";
else
div.style.display = "none";
}
<div class = "buttons">
<button onclick= "toggleFirst()"> Show me Hide me 1</button>
<button onclick= "toggleSecond()"> Show me Hide me 2</button>
<button onclick= "toggleThird();"> Show me Hide me 3</button>
</div>
<div style="display: none" id="one" > Random Content1 </div>
<div style="display: none" id="two" > Random Content 2</div>
<div style="display: none" id="three" > Random Content 3</div>
For that you can use the style.display property
function toggleFirst() {
let one = document.getElementById("one");
if (one.style.display == "none") {
one.style.display = "block"
} else {
one.style.display = "none"
}
}
function toggleSecond() {
let two = document.getElementById("two");
if (two.style.display == "none") {
two.style.display = "block"
} else {
two.style.display = "none"
}
}
function toggleThird() {
let three = document.getElementById("three");
if (three.style.display == "none") {
three.style.display = "block"
} else {
three.style.display = "none"
}
}
<div class="buttons">
<button onclick="toggleFirst()"> Show me Hide me 1</button>
<button onclick="toggleSecond()"> Show me Hide me 2</button>
<button onclick="toggleThird();"> Show me Hide me 3</button>
</div>
<div style="display: none" id="one"> Random Content1
</div>
<div style="display: none" id="two"> Random Content 2
</div>
<div style="display: none" id="three"> Random Content 3
</div>
change the functions onclick like i did and you don't have to do 3 functions
, you just need one
function toggContent(content_id) {
const x = document.getElementById(content_id)
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
<div class="buttons">
<button onclick="toggContent('one')"> Show me Hide me 1</button>
<button onclick="toggContent('two')"> Show me Hide me 2</button>
<button onclick="toggContent('three')"> Show me Hide me 1</button>
</div>
<div style="display: none" id="one"> Random Content1
</div>
<div style="display: none" id="two"> Random Content 2
</div>
<div style="display: none" id="three"> Random Content 3
</div>

Display and hide div contain after select

I have this javascript function that allows me to hide and display after clicking on a button. each button has a div linked to it. when i click on a button the previous button contain is hidden and the second button displays his contains. i woulk like to use a select instead to do the same job. i'm stuck there. Please help me to reach my goal i post the way i did it with button. Bear with me.
function visibilite(id) {
var divs = document.getElementsByTagName('div');
for(var no=0;no<divs.length;no++){
if(divs[ no].className=='divs')
{
'divs'
divs[ no].style.display = "none";
}
}
document.getElementById(id).style.display = "block";
<a href="javascript:visibilite('test1');" class="btn btn-primary btn-sm">
1 year
</a>
<a href="javascript:visibilite('test2');"class="btn btn-primary btn-sm">
2 year
</a>
<div id="test1" class="divs" style="display:yes">
sfssdfsdfsfsf
</div>
<div id="test2" class="divs" style="display:none">
sfssdfsdfsfsf
</div>
Working fiddle.
You can use onchange in select tag, check the following example.
NOTE : in display:yes yes is not a valide value for display attribute.
Hope this helps.
function visibilite(_this)
{
var id = _this.value;
var divs = document.getElementsByTagName('div');
for(var i=0;i<divs.length;i++){
if(divs[i].className=='divs')
{
divs[i].style.display = "none";
}
}
document.getElementById(id).style.display = "block";
}
<select onchange='visibilite(this)'>
<option value='test1'>1 year</option>
<option value='test2'>2 year</option>
</select>
<div id="test1" class="divs">First year content</div>
<br>
<div id="test2" class="divs" style="display:none">Second year content</div>

How to calculate child div length from parent div; using classnames; in JQuery?

The parent div have class name 'panel'.
It contains further child divs have class name 'clonablePart' and also one button.
We need to check
1) if there are multiple clonablePart then the button which is by default disable should turn enable
2) if there is one clonable part then button should remain disabled
Note: Class name 'panel' in parent div panel; can also exist in its child div's. Also 'Input' can be multiple
Please see fiddle for more details for HTML structure.
https://jsfiddle.net/k2rbs70m/
Following is JQuery in Use:
$('.myclass').each(function () {
var lengthOfClones = $(this).closest('div.panel').find('.clonablePart').length;
var typeOfClone = $(this).data("type");
console.log('Length of Clones:' + typeOfClone + " - " + lengthOfClones);
lengthOfClones > 1 ? $('#delete' + typeOfClone).attr('disabled', false) : $('#delete' + typeOfClone).attr('disabled', true);
});
If anything unclear please write.
Following is HTML for an idea:
<div id="Bank_panel" class="panel">
<div id="Bank_panel1" class="clonablePart">
1) Bank Account
</div>
<div id="Bank_panel1" class="clonablePart">
2) Account Name
</div>
<input type="button" value="delete" id="deleteBank" data-type="Bank" disabled /> <i> Make it Enable onload as it have two values</i>
</div>
If you have only one input child per panel class, you can target it like this:
$(this).find('input')
In your code, this would give:
lengthOfClones > 1 ? $(this).find('input').attr('disabled', false) : $(this).find('input').attr('disabled', true);
https://jsfiddle.net/ggngygzy/
EDIT
IF you have more than one input child per panel, you can find a unique property and target it. Like this for example:
$(this).find('input[type=button]')
There are problem in your code
$(this).data("type") always returns Clones, which is incorrect.
So, give a custom attribute data-type to each of the div under .panel, say for Bank, give data-type="Bank" and so on.
So the HTML becomes:
<div id="Bank_panel" class="panel" data-type="Bank">
<div id="Bank_panel1" class="clonablePart">
1) Bank Account
</div>
<div id="Bank_panel1" class="clonablePart">
2) Account Name
</div>
<input type="button" value="delete" id="deleteBank" data-type="Bank" disabled /> <i> Make it Enable onload as it have two values</i>
</div>
<br/>
<div id="insurance_panel" class="panel" data-type="Insurance">
<div id="insurance_panel1" class="clonablePart">
1) Insurance Account
</div>
<div id="insurance_panel1" class="clonablePart">
2) Insurance Name
</div>
<input type="button" value="delete" id="deleteInsurance" data-type="insurance" disabled /> <i> Make it Enable onload as it have two values</i>
</div>
<br/>
<div id="economy_panel" class="panel" data-type="economy">
<div id="economy_panel1" class="clonablePart">
1) Economy Account
</div>
<input type="button" value="delete" id="deleteeconomy" data-type="economy" disabled /> <i> Keep it disable</i>
</div>
See the working fiddle here: "http://jsfiddle.net/k2rbs70m/7/"
You can use the following code:
$('.panel').each(function () {
var lengthOfClones = $(this).find('.clonablePart').length;
var flagDisable = lengthOfClones == 1
$(this).find("input[type='button']").prop('disabled',flagDisable);
});
It will fix your problem.
https://jsfiddle.net/k2rbs70m/9/
This will solve your issue you presented in the Fiddle:
$('.panel').each(function () {
// Find the button with a value of `delete`
var button = $(this).find("input[value='delete']");
var clones = $(this).find('.clonablePart');
if(clones.length > 1)
button.removeAttr('disabled')
else
button.attr('disabled', true) ;
});
The trick is: you only want children to be counted, so use .find(). Then, find the button inside your wrapper and enable and disable that by the amount of results found.
//Will take outer panels only
$('.panel').each(function () {
var button = $(this).find("input[value='delete']");
var clones = $(this).find('.clonablePart');
var type = button.data("type");
if(clones.length > 1)
button.removeAttr('disabled')
else
button.attr('disabled', true) ;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<div id="Bank_panel" class="panel">
<div id="Bank_panel1" class="clonablePart">
1) Bank Account
</div>
<div id="Bank_panel1" class="clonablePart">
2) Account Name
</div>
<input type="button" value="delete" id="deleteBank" data-type="Bank" disabled /> <i> Make it Enable onload as it have two values</i>
</div>
<br/>
<div id="insurance_panel" class="panel">
<div id="insurance_panel1" class="clonablePart">
1) Insurance Account
</div>
<div id="insurance_panel1" class="clonablePart">
2) Insurance Name
</div>
<div class="panel"></div> <!--Remember outer panel can have inner panel-->
<input type="button" value="delete" id="deleteInsurance" data-type="insurance" disabled /> <i> Make it Enable onload as it have two values</i>
</div>
<br/>
<div id="economy_panel" class="panel">
<div id="economy_panel1" class="clonablePart">
1) Economy Account
</div>
<input type="button" value="delete" id="deleteeconomy" data-type="economy" disabled /> <i> Keep it disable</i>
</div>

jquery show/hide two divs on click and hide link

Im using the following JS
Add a Street Address
and the following html
<div id=entry>
<div id=label>Street</div>
<div id=input><input name="" type="text" class="longtext" /></div></div>
<div id=entry>
<div id=label>City/Town</div>
<div id=input><input name="" type="text" class="longtext" /></div></div>
How would i modify the JS to show/hide both of those divs at once, and then make the link disappear?
a. you better off using class instead of id where both share the same value (e.g. entry)
<div class=entry>
<div id=label>Street</div>
<div id=input><input name="" type="text" class="longtext" /></div></div>
<div class=entry>
<div id=label>City/Town</div>
<div id=input><input name="" type="text" class="longtext" /></div></div>
b. Hiding both divs can be done as:
$('.entry').hide();
hiding the clicked link
$(this).hide();
return true;
e.g.
<a id='myLinkId' href='#'>Click To Hide</a>
$('a#myLinkId').click(function(){
$('.entry').hide();
$(this).hide();
return true;
});
First give an id to your link tag like 'link', then give you two dives two different ids, then write a js function like this :
show_hide = function()
{
if(document.getElementById('link').style.display == 'none'){
document.getElementById('link').style.display = 'inline';
document.getElementById('entry1').style.display = 'inline';
document.getElementById('entry2').style.display = 'inline';
}else{
document.getElementById('link').style.display = 'none';
document.getElementById('entry1').style.display = 'none';
document.getElementById('entry2').style.display = 'none';
}
}
IDs need to be unique so I have changed the ids to classes. Also, I have changed the code from being inline to being unobtrusive The jQuery would be something like the following
$(function() {
$('#addressLink').click(function() {
$('div.entry').toggle();
$(this).hide();
return false; // prevent the default anchor behaviour
});
});
<a id="addressLink" href="#">Add a Street Address</a>
<div class="entry">
<div class="label">Street</div>
<div class="input"><input name="" type="text" class="longtext" /></div>
</div>
<div class="entry">
<div class="label">City/Town</div>
<div class="input"><input name="" type="text" class="longtext" /></div>
</div>
Assuming that you want the <div> elements to be hidden initially, simply add $('div.entry').hide(); into the document ready handler. There are other techniques that you can use here, but I would suggest hiding using JavaScript for graceful degradation purposes
Here's a Working Demo. Add /edit to the URL to see the code

Categories

Resources