Close sidebar on click outside - javascript

I'm working a site using this Bootstrap example, with a simple slide in sidebar navigation.
http://ironsummitmedia.github.io/startbootstrap-simple-sidebar/#
It is slightly modified, so I have a button for the menu to open:
// Opens the sidebar menu
$("#menu-toggle").click(function (e) {
e.preventDefault();
$("#sidebar-wrapper").toggleClass("active");
});
And a button for the menu to close:
// Closes the sidebar menu
$("#menu-close").click(function (e) {
e.preventDefault();
$("#sidebar-wrapper").toggleClass("active");
});
I want to add functionality, so it will close if I click anywhere outside the sidebar. So far I have this:
// Close the menu on click outside of the container
$(document).click(function (e) {
var container = $("#sidebar-wrapper");
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0 // ... nor a descendant of the container
&& event.target.id !== "menu-toggle") // for the functionality of main toggle button
{
container.removeClass("active");
}
});
But it seems to remove the "active" class this way.
Best regards.

So the solution should be that if you click anywhere inside the container the click handler should do nothing and just return. But if the click is outside the container then it should close it.
Below is the click handler code which might help you.
$(document).click(function(e) {
var node = e.target;
// loop through ancestor nodes to check if the click is inside container.
// If yes then return from the handler method without doing anything
while(node.parentNode) {
if (node === container) {
return;
}
node = node.parentNode;
}
container.removeClass('active')
});

Try this
$(document).click(function (e)
{
var container = $("#wrapper");
if (!container.is(e.target) && container.has(e.target).length === 0 && event.target.id!=="menu-toggle")
{
container.addClass("toggled");
}
});
So what basically it is doing is if e is element you want to toggle the class and if the clicked e is also that then the class wil not toggle otherwise it will.

You can use a recursive function that check if a element clicked exists in cointainer from sidebar menu:
function hasElement(node, element) {
return node == element
|| (node.childNodes || []).length && Array.from(node.childNodes)
.filter(x => x.nodeType == 1)
.some(x => hasElement(x, element));
}
$('body').click(function (event) {
var container = Array.from($("#sidebar")); //Add another containers that would be clicked wihtout close sidebar
var exists = container.some(node => hasElement(node, event.target));
if (!exists)
//TODO Close sidebar here...
});

Related

Bootstrap 3 close nav menu when you click outside

I am using the following jQuery:
jQuery(document).click(function (event) {
var clickover = jQuery(event.target);
var _opened = jQuery(".navbar-collapse2").hasClass("in");
if (_opened === true && !clickover.hasClass("navbar-toggle")) {
jQuery("button.navbar-toggle").click();
}
});
The problem is within navbar-collapse I have some sub menus and when I click to expand/collapse them. It also collapses the main nav menu.
You should probably check if your clicked element is not a child of .navbar-toggle. You can do that with the closest() function. This will find the first parent that matches the selector.
if (_opened === true && !clickover.hasClass("navbar-toggle") && clickover.closest(".navbar-toggle").length === 0)

how to close created div by clicking outside of it?

