Jquery addClass to navigation not working - javascript

I am having an issue trying to set a class to the active nav item.
I need some help trying to figure out where i am going wrong.
It is some what working but not correctly, it defaults to the menu item which has a sub menu and i can't see where i have gone wrong.
When clicking on say "contact us" for example - the href takes me to the contact page but the active class does not apply and remains on "Products"
What i want to happen is the active class applies to the item that is clicked and not stuck on "products"
Here is JSFiddle https://jsfiddle.net/2yv92roL/
Thanks for help in advance!
Here is HTML:
<nav class="navigation">
<ul class="mainmenu">
<li>Home</li>
<li>Our Philosophy</li>
<li>Products
<ul class="submenu">
<li>Charbonnier Cookware</li>
<li>Charbonnier Dinnerware</li>
<li>Charbonnier Storageware</li>
</ul>
</li>
<li>Contact us</li>
</ul>
</nav>
Here is my CSS:
/* define a fixed width for the entire menu */
.navigation {
width: 150px;
}
/* reset our lists to remove bullet points and padding */
.mainmenu, .submenu {
list-style: none;
padding: 0;
margin: 0;
}
/* make ALL links (main and submenu) have padding and background color */
.mainmenu a {
display: block;
text-decoration: none;
padding: 10px;
}
/* add hover behaviour */
.mainmenu a:hover {
background-color: #C5C5C5;
}
/* when hovering over a .mainmenu item,
display the submenu inside it.
we're changing the submenu's max-height from 0 to 200px;
*/
.mainmenu li:hover .submenu {
display: block;
max-height: 200px;
}
/*
we now overwrite the background-color for .submenu links only.
CSS reads down the page, so code at the bottom will overwrite the code at the top.
*/
/* hover behaviour for links inside .submenu */
.submenu a:hover {
background-color: #C5C5C5;
}
/* this is the initial state of all submenus.
we set it to max-height: 0, and hide the overflowed content.
*/
.submenu {
overflow: hidden;
max-height: 0;
-webkit-transition: all 0.5s ease-out;
}
.navigation ul li .active {
color: #0080A6;
}
Here is my JQuery
$(function() {
var pgurl = window.location.href.substr(window.location.href.lastIndexOf("/")+1);
$(".navigation ul li a").each(function(){
if($(this).attr("href") == pgurl || $(this).attr("href") == '' )
$(this).addClass("active");
})
});

You need to make a couple of changes:
Remove "$(this).attr("href") == ''" from your if condition, this is the reason your "Products" menu is getting the active class by default
Add "$(".navigation ul li a").removeClass("active");" before your each to remove the active class from the previously selected menu
Add "/" to your pgurl so that it matches the href attribute of your menus
Here is the updated code:
$(function () {
var pgurl = "/" + window.location.href.substr(window.location.href.lastIndexOf("/") + 1);
$(".navigation ul li a").removeClass("active");
$(".navigation ul li a")
.each(function() {
if ($(this).attr("href") == pgurl)
$(this).addClass("active");
});
});

Related

How to make all elements in a node list disappear except target element?

