Remember menu state on reload - javascript

I want to create a navigation menu with the exact same functionality as the one on this site: http://www.rex-ny.com/
I would prefer to do it only using HTML and CSS, but I tried all day and couldn't find a solution.
When I select a menu item, I want that menu to stay open after the page loads. Is this possible?
I want to also make the Main menu items clickable, so that they load a new page AND when that page loads that menu is open.
Here is what I have so far:
http://jsfiddle.net/MEL9d/
Here is the jquery:
$(document).ready(function () {
$('#menu > li > a').click(function(){
if ($(this).attr('class') != 'active'){
$('#menu li ul').hide();
$(this).next().toggle();
$('#menu li a').removeClass('active');
$(this).addClass('active');
}
});
});
And CSS:
#menu {
float: left;
}
#menu li a {
display: block;
}
#menu li ul {
display: none;
}

You can do this is plain HTML and CSS. Assuming you have a structure like this:
- site
+ css
+ js
index.html
about.html
You can add a class to the body of each page, so index for index.php and about for about.php:
<body class="about">
Then in your menu, add an id (or a class if you plan on having the menu in many places) to each item that corresponds to the page:
<ul id="menu">
<li id="index" class="active"><a href="index.html"></li>
<li id="about"><a href="about.html"></li>
</ul>
Finally, using CSS you can style the menu items for each page specifically:
.index #index,
.about #about,
#menu .active {
// styles for active item
}

Related

jQuery on click, add class but also remove if the class is already present