I have a div that is created on a button pressed and I'm trying to have it deleted by clicking outside of it but it takes the original button press as clicking outside and immediately closes the div.
closediv();
}
function closediv() {
document.addEventListener("click", (evt) => {
const maindiv = document.getElementById('div3');
let targetElement = evt.target;
do {
if (targetElement == maindiv.childNodes[1]) {
return;
}
targetElement = targetElement.parentNode;
} while (targetElement);
var viewpost = maindiv.childNodes[1];
viewpost.parentNode.removeChild(viewpost);
});
}
In your button click handler, you could use
theButton.addEventListener("click", function(ev) {
ev.stopPropagation();
// rest of the code
});
and the click event would not propagate to the parent containers.
just add a click event on body to close your div and then add prevent default into your div to block closing action when user click on your div
document.body.addEventListener('click', (e) =>{
//close your div here
})
document.addEventListener("click", (evt) => {
evt.preventDefault()
// your code
}

How do I get my modal to close when a user clicks on the container?

I'm currently studying a full stack course and my modal isn't behaving as expected
I'm a bit lost on what to do as I can't find any documentation anywhere and while clicking on the close button or pressing ESC works, clicking outside of the box doesn't.
The following code is how it has been suggested I approach the issue but, it doesn't work. I've honestly stared at this for about an hour and just can't connect the dots on what is (not) happening? Please excuse all the commenting and additional code as I'm still learning so, it's how I'm able to follow what's going on:
function showModal() {
var $modalContainer = document.querySelector('#modal-container');
$modalContainer.classList.add('is-visible');
}
function hideModal() {
var $modalContainer = document.querySelector('#modal-container');
$modalContainer.classList.remove('is-visible');
}
//modal IFFE
document.querySelector('#modal-button').addEventListener('click', () => {
showModal();
});
//-- show modal --
function showModal(title, text) {
var $modalContainer = document.querySelector('#modal-container');
//Selects the element with the associated id
// Clear all content for the selected element
$modalContainer.innerHTML = '';
var modal = document.createElement('div'); //creates a div element withing selected element
modal.classList.add('modal'); //assigns new class to the div element
// Add the new modal content
var closeButtonElement = document.createElement('button'); //creates the close button
closeButtonElement.classList.add('modal-close'); //assigns a class to the new (close) button
closeButtonElement.innerHTML = "×"; //inserts text within the new(close) button
closeButtonElement.addEventListener('click', hideModal);
var titleElement = document.createElement('h1');
titleElement.innerText = title;
var contentElement = document.createElement('p');
contentElement.innerText = text;
modal.appendChild(closeButtonElement);
modal.appendChild(titleElement);
modal.appendChild(contentElement);
$modalContainer.appendChild(modal);
$modalContainer.classList.add('is-visible');
}
document.querySelector('#modal-button').addEventListener('click', () => {
showModal('PokéMon', 'Here is all of the info about your PokéMon');
});
window.addEventListener('keydown', (e) => {
var $modalContainer = document.querySelector('#modal-container');
if (e.key === 'Escape' && $modalContainer.classList.contains('is-
visible')) {
hideModal();
}
});
$modalContainer.addEventListener('click', (e) => {
var target = e.target;
if (target === $modalContainer) {
hideModal();
}
});
Expected result: User clicks outside of the modal (on the container) and the modal closed.
Current result: No change in state, modal remains active and visible. Only by clicking on the close button (x) or by pressing ESC is the desired result achievable.
By Looking at this code I am not sure what is actually supposed to make the modal visible or hide it. Without access to your css (if you have any). I am assuming that all you are doing is adding and removing the class .is-visible from the #modal-container element.
I would suggest that you apply this class to the modal itself, and then you could toggle this class on and off,
Modify your code to do this by doing something like this (added on top of your code):
function showModal() {
var $modalContainer = document.querySelector('#modal-container');
$modalContainer.classList.add('is-visible');
document.querySelector('.modal').classList.remove('hide-el')
}
function hideModal() {
var $modalContainer = document.querySelector('#modal-container');
$modalContainer.classList.remove('is-visible');
document.querySelector('.modal').classList.add('hide-el')
}
Where hide-el in your css is:
.hide-el {
display: none;
}
You could also modify your code to appply the is-visible class to your modal element. You should always try to attach the class/id to the element you want to manipulate if you have that option.
Or if you do not have access to a css file:
document.querySelector('.modal').style.display = "none"
and
document.querySelector('.modal').style.display = "block"
Also, your code seems very verbose, was this boilerplate part of the assignment?
heres a working example: https://codepen.io/mujakovic/pen/zVJRKG
The code was in the incorrect place in the end and should have looked something like this:
modal.appendChild(closeButtonElement);
modal.appendChild(titleElement);
modal.appendChild(contentImage);
modal.appendChild(contentHeight);
modal.appendChild(contentElement);
$modalContainer.appendChild(modal);
$modalContainer.classList.add('is-visible');
$modalContainer.addEventListener('click', (e) => { //listening for an event (click) anywhere on the modalContainer
var target = e.target;
console.log(e.target)
if (target === $modalContainer) {
hideModal();
}
});
};
window.addEventListener('keydown', (e) => { //listening for an event (ESC) of the browser window
var $modalContainer = document.querySelector('#modal-container');
if (e.key === 'Escape' && $modalContainer.classList.contains('is-visible')) {
hideModal();
}
});
This is because the action was originally being called on page load and targeted within the window instead of being called within the container and being loaded when the modal loads.
Thank for your help

Closing toggle menu not working properly with JQuery code

I am working on closing toggle menu for mobiles and having a small problem. So what i want is when the toggle menu is active, user to be able to close it by touching somewhere on the screen on his device. I almost got it working, but when closed the basket in the header disappears and the menu doesn't retrieve to a hamburger icon. I am working on Wordpress website, just to notice.
I guess the problem comes from this: aria-expanded="true" , because the default value should be false after the user has closed it.
So my website is:
https://www.ngraveme.com/bg
my JQuery code is:
jQuery(document).ready(function($) {
var $menu = $('.menu');
$('.menu-toggle').click(function() {
$menu.toggle();
});
$(document).mouseup(function(e) {
if (!$menu.is(e.target) // if the target of the click isn't the container...
&&
$menu.has(e.target).length === 0) // ... nor a descendant of the container
{
$menu.hide();
}
});
});
and the original js code written from the theme i am using in wordpress is:
/**
* navigation.js
*
* Handles toggling the navigation menu for small screens.
* Also adds a focus class to parent li's for accessibility.
* Finally adds a class required to reveal the search in the handheld footer bar.
*/
(function() {
// Wait for DOM to be ready.
document.addEventListener('DOMContentLoaded', function() {
var container = document.getElementById('site-navigation');
if (!container) {
return;
}
var button = container.querySelector('button');
if (!button) {
return;
}
var menu = container.querySelector('ul');
// Hide menu toggle button if menu is empty and return early.
if (!menu) {
button.style.display = 'none';
return;
}
button.setAttribute('aria-expanded', 'false');
menu.setAttribute('aria-expanded', 'false');
menu.classList.add('nav-menu');
button.addEventListener('click', function() {
container.classList.toggle('toggled');
var expanded = container.classList.contains('toggled') ? 'true' : 'false';
button.setAttribute('aria-expanded', expanded);
menu.setAttribute('aria-expanded', expanded);
});
// Add class to footer search when clicked.
document.querySelectorAll('.storefront-handheld-footer-bar .search > a').forEach(function(anchor) {
anchor.addEventListener('click', function(event) {
anchor.parentElement.classList.toggle('active');
event.preventDefault();
});
});
// Add focus class to parents of sub-menu anchors.
document.querySelectorAll('.site-header .menu-item > a, .site-header .page_item > a, .site-header-cart a').forEach(function(anchor) {
var li = anchor.parentNode;
anchor.addEventListener('focus', function() {
li.classList.add('focus');
});
anchor.addEventListener('blur', function() {
li.classList.remove('focus');
});
});
// Add an identifying class to dropdowns when on a touch device
// This is required to switch the dropdown hiding method from a negative `left` value to `display: none`.
if (('ontouchstart' in window || navigator.maxTouchPoints) && window.innerWidth > 767) {
document.querySelectorAll('.site-header ul ul, .site-header-cart .widget_shopping_cart').forEach(function(element) {
element.classList.add('sub-menu--is-touch-device');
});
}
});
})();
Try replacing your jQuery code with this:
jQuery(document).ready(function($) {
$(document).mouseup(function(e) {
var $menuContainer = $('.menu');
var $menu = $menu.find('ul');
var $container = $('.site-navigation');
var $button = $container.find('button')
if (!$menuContainer.is(e.target) && $menuContainer.has(e.target).length === 0) {
if ($container.hasClass('toggled')) {
$button.attr('aria-expanded', false);
$menu.attr('aria-expanded', false);
}
}
});
});
It uses the vanilla-js code from the template for hiding/showing the menu, but with jQuery synthax.

jquery click outside - $(this) stop works

I wanted to ask, where i have error, it piece of code.
Button class show / hide filter element, and this is ok. But i want to archive "click outside effect" - close filter on some body element click, not filter itself.
$('.button').on('click',function() {
var filters = $('#filters');
if (filters.is(':hidden')) {
filters.show();
} else {
filters.hide();
}
// Now i want to close filter, on click on body element, not filter itself.
// Now, this code below, closes filter, on click on body element, but now .button is not closing filter. So code below is not working...
$(document).mouseup(function (e) {
var container = filters;
if (!container.is(e.target) && container.has(e.target).length === 0) {
container.hide();
}
});
});
But now, $(document).mouseup(function (e) - it prevents .button, from filters close....
What's wrong ?
Thanks for advice.
Have a look at this:
https://jsfiddle.net/t1nxwvy2/3/
You can use the following to see if the click was inside the button or not:
$(document).mouseup(function (e) {
var container = $('.button');
if (!container.is(e.target) && (container.has(e.target).length === 0)) {
if (!filters.is(e.target) && (filters.has(e.target).length === 0)) {
filters.hide();
}
} else filters.toggle();
});

Categories

Resources