Hiding and showing a subnav when clicked and adding and removing classes - javascript

Think i may be getting a little confused:
I have 2 nav buttons, 1 of which has a subnav. When i click link 1 once this should add an active class to the li if not already active, on the second click you should be able to see the subnav. Link 2 is just a plain button, click it and you add active to the li and reset the Link 1 height.
I have a couple of problems, first off I want to reset the height of Link 1 if I click the Link 1 button when the subnav is visible then show it if clicked again etc. I also want to remove .active from Link 2 when I click Link 2? If someone could explain a much better way of completing this task that would be great, thanks!
My JavaScript:
$(document).ready(function(){
$('#link1').click(function(e) {
if( $(this).parent().hasClass('active') ) {
$(this).parent().css('height', '90');
} else {
$(this).parent().addClass('active');
}
// if i click again i want to reset css height to 45?
});
$('#link2').click(function(e) {
if( !$(this).parent().hasClass('active') ) {
$('#navigation > li').removeClass('active');
$('#link1').parent().css('height', '45');
$(this).parent().addClass('active');
}
});
});
My HTML:
<ul id="navigation">
<li class="active">
Link 1
<ul id="inner">
<li>Link 1</li>
<li>Link 1</li>
<li>Link 1</li>
</ul>
</li>
<li>Link 2</li>
</ul>
Link to jsbin here http://jsbin.com/utuwor/3/edit

you can do this without all the ID's just controlling the sub navigation showing throw CSS: http://jsfiddle.net/J7aVC/1/
jQuery(function($) { // This is a shorten for jQuery.ready and you are sure that $ === jQuery in this scope
$("#navigation li > a").bind("click", function() {
var $this = $(this),
hasActive = !!$this.parent(".active").length;
if ( !hasActive ) {
$this.closest("ul").find(".active").removeClass("active");
$this.parent().andSelf().addClass("active");
}
});
});​
And your CSS:
#navigation li > ul {
display:none;
}
#navigation li.active > ul {
display:block;
}
And this works for lists in lists in lists in...
-> List1
-> List1.1
-> List1.2
-> List1.2.1
-> List 1.2.1.1
-> List1.2.1
-> List1.3
-> List2
etc...
E > E, !!, andSelf(), closest:
E > E means that you search E for it's children E.
In your CSS you have:
#navigation li.active > ul
This means that any ul-tags that are a child of li.active becomes visible.
Take this example:
ul#navigation
-> li.active
-> ul // This is visible
-> li
-> ul // This is not
-> li
-> li
-> ul // This is not
!! turns any String, Object, Integer, etc into a Boolean.
Any falsy value ("", 0, null, undefined, false, NaN) becomes false
andSelf() is a jQuery method that takes your filtered statement and includes it's original selector, It's the same as writing:
$(this).parent().add( this );
$(this).parent().andSelf();
But if you have a long selector it's nice:
$("#very .long .selector.we > .have .to.search").parent().add("#very .long .selector.we > .have .to.search");
$("#very .long .selector.we > .have .to.search").andSelf();
You use closest() to start beginning at the current element and progressing up through the DOM tree.

Related

Activate ':hover' only when mouse moves down list and remove when mouse moves up

