Slicknav autoclosing multilevel menus - javascript

I'm working with slicknav for my mobile menu. I came across a cool little way to have the Parent menu close automatically if you click on another Parent menu and I have it working perfectly if I'm using it like below (please note, i do not know javascript. What you see is me hacking some together from other code I've found online):
<ul id="menu">
<li class="first">Parent1
<ul>
<li>Child1</li>
<li>Child2</li>
</ul>
</li>
<li>Parent2
<ul>
<li>Child3</li>
<li>Child4</li>
</ul>
</li>
<li>Parent3
<ul>
<li>Child5</li>
<li>Child6</li>
</ul>
</li>
</ul>
javascript:
<script>
$(function(){
$('#menu').slicknav({
label: 'MENU',
duration: 150,
allowParentLinks: true,
'open': function(trigger){
var that = trigger.parent().children('ul');
$('.slicknav_menu ul li.slicknav_open ul').each(function(){
if($(this).get( 0 ) != that.get( 0 )){
$(this).slideUp().addClass('slicknav_hidden');
$(this).parent().removeClass('slicknav_open').addClass('slicknav_collapsed');
}
})
},
closeOnClick:true
});
});
$("#content").click(function(){
$('#menu').slicknav('close');
});
</script>
I'm needing to make some of the children items have their own dropdowns. Is there a way to make the javascript function with the same idea? If it is unchanged, when you tap/click on any of the children items with their own ul li items, it opens, then immediately closes.
if I remove this:
var that = trigger.parent().children('ul');
$('.slicknav_menu ul li.slicknav_open ul').each(function(){
if($(this).get( 0 ) != that.get( 0 )){
$(this).slideUp().addClass('slicknav_hidden');
$(this).parent().removeClass('slicknav_open').addClass('slicknav_collapsed');
}
})
then the autoclosing stops. Parent and children/parents remain open.
I'd like to be able to tap the children/parent and have it remain open unless you're tapping on another children/parent item. I'm sorry if i'm not making sense. Tired and this is about the best I can do....
As stated at the beginning of this post, javascript is not my language... Any ideas or pointers would be greatly appreciated.

Related

mmenu: sliding menu clears title on sublevels

I am trying to use mmenu for an application and everything is going great, except the menu title.
As for now, the menu has 1 parent-item, 'Menu A', and the menu hierarchy is the following:
Menu A
A1
A1a
A2
A2a
A2b
First level ('Menu A') slides into Second level (new menu with 'A1' and 'A2'). Third level is vertical and is expanded under its parent. More graphical detail comes up next.
First step (sorry, I'm only allowed to post 2 links, so I removed this screenshot): The initial state of the menu is the parent item A, with no title. OK
Second step: When I click the parent, the title changes to 'Menu A' and the children are loaded into the menu. OK
Third step: Lastly, when I click on a child loaded from the previous step, the title disappears, and I have no clue why. NOT OK Any ideas?
Here follows the javascript and HTML code of my menu:
$("#navigation").mmenu(
{ // options
"extensions": [
"border-full",
"multiline",
"iconbar"
],
navbar: {
title: ''
},
navbars: [
{
position : 'top',
content : ['prev','title']
}
],
},
{ // configuration
offCanvas: {
pageSelector: "#wrapper",
wrapPageIfNeeded: false
}
}
);
<nav class="sort-pages modify-pages" id="navigation">
<ul>
<li class="">
<span>
<span>Menu A</span>
</span>
<ul class="child-menu" id="sub-0">
<li class="">
<span>
<span>A1</span>
</span>
<ul class="child-menu mm-vertical" id="sub-sub-1">
<li class="MenuTransactionLink">
<a href="#" link="a1a">
<span>A1a</span>
</a>
</li>
</ul>
</li>
<li class="">
<span>
<span>A2</span>
</span>
<ul class="child-menu mm-vertical" id="sub-sub-2">
<li class="MenuTransactionLink">
<a href="#" link="a2a">
<span>A2a</span>
</a>
</li>
<li class="MenuTransactionLink">
<a href="#" link="a2b">
<span>A2b</span>
</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
I am happy to help with more details, if needed.
Following the developer's Github issue list, i found this in particular:
I think this is because "vertical" panels (all panels when you use slidingSubmenus: false) do not have a navbar. I'll see if I can do something about that.
For now, I guess it's either slidingSubmenus or no title.
(source: github.com/FrDH/jQuery.mmenu/issues/535)
I even tried forcing it using Javascript, by binding an 'on click' event to the menu items:
$('nav a.mm-fullsubopen').on('click', function (e){
var title = $('#navigation').find('.mm-title')[0];
title.text = $('#' + $('.mm-opened.mm-panel.mm-highest').attr('id')).find('.mm-title').text();
$(title).removeClass('mm-hidden')
});
This works for a few miliseconds, until the mmenu plugin overwrites the title with an empty string (see link from third step above). It must have some kind of event that fires after this one, making mine completely useless.
How can I do a workaround to make this behaviour possible?

How to dynamically add a class to li item and change its background color using javascript and css

Here I have a list, what I want to do is I need to change the list ( li ) background color to different one after click on a specific list item. the thing is once it click on the link page will be redirected and refresh. please can me suggest a solution for to get this done?
<div id="main-menu">
<ul id="main-menu-list">
<li id="menu-home">Home</li>
<li id="menu-profile">My Profile</li>
<li id="menu-dashboard">My Dashboard</li>
<li id="menu-search">Search</li>
</ul>
</div>
what i did for this :
Java Script :
var make_button_active = function()
{
//Get item siblings
var siblings =($(this).siblings());
//Remove active class on all buttons
siblings.each(function (index)
{
$(this).removeClass('active');
}
)
//Add the clicked button class
$(this).addClass('active');
}
//Attach events to menu
$(document).ready(
function()
{
$("#main-menu li").click(make_button_active);
}
)
CSS :
#main-menu-list li.active {
background: #0040FF;
}
It's a little difficult to tell exactly what you want to do, but here's some quick and dirty (and untested) code:
/// when we click on an `a` tag inside the `#main-menu-list`...
$('#main-menu-list').on('click', 'a', function(e) {
// stop the link from firing
e.preventDefault();
e.stopPropagation();
// change the list item's background to green
$(this).closest('li').addClass('myClassName').css('background-color', 'green');
// do anything else, e.g. load in pages via ajax...
});
You could use CSS to apply the green background color, instead of jQuery:
.myClassName { background-color: green; }
This will stop the page from navigating, and I don't know if that's your intention. If you want to check the currently-loaded page against the menu to find the current item, you could do this (on page load) instead:
var currentPage = window.location.pathname;
$('#main-menu-list').find('a[href^="' + currentPage + '"]').closest('li').addClass('active');
EDIT:
Your amended Javascript code can be simplified to the following:
$('#main-menu li').on('click', 'a', function (e) {
e.preventDefault();
e.stopPropagation();
// only do the following if the clicked link isn't already active
if(!$(this).closest('li').hasClass('active')) {
$(this).closest('ul').find('.active').removeClass('active');
$(this).closest('li').addClass('active');
// load in your content via ajax, etc.
}
});
JSFiddle example
For each page you can add a class to the current list item that has "where the user is"..
CSS:
.selectedItem{
background-color: orange;//whatever color your want for the selected tab..
}
Then for each of your pages,
say you're in Dashboard.html
your menu code will look like:
<div id="main-menu">
<ul id="main-menu-list">
<li id="menu-home">Home</li>
<li id="menu-profile">My Profile</li>
<li id="menu-dashboard" class="selectedItem">My Dashboard</li>
<li id="menu-search">Search</li>
</ul>
</div>
in profile.html:
<div id="main-menu">
<ul id="main-menu-list">
<li id="menu-home">Home</li>
<li id="menu-profile" class="selectedItem">My Profile</li>
<li id="menu-dashboard">My Dashboard</li>
<li id="menu-search">Search</li>
</ul>
</div>
and so on..
You need to change the background color when the document is loaded (i.e. in document.ready).
Then you need a mechanism to connect the currently loaded page to one of your list items.
$(document).ready(function(){
//get the url from the current location or in some other way that suits your solution
//perhaps use window.location.pathname
var moduleId = "dashboard" // hardcoded to dashboard to make the point :);
$("#menu-"+moduleId).css("background-color", "#ccc");
});
http://jsfiddle.net/9JaVn/1/

jQuery: Delay showing of a dropdown menu content

I have built a dropdown menu that works fine. It goes like this:
Main menu items are in horizontal bar, then
When hover on any item, big dropdown box (with submenu links) is shown.
And here is my code for this:
HTML:
<!-- Based on Bootstrap -->
<div class="navbar navbar-inverse">
<div class="nav-collapse collapse">
<ul class="nav">
<li>First item
<div id="about-horizontal-submenu" class="horizontal-submenu">
<div class="submenu-container span3">
<ul>
<li>Links</li>
<li>Links</li>
</ul>
</div>
<!-- and 4x similar div (to have 12 cols) -->
</div>
</li>
<li>Dropdown
<div id="about-horizontal-submenu" class="horizontal-submenu">
<!-- 3x similar div (like above) and then: -->
<div class="submenu-container span3">
<ul>
<li>I want to go here</li>
<li>Links</li>
</ul>
</div>
</div>
</li>
<!-- And then goes another main menu item... -->
</ul>
</div>
</div>
</div>
JS:
jQuery(document).ready(function($) {
'use strict';
$('.navbar .nav > li').hover(function() {
var $el = $(this);
$el.addClass('hover');
var $submenu = $el.find('.horizontal-submenu');
if ($submenu.is(':hidden')) {
$submenu.slideDown(200);
}
}, function() {
var $el = $(this);
$el.removeClass('hover');
var $submenu = $el.find('.horizontal-submenu');
if ($submenu.is(':visible')) {
$submenu.hide();
}
});
});
Problem
I think I need to add a little delay before both - sliding Down submenu on very first hover and - changing submenu content (when switching/hovering to another menu item).
Why?
When you hover on "Dropdown" and want to choose "I want to move here":
You have to go down from "Dropdown" item and then to the right - which is ok (but not very usable).
Problem is, when you go like the image is showing (from the "Dropdown" straight to the "I want to move here" - you catch "Third item" on your way and immidiatelly see the content that belongs to "Third item". And that's not very good.
If you could show me how to delay/ignore hover on my menu items for very short time, I would be grateful. (I found great example behavior of menu on: http://FEI.com)
Ben Kamens from Khan Academy wrote an article regarding this exact problem, outlining how Amazon.com solved it. It is a great read!
http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown
He also put together a jQuery plugin to solve this problem with a working demo. You can find it on GitHub here:
https://github.com/kamens/jQuery-menu-aim
http://htmlpreview.github.io/?https://github.com/kamens/jQuery-menu-aim/blob/master/example/example.html
$(function($) {
var m;
var timer="";
var wait=200;
active=function(){
$('.navbar .nav > li').mouseover(function() {
m = $(this);
if(timer==""){
test();
unb();
timer = setTimeout(reb,wait);
}
});
}
test = function(){
$(".horizontal-submenu").stop().hide(300);
m.find(".horizontal-submenu").stop().show(300);
};
unb = function(){
$('.navbar .nav > li').unbind('mouseover');
};
reb = function(){
timer="";
active();
};
$(".horizontal-submenu").hide(300);
active();
});
Adjust 'wait' for your best timing; You can just copy and try on your script.
This might be what you are looking for:-
http://cherne.net/brian/resources/jquery.hoverIntent.html
From this you need 2 lines on your web page to activate the hover to working properly
1) Loading script hoverIntent
2) Change from hover to hoverIntent in your jQuery
please try setTimeout. It always does the trick.

jquery conditional logic problems

I need a drop down menu that only disappears, when both drop down menus itself and hovered list item aren't hovered over.
This what I'm already using makes the submenu appears, only when li item is hovered over, but it disappears when the submenu is hovered and I have to fix that.
Javascript:
<script>
$(document).ready(function () {
$("#menu-top li:nth-child(1)").hover(
function () { $('#dropdown_first').slideDown('fast'); },
function () { $('#dropdown_first').slideUp('fast'); } ); });
</script>
HTML:
<div id="menu-top">
<li>first item</li>
<li>second item</li>
<li>third item</li>
</div>
..further down page:
<div id="dropdown_first">
first menu dropdown
</div>
<style>#dropdown_first {display:none'}
I think I need an if statement here to say only to use callback slideup, when mouseout is true for both submenus and li item, but am stuck. Can anybody help me?
If you still want to use JS for the effect ,give the below a try.
I have written it off hand so have not been able to test it but it should resolve the problem you are having (hopefully).
At top:
<style>
#dropdown_first {
display:none;
}
</style>
Javascript:
<script>
$(document).ready(function() {
$("#menu-top li:nth-child(1)").hover(function(){
$('#dropdown_first').slideDown('fast');
});
$("#menu-top").mouseleave(function(){
$('#dropdown_first').slideUp('fast');
});
});
</script>
Hope that helps