https://codepen.io/m4rsibar/pen/zyPBoz?editors=0110
I've made a codepen example of the effect I'm going for (I've included the code that creates the effect at the very top of the css section), except I want to do it in javascript. (unless there's a way to fix the issues I'm having with the css version)
The issue: the hover is on the div containing the circular elements, if you hover in the div, and aren't on top of an element they all go out of view.
I'm using the :not selector in css to achieve this and to put it on the parent element is the only way I know how to get this to work, I've tried playing around and changing stuff up, to no avail, so I decided to do this with javascript.
In another codepen I tried to simplify as much as possible to try to achieve the effect I'm going for. I've only gotten thus far:
https://codepen.io/m4rsibar/pen/yGPqZM
as you can see when you leave the box it doesn't go back to the original opacity.
Should I be using classes and toggling them?
let lis= document.querySelectorAll('li')
console.log(lis)
lis.forEach(function(li) {
li.addEventListener("mouseover", function(e) {
lis.forEach(function(li) {
e.target.style.opacity="1";
if(e.target.style.opacity==="1"){
li.style.opacity="0.3";
}else{
li.style.opacity="1";
}
});
})
});
This is a simpler approach using only a line of CSS and no JavaScript. Because opacity: 1 is implicit, we don't have to declare that at all, only styles for the non-hovered state.
li {
list-style: none;
background-color: pink;
margin: 2px;
height: 200px;
width: 200px
}
ul {
display: flex;
}
li:not(:hover) {
opacity: 0.3;
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Update
After your feedback and latest example, I took another stab at it. My goal was avoid the double active class on both the ul and active li. It's not ideal from a performance standpoint, but beyond that, it's more JavaScript and CSS to maintain.
What I came up with is a function that detects if an li is the current target (while the mouse is somewhere inside the ul). If the current target is not an li it means that our ul is active but no children are being hovered. I toggle a class accordingly. I like that everything is stored in the ul and we no longer need any li event tracking.
var ul = document.querySelector('ul');
function boxEnter(e) {
this.classList.add('active');
}
function boxLeave(e) {
this.classList.remove('active');
}
function boxMove(e) {
this.classList.toggle('childrenInactive', e.target.tagName !== 'LI');
}
ul.addEventListener('mousemove', boxMove);
ul.addEventListener('mouseenter', boxEnter);
ul.addEventListener('mouseleave', boxLeave);
li {
list-style: none;
background-image: url('https://source.unsplash.com/collection/1163637/200x200');
border-radius: 50%;
margin: 2px;
height: 200px;
width: 200px;
transition: .3s ease;
cursor: crosshair;
will-change: filter, transform;
}
ul {
display: flex;
flex-wrap: wrap;
}
ul.active li {
opacity: .3;
transform: scale(1.1);
filter: blur(5px);
}
ul li:hover,
ul.active.childrenInactive li {
opacity: 1;
transform: scale(1);
filter: blur(0);
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
http://jsfiddle.net/j3reaqsw/

Change images in menu

I need to swap (change) the image in img tag after hover and click.
I'm not good in javascript so i need help.
If some image is active (clicked) and I click on next image in menu so other images must be change to default.
<ul id="ourteam">
<li><a data-target="#user1" class="active"><img src="/img/avatars/avatar1.png" data-other-src="/img/avatars/avatar1h.png" /></a></li>
<li><a data-target="#user2"><img src="/img/avatars/avatar_t.png" /></a></li>
<li><a data-target="#user3"><img src="/img/avatars/avatar3.png" data-other-src="/img/avatars/avatar3h.png" /></a></li>
<li><a data-target="#user4"><img src="/img/avatars/avatar4.png" data-other-src="/img/avatars/avatar4h.png" /></a></li>
</ul>
add onclick to the anchor
function set_anch_image(anch) {
var imgs = document.getElementById("ourteam").getElementsByTagName("img");
for(var i=0;imgs.length;i++) hold[i].src = "avatar"+(i+1)+".png" ;
anch.getElementsByTagName("img")[0].src = "avatar_t.png" ;
}
You should definitely be using CSS to change the image on hover. Not to mention the fact that you can add a class on hover or click to achieve the same effect using a combination of CSS and JavaScript. However, if you need to accomplish using JavaScript alone, I would recommend using jQuery or another library that has these methods and many others already built-in. Especially if you are not so well versed in plain JavaScript.
CSS
This option removes the need for the image tag completely. In order to ensure that your image is displayed properly you will need to provide dimension to your LI elements within the CSS and also make the A element display: block.
#ourteam li a { display: block; }
#ourteam li:nth-child(1) a { background: url('/img/avatars/avatar1.png'); }
#ourteam li:hover:nth-child(1) a { background: url('/img/avatars/avatar11.png'); }
#ourteam li:nth-child(2) a { background: url('/img/avatars/avatar_t.png'); }
#ourteam li:nth-child(3) a { background: url('/img/avatars/avatar3.png'); }
#ourteam li:hover:nth-child(3) a { background: url('/img/avatars/avatar3h.png'); }
#ourteam li:nth-child(4) a { background: url('/img/avatars/avatar4.png'); }
#ourteam li:hover:nth-child(4) a { background: url('/img/avatars/avatar4h.png'); }
jQuery
This will handle all 3 events - click, mouse enter and mouse leave. It simply swaps the values of the "src" and your "data-other-src".
$(function(){
$('#ourteam img').on('click mousenter mouseleave', function( e ){
e.preventDefault();
var _this = $(this),
oldSrc = _this.attr('src'),
newSrc = (_this.attr('data-other-src')) ? _this.attr('data-other-src') : oldSrc;
_this.attr('src', newSrc).attr('data-other-src', oldSrc);
});
});
Alternatively, we can use the hover and click events to toggle an active class to either the list item or the a. For this example, let's go with the anchor.
CSS
#ourteam li:nth-child(1) a { background: url('/img/avatars/avatar1.png'); }
#ourteam li:nth-child(1) a.active { background: url('/img/avatars/avatar1h.png'); }
#ourteam li:nth-child(2) a { background: url('/img/avatars/avatar_t.png'); }
#ourteam li:nth-child(2) a.active { background: url('/img/avatars/avatar_t.png'); }
#ourteam li:nth-child(3) a { background: url('/img/avatars/avatar3.png'); }
#ourteam li:nth-child(3) a.active { background: url('/img/avatars/avatar3h.png'); }
#ourteam li:nth-child(4) a { background: url('/img/avatars/avatar4.png'); }
#ourteam li:nth-child(4) a.active { background: url('/img/avatars/avatar4h.png'); }
jQuery
$(function(){
$('#ourteam li a').on('click mousenter mouseleave', function( e ){
e.preventDefault();
$(this).toggleClass('active');
});
});

Dropdown menu not closing jQuery

Can someone explain me what I'm doing wrong, if you click on the first link(link 1) it opens a menu, if you click on one of the 'li' inside the menu it closes the menu.
If I click on the second link(link 2) it opens a different menu but when I click on one of the 'li' inside the menu nothing happens, and what I am trying to do is to close the menu.
jsfiddle (http://jsfiddle.net/BdhxL/)
The HTML code:
Link 1
<div id="dropMenu">
<ul>
<li>Portfolio</li>
</ul>
</div>
<br><br>
Link 2
<div id="dropMenu">
<ul>
<li>Contact us </li>
</ul>
</div>
The JS code:
$(document).ready(function() {
$("li").click(function()
{
$("#dropMenu").hide("slow");
});
$("a").click(function()
{
$(this).toggleClass("active");
$(this).next("div").stop('true','true').slideToggle("slow");
});
});
#dropMenu {
display: none;
position: relative;
right: 5px;
background: #000;
color: black;
margin:50px -5% 0% -142%;
padding: 0px 0px 0px 10px;
}
#dropMenu a {
display: block;
color: #fff;
text-decoration: none;
padding:10px 6px;
font-weight:400;
border-bottom: solid 1px #fff;
}
The CSS code:
#dropMenu ul {
margin:0;
}
#dropMenu a:hover {
background: #57585A;
}
#dropMenu ul {
list-style:none;
padding:0;
}
You have duplicate ids.$("#dropMenu").hide("slow"); is always targetting first dropMenu. Use $(this) to target current and hide the closest div.Try this:
$(document).ready(function() {
$("li").click(function()
{
$(this).closest("div").hide("slow");
});
$("a").click(function()
{
$(this).toggleClass("active");
$(this).next("div").stop('true','true').slideToggle("slow");
});});
Working Demo
Currently, you're having duplicated id for parent div of your list which is <div id="dropMenu"> , you need to use class instead:
<div class="dropMenu">
then you can use .closest() to target closest matching .dropMenu of clicked li:
$(document).ready(function () {
$("li").click(function () {
$(this).closest(".dropMenu").hide("slow");
});
$("a").click(function () {
$(this).toggleClass("active");
$(this).next("div").stop('true', 'true').slideToggle("slow");
});
});
You also need to change all #dropMenu to .dropMenu in your CSS.
Updated Fiddle

