MegaMenu doesn't close submenu when open another menu item - javascript

I have a little problem with my MegaMenu, when i open a submenu (clicking on one item of main menu) i want that submenu to vanish when i click anywhere on the document body or if i choose other menu item, the the previous submenu has to close, if i click on that submenu ('ul'), or one particular item on submenu it works like i want (it closes), but if i click on other menu item the previous submenu keeps opened, creating layers of submenus that i have to click on to make them vanish (or click on the main menus item that make them appear) im not sure i am clear,
The function JS im using:
$(".menu > ul > li").click(function(e) {
if ($(window).width() > 943) {
$(this).children('ul').fadeToggle(15);
$(this).children('ul').toggleClass('center');
e.preventDefault();
}
});
so there's a fiddle of my code:
https://codepen.io/anon/pen/JpBrRp

Break, I believe i understood the problem.
First you have to check if the element wich you want to open is already open. If is open you will to close if not you will open.
$(".menu > ul > li").click(function(e) {
if ($(window).width() > 943) {
if ($(this).children('.menu-list').is(":visible")){
$(this).children('.menu-list').fadeToggle(15);
$(this).children('.menu-list').toggleClass('center');
e.preventDefault();
} else {
$('.menu-list').hide();
$('.menu-list').removeClass('center');
$(this).children('.menu-list').fadeToggle(15);
$(this).children('.menu-list').toggleClass('center');
e.preventDefault();
}
}
});
Then you need another function to verify if the user clicked in another place that was not the menu to close the submenu.
$("body").click(function(e) {
var target = e.target;
if (target.className.indexOf("menu-button") == -1 && target.offsetParent.className.indexOf("menu-button") == -1 ) {
$('.menu-list').hide();
$('.menu-list').removeClass('center');
return;
}
});
See if this help you:
https://codepen.io/beduardo/pen/zReyjj
Tip: I recommend avoid use, only tag to refer your elements in js. This can be a problem in the future.

Thank you my friend Bruno Eduardo, i believe you understand Portuguese!! Obrigado amigo!!
There's only one minor bug, it only work if you click on the button, if you click on image it doesn't work, to fix that you need to add menu-button to every tag inside your link.
ex:
<a role="button" class="button button4 **menu-button**"><i class="icon-crm fs1 icon **menu-button**"></i><span class="button-text rowcenter **menu-button**">{{'MenuItem1' | translate}}</span></a>
Thank you friend!

Yes, i understand portuguese =). This approach is good, an other way is improved the function wich verify if the user clicked in another place.
if (target.className.indexOf("menu-button") == -1 && target.offsetParent.className.indexOf("menu-button") == -1 )
Feel free to choose the better to you =)

Related

Jquery. Hide other elements, except this