jQuery .toggle woes

My 1st question on here so I'll try to be as concise as possible.
I have a series of nav elements, some of which have nav sub-elements. My basic structure is:
<nav role="navigation" class="primary-nav main-nav">
<ul>
<li>home</li>
<li class="about-item">about</li>
<li class="study-item">study</li>
<li class="apply-item">apply</li>
<li>people</li>
<li>shows</li>
<li>contact</li>
</ul>
</nav>
<!-- secondary navs -->
<!-- about -->
<nav role="navigation" class="sec-nav sec-nav-about">
<ul>
<li>history</li>
<li>facility</li>
<li>alumni</li>
<li>friends</li>
<li>patrons</li>
<li>singers</li>
</ul>
</nav>
<!-- study -->
<nav role="navigation" class="sec-nav sec-nav-study">
<ul>
<li>foundation</li>
<li class="study-undergrad-item">undergrad</li>
<li class="study-postgrad-item">postgrad</li>
<li>part time</li>
<li>exams</li>
<li>saturday school</li>
<li>sunday school</li>
<li>summer school</li>
</ul>
</nav>
<!-- apply -->
<nav role="navigation" class="sec-nav sec-nav-apply">
<ul>
<li>loans</li>
<li>auditions</li>
<li>fees</li>
<li>exams</li>
<li>saturday school</li>
<li>sunday school</li>
<li>summer school</li>
</ul>
</nav>
(I know these lists could - and should - be nested but this is code I've inherited rather than written myself and I don't want to screw with anything else that might be in the styles).
So - what I want is when the 3rd, 4th and 5th main-nav items are clicked, their corresponding submenu animates using margin-left.
I'm currently using jQuery .toggle() to try and achieve this effect. Here is my jQuery:
$(document).ready(function(){
$('.main-nav .about-item a').toggle (
function(){
$('.sec-nav-about').animate({marginLeft: "480"}, 500);
},
function(){
$('.sec-nav-about').animate({marginLeft: "-250"}, 500);
});
$('.main-nav .study-item a').toggle (
function(){
$('.sec-nav-study').animate({marginLeft: "480"}, 500);
},
function(){
$('.sec-nav-study').animate({marginLeft: "-250"}, 500);
});
$('.main-nav .apply-item a').toggle (
function(){
$('.sec-nav-apply').animate({marginLeft: "480"}, 500);
},
function(){
$('.sec-nav-apply').animate({marginLeft: "-250"}, 500);
});
});
Up to this point, its fine. However, I cannot get beyond this point. I have no idea how to re-work the code to achieve the following:
1) When each main menu item is clicked, if it has a sub-menu and if its not already showing, then the sub-menu animates out (this is working fine).
2) If a sub-menu is already showing, then when its main menu item is clicked then the sub menu animates back in until its not showing (this is also working).
3) If a sub menu is showing and another sub menu item is clicked, the first sub-menu animates back in until its not showing and the new sub-menu animates out. This not working.
I have attempted to add/remove an .active class to each sub-menu like so (just one here for illustrative purposes but all three sub-menus have this applied to them):
$('.main-nav .about-item a').toggle (
function(){
$('.active').animate({marginLeft: "-250"}, 500).removeClass('active');
$('.sec-nav-about').animate({marginLeft: "480"}, 500).addClass('active');
},
function(){
$('.sec-nav-about').animate({marginLeft: "-250"}, 500).removeClass('active');
});
});
Then what happens is that, it seems to work and then after awhile, it stops removing/adding the .active class. I double checked in Chrome's Element Inspector and can see it (not) happening. I need to click the links twice to get the toggle() to work and drive the animation.
Any ideas/suggestions/solutions would be very gratefully appreciated.
(edited for spelling errors).
Thanks,
Will Moore's answer explains why your current method doesn't work. The following should fix your problem. Using the regex on the className property means that we can apply this to all items in your list without having to set each one up individually.
Also, note that we query the 'sub menus to hide' before adding the .active class to the currently selected sub-menu; this avoids hiding it as soon as we show it.
$('.main-nav li').click(function() {
var itemType = this.className.match(/(^| )([^ ]+)-item( |$)/);
if(itemType != null) {
itemType = itemType[2];
}
$secNavItem = $('.sec-nav-' + itemType);
$subMenusToHide = $('.active');
if(!$secNavItem.hasClass('active')) {
$secNavItem
.addClass('active')
.animate({marginLeft: "480"}, 500);
}
$subMenusToHide
.animate({marginLeft: "-250"}, 500)
.removeClass('active');
});
You can see it working in this fiddle: http://jsfiddle.net/ET475/23/
When you click 'Study' it SHOWS the study submenu.
Then you click the 'About' and it HIDES the study menu (shows the about menu).
Now you click 'Study' again. This is only the second click on the study button, so it's going to do the opposite of the last time you clicked it: ie it's going to HIDE the study submenu when you want it to show the study menu.
This works for me:
$('.main-nav .about-item a').click (function(){
var $submenu = $('.sec-nav-about');
// if the submenu you want isn't showing...
if (!$submenu.hasClass('active')) {
// if any other submenu is showing, hide it...
if ($('.active').length > 0){
$('.active').animate({marginLeft: "-250"}, 500, function(){
// ...show submenu AFTER previous submenu is hidden
$submenu.animate({marginLeft: "480"}, 500).addClass('active');
}).removeClass('active');
} else {
// no submenus showing: simply display
$submenu.animate({marginLeft: "480"}, 500).addClass('active');
}
}
});

Categories