Jquery - dropdown menu on click

I am relatively new to jquery and I am seeking help. The aim is to click on a list item attached to a ul and have it appear whilst any other list items disappear. Only the active one is viewable
The Issue I am having is that when I click on another list item the active one disappears (as intended), but it doesn't reveal the other one, it remains hidden. I am looking for a way to reveal the list, while hiding the ones that are in-active.
I have uploaded my problem: http://jsfiddle.net/CbU4d/
html:
<div id="secondary-nav"><!--secondary-nav-->
<ul>
<li>Current Article
<ul>
<li>Example 1</li>
</ul>
</li>
<li class="active">Past Articles
<ul>
<li>Example 1</li>
<li>Example 2</li>
<li>Example 3</li>
</ul>
</li>
</ul>
</div><!--/secondary-nav-->
css:
#secondary-nav {
float:left;
height:auto;
width:23%; /*210px*/
border-right:2px solid #000;
position:relative;
}
/*heading styles*/
#secondary-nav ul li {
padding: 0 10px;
list-style-type: none;
}
#secondary-nav ul li a {
font-family:TrajanPro;
font-size:1em;
line-height: 32px;
color:#000;
}
/*links*/
#secondary-nav ul ul li a {
display: block;
font-family:TrajanPro;
font-size:0.9em;
line-height: 27px;
text-decoration: none;
color:#000;
transition: all 0.15s;
}
#secondary-nav ul li a:hover {
display:block;
color:#af2931;
text-decoration:underline;
}
#secondary-nav ul ul {
display: none;
}
#secondary-nav li.active ul {
display: block;
}
/css
jquery using 1.7.1
$(document).ready(function(){
$("#secondary-nav ul").click(function(){
//slide up all the link lists
$("#secondary-nav ul ul").slideUp();
//slide down the link list below the h3 clicked - only if its closed
if(!$(this).next().is(":visible"))
{
$(this).next().slideDown();
}
})
})
Try with
$("#secondary-nav ul ul").slideToggle();
Demo
I got it to work (I think) by making two changes:
Change the selector on line 2 to this:
"#secondary-nav ul li"
This means the event will be attached to the list item you click, not the entire list.
Remove the if statement on line 6. Since we're hiding all of the second level uls in the previous line, we don't need to check if it's visible; we know it isn't.
Change line 6 to this:
$(this).children('ul').slideDown();
This is because the ul you want to unfold is a child of the li you're clicking, not a sibling.
Here's my fixed jsFiddle.
Edit: If you want to stop it from hiding and re-showing when you click the one that's already expanded, just chuck this at the top of the handler:
if ($(this).children('ul').is(':visible')){
return
}