I‘m using Pollate Template for creating polls. There is a list of user's created Polls, after clicking 3 dots (menu icon), the dropdown list shows up with the option to delete this poll. If the submenu is shown and you click anywhere on the screen it hiding.
But I found a bug, that if you clicking on another sub-menu icon it not hiding other sub-menus (look at the image below).
It should be hidden when clicking anywhere, even if it's a sub-menu icon of another entry.
There is HTML structure:
<div class="pl-options">
<ul class="dropdown"></ul>
</div>
<div class="pl-options">
<ul class="dropdown"></ul>
</div>
After clicking a - dropdown shows up.
There is JQuery:
$.puerto_droped = function( prtclick, prtlist = "ul.dropdown" ){
$(prtclick).livequery('click', function(){
var ul = $(this).parent();
if( ul.find(prtlist).hasClass('open') ){
ul.find(prtlist).removeClass('open');
$(this).removeClass('active');
if(prtclick == ".pl-mobile-menu") $('body').removeClass('active');
} else {
ul.find(prtlist).addClass('open');
$(this).addClass('active');
if(prtclick == ".pl-mobile-menu") $('body').addClass('active');
}
return false;
});
$("html, body").livequery('click', function(){
$(prtclick).parent().find(prtlist).removeClass('open');
$(prtclick).removeClass('active');
if(prtclick == ".pl-mobile-menu") $('body').removeClass('active');
});
}
prtclick -> .pl-user-options
I think that this function $("html, body").livequery('click', function(){... should be edited, but can't achieve it successfully. I've tried in many ways but failed.
One of my tries was:
$(prtclick).click(function(evt){
$(prtclick).find(prtlist).removeClass('open');
$(prtclick).removeClass('active');
if(prtclick == ".pl-mobile-menu") $('body').removeClass('active');
});
But now it not showing sub-menu at all. I need to make an exception for the current entry. Have you any ideas? Thank you.
Before you check for .open class, you can toggle off all other ul.dropdowns.
$(this).closest('.row').siblings('.row').removeClass('active')
.find('ul.dropdown').removeClass('open');
Get current clicked a main parent which has 'row' class,
get its siblings, remove 'active' class of them,
get all ul.dropdowns inside those siblings and remove 'open' class of those uls

jquery toggle won't close on click

I have this code for an accordion style toggle. Works great, only problem is, if you click on an open accordion, it slides up then back down. It doesn't slide closed.
Any thoughts?
Thanks!
//toggles 2
$('body').on('click','.toggle h3 a', function(){
if($(this).parents('.toggles').hasClass('accordion')) return false;
$(this).parents('.toggles').find('.toggle > div').slideUp(300);
$(this).parents('.toggles').find('.toggle h3 a i').attr('class','icon-plus-sign');
$(this).parents('.toggles').find('.toggle').removeClass('open');
$(this).parents('.toggle').find('> div').slideDown(300);
$(this).parents('.toggle').addClass('open');
//switch icon
if( $(this).parents('.toggle').hasClass('open') ){
$(this).find('i').attr('class','icon-minus-sign');
} else {
$(this).find('i').attr('class','icon-plus-sign');
}
return false;
});
<div class="toggles">
<div class="toggle accent-color"><h3><i class="icon-minus-sign"></i>First Accord</h3>
<div>
Content
</div>
</div>
<div class="toggle accent-color"><h3><i class="icon-minus-sign"></i>Second Accord</h3>
<div>
Content
</div>
</div>
It's pretty simple why it does that. Your function always execute slideUp and slideDown. In that order. So when your div is collapsed, it will execute slideUp(which doesn't really make anything because it's already collapsed) and then it will slideDown. Now, when the div is expanded: The div will slideUp (this time it does go Up because it's not collapsed) and then it will go Down.
A better way to do it would be with SlideToggle.
http://api.jquery.com/slidetoggle/
EDIT: Also, you can check if the div is collapsed or not with...
if($(element).is(':visible')){
//expanded
} else {
//collapsed
}
Sorry I didn't really understand what was happening with your code so I rewrote the js part from scratch: http://jsfiddle.net/d503n47r/2/
$('body').on('click','.toggle h3 a', function(e){
e.preventDefault();
if($(this).parents('.toggles').hasClass('accordion')) return false;
if ($(this).parents('.toggle').find('div').eq(0).hasClass('open')) {
$(this).parents('.toggle').find('div').eq(0).removeClass('open').slideUp();
} else {
$('.toggle.open').removeClass('open');
$(this).parents('.toggle').find('div').eq(0).addClass('open').slideDown();
}
});
Please take a look at jquery UI as it helps a lot with all this common things http://jqueryui.com/ (No need to reinvent the wheel)
MinusFour was correct that it was firing both at the same time.
A way to remedy this is to do an if / then statement that checks whether or not it's open, and then fire's the open / close dependent on that.
Here's a link to a JSfiddle
I also added the class "toggle-panel" to the container that was sliding up / down, just so that following would be easier to read.
if($(this).closest('.toggle').hasClass('open')){
console.log('open');
$(this).parents('.toggle').find('.toggle-panel').slideUp(300);
$(this).closest('.toggle').removeClass('open');
return
}
else {
console.log('close');
$(this).parents('.toggles').find('.toggle h3 a i').attr('class','icon-plus-sign');
$(this).parents('.toggle').find('.toggle-panel').slideDown(300);
$(this).parents('.toggle').addClass('open');
}

Javascript not working - 2 different div containers

I am struggling with trying to make a link in a separate div container open a panel in a completely different div container (which if you click on the second div containers link, the panel also opens and the link itself has an active state) - I got the part down where if I click on a link in the first div container, the panel opens up from the second div container, but am struggling with making that first div containers link activate the active state in the second div container...
If you take a look at the demo, simply click on the {Ñا} Members tab, as the other 2 are inactive atm...Once you click on that tab, a panel opens (not the one I am talking about though), now that; that panel is open, look at the very bottom, on the left side in the div container that holds the info title: "Official Roster", there is a link in there that says "rank", if you click on that specific link, the O.F. panel opens up like it should, however, the active state selects them all rather than just the 1 that is selected...I'm getting close, but am seriously stuck and can't seem to figure it out...
Demo: http://jsfiddle.net/Djdzw/2/
I believe it is pure javascript that would be needed, however, it could also be the css as well. I'll provide what code I have atm below, however - I'll only provide the javascript since posting all the code that is required would simply be too much...So, if you could simply take a look at the demo above, it might be easier on the eyes ;)
JAVASCRIPT:
/* ===== The section below is what needs to be edited ===== */
$('.info_box p a').click(function () {
var a = $('#profile_list a');
$('#profile_list a').removeClass('active');
$('#profile_list a').addClass('active');
});
Did you mean this?
$('.info_box p a').click(function () {
var id = this.id; //get the id of the clicked item
var a = $('#profile_list a[href="#' + id +'"]'); //construct the selector to select the menu item which has the same href
$('#profile_list a').not(a.addClass('active')).removeClass('active'); //now do the add/remove class
});
Fiddle
I did this and it worked. I hope it is what you're looking for:
$('.info_box p a').click(function () {
var a = $('#profile_list a');
$('#profile_list a').removeClass('active');
$('#profile_list a.panel[href=' + $(this).attr('href') + ']').addClass('active');
});
jsFiddle

