Bootstrap Dropdown not toggling, just "show" works - javascript

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

Related

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(....)}>

Show/Hide Divs from Dropdown

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>

expand menu to expand/collapse all menues regardless if they are expanded or closed

I have 4 expandable menus and 5 buttons. Collapse first button expands/closes the first menu, Collapse second button expands/closes the second menu and so on.
As it is: Button Collapse all for each menu closes it if it is expanded and expands it if it is closed.
Want to be: Whereas I want my Collapse all button to expand all menus if they are closed and don't change them if they are expanded. And then if clicked again closes all the menus that are expanded and don't change the closed menus.
Here is a fiddle I wrote for As it is: expand menu fidlle
.row {
background: #f8f9fa;
margin-top: 20px;
}
.col {
border: solid 1px #6c757d;
padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css" rel="stylesheet"/>
<p>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample1, #collapseExample2, #collapseExample3, #collapseExample4" aria-expanded="false" aria-controls="collapseExample">
Collapse all
</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample1" aria-expanded="false" aria-controls="collapseExample">
Collapse first
</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample2" aria-expanded="false" aria-controls="collapseExample">
Collapse second
</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample3" aria-expanded="false" aria-controls="collapseExample">
Collapse third
</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample4" aria-expanded="false" aria-controls="collapseExample">
Collapse fourth
</button>
</p>
<div class="collapse" id="collapseExample1">
<div class="card card-body">
hi first
</div>
</div>
<div class="collapse" id="collapseExample2">
<div class="card card-body">
hi second
</div>
</div>
<div class="collapse" id="collapseExample3">
<div class="card card-body">
hi third
</div>
</div>
<div class="collapse" id="collapseExample4">
<div class="card card-body">
hi fourth
</div>
</div>
How can I do it?
A naive solution I can think of now is to bind the collapse all click event via a custom handler that shows or hides all collapsibles based on a state on the collapse all button, instead of via Bootstrap built-in data-toggle="collapse" and data-target="*".
<p>
<button id="toggle-all" class="btn btn-primary" type="button">
Collapse all
</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" ... />
...
</p>
<div class="collapse" />
...
Then in this Collapse all's button click event, you can have a state on this button itself (via data-) to memorize whether to show or hide all collapsibles. And based on that state variable, you can call either .collapse('show') or .collapse('hide') on all collapsibles manually.
The show method won't show a collapsible again if it's already shown. And the hide method won't hide a collapsible if it's already hidden.
$(function() {
$('#toggle-all').click(function() {
// Declare a variable, `data-to-show`, to contain the state whether to show/hide
// all collapsibles.
// It defaults to true, which means it's about to show all.
if (!$(this).data('to-show')) {
$(this).data('to-show', true);
} else {
$(this).data('to-show', !$(this).data('to-show'));
}
if ($(this).data('to-show')) {
$('.collapse').collapse('show');
} else {
$('.collapse').collapse('hide');
}
return false;
});
});
demo: https://jsfiddle.net/davidliang2008/cvy2kbpz/28/
Another better "solution" I can think of is to declare an extra data attribute, maybe something like data-toggle-all-at-the-same-time="true", and override Bootstrap's built-in .collapse() so that when it sees that data attribute being true, it doesn't toggle the target elements which are already toggled?
Sadly I haven't found an easy way to do so, yet.
I would use the toggle function from jQuery. Here is a link to its docs https://api.jquery.com/toggle/
This function hides an element if it is beign shown; or shows it if it is hidden. Simple and works like a charm without many checks.
You need to include jQuery onto your html page. Right at the bottom.
Let this script be the last element within your body tag.
Then you will need to include all the javascript files that come within the boostrap folder (if you have downloaded the folder).
Add the following tags on your script. As mentioned, right before the tag
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>

jQuery modal pop up disappears when mouse pointer leaves the browser

I'm working on a reactjs project in which i have nav menus, and i'm using jquery modal pop up, one of my menus is "Import" which contains two sub menus "CCAWB & GAWB" i'm using react component to render these two submenus under "Import"
<li className="has-submenu">
<a href="#">
<span>Import</span>
</a>
<ul className="submenu">
<li>
<ul>
<RenderCCAWB_GAWBPopUp submenu ="CCAWB"/>
<RenderCCAWB_GAWBPopUp submenu ="GAWB"/>
</ul>
</li>
</ul>
</li>
RenderCCAWB_GAWBPopUp Component returns the following
render(){
return(<li onClick={this.handleShowModal}>
{this.props.submenu}
{this.state.view.showModal ? <UpdateQualityHeaderDummy
handleHideModal={this.handleHideModal} menuName={this.props.submenu} />:null}
</li>);}
on click of any of the sub menus "CCAWB/GAWB" i want to show the modal pop up
which's returned by another component
UpdateQualityHeaderDummy returns the modal itself
return (
<div className="modal" data-backdrop='static' id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div className="modal-dialog" >
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel">{title}</h5>
<button onClick={this.closePop} type="button" className="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
<div className="row">
<div className=" col-lg-12 col-xl-12
qcUpdateStatus">
</div>
<FileUpload menuTitle={this.props.menuName}/>
</div>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" data-dismiss="modal" onClick ={this.closePop}>Close</button>
<button type="button" className="btn btn-danger" data-dismiss="modal" onClick ={this.downloadFeed}>Download Feed</button>
<button type="button" className="btn btn-primary" onClick={this.validateForm}> Upload </button>
</div>
</div>
</div>
</div>);
} });
till here everything works fine and the modal shows up as attached bellow
[Screen 1 for the scenario ][1]
*= > the problem is here, whenever the mouse pointer leaves the browser (i.e goes to the url bar) the modal and the sub menus disappear but the modal opacity stays there (attached bellow)
Screen 2 when the pointer is outside the page
*= >but they show up immediately as soon as the pointer is back to the page (any where)
attached bellow screen 3
Screen 3 when the pointer is inside the page
*=> my trials: i have tried the event mouseleave(when mouse leaves the browser) and set the visibility of the sub menus as visible but they keep disappearing i even set the modal show property as true in the same event but also doesn't work.
$(document).mouseleave(function () {
$('.modal').css('visibility','visible');
$('#navigation > div > ul > li:nth-child(5) >
ul').css('visibility','visible');
$('#myModal > div').css('visibility','visible');
$('#myModal > div > div').css('visibility','visible');});
any suggestions please ?

Using jQuery html() method in several clicks

I am working on this demo. I am trying to find out why the HTML disappears after using the second button.
As long as you only click on btn #from-content-1 or only on #from-content-2 every thing is fine but if you click on #from-content-1 and then on #from-content-2 and back to the #from-content-1 again, the content disappears!
Here is the code which I have:
<div class="row">
<div class="container">
<div id="dest">Here is the Destination</div>
</div>
</div>
<div class="sr-only">
<div id="content-1">This Is From Content 1</div>
<div id="content-2">This Is From Content 2</div>
</div>
<button class="btn btn-default" id="from-content-1">From Content 1</button>
<button class="btn btn-default" id="from-content-2">From Content 2</button>
and js script is
<script>
$("#from-content-1").on("click",function(){
$("#dest").html($('#content-1'));
});
$("#from-content-2").on("click",function(){
$("#dest").html($('#content-2'));
});
</script>
How can I fix this?
You move the nodes! Do that instead:
<script>
$("#from-content-1").on("click",function(){
$("#dest").html($('#content-1').html());
});
$("#from-content-2").on("click",function(){
$("#dest").html($('#content-2').html());
});
</script>
$("#dest").html($('#content-1')); should be $("#dest").html($('#content-1').html()); and $("#dest").html($('#content-2')); should be $("#dest").html($('#content-2').html());
$("#from-content-1").on("click",function(){
$("#dest").html($('#content-1').html());
});
$("#from-content-2").on("click",function(){
$("#dest").html($('#content-2').html());
});

Categories