Please see this fiddle
If you hover your mouse exactly on the link, a different link appears. But different text is also appearing when you hover on left or right of the link. I want to make the hover effect only when it is being hovered on the exact link.
How can I do this?
My HTML code:
<ul id="nav">
<li id="a1">original link 1</li>
<li id="a2" class="hack">hover link 1</li>
<li id="b1">original link 2</li>
<li id="b2" class="hack">hover link 2</li>
<li id="c1">original link 3</li>
<li id="c2" class="hack">hover link 3</li>
</ul>
My Javascript code:
$('.hack').hide();
$("#nav li").mouseenter(function() {
$('#' +this.id.charAt(0)+"2").show();
$('#' +this.id.charAt(0)+"1").hide();
}).mouseleave(function() {
$('#' +this.id.charAt(0)+"1").show();
$('#' +this.id.charAt(0)+"2").hide();
});
Please see the fiddle to see the effect I'm referring to.
Instead of using mouseenter event shortcut it would be better if you use event delegation and add event on "a" element like this...
$("#nav li").on({
"mouseenter" : function() { },
"mouseleave" : function() { }
}, "a");
Try the following:
$('.hack').hide();
$("#nav li a").mouseenter(function() {
$('#' +this.parentNode.id.charAt(0)+"2").show();
$('#' +this.parentNode.id.charAt(0)+"1").hide();
}).mouseleave(function() {
$('#' +this.parentNode.id.charAt(0)+"1").show();
$('#' +this.parentNode.id.charAt(0)+"2").hide();
});
You want to initiate the hover events on the a tags rather than the lis themselves.
EXAMPLE
I guess i updated the fiddle. I just added this style:
#nav li {
display: inline-block;
}
In your js, bind your function to "#nav li a" instead.
Related
I have searched a lot for adding active class to the parent menu using javascript.
I found many more examples but not a single one is working for me, below is my code
HTML
<div id="menu1" class="hmenu">
<ul>
<li>Item1
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
<li>SubItem2 </li>
<li>SubItem3
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
<li>Item2</li>
<li>Item3
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
</ul>
<br style="clear: left" />
</div>
My requirement is when i click on SubItem1 then both Item1 and SubItem1 should be active.
And when i click on SubSubItem1 then SubSubItem1 ,SubItem1 and Item1 should be active.
Means when click on any link then its all parent link and the same link should be active.
I have tried with this javascript code :
$(document).ready(function () {
$('.hmenu ul li ul').find('li').click(function () {
//removing the previous selected menu state
$('.hmenu').find('li.active').removeClass('active');
//adding the state for this parent menu
$(this).parents('li').addClass('active');
});
});
Actually i don't have any experience with javascript coding and unable to figure out the problem in my code.
Can anyone suggest me for the same.
The issue comes from .find('li').click().
As you use nestsed <li>, this will cause the event to be fired two times when you click on a child <li>. This causes problems. Can not you add the click() to <a> elements?
$(document).ready(function () {
$('.hmenu a').click(function () {
//removing the previous selected menu state
$('.hmenu').find('li.active').removeClass('active');
//adding the state for this parent menu
$(this).parents("li").addClass('active');
});
});
It works just fine: https://jsfiddle.net/6put8tdx/
Note that your page will be bumped to the top while clicking to a tab because of # anchor. If you want to prevent this, you may pass the event to the function .click(function (event) {...} and add event.preventDefault inside.
If you need the click target to be the LI element (as opposed to Delgan's answer)
you can use .not() over the targeted LI's parents to prevent messing with the bubbling event targets:
$(document).ready(function () {
$('.hmenu').find('li').click(function(event) {
event.preventDefault(); // Prevent page jumps due to anchors
var $par = $(event.target).parents("li"); // get list of parents
$(".hmenu .active").not( $par ).removeClass("active"); // not them
$(this).addClass('active'); // let the event propagation do the work
});
});
$(document).ready(function () {
$('.hmenu').find('li').click(function(event) {
event.preventDefault();
var $par = $(event.target).parents("li");
$(".hmenu .active").not($par).removeClass("active");
$(this).addClass('active');
});
});
.active > a{
background: gold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu1" class="hmenu">
<ul>
<li>Item1
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
<li>SubItem2 </li>
<li>SubItem3
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
<li>Item2</li>
<li>Item3
<ul>
<li>SubItem1
<ul>
<li>SubSubItem1</li>
<li>SubSubItem2</li>
</ul>
</li>
</ul>
</li>
</ul>
<br style="clear: left" />
</div>
To better understand the above
The following example works out-of-the-box, and the clicked one and all it's LI parents get the "active" class.
Why? Cause the event target is li, means any li of .hmenu - so that click is attached to any of them, and clicking the subsub LI the event will propagate to the LI parents - triggering the same click behavior (this add class)!
$(".hmenu").on("click", "li", function(){
$(this).addClass("active"); // Wow! Event propagation rulez!!
});
But we need to remove existing .active and here it gets messy...
$(".hmenu").on("click", "li", function(){
$(".active").removeClass("active"); // triggered on every event bubble :(
$(this).addClass("active"); // leaving only the main parent with active class
});
That's caused by the concurrency that happens while the event bubbles and triggers the same actions for the parent elements.
One way to prevent that concurrency would be using a setTimeout of 1ms:
$(".hmenu").on("click", "li", function(){
$(".active").removeClass("active");
setTimeout(function(){ // Let the previous finish the bubbling mess
$(this).addClass("active"); // Yey! all fine! Every LI has the active class
}, 1);
});
But here the timeout of 1ms can lead to visual "blinking" issues.
Try this:
$(function () {
$("li a")
.on("click", function () {
$(this).toggleClass("active");
$(this).closest("ul").parent().children("li a").toggleClass("active")
.parent().parent().parent().children("li a").toggleClass("active");
});
});
fiddle
Traverse from the clicked element. And use toggleClass() to avoid the mundane checking if hasclass removeClass ...
I have a submenu like below:
<ul id="main-menu" class="" style="">
<li class="root-level has-sub">
Menu 1
<ul>
<li>Sub-menu 1</li>
<li>Sub-menu 2</li>
</ul>
</li>
<li>Menu 2</li>
<li class="root-level has-sub"> <!-- here -->
Menu 3
<ul>
<li class="root-level has-sub"> <!-- add class 'opened' here and -->
Sub-menu 3
<ul>
<li>Sub-sub-Menu 1</li> <!-- this -->
<li>Sub-sub-Menu 2</li> <!-- when user click this or -->
</ul>
</li>
</ul>
</li>
What I would like to have is, when I click to the child, it will add 'opened' class to parent and highlight the clicked element. My code only success on Menu 1 and failed on Menu 3.
Notice that, in Menu 3, there are 2 parents for Sub-sub-Menu 1 and Sub-sub-Menu 2. So my question is, if i click on Sub-sub-Menu 1 or Sub-sub-Menu 2 it will highlight and add 'opened' class to 2 parents li above.
Note: I try to implement unlimited level of menu
Here is my full code Fiddle
I think you should use a different selector(for the click event). Look for all li>a pairs, corresponding to the submenu items, inside your #main-menu list
$('#main-menu li>a').click(function (e) {
e.preventDefault();
$('.active').removeClass('active');
$('.opened').removeClass('opened');
$(this).parent('li').addClass('active').parents('.root-level').addClass('opened');
//------------------------------------------------------^-----------------------------
// selects all parents with the 'root-level' class
});
Modifying the css to:
#main-menu .active {
background-color:#df0000;
color:#fff;
}
DEMO
you simply use the not: attribute in your closest() method to exclude all classes root-level
$(function () {
$('ul#main-menu li ul li').click(function (e) {
e.preventDefault();
//we search for the first ancestor of this which is a li
$(this).closest('li:not(".root-level")').addClass('active').siblings().removeClass('active');
$('.active:first').closest('ul').addClass('opened');
});
});
check the link http://jsfiddle.net/GEj4z/11/
If I understood correctly what was desired was being able to produce a menu like behavior and it is because of that I would like to present an alternate solution:
Sample Fiddle
$('#main-menu').on('click','li:not(.root-level)',function(e){
$('.parent').removeClass('parent');
$('.selected').removeClass('selected');
$(this).parents('li.root-level').children('a').addClass('parent');
$(this).children('a').addClass('selected');
});
In this solution the parent menus are highlighted and the clicked item is marked as selected again I wanted to share my POV of this problem. I hope it helps.
Inside your click event use $(this).parents('li') to get the top level parent li of the clicked element. I hope this helps.
I found the solution! my jquery is:
$(function () {
$('ul#main-menu li ul li').click(function (e) {
e.preventDefault();
$(this).closest('li:not(".root-level")').addClass('active').siblings().removeClass('active');
$(this).parents('li').addClass('opened');
$(this).closest('li:has(".root-level")').removeClass('active');
});
});
Here is my full code JSFiddle
I plan to apply a custom show/hide effect on link, such that when a user hovers on a link, a different link appears in its place. I'm not so good in javascript and here is what I was trying:
<div id="nav">
<li id="a1">hover link 1</li>
<li id="a2">show link 1</li>
<li id="b1">hover link 2</li>
<li id="b2">show link 2</li>
<li id="c1">hover link 3</li>
<li id="c2">show link 3</li>
</div>
The javascript:
$("#nav a.li").hover(function () {
(this.id.charAt(0)+"1").hide();
});
Here is the fiddle
You missed $ and need to add # befor id your also need to change selector as you do not have anchor with class li
Change
(this.id.charAt(0)+"1").hide();
to
$('#' +this.id.charAt(0)+"1").hide();
Your code would be
Live Demo
$("#nav a li").hover(function () {
$('#'+ this.id.charAt(0)+"1").hide();
});
Edit If you want to remove the item being hovered then use $(this)
Live Demo
$("#nav a li").hover(function () {
$(this).hide();
});
I'm trying to figure out a function that will allow me to hide divs and show them if referring link is clicked.
Hard to explain but here is what I am looking for:
<ul>
<li>Link 1</li>
<li class="active">Link 1</li>
<li>Link 1</li>
<ul>
<div id="id-1">Some content</div> // Hidden
<div id="id-2">Some content</div> // This should only show in document
<div id="id-3">Some content</div> // hidden
Whenever other anchor is being clicked other divs should hide.
I hope his make sense and thank you for your help in advance
Dom
You can use something like this (untested so may need tweaking):
$(document).ready(function() { //fires on dom ready
$("a").click(function(e) { //assign click handler to all <a> tags
$(".classForYourDivs").hide(); //hide all divs (put class on ones you want to hide)
var element = $(e.target);
var href = element.attr("href"); //get the attribute
$(href).show(); //show the relevent one
return false; //important to stop default click behavior of link
});
});
Incidentally you should consider using something other than the href to store this information... take a look at the docs for the jquery data() function
Add a class to the ul and the divs.
<ul class="myUL">
<li>Link 1</li>
<li class="active">Link 1</li>
<li>Link 1</li>
<ul>
<div id="id-1" class="myDivs">Some content</div> // Hidden
<div id="id-2" class="myDivs">Some content</div> // This should only show in document
<div id="id-3" class="myDivs">Some content</div> // hidden
then in CSS,
.myDivs { display: none; }
and Try below js code,
var $myDivs = $('.myDivs');
$('.myUL a').on('click', function () {
$myDivs.hide();
$($(this).attr('href')).show();
});
DEMO: http://jsfiddle.net/LYKVG/
$("body").on("click","a", function(){
var divtoshowselector = $(this).attr("href");
$(divtoshowselector).show().siblings().hide();
})
http://jsfiddle.net/
html
<ul>
<li>Link 1</li>
<li class="active">Link 2</li>
<li>Link 3</li>
<ul>
<div id="id-1">Some content 1</div>
<div id="id-2">Some content 2</div>
<div id="id-3">Some content 3</div>
css
div {display: none;}
javascript/jquery
$("a").click( function(e) {
e.preventDefault();
var elId = $(this).attr('href');
$('div').hide();
$(elId).show();
});
I've set up a fiddle for you, check out: http://jsfiddle.net/UsGag/
function currentActive()
{
return $("li.active a").attr("href");
}
$("div:not(" + currentActive() + ")").hide();
$("li a").on("click", function()
{
//hide old active div
$("div" + currentActive()).hide();
$("li").removeClass("active");
//activate new div
$(this).parent().addClass("active");
$("div" + currentActive()).show();
});
Hope this helps you, extend to your own needs. And just for completeness: Don't use the - in ids / classnames.
Try
$("a").click( function( ) {
var elId = $(this).attr("href");
$(elId).show().siblings("div[id^=id-]").hide();
});
Fiddle here
Could some one please help with code.
I want to show the submenu only when submenu parent is clicked.
HTML
<ul>
<li>Item</li>
<li>Item
<ul class="sub-menu">
<li>Submenu</li>
<li>Submenu</li>
</ul>
</li>
<li>Item</li>
<li>Item
<ul class="sub-menu">
<li>Submenu</li>
<li>Submenu</li>
</ul>
</li>
<li>Item</li>
</ul>
So if you click on the parent submenu will show.
Here is fiddle link - http://jsfiddle.net/KhNCV/1/
$('.sub-menu').hide();
$("li:has(ul)").click(function(){
$("ul",this).slideDown();
});
http://jsfiddle.net/3nigma/KhNCV/2/
OR
$('.sub-menu').hide();
$("li:has(ul)").click(function(){
$("ul",this).toggle('slow');
});
http://jsfiddle.net/3nigma/KhNCV/4/
Here's your example working. It's unclear why you need the a tags, as you could use cursor: pointer in the CSS to make the li appear clickable. I'll assume you want to do some spiffy hovering on them in IE that's CSS only? If not, you could simplify by removing them.
Instead of doing hide() on .submenu, you should use CSS (parsed with DOM instead of onReady/load).
.sub-menu { display: none; }
And then here's you code to toggle the menus:
$('ul li a').click(function() {
$(this).parent().find('ul.sub-menu').toggle();
return false;
});
$('.sub-menu').hide();
$("a").click(function(){
$(this).parent().children("ul").toggle();
})
check out this link
http://jsfiddle.net/KhNCV/6/
$('li a').click(
function() {
$(this).next().slideToggle();
})
Try this
$(function(){
//Hide all the sub menus
$('.sub-menu').hide();
$("li:has(ul)").click(function(){
//Find the child ul and slideToggle
$(this).children("ul").slideToggle();
});
});