Might I have the wrong idea of hoverIntent

I have a div containing a collection of li to build up a menu.
Outside of the containing ul I have a div that should be displayed only when an item in the original menu is hovered.
Now, I understand the whole mouseout, mouseover effect but what I'm stuck with is to keep the content div active if the mouse is moved over it, but hide (cleared) and then displayed if any of the li elements are selected.
Code (trimmed for legibility)
<div id="menu-ext" class="ext-menu wrapper">
<div class="navigation">
<ul>
<li>
Menu Item 1
</li>
<li>
Menu Item 2
</li>
<li>
Menu Item 3
</li>
<li>
Menu Item 4
</li>
</ul>
</div>
<div class="clear"></div>
<div class="content window" style="display:none;">
this contains text to be displayed, based on a what is hoverd in the navigation above (template driven)
</div>
</div>
The important thing here is not the data that will be displayed in div.content.window but rather how to keep it open if the mouse is moved down after visibility has been set, and then how to hide it if the mouse is moved either outside of div.content.window or over any of the navigational items.
I figured hoverIntent would be able to do this, but the intent (I have) is not initialized.
My code for that:
<script type="text/javascript">
jQuery(document).ready(function ($) {
'use strict';
var config = {
interval: 100,
sensitivity: 1,
out: onHoverOut,
over: onHoverOver
};
$("li", $(".navigation")).hoverIntent(config);
});
function onHoverOver(parent) {
'use strict';
var $currentTarget = $(parent.currentTarget),
$hasTemplate = ($("selector", $currentTarget).length >= 1);
if ($hasTemplate) {
onPopulateMenu(parent);
// show menu
}
}
function onHoverOut(parent) {
'use strict'
onClearMenu();
// TODO: hide the menu
// I think the problem is here?
}
function onClearMenu() {
'use strict';
// TODO: clear the menu of all HTML
}
function onPopulateMenu(parent) {
'use strict';
// TODO: populate the content menu
}
</script>
I'm sure I would be able to keep the one div active, but I cannot seem to identify the solution to this problem. Is this possible?
Update
Apologies for not being very clear.
Basically, when user hovers over menu item, a mega-menu-type navigation should pop-up with additional links that users can click on. My current problem is that the "mega-menu" window is outside of each of the li elements in the original navigation, which is what hoverIntent is looking for.
My question here is, am I missing something? Because as soon as the mouse cursor is moved away from the li towards the menu pop-up, it disappears, which is not the functionality I'm looking for.
Should the menu window be embedded in each li? This does not make sense to me so I thought if I put it outside, it would work.
my fiddling
As stated, I need the window to stay active if the cursor is moved away from the li but I need it to disappear if the state is outside of the window.
I can write some intense JS to figure out the position of the cursor, see if the coordinates correspond with accepted locations and then toggle, but this seems a bit excessive as well?
If I understand you correctly you want something similar to this: Making the content-window appear and show some specific content based on which menu item is being hovered over and disappearing when you stop hovering over a menu item?
jQuery(document).ready(function () {
timeoutId = false;
$('.navigation li').on('mouseover', function () {
//If there is a timeoutId set by a previous mouseout event cancel it so the content-window is not hidden
if (timeoutId != false) {
clearTimeout(timeoutId);
}
$('.content-window').css('display', 'block');
$('.content-window .demo-content').html($(this).html());
});
$('.navigation li, .content-window').on('mouseout', function () {
//start a countdown of 3000 milliseconds before removing the content-window
timeoutId = setTimeout(function () {
$('.content-window').css('display', 'none');
}, 3000);
});
//if cursor moves over to the content-window, stop the timeout from occuring
$('.content-window').on('mouseover', function () {
if (timeoutId != false) {
clearTimeout(timeoutId);
}
});
});
http://jsfiddle.net/UHTAk/
Hope that helps,
R.
Update:
Due to your more specific question update I have amended the code above and updated a jsfiddle as below. What it does now is sets a timeout() timer to remove the content-window after a pre-determined time on a mouseout. This removal is halted if there is another mouseover over an li or the .content-window itself.
http://jsfiddle.net/UHTAk/1/

