Show/Hide Divs from Dropdown - javascript

This one is really straightforward but I somehow cannot get my head around it.
I have a Bootstrap Dropdown Menu with 3 Choices.
My page will be hosting 3 divs which should be hidden by default.
When clicking on one of the choice within the Dropdown, then I want the related div to appear.
HTML:
<div class="dropdown d-flex justify-content-center">
<button class="btn bg-dark text-light dropdown-toggle rounded-bottom" style="border-radius: 0 !important;" type="button" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Secure Acceptance Silent Order POST / Checkout API</button>
<div id="target" class="dropdown-menu" aria-labelledby="dropdownMenu2">
<button value="1" class="master dropdown-item" type="button">Auth/Sale using Transaction Endpoint</button>
<button value="2" class="master dropdown-item" type="button">Auth/Sale using iFrame Transaction Endpoint</button>
<button value="3" class="master dropdown-item" type="button">Auth/Sale with Token Creation</button>
</div>
</div>
<div id="1" class="SAformX hidden" style="background-color:red;">
<p>gergeyherghdesghderh</p>
</div>
<div id="2" class="SAformY hidden" style="background-color:blue;">
<p>gergeyherghdesghderh</p>
</div>
<div id="3" class="SAformZ hidden" style="background-color:green;">
<p>gergeyherghdesghderh</p>
</div>
By default, the forms with the class hidden are to be hidden :
<style>
.hidden{
visibility: hidden;
}
</style>
Using Vanilla Javascript, I want to generate a Node of elements containing the class Master which is related to each button/chocie within the dropdown. And then, I want to pass its related ID to another function where :
All divs will be reset to hidden by default
Then the div with the ID related to the button clicked would appear.
This way, everytime you click on a dropdown choice, the page "soft reset" and hides all the divs that were not selected.
Javascript :
<script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.master').forEach(item => {
item.addEventListener('click', () => {
const id = item.value;
MasterMenuToggle(id);
});
});
})
function MasterMenuToggle(id) {
document.querySelectorAll('.SAform').forEach(item => {
item.className = "hidden";
})
document.getElementById(id).className = "visible"
}
</script>
The issue here is the "reset" part of my function MasterMenuToggle
document.querySelectorAll('.SAform').forEach(item => {
item.className = "hidden";
})
Clicking on a dropdown item do make its related div appear but then they keep on appearing without the other hiding.
I do not have a set design yet so "breaking/changing" the class name would kill any formatting I might add to them. They do appear because the page cannot apply the visibility:hidden since the class changed. But if I had like "class="hidden pt-2 border bg-black", then the JS would update the className to "class="visible" killing the rest of the Bootstrap classes.
Can I loop through the IDs to simply ADD an inline CSS to each DIV to be safe?
The forEach in my reset part of the JS code is the blocker and generates console errors. I do not understand why since even console.log(item) instead of changing the className to hidden would not work.
Hope you can help !

You would need to use the classList.add or classList.remove function.
So if you want to reveal, use the remove to remove the hidden, else use the .add to hide again.
E.g. item.classList.add("hidden"); or item.classList.remove("hidden")
There are plenty of actions you can perform with classList which state here:
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList

You used the code for hide all divs
function MasterMenuToggle(id) {
document.querySelectorAll('.SAform').forEach(item => {
item.className = "hidden";
})
}
But your div's class names are "SAformX", "SAformY" and "SAformZ". So the querySelectorAll('.SAform') cannot found any div. You can add "SAform" class name to your hidden divs.
*Sorry for my bad English :/
Here is working JSFiddle
https://jsfiddle.net/7nf18dr6/3/

