A simple error in jQuery code - javascript

When I hover on .menu li all of a take this class.
I want to hover on .menu li so that just his child a takes the class.
$(document).ready(function() {
// Menu is hover
$('.menu li').hover(function(){
$(this).addClass('liHoverMnue');
$('.menu li a').addClass('aHoverMnue');
}, function() {
$(this).removeClass('liHoverMnue');
$('.menu li a').removeClass('aHoverMnue');
});
});

Use the this keyword again
$(document).ready(function() {
// Menu is hover
$('.menu li').hover(function(){
$(this).addClass('liHoverMnue');
$(this).find('a').addClass('aHoverMnue');
}, function() {
$(this).removeClass('liHoverMnue');
$(this).find('a').removeClass('aHoverMnue');
});
});
You could also chain it
$(this).addClass('liHoverMnue').find('a').addClass('aHoverMnue');

Related

CSS: Failing to display unless refreshed - Navigation bar

I have been working on navigation bar and the strangest issue is occurring.
Please use the JSFiddle link to see what I mean.
To duplicate the error:
Run the code when the desktop view is active i.e. when the navigation links are in a line.
Then resize the screen till the "click me" is displayed.
Then press it.
Now run the code while you see the "click me" and press it again.
JS information
jQuery(document).ready(function($) {
// UserCP
$('.rotate').on('click', function() {
$(this).toggleClass("down");
});
$('.nav-start').on('click', function() {
$("#nav2").removeClass("hidden");
$('#nav2 li a').stop().slideToggle('100');
return false;
});
$(document).ready(function() {
$('#nav2 li a').stop().slideToggle('100');
});
$('body').on('click', function() {
$('#nav2 li a').stop().slideUp('100');
});
$("#nav2 li a").click(function(e) {
e.stopPropagation();
});
$(document).click(function(event) {
if (!$(event.target).closest('#nav2 li a').length) {
if ($('#nav2 li a').is(":visible")) {
$('html, body').on('click', function() {
$('#nav2 li a').stop().slideUp('100');
});
};
};
});
});
FIXED - UPDATED JSFiddle! Thanks #Louys Patrice Bessette #Titus #Rick
You are using two click events on this "Click me" li...
(One on .navstart and one on .rotate)
It may not be an issue, but this make the code harder to read.
Then, when you slideToggle(), if you want the submenu to slide down, it has to be hidden.
Because, since you remove the hidden class (probably usefull on load), the submenu is visible.
A Toggle hides it.
I simplified your script to this.
Have a look at this updated Fiddle.
$(document).ready(function() {
// Show submenu on "Click me"
$('.nav-start').on('click', function() {
$('.rotate').toggleClass("down");
$("#nav2").removeClass("hidden");
var subNav = $('#nav2 li a');
if(subNav.css("display")=="block"){
subNav.stop().slideUp('100');
}else{
subNav.stop().slideDown('100');
}
return false;
});
$("#nav2 li a").click(function(e) {
e.stopPropagation();
});
// Hide submenu on document click
$(document).click(function(event) {
if (!$(event.target).closest('#nav2 li a').length && $('#nav2 li a').is(":visible")) {
$('#nav2 li a').stop().slideUp('100');
};
});
});

Toggle only when parent list items is clicked

I have a simple ol li based list which toggles when i click on parent item or child item. I want it to toggle only when parent item is clicked.
$("#expList > li").click(function () {
$(this).find("ol").slideToggle();
});
https://jsfiddle.net/k2jqqbbk/3/
I tried to target it with $("#expList ol li") but this is not working. I tried few other options which didn't work either.
You could use the event.target to check whether its closest li contains an ol, and only toggle if it does:
$('#expList > li').click(function(evt) {
if ($(evt.target).closest('li').has('ol').length) {
$(this).find("ol").slideToggle();
}
});
Here's a fiddle
You need to target the a tag. Because the ol is the next child, the find call has been replaced with a call to next:
$("#expList > li > a").click(function () {
$(this).next().slideToggle();
});
If you want the functionality to extend to children of children, just omit #expList from the selector:
$("li > a").click(function () {
$(this).next().slideToggle();
});
Fiddle
Try to add the following code :
$("#expList > li").click(function () {
$(this).find("ol").slideToggle();
});
$("#expList > li ol li").click(function () {
return false;
});
The click event bubbles up to ancestor elements. So the click is fired first against the second-level list items, then bubbles up to the first-level list items. This is why you're seeing the toggling happen.
All you need to do is stop the click event bubbling up the element chain from the second-level list items.
Add this to fix:
$("#expList ol li").click(function(e) {
e.stopPropagation();
});
Here's the example: https://jsfiddle.net/sxn5bg3x/

How to not add arrows to links in my submenu in jQuery?