So I have to implement a Jquery function in which every li Element is executing the :hover pseudo class (which only changes the background color). So if I hover down to the 4th Element ALL previous li Elements (1st, 2nd, 3th) should have the changed background color from the :hover pseudo class!! But if I move up with the mouse again the :hover effect should disappear (normal background color again) up to the point where my mouse is (if it is on 2nd element only 1st and 2nd have the hover effect now) ... I have absolutely no idea how I can create such a method... I did something like
$('ul li').on('mouseenter') {
$(this).addClass('hover'); //alternatively $(this).css('background-color', 'grey');
}
but it does not remove any :hover effect and it makes failures possible like that only the first and the 5th li Element have the :hover effect but all in between remain normal which I don't want... Could you please help me?
Link to working example on jsfiddle.net
So lets start with some sample markup for a list:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
Then some css for your 'hover':
.hover {
background-color: red;
}
And some javascript to give the functionality:
$(function(){
// Our list items.
var listItems = $('ul').children();
// An event listener over all list items.
$('li').hover(hoverIn, hoverOut);
// Find the index of the current element
// and set all elements up to this element as hover.
function hoverIn() {
var index = listItems.index(this);
$.each(listItems, function(idx, ele) {
if (idx <= index) {
$(this).addClass('hover');
} else {
$(this).removeClass('hover');
}
});
}
// Remove all hover.
function hoverOut() {
$.each(listItems, function(idx, ele) {
$(this).removeClass('hover');
});
}
});
In fact this could be done entirely with css. No jQuery or JavaScript is required for this. You should consider using some html structure like this:
<ul>
<li><span>Menu item 1</span></li>
<li>
<span>Menu item 2</span>
<ul>
<li><span>Submenu item 1</span></li>
<li>
<span>Submenu item 2</span>
<ul>
<li><span>Subsubmenu item 1</span></li>
<li><span>Subsubmenu item 2</span></li>
<li><span>Subsubmenu item 3</span></li>
</ul>
</li>
<li><span>Submenu item 3</span></li>
</ul>
</li>
</ul>
Then you can use css like this
li:hover > span {
background: #9a0000;
}
See this jsfiddle: https://jsfiddle.net/aey5cusm/
Or if you ment by first, second, thirth of a single list, it can be done with css too.
ul {
list-style: none;
margin: 0;
padding: 0;
}
ul:hover li {
background: #9a0000;
}
li:hover ~ li{
background: none;
}
Just look at this jsfiddle: https://jsfiddle.net/aey5cusm/1/

Adding an active class to a ul list in nav

I am trying to add a position indicator to my nav bar using the snippet below (i.e. a border should appear when a list item is selected). I currently have the rest of my css code nested using scss in the form nav{ li{/*code here */} a{/code here/}} and so on. When I add this active tag, nothing happens. Should I be formatting this differently with the active tag? Is there an easier way to do this? Why dosen't the active tag work? Thanks!!
HTML
<nav class="navbar navbar-main">
<ul class="top-menu">
<li id="home">HOME</li>
<li id="about">ABOUT</li>
<li id="info">MEDIA</li>
<li id="social">SOCIAL</li>
</ul>
</nav>
CSS
#nav ul li .active {
border-bottom:3px #FFF solid;
}
JS
$(function() {
var pgurl = window.location.href.substr(window.location.href
.lastIndexOf("/")+1);
$("#nav ul li a").each(function(){
if($(this).attr("href") == pgurl || $(this).attr("href") == '' )
$(this).addClass("active");
})
For starters the css is not targeting the element correctly. Your css is looking for an element with an id of nav, which doesn't exist.
The nav element has two classes (navbar and navbar-main), so you can use either to start off the selection. Because the jquery is adding a class of active to a matching link, the css rule would need to include a. To actually see the border, you'd also need to set a display property. One that is used quite often is block e.g:
.navbar ul li a.active {
display:block;
border-bottom:3px #FFF solid;
}
In the example I've provided below, I've updated the jquery to target a specific link, just for illustration purposes.
$(document).ready(function() {
var pgurl = "#about"; //Using a static value for illustration purposes.
$(".navbar ul li a").each(function(){
if($(this).attr("href") == pgurl || $(this).attr("href") == '' ) {
console.log($(this).attr("href"));
$(this).addClass("active");
}
});
});
Fiddle example
Below code will find all <a> tag whose href attribute contains the current pathname.
$(function () {
$("a[href*='" + location.pathname + "']").addClass("active");
})
This will work for you. That's how I use mine.
$(document).ready(function () {
$(".top-menu > li > a[href*='" + location.pathname + "']").addClass('active'); //the .top-menu is your ul class
});(jQuery);

Problems creating sidebar toggle dropdown menu

I'm working on http://www.variied.com/market/men/. I'm trying to create a toggle dropdown menu on the sidebar that is triggered when someone hits the "Tops" link on the sidebar, which will then toggle the content in the sub-menu to be displayed. Here's my current code
<style>
ul.category ul.sub-menu ul.sub-menu li a{
display:none
}
</style>
<script>
jQuery(document).ready(function() {
jQuery("#menu-item-746").click(function() {
jQuery(this).next("ul.category ul.sub-menu ul.sub-menu li a").toggle();
return false;
});
});
</script>
There are a few issues in this fiddle:
You have a class called #submenu it should just be submenu
You're passing the event so you can use e.preventDefault() (unless you prefer return false)
I would suggest setting the subnav ul to display: none and just toggling that and I would use slideToggle for a nicer effect.
JS
$("#menu-item-746").click(function(e) {
e.preventDefault();
$(this).next("ul").slideToggle();
});
HTML
<ul class="submenu">
<li id="menu-item-746">Test Item</li>
<ul>
<li>Test1</li>
<li>Test2</li>
</ul>
</ul>
CSS
.submenu ul{
display: none;
}
FIDDLE
UPDATE
I looked at your HTML on your site and it appears that your ul subnav is a child of your li not a sibling (it was a sibling in your fiddle). Try this:
$(this).find("ul").slideToggle();
Also from the code you have provided you are targeting an id which means this would only work for that 1 element. It appears the ones with a subnav have a class called .menu-item-has-children so I would target that, like so:
$(".sub-menu .menu-item-has-children").click(function(e) {
e.preventDefault();
$(this).find("ul.sub-menu").slideToggle();
});
NEW UPDATE
Target the a instead then:
$(".sub-menu .menu-item-has-children").on("click", " a:first", function(e) {
e.preventDefault();
$(this).siblings("ul.sub-menu").slideToggle();
});

Add PlusMinus to Accordion Menu

My Accordion Menu has a Counter to count the Submenus. I want to change it to Plus Minus.
If there is a Submenu than "Plus" should be add if is closed, if is opened than a Minus.
If there is no SubMenu than nothing should be added.
The Counter code
$('#cssmenu > ul > li ul').each(function(index, e){
var count = $(e).find('li').length;
var content = '<span class="cnt">' + count + '</span>';
$(e).closest('li').children('a').append(content);
});
jsFiddle Demo
Well you could achieve this by first getting two icons 1. Plus 2. Minus and putting something like this in your css:
#cssmenu > ul > li.has-sub > a span {
background: url(images/icon_plus.png) 90% center no-repeat;
}
#cssmenu > ul > li.has-sub.active > a span {
background: url(images/icon_minus.png) 90% center no-repeat;
}
Here my menu is as follows:
<div id="cssmenu">
<ul>
<li><span>Products</span>
<ul>
<li>Widgets</li>
<li>Menus</li>
<li>Products</li>
</ul>
</li>
</ul>
</div>
Now with jquery check if your menu has a submenu using:
$('#cssmenu > ul > li:has(ul)').addClass("has-sub");
And add the two css classes you made and drop down using jquery. I made a jfiddle as that would be too much to put here.
Here you go Jfiddle - accordian plus minus
Hope this helps! Not all of the code is mine. Cheers!
I would suggest you to use the Accordion Jquery-Ui for that
Jquery-ui