hiddenDivs = document.querySelectorAll('.SAform');
document.addEventListener('DOMContentLoaded', function() {
hiddenDivs.forEach((x) => x.classList.add('.hidden'));
document.querySelectorAll('.master').forEach((item) => {
item.addEventListener('click', () => {
const id = item.value;
MasterMenuToggle(id);
});
});
});
function MasterMenuToggle(id) {
hiddenDivs.forEach((x) => {
if (x.id == id) {
x.classList.remove('hidden');
} else {
x.classList.add('hidden');
}
});
}
.hidden {
visibility: hidden;
}
<div class="dropdown d-flex justify-content-center">
<button class="btn bg-dark text-light dropdown-toggle rounded-bottom" style="border-radius: 0 !important;" type="button" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Secure Acceptance Silent Order POST / Checkout API
</button>
<div id="target" class="dropdown-menu" aria-labelledby="dropdownMenu2">
<button value="1" class="master dropdown-item" type="button">Auth/Sale using Transaction Endpoint</button>
<button value="2" class="master dropdown-item" type="button">Auth/Sale using iFrame Transaction Endpoint</button>
<button value="3" class="master dropdown-item" type="button">Auth/Sale with Token Creation</button>
</div>
</div>
<div id="1" class="SAform " style="background-color:red;">
<p>gergeyherghdesghderh</p>
</div>
<div id="2" class="SAform " style="background-color:blue;">
<p>gergeyherghdesghderh</p>
</div>
<div id="3" class="SAform " style="background-color:green;">
<p>gergeyherghdesghderh</p>
</div>

The task is quite simple if you break it down into two stages. The first stage is to hide all div elements when one of the three buttons is clicked and then show the relevant div based upon value & data-id of the button and div respectively. Rather than using a new class (hidden) you can use the inline declaration display='none' instead or, as suggested above by #connexo, use hidden=true ~ though I think there is a difference in how these are represented on the page with one occupying no space and the other will.
document.querySelectorAll('div#target > button').forEach( bttn=>{
bttn.addEventListener('click',function(e){
let col=document.querySelectorAll('div[data-id]');
col.forEach( div=>{ div.style.display='none' } )
document.querySelector('div[ data-id="'+this.value+'"]').style.display='block'
})
})
/* css here only to prettify things */
div{ padding:0.25rem; color:white }
button{padding:0.5rem;margin:0.25rem;}
<div class="dropdown d-flex justify-content-center">
<button class="btn bg-dark text-light dropdown-toggle rounded-bottom" style="border-radius: 0 !important;" type="button" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Secure Acceptance Silent Order POST / Checkout API
</button>
<div id="target" class="dropdown-menu" aria-labelledby="dropdownMenu2">
<button value="1" class="master dropdown-item" type="button">Auth/Sale using Transaction Endpoint</button>
<button value="2" class="master dropdown-item" type="button">Auth/Sale using iFrame Transaction Endpoint</button>
<button value="3" class="master dropdown-item" type="button">Auth/Sale with Token Creation</button>
</div>
</div>
<!-- HTML element IDs cannot begin with a number, use a dataset attribute instead -->
<div data-id=1 class="SAformX hidden" style="background-color:red;">
<p>Red div - data-id=1</p>
</div>
<div data-id=2 class="SAformY hidden" style="background-color:blue;">
<p>Blue div - data-id=2</p>
</div>
<div data-id=3 class="SAformZ hidden" style="background-color:green;">
<p>Green div - data-id=3</p>
</div>

Related

Select interact to a specific html element with a button