cannot make list item visible with > CSS selector

I'm unable to make the popups 'redItem', 'blueItem' and 'greenItem' below visible again after setting their display to 'none'. I'm using a CSS selector to get them visible again when the mouse hovers over a node higher up in the nested list to no avail.
Here's the code:
<ul class="popups" style="vertical-align: bottom; padding: 0px; margin: 0px;">
<li style="width: 165px"><a id="topmostBox" href="#">One_high-up_item</a>
<ul class="popups">
<li>First-lower-item
<ul class="popups">
<li name="redItem" >Red</li>
<li name="blueItem">Blue</li>
<li name="greenItem">Green</li>
</ul>
</li>
</ul>
</li>
</ul>
.popups:hover > li {
display: block;
}
.popups {
background-color: white;
font-family: sans-serif;
font-size: 13.5px;
list-style: none;
position: relative;
border: 1px solid lightgray;
border-width: .05em;
border-top-color: rgb(165,165,165);
line-height: 1.2em;
display: inline-table;
}
function setTopColorAndVis(theNestedPopupAnchor)
{
var theColorName = theNestedPopupAnchor.innerHTML;
var topMenuBox = document.getElementById('topmostBox');
topMenuBox.innerHTML = theColorName ;
theNestedPopupAnchor.parentNode.style.display = "none";
}
What happens is this:
1) I select the color 'Red' (the 1st list item)
2) my call to setTopColorAndVis(this) makes the popup disappear (because the user selected an item, the color "Red", and now the popup is not needed for now)
3) but when I later hover the mouse over the "First-lower-item" list item, the child li that has the ul containing 'redItem', 'greenItem', 'blueItem' does not appear.
So my experience here is that I'm successfully able to hide the list items named 'redItem', 'blueItem' and 'greenItem' -- but when I hover over the "First-lower-item", despite my CSS code:
.popups:hover > li {
display: block;
}
The 'redItem', 'greenItem' and 'blueItem' do NOT reappear.
What am I missing here?
The inline style overrides you style in your css code. you should use onmouseover event and onmouseout instead.
Try
<li name="redItem" >Red</li>
function show(elem){
elem.parentNode.style.display = "block";
}
function hide(elem){
elem.parentNode.style.display = "none";
}
You cannot :hover over an element with display:none as it has no size...
instead of working with display, you can work with visibility - which will leave an area to hover over.
like so:
theNestedPopupAnchor.parentNode.style.visibility = 'hidden'
.popups:hover > li {
visibility: visible;
}
http://www.w3schools.com/cssref/pr_class_visibility.asp

Categories

Resources