jQuery Adding / Removing classes on a button to hide elements - javascript

Trying to get a mobile footer menu (#mobile-menu) to hide / show when the floating button is clicked or tapped. I'm able to add the click event handler to the button (#mobile-footer-btn) which in turns applies a class to the menu and animates it off screen.
<footer id="mobile-footer">
<div id="mobile-menu">
<div id="mobile-footer-container">
<div class="mobile-link">
My Account
</div>
<div class="mobile-link">
Reviews
</div>
<div class="mobile-link">
Contact Us
</div>
</div>
</div>
<div id="mobile-footer-close">
<button id="mobile-footer-btn">
<div class="mobile-btn-close">
<span></span>
</div>
</button>
</div>
</footer>
For whatever reason, I'm not able to remove that class and add a new class to the same ID, which would add a class to show the menu again.
jQuery(document).ready(function($){
// Store menu container
var mobileMenu = '#mobile-menu';
// Store Trigger
var mobileBtn = '#mobile-footer-btn';
//Trigger closing the footer menu
$(mobileBtn).on("click", function() {
$(mobileMenu).addClass('mobile-menu-hide');
});
$('.mobile-btn-close').click(function() {
$(this).addClass('is-rotating');
});
if($(mobileMenu).hasClass('mobile-menu-hide')) {
$(mobileBtn).on("click", function(e) {
e.stopPropagation();
$(mobileMenu).removeClass("mobile-menu-hide").addClass("mobile-menu-show");
});
}
});
Any help would be much appreciated!

You only need one on click event! Your if condition never gets evaluated to true, therefor your onclick event is never triggered. It's better to house it in one onclick event. Here's the code:
jQuery(document).ready(function($){
// Store menu container
var mobileMenu = '#mobile-menu';
// Store Trigger
var mobileBtn = '#mobile-footer-btn';
$('.mobile-btn-close').click(function() {
$(this).addClass('is-rotating');
});
$(mobileBtn).on("click", function(e) {
e.stopPropagation();
if($(mobileMenu).hasClass('mobile-menu-hide')) {
$(mobileMenu).removeClass("mobile-menu-hide").addClass("mobile-menu-show");
} else {
$(mobileMenu).removeClass("mobile-menu-show").addClass("mobile-menu-hide");
}
});
});
Here's the plunker: https://plnkr.co/edit/SG8eFns91wV4adxapFDB
Even better now that I think about it: just toggle the one class that hides the menu and just use jQuery's toggleClass function. Something like this:
$(mobileBtn).on("click", function(e) {
e.stopPropagation();
$(mobileMenu).toggleClass('mobile-menu-hide');
});

The problem is that your if condition in the block only executes once. However, you need it to be called on every click. Hence, you need to update your code to following
jQuery(document).ready(function($){
// Store menu container
var mobileMenu = '#mobile-menu';
// Store Trigger
var mobileBtn = '#mobile-footer-btn';
//Trigger closing the footer menu
$(mobileBtn).on("click", function() {
// moved your if block inside the click handler
if($(mobileMenu).hasClass('mobile-menu-hide')) {
e.stopPropagation();
$(mobileMenu).removeClass("mobile-menu-hide").addClass("mobile-menu-show");
} else {
$(mobileMenu).addClass('mobile-menu-hide');
}
});
$('.mobile-btn-close').click(function() {
$(this).addClass('is-rotating');
});
});

Your $(mobileBtn).on("click", function(e) { ... code never executes and, therefore, never adds the click event handler because the menu doesn't start out as .mobile-menu-hide Try this
$(mobileBtn).on("click", function(e) {
if($(mobileMenu).hasClass('mobile-menu-hide')) {
e.stopPropagation();
$(mobileMenu).removeClass("mobile-menu-hide").addClass("mobile-menu-show");
}
});

Related

Click outside menu to close it

Here's my function,
$(document).ready(function () {
$('.a').click(function () {
var here = $(this).next('.b');
if (here.is(":visible")) {
here.hide();
} else {
here.show();
}
return false;
});
});
So, whenever I click the button it opens a small tab on same webpage & whenever I click it again it closes it. But once I open the tab I can't close it by just clicking somewhere on webpage apart from tab. I have to click the button again to close it.
How can I close tab just by clicking somewhere on webpage also by on the button?
I end up searching for this on almost every project, so I made this plugin:
jQuery.fn.clickOutside = function(callback){
var $me = this;
$(document).mouseup(function(e) {
if ( !$me.is(e.target) && $me.has(e.target).length === 0 ) {
callback.apply($me);
}
});
};
It takes a callback function and passes your original selector, so you can do this:
$('[selector]').clickOutside(function(){
$(this).removeClass('active'); // or `$(this).hide()`, if you must
});
Nice, chainable, elegant code.
On document click, the closest helps to check whether the tab has been clicked or not:
$(document).click(function (e) {
if($('.b').is(':visible')&&!$(e.target).closest('.b').length){
$('.b').hide();
}
});
You want to check for a click on the body :
$("body").click(function(e) {
if(e.target.id !== 'menu'){
$("#menu").hide();
}
});
menu would be the id of the menu.
If the body is clicked and the id of the div clicked doesn't equal that of the menu, then it closes.
Check this implementation
jQuery(document).ready(function() {
$(document).on('click','body, #btn',function(ev){
ev.stopPropagation()
if(ev.target.id== "btn"){
if($('#modal').is(':visible')) {
$('#modal').fadeOut();
} else{
$('#modal').fadeIn();
}
} else {
$('#modal').fadeOut();
}
});
});
html, body {
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn">
Click Me!
</button>
<div id="modal" style="background-color:red;display:none;">
BLA BLA BLA
</div>
To check if the clicked element is outside of a given container, i.e. a menu, we can simply check if the event target is a child of the container. Using JQuery -
$('body').click(function(e) {
if ( 0 === $(e.target).parents('#container-id').length ) {
/// clicked outside -> do action
}
})
you have to add a click listener to the parent element, like here:
$('.parent-div').click(function() {
//Hide the menus if visible
});
Also because click events bubbled up from child to the parent,
you can exclude the click on the child element to get bubbled up and count as the parent click too. you can achieve this like below:
//disable click event on child element
$('.child-div').click(function(event){
event.stopPropagation();
});

Ignored attempt to cancel a touchstart : fastclick warning

I'm having the first popup on which another popup comes to select few fields.
To show the second popup this is the code I'm trying:
$("#select1").click(function(e) {
e.stopPropagation();
//$('#sellerModal').hide();
var tmplData = {
string:['Ready','2-3 Days','4-5 Days','1 Week','10+ Days']
};
$("#countTypePopupTemplate").tmpl(tmplData).appendTo(".maindiv");
that.closePopup();
$("#count_div").each(function() {
$("#count_div").click(function(evt) {
evt.stopPropagation();
$("#select1").text($(this).text());
$("#myCounttype").remove();
});
});
});
Here is the HTML template:
<script id="countTypePopupTemplate" type="text/x-jquery-tmpl">
<div id="myCounttype" class="popup1 layer-2">
<div class="popup5">
{{each string}}
<div id="count_div" class="popup4 bottom-border">${$value}</div>
{{/each}}
</div>
</div>
</script>
I'm getting a warning:
Ignored attempt to cancel a touchstart event with cancelable=false, for example, because scrolling is in progress and cannot be interrupted. fastclick.js
Here I'm not able to click the 4 out of 5 elements in the second popup. Only first 1 is clickable.
Snapshot of second popup.
I read all the blogs where the topic is disscussed. But didn't got any solution working for me. Looks like there is some corner case.
Try using some parent selector before $("#count_div").each(function() {
$("#count_div").click(function(evt) {
Like this $(".parent_class #count_div").each(function() {
$(".parent_class #count_div").click(function(evt) {
This will solve 1 time running each() for "#count_div".
So the actual problem is each() is running only 1 time, that's why your first element that is Ready click event is working, not others.
Your each function is pointing to id which makes you cannot click other buttons. You should use class to recognize the buttons.
$("#select1").click(function(e) {
e.stopPropagation();
//$('#sellerModal').hide();
var tmplData = {
string:['Ready','2-3 Days','4-5 Days','1 Week','10+ Days']
};
$("#countTypePopupTemplate").tmpl(tmplData).appendTo(".maindiv");
that.closePopup();
$(".pop_btns").each(function() {
$(this).click(function(evt) {
evt.stopPropagation();
$("#select1").text($(this).text());
$("#myCounttype").remove();
});
});
});
HTML template:
<script id="countTypePopupTemplate" type="text/x-jquery-tmpl">
<div id="myCounttype" class="popup1 layer-2">
<div class="popup5">
{{each string}}
<div id="count_div" class="popup4 bottom-border pop_btns">${$value}</div>
{{/each}}
</div>
</div>
</script>

jQuery - How to remove class if clicking outside of div or open/close button

I'm fairly new to JS and I can't quite figure out how to get this to work. Any help is very much appreciated! So I have a hamburger button that, when clicked, simultaneously toggles the animation of a slide-in panel and hamburger animation by adding a class to the panel and button. I have successfully added a click event to close the panel if user clicks anywhere outside of the panel but I can't get the hamburger button to remove the added classes as well. I'd like the user to have both options (click button or click outside of panel).
HTML:
<ul class="nav nav--right">
<li class="v-button--slide-right" id="toggle-menu">
<button class="mpp-menu-icon mpp-menu-icon--cross toggle-menu">
<span class="toggle"></span>
<span class="menu">menu</span>
</button>
</li>
</ul>
<nav id="menu--slide-right" class="nav menu--slide-right">
<ul class="main-menu">
<li>Home</li>
<li>About</li>
</ul>
</nav><!-- end slide menu -->
JS:
jQuery(document).ready(function($) {
var openSidebar = function() {
$('.menu--slide-right').addClass('is-active');
$('.toggle-menu').addClass('is-active');
$('#toggle-menu').addClass('toggle-close');
}
var closeSidebar = function() {
$('.menu--slide-right').removeClass('is-active');
$('.toggle-menu').removeClass('is-active');
$('#toggle-menu').removeClass('toggle-close');
}
$('.toggle-menu').click(function(event) {
event.stopPropagation();
openSidebar();
});
$(document).click(function(event) {
if (!$(event.target).closest('.menu--slide-right').length) {
closeSidebar();
}
});
});
And here's a JSFIDDLE to demo what I have so far
Very simple fix - add an "open" variable which changes to true when the sidebar opens, and evaluate this variable in your click event handler.
Add the variable:
var open = false;
Add the variable mutators to your open and close functions:
var openSidebar = function(){
$('.menu--slide-right').addClass('is-active');
$('.toggle-menu').addClass('is-active');
$('#toggle-menu').addClass('toggle-close');
open = true; //This is the new part!
}
Then toggle which function to call on button click - I achieve this with a ternary operator:
$('.toggle-menu').click( function(event) {
event.stopPropagation();
var toggle = open ? closeSidebar : openSidebar;
toggle();
});
Check the fiddle here
A quick and dirty way to fix this is to change your openSideBar function to use jQuery's toggleClass method, i.e.:
var openSidebar = function() {
$('.menu--slide-right').toggleClass('is-active');
$('.toggle-menu').toggleClass('is-active');
$('#toggle-menu').toggleClass('toggle-close');
}
This way when a user clicks on the button, it will toggle the class on/off, and you already have the code to turn it off when they click outside of the button.
Check it out here: https://jsfiddle.net/5ssccz2a/2/
jQuery .toggleClass(): http://api.jquery.com/toggleclass/
The simplest and most robust way would be to check if one of your classes are active on the button. So also no extra variables are needed. I would recommend, deciding on one class to control the others.
$('.toggle-menu').click(function(event) {
if ($('.toggle-menu').hasClass('is-active') {
closeSidebar();
}
else {
openSidebar();
}
event.stopPropagation();
});
Test for .is-active class before deciding whether to run closeSidebar() or openSidebar() when .toggleMenu is clicked.
$('.toggle-menu').click( function(event) {
event.stopPropagation();
if( $(this).is('.is-active') ) {
closeSidebar();
} else {
openSidebar();
}
});
DEMO
Or, using the ternary operator:
$('.toggle-menu').click( function(event) {
event.stopPropagation();
$(this).is('.is-active') ? closeSidebar() : openSidebar();
});
DEMO

I Need to fire an event after stopPropagation has been called

I need to fire an event after stopPropagation has been called.
I am hiding the div on html click and when someone clicks on the notif_noti button I am showing the div which then loads some items with the id #freq.
The problem is #freq will be inside #notification_load which is inside of #notification_box and the stopPropagation is attached to #notif_noti and also #notification_box so basically when you click on these two items it will not fire the event I am trying to fire. e.g you can not .click() on #freq because it will not register because it is inside of #notification_box
Hopefully someone can help me as to how to achieve this. If you do not understand I will try to rewrite this for you.
Thanks
$("#notif_noti, #notification_box").click(function(event){
event.stopPropagation();
});
$("#notif_noti").click(function() {
$("#notification_box").show();
$("#notification_load").html('<div style="width:100%; text-align:center; height: 20px;line-height: 50px;padding-top: 20px;padding-bottom: 20px;color: #999;"><i class="fa fa-circle-o-notch fa-spin" style="font-size:20px;"></i></div>');
});
$("html").click(function() {
$("#notification_box").hide();
});
<div id='notification_box'>
<div id='notification_arrow'></div>
<div id='notification_hd'>
<span id='notification_header' style='padding-left:05px;'></span>
</div>
<div id='notification_load'></div>
</div>
Provide the full code snippet. remaining that once call the event.stopPropagation() method. it can not be resumed so you use the below work around:
var stop = false;
// do your logic here
if(stop){
event.stopPropagation();
}
$(document).mouseup(function (e)
{
var container = $("YOUR CONTAINER SELECTOR");
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
{
container.hide();
}
});
this works. thanks.

How to close a javascript menu

I'm creating pulldown menus that must be clicked on to open. This code lets the user opening menus just fine. The only problem is I haven't figured out how to close the menus yet by clicking outside the menus. I tried adding the "document.onclick" shown, but it takes effect even in the menus.
I think I need to prevent document.onclick from being captured by other elements, but am not sure how to do this cross-platform. Can someone please show me how?
<script type="text/javascript">
var lastOpenedMenuId = null;
function showMenu(menuId) {
if (lastOpenedMenuId != null && lastOpenedMenuId != menuId) {
hideLastOpenedMenu();
}
setMenuVisibility(menuId, 'visible');
lastOpenedMenuId = menuId;
}
function hideMenu(menuId) {
setMenuVisibility(menuId, 'hidden');
}
function hideLastOpenedMenu() {
if (lastOpenedMenuId != null) {
hideMenu(lastOpenedMenuId);
}
}
function setMenuVisibility(menuId, visibleOrHidden) {
var menuElement = document.getElementById(menuId);
menuElement.style.visibility = visibleOrHidden;
}
document.onclick = hideLastOpenedMenu;
</script>
<div onmousedown="showMenu('foodmenu')"><a>FOOD</a></div>
<div id="foodmenu" onmouseup="hideMenu('foodmenu');">
Meat
Tofu
</div>
Thanks in advance.
I have made some progress and have reformulated the question here:
How to stop onclick event in div from propagating to the document?
Depending on whether you have a page layout like this:
<body>
<div id="menu"><!--Menu Stuff--></div>
<div id="main"><!--Main page stuff--></div>
</body>
you could put the onClick handler to close the menu on the div with the id "main" which should work
Someone pointed me to a solution that uses addEventListener. Say, the div is the menu. This code allows the user to click on the document outside the div to do something, such as close the menu. Clicking on the div (say, on a link) will not propagate to the document.
<head>
<script>
function menuHandler(event) {
alert("div clicked");
// Don't propogate the event to the document
if (event.stopPropagation) {
event.stopPropagation(); // W3C model
} else {
event.cancelBubble = true; // IE model
}
}
document.onclick = function() {
alert('document clicked');
};
function addListener() {
var foodMenuElement = document.getElementById('foodmenu');
if (foodMenuElement.addEventListener) {
foodMenuElement.addEventListener('click', menuHandler, false);
} else {
foodMenuElement.attachEvent('onclick', menuHandler);
}
}
</script>
</head>
<body onload="addListener()">
<div id="foodmenu" style="border: 1px solid red;">Click inside this div</div>
or click outside the div.
</body>
Note that the third argument "false" to addEventListener means "fire the event during the capturing phase", but the value doesn't matter because the event propagation is canceled in menuHandler.
This solution works, but I'd like to do the same thing more simply, without addEventListener, so have posted a question at How to stop onclick event in div from propagating to the document?

Categories