I am writing my own jQuery navigation submenu script. When you hover over a link in the horizontal nav that has a ul tag, it makes that ul appear. I have a bit of code that adds an arrow to the links in the horizontal nav if it has a submenu. My problem is that it also adds the arrows to the links in the submenu. This is not a big deal functionally, but it does look bad.
The odd part is that if I use $(this).find('> a') it screws up the appearance of the submenu. The submenu appears when I hover over the top-level link, but then disappears right away when the mouse leaves that link. So I can basically see the entire submenu when the mouse is hovered over the top level link. When the mouse leaves the top level link, the submenu disappears and I can't click on the submenu links. What am I doing wrong?
Here is a JSFiddle. Change $(this).find('a') to $(this).find('> a') and you'll see what I mean. Thanks for your time!
$(document).ready(function(){
$('nav ul li:has(ul)').each(function(){
var listItem = $(this);
$(this).find('> a').each(function(){
var aTag = $(this);
aTag.append('<img src="{img_url}/caret.png" width="8" height="8">');
aTag.on('mouseover', function(){
listItem.find('ul').each(function(){
$(this).css('display', 'block');
});
})
.on('mouseout', function(){
listItem.find('ul').each(function(){
$(this).css('display', 'none');
});
});
});
});
});
you have to pull out the first a tag from your loop through .each
$(document).ready(function () {
$('nav ul li:has(ul)').each(function () {
var listItem = $(this);
// first a tag as new var
var aTagFirst = listItem.children('a');
aTagFirst.append('<img src="{img_url}/caret.png" width="8" height="8">');
$(this).find('a').each(function () {
var aTag = $(this);
aTag.on('mouseover', function () {
listItem.find('ul').each(function () {
$(this).css('display', 'block');
});
})
.on('mouseout', function () {
listItem.find('ul').each(function () {
$(this).css('display', 'none');
});
});
});
});
});
DEMO
I guess you can do it by CSS, I have removed events mouseover, mouseout and added this styles:
li:hover ul {
display: block;
}
li:hover a {
background: #66cc00;
}
li:hover li a {
background: #333;
}
DEMO
$(document).ready(function () {
$('nav ul li:has(ul)').each(function () {
var listItem = $(this);
$(this).find('> a,>ul').each(function () {
var aTag = $(this);
aTag.append('<img src="{img_url}/caret.png" width="8" height="8">');
aTag.on('mouseover', function () {
listItem.find('ul').each(function () {
$(this).css('display', 'block');
});
})
.on('mouseout', function () {
listItem.find('ul').each(function () {
$(this).css('display', 'none');
});
});
});
});
});
Here only update is:
$(this).find('> a,>ul')
Css:
only update is one:
nav > ul > li > a {
display: block;
margin: 0px;
border-bottom: 0;
color: #333;
height: 52px;
padding: 0px 25px 0px 25px;
font-size: 1.25em;
line-height:55px;
}
Update in padding and add line-height.
Demo: http://jsfiddle.net/fsrf5jw3/5/
You need to add hover callbacks to your li element, not a element, so the code becomes:
var listItem = $(this);
listItem.find('> a').each(function(){
var aTag = $(this);
aTag.append('<img src="{img_url}/caret.png" width="8" height="8">');
});
listItem
.on('mouseover', function(){
listItem.find('ul').each(function(){
$(this).css('display', 'block');
});
})
.on('mouseout', function(){
listItem.find('ul').each(function(){
$(this).css('display', 'none');
});
});
Also, as marsh answer goes, it is more proper performance-wise to do such things with css, not javascript.

How to add a class onto the selected li element and make li full-sized-clickable