jQuery - Click sub element but hightlight parent?

I have a html code like this:
<ul>
<li class="curent">Home</li>
<li>
Products
<ul class="sub">
<li>Samsung</li>
<li>Lenovo</li>
</ul>
</li>
<li>News</li>
</ul>
http://img38.imageshack.us/img38/5795/70a.png
I want to click any a tag and li tag parent is hightlighted. I try this code but it doesn't work with a tag in ul has sub class:
var this_url = window.location.href;
$('#block_nav_primary ul li').each(function() {
if ($(this).children().attr('href') == this_url) {
$('#block_nav_primary ul').find('li[class="curent"]').removeClass('curent');
$(this).addClass('curent');
}
});
Can anyone point me in the right direction here?
Thanks for your help!
P/S: it looks like this thread Highlight Parent Link in Navigation Menu With Jquery
I'm not sure I quite understand your wording, but you want to apply the same effect to all LI tags, including those in a sublist?
Replace this:
$('#block_nav_primary ul li').each(function() {
With this:
$('#block_nav_primary ul').find('li').each(function() {
Try
val items = $('#block_nav_primary ul li').click(function(){
items.filter('.current').removeClass('current');
$(this).addClass('current')
})
Why don't you try styling it such that the A tag takes the width of the entire LI tag and so when you click A tag, it would highlight the entire thing. The CSS code for it would be something like:
li a {display: block; width: 100%; padding: 10px 0; background-color: pink;}
li a:hover {background-color: orange;}
Try this:
$("ul a").click(function () {
$(this).parent().parent().addClass("blue");
});
or
$("ul a").click(function () {
$(this).closest("ul").addClass("blue");
});
CSS in both cases:
.blue > a {
color: blue;
}
JSFiddle to a quite similar scenario.

Categories