I'm creating something many would call a bookmark bar, but within the website itself. Basically I have a regular Bootstrap navbar with few menu items that have a "thumb-tack" on them. By pressing the thumb-tack, user can pin that menu item for quick access to a sidebar I've created.
Now before this explanation goes way too messy, here is my current code, which is partially working, but on the other hand it is not.
JSFiddle
HTML
<nav id="oa-navbar" class="navbar navbar-default">
<div class="container-fluid">
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active">
<i class="fa fa-area-chart" aria-hidden="true"></i> Dashboard
</li>
<li>
<i class="fa fa-pencil-square-o" aria-hidden="true"></i> Edit content
</li>
<!-- PINNABLE MENU ITEM!! -->
<li class="pinnable">
<i class="fa fa-picture-o" aria-hidden="true"></i> Media
</li>
</ul>
</div>
</div>
</nav>
<!-- The "Quick-Access" navbar -->
<div id="oa-toolbar">
<div class="container-fluid">
<div id="oa-toolbarbtn" class="oa-btn btn btn-default">
<i class="fa fa-bars" aria-hidden="true"></i> Quick-Access
</div>
<div id="oa-toolbar-pinned">
</div>
</div>
</div>
JS
// Adding the "pinicon" to the pinnable link
$.each($("#oa-navbar li"), function () {
if ($(this).hasClass("pinnable")) {
var pinicon = '<a class="pin-it"><i class="fa fa-thumb-tack" aria-hidden="true"></i></a>';
$(this).find("a").append(pinicon);
}
});
// Pinning the link itself
$("#oa-navbar li .pin-it").click(function () {
var pinMenu = $("#oa-toolbar-pinned");
var nl_content = $(this).parent().html();
var nl = $("<li class='pinnedItem'>"+ nl_content +"</li>");
$(pinMenu).removeClass("active");
if (!$(this).parent().hasClass("pinned")){
$(nl).appendTo(pinMenu);
$(pinMenu).addClass("active");
}
$(this).parent().toggleClass("pinned");
});
The way it works now is that it does add the menu item to the quick-access menu, but it does not take the <a> tags, just what's inside of them.
The other issue is that when I press the thumb-tack on the navigation bar again, it does not remove the pinned item from the quick-access menu. There's got to be an easy way to do this, but I've taken the long road it seems.
Any advice will be more than welcome!
Try this example, actually you were close, I have just reversed your code
$("#oa-toolbar-pinned").on('click','.pinnedItem',function () {
var navBar = $("#oa-navbar ul li"); // find navbar
var content = $(this).find("a").html();
var appendCont = "<li class='pinnable'> <a class='pin-it' href='#'>" + content + "</a></li>"; // take content and surround with li
$(appendCont).appendTo(navBar.parent()); // append to navbar
$(this).remove(); // remove from pinned list
});
Edit 1:
Changed click event to delegate, because there was a problem that newly appended a tags don't fire click event, solved with this,
$(document).on('click', '#oa-navbar li .pin-it' ,function() {}
Hope helps,
Related
I have the basis of my menu working, where when I click a menu element, it opens (similar to JQuery accordion), and when I click on another element in the menu, the previously opened menu closes and the newly clicked on opens. Here's what it looks like:
Now, I'm trying to implement functionality to close the currently opened menu if it is clicked again. I'm using the slideUp(); method, but having a hard time figuring out where to put the additional code for the 2nd click on the same element.
Here's what I have:
navigation.html.erb
<!-- menu links -->
<div id="sidebar-menu" class="main_menu_side hidden-print main_menu">
<div class="menu_section">
<h3>General</h3>
<ul class="nav side-menu">
<li><a><i class="fa fa-home"></i> Home <span class="fa fa-chevron-down"></span></a>
<ul class="nav child_menu" style="display: none">
<li>Dashboard
</li>
</ul>
</li>
<li><a><i class="fa fa-edit"></i> Forms <span class="fa fa-chevron-down"></span></a>
<ul class="nav child_menu" style="display: none">
<li>General Elements
</li>
</ul>
</li>
<li><a><i class="fa fa-bar-chart-o"></i> Data Presentation <span class="fa fa-chevron-down"></span></a>
<ul class="nav child_menu" style="display: none">
<li>Chart JS
</li>
</ul>
</li>
</ul>
</div>
</div>
custom.js
var URL = window.location,
$BODY = $('body'),
$MENU_TOGGLE = $('#menu_toggle'),
$SIDEBAR_MENU = $('#sidebar-menu'),
$SIDEBAR_FOOTER = $('.sidebar-footer'),
$LEFT_COL = $('.left_col'),
$RIGHT_COL = $('.right_col'),
$NAV_MENU = $('.nav_menu'),
$FOOTER = $('footer');
var setContentHeight = function () {
// reset height
$RIGHT_COL.css('min-height', $(window).height());
var bodyHeight = $BODY.height(),
leftColHeight = $LEFT_COL.eq(1).height() + $SIDEBAR_FOOTER.height(),
contentHeight = bodyHeight < leftColHeight ? leftColHeight : bodyHeight;
// normalize content
contentHeight -= $NAV_MENU.height() + $FOOTER.height();
$RIGHT_COL.css('min-height', contentHeight);
};
$SIDEBAR_MENU.find('a').on('click', function(ev) {
var $li = $(this).parent();
if ($li.hasClass('.active')) {
$li.removeClass('active');
$('ul:first', $li).slideUp(function(){
setContentHeight();
});
} else {
$li.addClass('active');
$SIDEBAR_MENU.find('.side-menu li').not($li).removeClass('active');
$SIDEBAR_MENU.find('.side-menu li').not($li).find('.child_menu').removeClass('active').slideUp();
$('ul:first', $li).slideDown(function(){
setContentHeight();
});
}
});
Change if ($li.hasClass('.active')) to if ($li.hasClass('active')) and that should resolve the issue. Check this fiddle. I have created an empty setContentHeight function to make it work.
I've got a hidden div that successfully slides out on click. However the content inside that div is dependent on which link is clicked and I'm trying to get it to show/hide depending on which link is clicked.
JS Fiddle Here.
All help is greatly appreciated
HTML
<div id="main-nav">
<ul class="list-unstyled">
<li class="sub director-sub">Directors</li>
<li>News</li>
<li class="sub contact-sub">Contact</li>
<li>
<ul class="list-inline social">
<li class="fb"><i class="fa fa-facebook" aria-hidden="true"></i></li>
<li><i class="fa fa-twitter" aria-hidden="true"></i></li>
<li><i class="fa fa-envelope-o" aria-hidden="true"></i></li>
</ul><!-- /.list-inline social -->
</li>
<li class="sparks">
lorem ipsum
</li>
</ul><!-- /.list-unstyled -->
</div><!-- /#main-nav -->
<div id="sub-nav">
<div class="sub-content">
<!--begin directors-->
<div class="directors-subnav">
<h2 style="background:orange;">Directors Sub Nav</h2>
<ul class="list-unstyled">
<li>Lorem ipsum.</li>
<li>Atque, neque.</li>
<li>Omnis, inventore!</li>
<li>Fugit, atque.</li>
<li>Nisi, temporibus.</li>
</ul><!-- /.list-unstyled -->
</div><!-- /.directors-subnav -->
<!--end directors-->
<!--begin Contact-->
<div class="contact-subnav">
<h2 style="background:green;">Contact Sub Nav</h2>
<ul class="list-unstyled">
<li>Lorem ipsum.</li>
<li>Atque, neque.</li>
<li>Omnis, inventore!</li>
<li>Fugit, atque.</li>
<li>Nisi, temporibus.</li>
</ul><!-- /.list-unstyled -->
</div><!-- /.directors-subnav -->
<!--end directors-->
</div><!-- /.sub-content -->
</div><!-- /#subnav -->
JS Here:
$(document).ready(function(){
//get nav container width
var boxWidth = $('#sub-nav').width();
// hide subnav
$('#sub-nav').width(0);
$('.directors-subnav, .contact-subnav').hide();
//set nav width to zero
$('#main-nav li.sub a').click(function(e){
// remove opened class from other links not clicked
$("#main-nav li.sub a").not(this).removeClass('opened');
e.preventDefault();
if($(this).hasClass('opened')){
// slide the box closed
$("#sub-nav").animate({
width: '0' + 'px'
});
} else {
$("#sub-nav").animate({
width: boxWidth + 'px'
});
}
// toggle class so we can animate box based on class
$(this).toggleClass('opened');
/****** show/hide of page specific content******/
if($(this).parent().hasClass('.director-sub')){
// show/hide directors subnav
$('.directors-subnav').toggle();
$console.log('directors clicked');
} else if($(this).parent().hasClass('.contact-sub')) {
// show/hide contaxct sub nav
$('.contact-subnav').toggle();
$console.log('contact clicked');
}
/****** end show/hide of page specific content******/
})
})
You don't need dot in hasClass in lines 34 and 40. It's supposed to be hasClass('director-sub') not hasClass('.director-sub')
This is what you need.
couple of things needed changing.
In both the hasClass function arguments, the class name can not be preceded by a ".".
In the console.log statement, you cant have a $ preceding console.
There was an error in the html as well. in one location (line 14) you need to have target="blank" and not target="blank".
These changes makes the above piece of code work in the fiddle.
Thanks
Paras
/****** show/hide of page specific content******/
if($(this).parent().hasClass('director-sub')){
// show/hide directors subnav
$('.directors-subnav').toggle();
console.log('directors clicked');
} else if($(this).parent().hasClass('contact-sub')) {
// show/hide contaxct sub nav
$('.contact-subnav').toggle();
console.log('contact clicked');
}
/****** end show/hide of page specific content******/
just change it to hasClass('className') from hasClass('.className')
Not sure I've formulated my question well, hope the details will cover the issues.
So, I'm building an "artificial" full-height slide-like submenu, and I have an empty container there:
<section class="masking_sublevel">
</section>
Further, I have a bunch of ul elements in my HTML that are hidden by default in their containing section:
I'm updating the HTML part with a more complete piece:
<div id="sldbr_overlay" class="newully">
<section class="masking_sublevel">
</section>
<ul class="sidebar_bumenu">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
Beauty <i class="fa fa-chevron-right bu_chevright"></i>
<i class="fa fa-chevron-down bu_chevdown"></i>
</a>
<section class="hidden_ul">
<ul>
<li>Aerobics</li>
<li>Pilates</li>
<li>Yoga</li>
<li>Massage</li>
<li>Peeling</li>
<li>Bikini Area Sugaring</li>
<li>Piercing</li>
<li>Tattoo</li>
<li>Shaping</li>
<li>Sauna</li>
<li>Mud SPA</li>
<li>Needle Therapy</li>
<li>Shaping</li>
<li>Leech Therapy</li>
<li>Thai Massage</li>
<li>Wushu</li>
</ul>
</section>
</li>
<li>Clothing</li>
<li>Computers</li>
<li>Construction</li>
<li>Entertainment</li>
<li>Financial</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
Food <i class="fa fa-chevron-right bu_chevright"></i>
<i class="fa fa-chevron-down bu_chevdown"></i>
</a>
<ul class="hidden_ul">
<li>Pizza</li>
<li>Cheboorackee</li>
<li>Khash</li>
<li>Pork</li>
<li>Hamburgers</li>
<li>Greek Salad</li>
<li>BBQ</li>
<li>Tortillas</li>
<li>Spaghetti</li>
<li>Pasta</li>
<li>Ice Cream</li>
<li>Jelly Sugar</li>
<li>Lolly Pop</li>
<li>Cupcakes</li>
</ul>
</li>
<li>Health</li>
<li>Kids</li>
<li>Services</li>
<li>Travel</li>
<li>Tourism</li>
</ul>
<div class="pzik">
<a href="javascript:void(0);" data-toggle=".sidebar_wrapper" id="sidebar-toggle_abs">
<img src="svg/filter.svg" class="filter_icon hvr-wobble-bottom">
</a>
<a href="javascript:void(0);" id="go-2-top" class="gotop_chevron">
<i class="fa fa-chevron-up"></i>
</a>
</div>
</div>
So, what I'm doing is selecting the above mentioned ul and put it within the empty section on a hover event and emptying it on a mouseleave, like this:
$(document).ready(function(){
var dropdownLi = $('li.dropdown');
var maskingSubLvl = $('.masking_sublevel');
var importedUl = $('.masking_sublevel ul');
var hiddenUl = $('.hidden_ul ul');
$(dropdownLi).on('mouseover',function(){
$(hiddenUl).appendTo(maskingSubLvl);
$(maskingSubLvl).css('display','block');
});
$(dropdownLi).on('mouseleave',function(){
$(maskingSubLvl).css('display','none');
$(importedUl).empty();
$(maskingSubLvl).on('mouseenter',function(){
$(this).css('display', 'block');
});
});
});
The problem is that with this piece of code I probably select just the first ul with the class of .hidden_ul', since as I hover on the other items (randomly), it keeps on loading the content of the first list. How can I select the VERY ul element with the same class that I'm currently hovering?
Thanks!
So you want to traverse from the element that has mouseover to the parent ul, which is a child of the grand-parent .hidden_ul
// remove this, it has no context to each drop down
// var hiddenUl = $('.hidden_ul ul');
$(dropdownLi).on('mouseover',function(){
$(this).closest('.hidden_ul').children('ul').appendTo(maskingSubLvl);
// though if there are no child uls in your lis, this will do
$(this).closest('ul').appendTo(maskingSubLvl);
Since your hidden_ul is direct child of .dropdown you need to get it using its parent context as below:
$(dropdownLi).on('mouseover',function(){
var hiddenUl=$(this).find('.hidden_ul')[0];//find the child
$(hiddenUl).appendTo(maskingSubLvl);
$(maskingSubLvl).css('display','block');
});
Update
Instead of appendTo try keeping changing the html of .maskingSubLvl so that no need to remove the content again before appending another. For Ex:
DEMO
$(document).ready(function(){
var dropdownLi = $('li.dropdown');
var maskingSubLvl = $('.masking_sublevel');
var importedUl = $('.masking_sublevel ul');
$(dropdownLi).on('mouseover',function(){
$(maskingSubLvl).css('display','block');
var hiddenUl = $(this).find('.hidden_ul ul').clone(); //clone the content
$(maskingSubLvl).html(hiddenUl);
});
$(dropdownLi).on('mouseleave',function(){
$(maskingSubLvl).css('display','none');
});
$(maskingSubLvl).on('mouseenter',function(){
$(this).css('display', 'block');
});
});
My bootstrap menu is as follows (this is the code snippet for one menu-item out of many):
<!-- Code for Navigable menu (mobile) -->
<nav class="navbar navbar-default" role="navigation">
<div class="container commonWidth">
<button type="button" style="width: 100%" class="navbar-toggle" data-toggle="collapse" data-target="#led-collapse">
LED & Lighting <b class="caret"></b>
</button>
<!-- Collect the nav links for toggling -->
<div class="collapse navbar-collapse hidden-sm" id="led-collapse">
<ul class="nav navbar-nav">
<li class="dropdown visible-xs">
LED Lights<b class="caret visible-xs"></b>
<ul class="dropdown-menu">
<li>LED Lamps & Tubes</li>
<li>Downlights, Spotlights & COB</li>
<li>LED Panels</li>
<li>LED Surface</li>
<li>Commercial & Industrial</li>
<li>LED GU10 Fittings</li>
<li>LED Strips</li>
</ul>
</li>
<li class="dropdown visible-xs">
Luminaires (Fittings)<b class="caret visible-xs"></b>
<ul class="dropdown-menu">
<li>Domestic Tube Fittings</li>
<li>Floodlights</li>
</ul>
</li>
</div> <!-- End LED Menu -->
</div> <!-- End commonWidth -->
</nav>
The issue is that immediately after clicking a 3rd level link (.dropdown-menu > li > a), entire 2nd level menu (li class="dropdown visible-xs") collapses. However, I want this to stay open after the 3rd level link is clicked.
Here is the fiddle: http://jsfiddle.net/dk49/ugzwmhm6/
Any Suggestions?
Thanks.
Once the economy link is clicked the click event is getting propagated to its parent, from there it goes to the next parent and so on . when it reaches the third parent, the third parent element is reacting to it by toggling the open class. So if you stop the propagation it will stay as it is.
Try the code below.
$('.dropdown-menu a').click(function(e){
e.stopPropagation();
})
This code will stop the propagation of the anchor tag to its parent
In case if you want to prevent the default click action use
$('.dropdown-menu a').click(function(e){
if($(this).attr('href') == "#" || $(this).attr('href') == "") // New code
e.preventDefault();
e.stopPropagation();
})
Update
I have updated the code to prevent scrolling if the URL is # or if there is no URL. this should serve the purpose
I have the following bootstrap html menu:
<ul class="nav navbar-top-links navbar-right">
<li class="dropdown menustatus">
<a class="dropdown-toggle" href="#">
<div class="busy-status"></div>
<div class="online-status" style="display:none;"></div>
</a>
<ul class="dropdown-menu dropdown-user" style="margin-top: 10px;">
<li class="status">
<i class="fa fa-circle online"></i> Online
</li>
<li class="status">
<i class="fa fa-circle busy"></i> Busy
</li>
</ul>
</li>
</ul>
I'm trying to hide the menu when the user click on any item, like this:
$("#online-status").click(function (){
$(".busy-status").hide();
$(".online-status").show();
$("li.dropdown.menustatus.open").removeClass("open");
});
$("#busy-status").click(function (){
$(".online-status").hide();
$(".busy-status").show();
$("li.dropdown.menustatus.open").removeClass("open");
});
But it does not work.
I also tried:
$(".dropdown.menustatus.open").removeClass("open");
or
$("dropdown.menustatus").removeClass("open");
or
$(".menustatus").removeClass("open");
or
$(".open").removeClass("open");
But I couldn't hide the menu.
What I'm doing wrong.
Thanks for your help
#online-status is an anchor.
Try:
$("#online-status").click(function(e){
e.preventDefault();
....
});
Check how you did it with the other elements in the click events: You can in a similar way use .hide() and .show(), or even .toggle() if needed.
$(".menustatus").hide();
How specific the selector needs to be is up to you to decide / find out.
If you absolutely want to do it the "class way", my guess is that your ".open" class sets the visibility or display properties to visible/block or something similar to show the element, but your ".menustatus" does not seem to hide it. What I mean is: if you remove the .open class from the element, there is nothing that specifies whether it should be hidden or not. Try this:
.menustatus {
display: none;
}
.menustatus.open {
display: block; // Add !important if needed.
}
Change "block" to whatever you want, as long as it's not none.