I want to add a class to the selected 'li' and at the same time, remove the class:selected from previous selected li element.
I have worked on it hours and still haven't got any luck. I also checked others questions, but their solutions don't work for me.
Help please....
<ul id='mainView' class='menu' style='float: left; clear: both;'>
<li>Patient</li>
<li>Recommendations</li>
</ul>
<script type="text/javascript">
$(document).ready(function () {
$('.menu ul a').on('click', function (event) {
$('.menu ul a.selected').className = '';
alert($(this).attr('id'));
$(this).attr('class') = 'selected';
});
});
// $('.menu li').on('click', function () {
// $('.menu li.selected').className = '';
// this.className = 'selected';
// });
</script>
Update:
I did put a inside li, but if I click on the li not the a inside of the li, the webpage does not redirect. That's the reason why I do it in a reversed way.
Update 2
The reason why the selected li does not get the "selected" class is because the whole webpage is redirected to a new page which has the same navigation bar.
So now the question is how to highlight the selected li(it was selected on the previous page) on the new webpage.
Inside an UL everybody (even a browser) is expecting to see a LI
so your HTML:
<ul>
<li>Patient</li>
<li>Recommendations</li>
</ul>
And your jQ:
$('ul li').click(function(){
$(this).addClass('selected').siblings().removeClass('selected');
});
Building web pages you should know how to treat LI elements. Simple, like dummy containers with minimal styling.
That means that you rather add a display:block ... float:left and other cool stuff to the <A> elements, than setting a padding there you go with your full-sized-clickable A elements.
Additionally (if you don't have time to play with CSS) to make a LI fully clickable use:
$('ul li').click(function(){
var goTo = $(this).find('a').attr('href');
window.location = goTo ;
// $(this).addClass('selected').siblings().removeClass('selected'); // than you don't need this :D
});
After the OP late edit - and to answer the question
After the pages refreshes to get which one is the active one use:
// ABSOLUTE PATH
var currentPage = window.location;
// RELATIVE PATH
// var currentPage = window.location.pathname;
$('li a[href="'+ currentPage +'"]').addClass('selected');
<script type="text/javascript">
$(document).ready(function () {
$('.menu ul a').on('click', function (event) {
$('.menu ul a.selected').removeClass('selected');
alert($(this).attr('id'));
$(this).addClass('selected')
});
});
</script>
Try addClass and removeClass, they're jQuery functions:
$(document).ready(function () {
$('.menu ul a').on('click', function (event) {
$('.menu ul a.selected').removeClass("selected");
$(this).addClass('selected');
});
});

How would I add a 1 second delay to the hide JavaScript function

This is some JavaScript I have for a simple navigation bar but I have issues with the drop down disappearing before you can click on them so I want to add a delay after the mouse leaves the bar before they hide.
How would I do that?
<script type="text/javascript">
$(document).ready(function () {
// Navigation bar drop-down
$("nav ul li").hover(function () {
$(this).addClass("active");
$(this).find("ul").show().animate({ opacity: 1 }, 400);
}, function () {
// Delay on hiding should go here
$(this).find("ul").hide().animate({ opacity: 0 }, 200);
$(this).removeClass("active");
});
$('nav ul li ul li:first-child').prepend('<li class="arrow"></li>');
$('nav ul li:first-child').addClass('first');
$('nav ul li:last-child').addClass('last');
$('nav ul li ul').parent().append('<span class="dropdown"></span>').addClass('drop');
});
</script>
Thanks in advance to anyone who can help
P.S. This is probably really obvious but I know very little about JavaScript. :L
I have a simple navigation bar
Don't use JavaScript then. This can and should be done with CSS. CSS transitions and selectors allow to define exactly what you want.
See also Delay :Hover in CSS3? and the excellent example from there.
Don't use a huge function such as delay(). Just use setTimeout().
var that = this
setTimeout(function() {
$(that).hide() // Do your stuff, just don't forget that "this" has changed
}, 1000) // Define your delay in milliseconds here
The function inside the setTimeout will execute after the delay specified as a second argument.
You can do it like this. You use the delay() method to set up the delay and you use .stop(true) on both hover functions in case the user goes out and comes back in during the delay. The .stop(true) will clear any queued animations. I also switched the code to fadeIn() and fadeOut() because those automatically do the show() and hide() as needed.
<script type="text/javascript">
$(document).ready(function () {
// Navigation bar drop-down
$("nav ul li").hover(function () {
$(this).addClass("active");
$(this).find("ul").stop(true).fadeIn(400);
}, function () {
// Delay on hiding should go here
var self = $(this);
self.find("ul").stop(true).delay(1500).fadeOut(400, function() {
self.removeClass("active");
});
});
$('nav ul li ul li:first-child').prepend('<li class="arrow"></li>');
$('nav ul li:first-child').addClass('first');
$('nav ul li:last-child').addClass('last');
$('nav ul li ul').parent().append('<span class="dropdown"></span>').addClass('drop');
});
</script>
I think you can do something like this:
<script type="text/javascript">
$(document).ready(function () {
// Navigation bar drop-down
$("nav ul li").hover(function () {
$(this).addClass("active");
$(this).find("ul").show().animate({ opacity: 1 }, 400);
}, function () {
// Delay on hiding should go here
$(this).find("ul").hide().delay(1000).animate({ opacity: 0 }, 200, function() {
$(this).removeClass("active");
});
});
$('nav ul li ul li:first-child').prepend('<li class="arrow"></li>');
$('nav ul li:first-child').addClass('first');
$('nav ul li:last-child').addClass('last');
$('nav ul li ul').parent().append('<span class="dropdown"></span>').addClass('drop');
});
</script>
You could use delay().
<script type="text/javascript">
$(document).ready(function () {
// Navigation bar drop-down
$("nav ul li").hover(function () {
$(this).addClass("active");
$(this).find("ul").show().animate({ opacity: 1 }, 400);
}, function () {
// Delay on hiding should go here
$(this).find("ul").delay(5000).fadeOut();
$(this).removeClass("active");
});
$('nav ul li ul li:first-child').prepend('<li class="arrow"></li>');
$('nav ul li:first-child').addClass('first');
$('nav ul li:last-child').addClass('last');
$('nav ul li ul').parent().append('<span class="dropdown"></span>').addClass('drop');
});
</script>
Very interesting. Nothing hides, until you mouseout.
FIDDLE

Categories

Resources