Bootstrap 3 close nav menu when you click outside - javascript

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)

Related

How to correctly handle event with dynamically added elements?

I am developing a ToDo app with HTML and JS, while got stuck with removing dynamically added elements. Is there any way to remove the selected element?
I have tried to delete an element via selecting its parent and then reaching to the child and removing it. Could not arrange to remove the selected element though. el.removeChild(el.childNodes[0]) removes the element from the beginning. Is there any way to remove the selected-active element?
document.addEventListener('click',function(e){
if(e.target && e.target.id== 'rem'){
let el = document.getElementById('uList');
el.removeChild(el.childNodes[0]); // How to remove the clicked el?
}
});
I expect the code to remove the clicked element, rather deleting the nodes starting from the 0 element.
Many thanks!
document.addEventListener('click', function(e) {
if (!e.target || e.target.id !== 'rem') {
return;
}
let parent = e.target.parentElement;
if (!!parent) {
parent.removeChild(e.target);
}
});
for the parent of parent:
document.addEventListener('click', function(e) {
if (!e.target || e.target.id !== 'rem') {
return;
}
const parent = e.target.parentElement;
if (!parent) {
return;
}
const parentOfParent = parent.parentElement;
parent.removeChild(e.target);
if (!!parentOfParent) {
parentOfParent.removeChild(parent);
}
});

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.

Hide a list when clicking outside

I have a share link that shows a list of links when clicked. I'm using toggle to hide and show this list.
When the list is visible, the user can click share to hide (toggle) the visibility of the list of links.
However, the small problem with this is, the list of links remain visible until the user toggles the list by pressing share.
I added this script to make it possible to close the list if the user clicks outside the list.
$(".meta-share").click(function() {
event.preventDefault();
$(".social-share").fadeToggle();
});
$(document).mouseup(function(e) {
var container = $(".social-share");
if (!container.is(e.target) && container.has(e.target).length === 0) {
container.fadeOut();
}
});
However, the toggle doesn't work as expected now.
Can anyone help?
Here's a jsFiddle showing the problem.
that's because you say to fade when you click on the target and next to the target. all you have to do is return false when the target is meta--share in your document.mouseup.
$(".meta--share").click(function() {
event.preventDefault();
$(this.nextElementSibling).fadeToggle();
});
$(document).mouseup(function(e) {
if(e.target.className == "meta--share"){
return false;
}
var container = $(".social-share");
if (!container.is(e.target) && container.has(e.target).length === 0) {
container.fadeOut();
}
});
here's your adjusted fiddle: https://jsfiddle.net/9hpw15oq/2/
Update
in the .click function. instead of looking for the element through class. select the element using the .click event.
I have updated the code and fiddle
This code should work fine :
$(".meta--share").click(function() {
event.preventDefault();
if($('.social-share').is(':visible')){
$(".social-share").fadeOut();
}
else{
$(".social-share").fadeToggle();
}
});
$(document).mouseup(function(e) {
var container = $(".social-share");
if (!container.is(e.target) && container.has(e.target).length === 0) {
container.fadeOut();
}
});
$(".meta--share").click(function() {
event.preventDefault();
$(".social-share").toggle();
});
$(document).mouseup(function(e) {
var container = $(".social-share");
if (!container.is(e.target) && container.has(e.target).length === 0) {
container.fadeOut();
}
});
.social-share {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><a class="meta--share" href="#">Share</a>
<ul class="social-share">
<li class="facebook"><a title="Share on Facebook" href="#">Facebook</a></li>
<li class="twitter"><a title="Share on Twitter" href="#">Twitter</a></li>
<li class="linkedin"><a title="Share on Linked" href="#">Linkedin</a></li>
</ul>
</li>
</ul>

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

Close sidebar on click outside

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

Categories

Resources