I have a few buttons in the HTML file code with Bulma similar like this:
<a class="button" data-target="A">Section A</a>
<a class="button" data-target="B">Section B</a>
<a class="button" data-target="C">Section C</a>
And there are a few section like this which can interact with the buttons:
<div id="A" class="contentswitch">
<article class="message">
<div class="message-header" id="h1">
<p>Section A-1</p>
</div>
<div class="message-body">
Message 1 of section A
</div>
<div class="message-header">
<p>Section A-2</p>
</div>
<div class="message-body">
Message 2 of section A
</div>
</article>
</div>
As I add code like this in the JS, it can add a class called "is-hidden" to all the div ejectment which contains "contentswitch" class.
$("a.button").on("click", function(){
$("div.contentswitch").addClass("is-hidden");
});
What can I do if I want to remove the class ("is-hidden") from specific div element, like if I click the button of Section A, then it add "is-hidden" class to all the div element contain content switch then remove it from the div element with the id "A"?
Thank you so much
You can use data-target to connect the clicked button to the div you want to show. And hide the rest of them.
Also, use button iso a tag. a tag has a specific purpose in HTML and should be used only in combination with href attribute.
const buttons = $('.button');
const contentSwitchDivs = $('.contentswitch');
buttons.on("click", function(){
const btnTarget = $(this).data('target')
const contentToShow = $(`#${btnTarget}`)
contentSwitchDivs.not(btnTarget).hide();
contentToShow.show();
});
.contentswitch {
display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="button" data-target="A">Section A</button>
<button class="button" data-target="B">Section B</button>
<button class="button" data-target="C">Section C</button>
<div id="A" class="contentswitch">
A contentswitch
</div>
<div id="B" class="contentswitch">
B contentswitch
</div>
<div id="C" class="contentswitch">
C contentswitch
</div>

Checkbox input triggering Bootstrap accordion collapse event

Hello guys I'm using Bootstrap 5 accordion, the only problem I have is that the input checkbox is triggering the "collapse" event from the accordion, I tried to move the checkbox outside the range of the button from the accordion but that will look horrible.
I'm using Svelte, rendering each accordion with Each block with Data from the backend!
This is my code right now:
<div class="container">
<div class="row">
<div class="col-md-10 col-10 col-sm-10 responsiveFix">
<div class="accordion" id="accordionObjective">
{#each objectives as objective}
<div class="accordion-item">
<h2
class="accordion-header"
id={"heading" + objective.objectiveId}
>
<button
class="accordion-button objectiveTitle collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target={"#collapse" +
objective.objectiveId}
aria-expanded="false"
aria-controls={"collapse" +
objective.objectiveId}
>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value={objective.objectiveId}
id="myCollapse"
checked={objective.value}
on:click={postObjective(
objective.objectiveId,
objective.value
)}
/>
</div>
<span> {objective.title}</span>
</button>
</h2>
<div
id={"collapse" + objective.objectiveId}
class="accordion-collapse collapse"
aria-labelledby={"heading" +
objective.objectiveId}
data-bs-parent="#accordionObjective"
>
<div class="accordion-body">
<span>{objective.description}</span>
</div>
</div>
</div>
{/each}
</div>
</div>
</div>
</div>
The output of this code its
and this is the picture showing my problem after clicking on any checkbox:
I also tried to bind a bootstrap 5 function to the checkbox input but it didn't work
What can I do? Can you throw me any clue? Thank you!
I am not familiar with Bootstrap 5 as such, but a quick glance at your code shows this: <button on:click={postObjective(objective.objectiveId, objective.value )}>
This function is executed at render time and the return value added as the event listener for your on:click
The correct syntax would be <button on:click={() => postObjective(....)}>
As the code is now it probably does not do what you expect.
Edit:
In your case the input is also inside a button, clicking the input will therefore also click the button. To stop this from happening you have to prevent the event from bubbling up, Svelte has a handy helper for that: <button on:click|stopPropagation={() => postObjective(....)}>

Bootstrap Dropdown not toggling, just "show" works

I am using the bootstrap drop down for a div that contains buttons. The div appears and all, and I see in the dropdown class that a class of "open" is added and the drop down menu has an attribute of "aria-expanded" set to "true". I am pretty sure the bootstrap is working, but I am missing something.
Here is my cshtml template:
#using entryIconContent = Lifegunk.Engine.Resources.Components.EntryIcon
<div class="entry-icon-wrapper">
<div class="entry-type"></div>
<div class="dropdown actions-dropdown">
<div class="dropdown-menu entry-icon-actions">
<button class='change-btn btn btn-default'>
<div class="entry-type"></div>
<span>#entryIconContent.ChangeText</span>
</button>
<button class="move-btn btn btn-default">
<div class="icon-move"></div>
<span>#entryIconContent.MoveText</span>
</button>
<button class='go-btn btn btn-default'>
<div class="icon-arrow-right"></div>
<span>#entryIconContent.GoText</span>
</button>
</div>
</div>
<div class="dropdown entry-types-dropdown">
<ul class='dropdown-menu'></ul>
</div>
</div>
And here is my snippet of javascript code where I call the .dropdown() func:
$entryTypeIcon.click(function () {
if (isEditMode) {
$entryTypesDropMenu.dropdown("toggle");
renderEntryTypes();
} else {
$entryActionsDropdown.dropdown("toggle");
}
if ($entryTypesDropMenu.is(":visible")) {
$entryTypesDropMenu.hide();
$entryActionsDropdown.hide();
}
});//end $entryTypeIcon click handler

Jquery not recognizing events that takes place on the HTML templates that is generated on fly

I am using Handlerbars.js and it gives me a dynamic template that is generated on the fly. When I do some Jquery events like click etc .. Jquery is not able to catch those events. Please help me out.
I want to trigger a event when the button with id hitUp is clicked
HandlerBar.js code
{{#each this}}
<div id="accordion2" class="panel-group">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a href="#{{log}}" data-parent="#accordion2"
data-toggle="collapse" class="btn-block" > <img
class="img-rounded" src="/assets/images/default-food.png" /> {{log}}
</a>
</h4>
</div>
<div class="panel-collapse collapse" id="{{log}}">
<div class="panel-body food-details">
<div class="bm pzero col-xs-12">
<div class="input-group spinner">
<input id="spinid" type="text"
name="demo_vertical2" class="form-control input-sm"
/> <span class="input-group-btn vertical">
<button id="hitUp"
class="btn btn-default bootstrap-touchspin-up"
type="button">
<i class="fa fa-caret-up"></i>
</button>
<button id="hitDown"
class="btn btn-default bootstrap-touchspin-down "
type="button">
<i class="fa fa-caret-down"></i>
</button>
</span>
</div>
HTML code
<div id="accordion2" class="panel-group">
</div>
Jquery code
Try1
$('body').on("click",'#hitUp',function(){
console.log("Functionclicked")
});
Try2
$('#hitUp').click(function(){
console.log("Functionclicked")
});
Try3
$( document ).ready(function( $('body').on("click",'#hitUp',function(){
console.log("Functionclicked")
});){})
I have tried the above Jquery methods but no use. Give me some solutions
Just like in the link that #adeno posted, jQuery event handlers need to be registered as the very last thing that happens when all the JavaScript files and libraries are loaded. Calling $(document).ready() does not mean that all JS files have been loaded, it just means that the DOM has been put in place and is ready for manipulation. If you're going to do more DOM manipulation with a library like Handlebars, you need to make sure that your event handlers are registered after all that dynamic generation has already happened.
So if this is my template:
<h1>{{title}}</h1>
<div>{{body}}</h1>
<br />
{{#each buttonIds}}
<input type="button" id="{{this}}" value="Click me" />
{{/each}}
And this is my javascript:
var data = {
title: 'The Title',
body: 'Document Body',
buttonIds: [ 'hitUp1', 'hitUp2', 'hitUp3' ]
};
var templateScript = $('#header').html();
var template = Handlebars.compile(templateScript);
$(document.body).append(template(data));
$('#hitUp1').on('click', function () { alert('clicked 1'); });
$('#hitUp2').on('click', function () { alert('clicked 2'); });
$('#hitUp3').on('click', function () { alert('clicked 3'); });
I'm waiting til very last to register the on click handlers, and they are each unique identifiers.
Here is a working fiddle to demonstrate what I'm saying.
was facing the same issue. use
$('body').on("change", '#amountType', function (){
});
this worked for me

replace class name without full class name

Alright so I am trying to make a PHP page builder using jQuery and bootstrap.
I got almost everything working except being able to see the change in the column size.
My problem is I am not sure how to replace the column size class variable which could be anything between col-lg-1 to col-lg-12
So using jquery I would like to be able to do the following.
Get the current column size base on class: So if the column is col-lg-4 I want to get the 4
replace the 4 with a 3 or 5 based on which direction the user selected.
remove the class col-lg-4 and add either the class col-lg-3 or col-lg-5
This way on the screen the user can see how big that column is going to be.
To provide more information. Here is the HTML
<div class="col-lg-4 bs-example-popover">
<div class="popover" style="width:100%;">
<h3 class="popover-title">[Module Title] <button type="button" class="close">×</button></h3>
<div class="popover-content">
<p>[Module Description]</p>
<ul class="list-unstyled">
<li class="pull-right"><button class="btn btn-default btn-xs"><span class="icon-icomoon-arrow-right"></span></button></li>
<li class="pull-right"> </li>
<li class="pull-right"><button class="btn btn-default btn-xs"><span class="icon-icomoon-arrow-left"></span></button></li>
<li> </li>
</ul>
</div>
</div>
</div><!-- /column -->
and my basic JS will get the parent and the button. But I don't know how to get just the size of the class, then add or subtract, and lastly replace the class.
$('.page-builder-column ul li .btn').on('click', function(e) {
e.preventDefault();
var _btn = $(this).find('span'),
_parent = $(this).parents().eq(4);
if (_btn.hasClass('icon-icomoon-arrow-right')) {
console.log('larger');
}else{
console.log('smaller');
}
console.log(_parent.hasClass('col-lg-*'));
});
You can do the following:
_parent.attr('class').match(/\d+/)[0]
which will return the 4

Categories