Collapsible Menu Not Staying Open

Hello ive followed the instructions from this webspage Add a Blogger-like collapsible archive block to your Drupal 7 site and suprised myself that everything seems to be 'sort of' working. As you can see from my 'collapsible block' on the right of THIS PAGE that the block doesnt seem to want to stay open when viewing other months. I dont think this was the intended behaviour.
jQuery(document).ready(function($) {
// init: collapse all groups except for the first one
$(".view-collapsible-archive ul").each(function(i) {
if (i==0) {
$(this).siblings("h3").children(".collapse-icon").text("▼");
} else {
$(this).hide();
}
});
// click event: toggle visibility of group clicked (and update icon)
$(".view-collapsible-archive h3").click(function() {
var icon = $(this).children(".collapse-icon");
$(this).siblings("ul").slideToggle(function() {
(icon.text()=="▼") ? icon.text("►") : icon.text("▼");
});
});
});
Could anyone suggest anything to me to make the menu block open on a month when clicked and to close the other 'months'?
thanks
The problem is that the code you have is already added inside the file http://netmagpie.com/sites/all/themes/feverultra/js/feverultra.js and by adding your file after that, you're binding twice to the event and the function toggles twice, so the elements open and close
If you want to only have one month open then you need to close any open months before opening the one that was clicked, something like:
jQuery(document).ready(function($) {
// init: collapse all groups except for the first one
$(".view-collapsible-archive ul").each(function(i) {
if (i==0) {
$(this).siblings("h3").find(".collapse-icon").text("▼");
} else {
$(this).hide();
}
});
// click event: toggle visibility of group clicked (and update icon)
$(".view-collapsible-archive h3").click(function() {
$('.view-collapsible-archive ul:visible').not($(this).next('ul')).slideUp();
var icon = $(this).find(".collapse-icon");
$(this).siblings("ul").slideToggle(function() {
(icon.text()=="▼") ? icon.text("►") : icon.text("▼");
});
});
});
It's because of this line:
$(this).siblings("ul").slideToggle
It says: "toggle the state of all the ul elements using a slide animation"
You will want to change this to slideDown when it's hidden in order to show it and slideUp when it's visible in order to hide it.
I would provide a code sample but I'm typing with one thumb on an iPhone at the moment.

Categories