I have a nav menu that needs to trigger with clicks rather than hovers. When the links are clicked, an .open class would be added to the parent li. If that parent already has the .open class, then it would get removed. It would also be removed if another link is clicked on. So far I can get the class added when clicked and removed when a sibling is clicked, but not removed when it's already .open.
I tried adding a hasClass conditional, but that didn't work either. Seemed like it reruns the function every time it's clicked and therefore ignores the hasClass conditional.
Can anyone provide help? I tried toggleClass, but that didn't work.
$('li a').on('click', function() {
$('li a').parent().removeClass('open');
$(this).parent().addClass('open');
});
ul {
list-style: none;
}
li {
display: inline-block;
padding: 10px;
}
.open {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<ul>
<li>
Item 1
</li>
<li>
Item 1
</li>
</ul>
</nav>
To do what you require you can use toggleClass() on the parent li when the element is clicked. To remove the class from all other li elements you can use removeClass() along with not() to exclude the current li. Try this:
$('li a').on('click', function() {
let $li = $(this).parent().toggleClass('open');
$('li').not($li).removeClass('open');
});
ul {
list-style: none;
}
li {
display: inline-block;
padding: 10px;
}
.open {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<ul>
<li>
Item 1
</li>
<li>
Item 1
</li>
</ul>
</nav>
You can use
jquery toggleClass() to toggle yellow highlight (.open css class) on click/unclicking the same link.
jquery siblings() to remove .open class on all the other li items.
Below is the link for the demo
https://jsfiddle.net/so1u8hq6/
$('li a').on('click', function() {
$(this).parent().siblings().removeClass('open');
$(this).parent().toggleClass('open');
});
ul {
list-style: none;
}
li {
display: inline-block;
padding: 10px;
}
.open {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<ul>
<li>
Item 1
</li>
<li>
Item 2
</li>
<li>
Item 3
</li>
</ul>
</nav>
Late to the party, but, after seeing the provided answers and some of the CSS you use I had to urge with my suggestions:
UX. Avoid styling LI tags in general, or at least set the desired display and move on. Style directly the a tag (with the necessary paddings etc.). You'll not only get less CSS to take care of, but also a larger touch interaction area. Makes no sense to style something yellow if it's not a UI part of something interactable. Also in JS, you don't need to take care about the LI wrappers any more - but only about the actual A Elements.
Don't use common selectors like $('li a') - those might target any LI→A elements in your app. Instead be more specific and use a Class like i.e: .tabs for the parent UL. Both in CSS and JS.
Try to use Event Delegation (in jQuey using the .on() method). Not only it will help you to catch the Event.delegateTarget parent UL where needed, but also the this (the clicked element), but mainly reference all the "group" of a elements enclosed in the common parent. That way you can have as many .tabs in a single page as you like. And yes, thanks to Event delegation you can even add dynamically LI Elements - and your JS will still work as expected.
Since you're using <a href="#"> Anchor elements, instead of (more properly) <button type="button>" Elements, you need to also use Event.preventDefault() in order to prevent the browser its default behavior and that's to follow anchors (scroll the page, navigate, etc...)
Use the selector "a.open" when you want to target and remove the "open" class. By just using "a" (or in other answers on this page - "li") you're uselessly touching elements trying to remove a class that's not there in the first place.
Finally, here's the CSS retouch and the proper jQuery needed for your task:
$(".tabs").on("click", "a", function(ev) {
ev.preventDefault();
$("a.open", ev.delegateTarget).not(this).removeClass("open");
$(this).toggleClass("open");
});
.tabs {
display: flex;
list-style: none;
padding: 0;
}
/* Style your Anchors, not the dummy LI wrappers */
.tabs a { padding: 10px; }
.tabs a.open { background-color: yellow; }
<ul class="tabs">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
To explain the only complicated line:
$(
"a.open", // Target just the ones (if any) of class "open"
ev.delegateTarget // inside the common ".tabs" ancestor
)
.not(this) // ... not the clicked element (since later we'll use .toggleClass on it)
.removeClass("open"); // ... remove that class "open"
the rest is pretty self explanatory.
Further read:
jQuery Event Delegation
jQuery event.delegateTarget
Event.preventDefault
So you only want the yellow background to appear as a signifier of user interaction rather than for the background color to be displayed? Have you tried using the mousedown/mouseup functions instead of .on('click', function(){...}?
I was able to simulate the click event where the color showcases via this method:
$('li a').mousedown(function() {
$('li a').parent().removeClass('open');
$(this).parent().addClass('open');
});
$('li a').mouseup(function() {
$('li a').parent().removeClass('open');
});
ul {
list-style: none;
}
li {
display: inline-block;
padding: 10px;
}
.open {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
<ul>
<li>
Item 1
</li>
<li>
Item 1
</li>
</ul>
</nav>

Jquery can't use 3 selectors

I'm writing a small script to make a mobile menu.
However I can't get my selectors to work together.
When I have $('#nav_button, .nav li, .nav li li') only #nav_button and .nav li works, however when I remove .nav li and leave $('#nav_button, .nav li li') this sub menu begins to work as well.
I have also tried using $('#nav_button, .nav li, .sub_menu li li') with the same results.
Does anyone have an idea why?
jquery:
var mobileMenu = function () {
var currentPosition = 'closed'
$('#nav_button, .nav li, .nav li li').click(function() {
if (currentPosition == 'closed') {
$('.nav').addClass('open');
currentPosition = 'open';
}
else {
$('.nav').removeClass('open');
currentPosition = 'closed';
}
});
};
html:
<div id="head">
<div class="container">
<div class="cover"></div>
<a href="#"><h1 class="logo pull-left">C<span class="logo_space">AV</span>O</h1>
</a> <!-- end logo !-->
<div id="nav_button"></div>
<ul class="nav pull-right">
<li>Menu
<ul class="sub_menu">
<li>Starters</li>
<li>Breakfast and Brunch</li>
<li>Salads</li>
<li>Sandwiches and Wraps</li>
<li>Pasta</li>
<li>Mains</li>
<li>Pizza</li>
</ul>
</li>
<li>About Us</li>
<li>Contact</li>
</ul>
</div><!-- end container !-->
</div> <!-- end header !-->
Firstly, two of your selectors match the same elements
$('#nav_button, .nav li, .nav li li')
.nav li matches any LI inside .nav, including nested LI's
.nav li li matches any LI's inside .nav that are inside another LI, i.e. nested LI's
In other words, LI elements inside LI elements, inside .nav are matched twice, but it shouldn't matter as jQuery removes duplicates, but it's uneccessary.
The real issue is that the event propagates, when you click a nested LI the event handler is called for the nested LI and the parent LI, so the click handler execute twice, and the class is first added, then removed (or vice versa) so there is no visible change.
Here's a simplified example
FIDDLE
Just doing
$('#nav_button, .nav li')
should be enough, but you have to add event.stopPropagation() to make sure the event doesn't propagate to the next parent LI when a LI is called, here's an example
FIDDLE
$('#nav_button, .nav li').on('click', function(e) {
e.stopPropagation();
// do stuff
});
As #adeneo said in nested li function will call twice unnecessarily. I think the other way to achieve this is divide click grabber in two selectors like below:
$('.nav').click(function() {
if (currentPosition == 'closed') {
alert('open');
$('.nav').addClass('open');
currentPosition = 'open';
}
else {
alert('close');
$(this).removeClass('open');
currentPosition = 'closed';
}
});
$('.nav > li > li').click(function() {
if (currentPosition == 'closed') {
alert('open');
$(this).addClass('open');
currentPosition = 'open';
}
else {
alert('close');
$('.nav').removeClass('open');
currentPosition = 'closed';
}
});
I wrote a fiddle to do what you expect. Please check and comment if that helpful.
http://jsfiddle.net/QMaster/y7d6osoq/

JQuery .mouseover and .mouseout change font color

I am newbie to JQuery and I try to make some basic tricks with it. So basicly, I have simple navigation made of unordered list, and I want to change font color on currently mouseover-ed list item with JQuery, but I have problem because my JQuery script is changing font color of all list items, and I want to change font color of ONLY currently mouseover-ed list item, not all. I tried to get currently mouseover-ed list item, but I don't know how to implement it so that my JQuery change only that list item. Here are pictures:
What I currently have: http://i.imgur.com/8vWcOci.jpg
What I want: http://i.imgur.com/4yD0bIc.jpg
Here is my JQuery code:
$(document).ready(
function(){
$('.nav1 ul li').mouseover(
function () {
var index = $( ".nav1 ul li" ).index(this);
$('.nav1 ul li a').css({"color":"white"});
}
);
$('.nav1 ul li').mouseout(
function () {
var index = $( ".nav1 ul li" ).index(this);
$('.nav1 ul li a').css({"color":"#6291d8"});
}
);
}
);
Here is my HTML:
<nav class="nav1">
<ul>
<li>HOME</li>
<li>SERVICES</li>
<li>THERAPIES</li>
<li>GALLERY</li>
<li>BOOKING</li>
<li>CONTACT</li>
<li>ABOUT ME</li>
</ul>
</nav>
Instead of:
$('.nav1 ul li a').css({"color":"white"});
and:
$('.nav1 ul li a').css({"color":"#6291d8"});
use:
$(this).css({"color":"white"});
$(this).css({"color":"#6291d8"});
if you wan to apply css on achor tag:
$(this).find("a").css({"color":"white"});
$(this).find("a").css({"color":"#6291d8"});
By using $('.nav1 ul li a') you are changing all anchor tags css but but by using $(this) will change the current clicked element css.
Why JQuery?
use a:hover in css it is pretty cleaner.
Like:
.nav1 ul li a {
color: #6291d8;
}
.nav1 ul li a:hover{
color:white;
}
For all other links you can again use a and a:hover also a:active will give you additional functionality.
this is a special word in JavaScript that refers to the element that triggers an event. In jQuery you can use $(this). So you can replaceyour code with:
$(document).ready(function () {
$('.nav1 ul li a').hover(function () {
$(this).css("color", "white");
}, function () {
$(this).css("color", "#6291d8");
});
});
jsFiddle example
Notice that I also changed the selector to '.nav1 ul li a'. The anchors have their own default styling, so to override that you should target them, and not the parent list item. I also replaced your mouseover and mouseout with the hover method as it saves a few characters. Finally, I used the more basic single property version of .css() which also saves a few characters.
There is no need for JS here. You can use the CSS :hover psuedo class:
.nav1 ul li a {
color: #6291d8;
}
.nav1 ul li a:hover {
color: #FFF;
}
Example fiddle

Activate dropdown with pure javascript

Right now I have a pure HTML CSS navigation bar with some dropdowns. However on ipad the hover will obviously not work.
I want to add a click event to the relevant menu items so the dropdown will also activate with an onclick event.
I've look at other answers but I'm not capable of reading javascript well enough so that I can modify them for my specific site.
here is a link to where I'm at now: http://2ftrade.nl/kareem/eindopdracht/
and this is the relevant html. In my css the default is display:none for the dropdown menus and is changed to display:block when hovered over the li that contains it.
<ul>
<li>Home</li>
<li><a title="">Opleiding</a>
<!-- the dropdown -->
<ul>
<li>Visie & Beleid</li>
<li>Opbouw Studieprogramma</li>
<li>Competenties</li>
<li>Diploma</li>
<li>Beroepen</li>
</ul>
</li>
<li>Onderwijsprogramma</li>
<li>Organisatie</li>
<li><a title="">Stages en Projecten</a>
<!-- another dropdown -->
<ul>
<li>Stages</li>
<li>Projecten</li>
</ul>
</li>
<li>Top</li>
</ul>
This is the css that hides the dropdown section
nav > ul > li > ul {
display: none;
position: absolute;
}
and this is what will display it when hovering
nav > ul > li:hover ul {
display: block;
}
you can attach event listener to your element:
var dropdown_button = document.getElementById('#your-button-that-activates-dropdown');
dropdown_button.addEventListener('click', function() {
//here do what you want to do when the button is clicked.
}, false);
you should use javascript events , some thing like this :
var btn = document.getElementById('btn') // this button is a key to run what you want
var drp = document.getElementById('drp') // this is your dropdown list
btn.onclick = function()
{
drp.style.display = 'block'
// other codes . . .
}
You can achieve this without using javascript.
Use the :target selector
example
Add an id and href for each target in the html
<ul>
<li>Home</li>
<li id="Opleiding">
<a title="" href="#Opleiding">Opleiding</a>
<!-- the dropdown -->
<ul>
<li>Visie & Beleid</li>
<li>Opbouw Studieprogramma</li>
<li>Competenties</li>
<li>Diploma</li>
<li>Beroepen</li>
</ul>
</li>
<li>Onderwijsprogramma</li>
<li>Organisatie</li>
<li id="StagesenProjecten">
Stages en Projecten
<!-- another dropdown -->
<ul>
<li>Stages</li>
<li>Projecten</li>
</ul>
</li>
<li>Top</li>
</ul>
in the css specify the style for the :target
nav > ul > li:target ul {
display: block;
}
nav > ul > li:hover ul {
display: block;
}
nav > ul > li > ul {
display: none;
position: absolute;
}

changing style sheet of clicked menu item asp.net master page

I have an asp.net master page with a menu like this:
<menu id="menu">
<nav id="main_nav">
<ul id="menu-primary">
<li >Home</li>
<li>Staff</li>
<li>Sales</li>
<li>Support</li>
<li>Administration</li>
</ul>
</nav>
</menu>
In master page, I want to change css for the menu item clicked. I have this jquery:
<script type="text/javascript">
jQuery(document).ready(function () {
$('ul li a').each(function () {
var text_splited = $(this).text().split(" ");
$(this).html("<span>" + text_splited.shift() + " " + text_splited.join(" ") + "</span> ");
});
// click on the first item on page load
$('#menu-primary li').eq(0).click();
$('#menu-primary li').click(function (e) {
alert('here');
// remove all active classes
$('#menu-primary li').removeClass('current-menu-item');
// add active class to clicked item
$(this).addClass('current-menu-item');
});
});
</script>
Here is the css
nav#main_nav ul li.current-menu-item a,
nav#main_nav ul li a:hover {background: url("../images/menu_bg.png") no-repeat scroll 0 -149px transparent; border-bottom:1px solid #edf7ff}
nav#main_nav ul li.current-menu-item a span,
nav#main_nav ul li a:hover span{background: url("../images/menu_bg.png") no-repeat scroll 100% -118px transparent;}
This one works :
// click on the first item on page load
$('#menu-primary li').eq(0).click();
$('#menu-primary li').click(function (e) {
// remove all active classes
alert($('#menu-primary li').html());
$('#menu-primary li').removeClass('current-menu-item');
// add active class to clicked item
$(this).addClass('current-menu-item');
return false;
});
But the page is not loaded because th efunction return false.
The alert is shown but the css is not applied to the clicked item.
Can you try doing something like this
$("#menu-primary li.current-menu-item").removeClass("current-menu-item");
$(this).addClass("current-menu-item");
To set first menu item to be selected by default add current-menu-item class to it like this
<li class="current-menu-item">Menu Item</li>
See Working Sample
Alternative approach based on Page URL
$('#menu-primary li a').each(function() {
var path = window.location.href;
var current = path.substring(path.lastIndexOf('/'));
var url = $(this).attr('href');
if(current=="")
$('#menu-primary li a').first().addClass('current-menu-item');
if (url == current) {
$(this).addClass('current-menu-item');
};
});

Categories

Resources