I am trying to have my links in a menu styled when I mouse over them.
Then when the mouse leaves the link (without clicking on it) I want the current link to go back to being styled.
html:
<div id="header">
<div id="title"><h1>Title<span id="Subtitle">Subtitle</span></h1></div>
<nav class="cf" id="menu">
<ul>
<li>ABOUT</li>
<li>GALLERY</li>
<li>BIO</li>
<li>CONTACT</li>
<li>HOME</li>
</ul>
</nav>
</div>
css
.current { color: #FFBB3F;}
js
$( "nav a" ).on('mouseover', function(){
$( "nav a.current" ).removeClass("current");
$(this).addClass("current");
});
$( "nav a" ).on('mouseleave', function(){
$(this).removeClass("current");
var pageURL = $(location).attr("href");
$('a[href="pageURL"]').addClass("current");
});
but this is not working. if I do an alert
alert(pageURL);
it gives me the path to the current page, and if I paste just an href
$('a[href="index.html"]').addClass("current");
it does style that link, but obviously I would want the current link to be styled. First time I try this. Any help appreciated. Thanks
This will add and remove the current class as well as style links being hovered over:
var anchors = document.querySelectorAll("#menu a");
// Assign mouseover and mouseout event handlers to each anchor
for(var i = 0; i < anchors.length; i++){
anchors[i].addEventListener("mouseover", styleIn);
anchors[i].addEventListener("mouseout", styleOut);
}
// This will hold a reference to whichever anchor has the current class
var currentAnchor = null;
function determineCurrent(){
for(var i = 0; i < anchors.length; i++){
if(anchors[i].classList.contains("current")){
currentAnchor = anchors[i];
}
}
}
function styleIn(e){
determineCurrent();
e.target.classList.add("hover");
currentAnchor.classList.remove("current");
}
function styleOut(e){
e.target.classList.remove("hover");
currentAnchor.classList.add("current");
}
a { text-decoration:none; }
.current { color: #FFBB3F; }
.hover { text-decoration:underline;}
<div id="header">
<div id="title"><h1>Title<span id="Subtitle">Subtitle</span></h1></div>
<nav class="cf" id="menu">
<ul>
<li>ABOUT</li>
<li>GALLERY</li>
<li>BIO</li>
<li>CONTACT</li>
<li>HOME</li>
</ul>
</nav>
</div>
Using just CSS, a combination of rules can get really close (perhaps close enough depending on how #menu is), see comments in CSS section:
/*
1. Color the current one if the menu isn't being hovered
2. Color the current link if being hovered
*/
#menu:not(:hover) .current, /* 1 */
#menu a:hover { /* 2 */
color: #FFBB3F;
}
<div id="header">
<div id="title"><h1>Title<span id="Subtitle">Subtitle</span></h1></div>
<nav class="cf" id="menu">
<ul>
<li>ABOUT</li>
<li>GALLERY</li>
<li>BIO</li>
<li>CONTACT</li>
<li>HOME</li>
</ul>
</nav>
</div>
That CSS-only version has the issue that if you're not hovering a link but you are hovering the #menu, nothing is highlighted. I can't think of a pure CSS way to handle that, so a bit of JavaScript (see comments):
// Set a class on #menu only when hovering a link
$("#menu")
.on("mouseenter", "a", function() {
$("#menu").addClass("link-hover");
})
.on("mouseleave", "a", function() {
$("#menu").removeClass("link-hover");
});
/*
1. Color the current one if the menu doesn't have the link-hover class
2. Color the current link if being hovered
*/
#menu:not(.link-hover) .current, /* 1 */
#menu a:hover { /* 2 */
color: #FFBB3F;
}
<div id="header">
<div id="title"><h1>Title<span id="Subtitle">Subtitle</span></h1></div>
<nav class="cf" id="menu">
<ul>
<li>ABOUT</li>
<li>GALLERY</li>
<li>BIO</li>
<li>CONTACT</li>
<li>HOME</li>
</ul>
</nav>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Related
I am new in Jquery
My Webpage structure is like this
<div id="MenuSection">
<ul>
<li>Master // Main Menu
<ul>
<li>Master1</li>
<li>Master2</li>
<li>Master3</li>
</ul>
</li>
<li>Transaction // Main Menu
<ul>
<li>Transaction1</li>
<li>Transaction2</li>
<li>Transaction3</li>
</ul>
</li>
<li>Report // Main Menu
<ul>
<li>Report1</li>
<li>Report2</li>
<li>Report3</li>
</ul>
</li>
</ul>
</div>
I want that when all the children of any Parent(main menu) are hidden, Parent should also be hidden. Let's say if Report1, Report2, Report3 are hidden then Parent that is "Report" should also be hidden.
How can I achieve this through Jquery ?
One way is to iterate over each main menu li to see if its children are all :visible:
$("#MenuSection>ul>li").each(function() {
if ($(this).find(">ul>li:visible").length == 0) {
$(this).hide();
}
});
there are other ways to do this, such as using .filter or .map, but this should get you what you need.
Given the nested ul's the above uses > to ensure only the directly ul>li children are processed. If you have multiple levels, you might need to change accordingly, eg for the first: #MenuSection li would apply to all lis and the second .find(">ul>li:visible") only looks at direct li children.
$("#MenuSection>ul>li").each(function() {
if ($(this).find("li:visible").length == 0) {
$(this).hide();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="MenuSection">
<ul>
<li>Master
<ul>
<li>Master1</li>
<li>Master2</li>
<li>Master3</li>
</ul>
</li>
<li>Transaction
<ul>
<li>Transaction1</li>
<li>Transaction2</li>
<li>Transaction3</li>
</ul>
</li>
<li>Report
<ul>
<li style='display:none'>Report1</li>
<li style='display:none'>Report2</li>
<li style='display:none'>Report3</li>
</ul>
</li>
</ul>
</div>
JavaScript does it fairly easy. You would need expand on this to execute this check every on the relevant list every time you hide or show a list item.
function isHidden(array) {
for(var i = 0; i < array.length - 1; i++) {
if(array[i+1].style.display != "none") {
return false;
};
};
return true;
};
var children = document.getElementById("report").getElementsByTagName("LI");
if (isHidden(children)) {
document.getElementById("report").style.display = "none";
};
You can use the the .is(':visible')
See the code:
(function($) {
$(document).ready(function() {
var $mainLinks = $('#MenuSection > ul > li');
$.each($mainLinks, function() {
if (!$(this).find('li').is(':visible')) {
$(this).hide();
}
});
});
})(jQuery);
#MenuSection > ul > li:last-child li {
display: none;
}
#MenuSection > ul > li:first-child li:first-child {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="MenuSection">
<ul>
<li>Master // Main Menu
<ul>
<li>Master1</li>
<li>Master2</li>
<li>Master3</li>
</ul>
</li>
<li>Transaction // Main Menu
<ul>
<li>Transaction1</li>
<li>Transaction2</li>
<li>Transaction3</li>
</ul>
</li>
<li>Report // Main Menu
<ul>
<li>Report1</li>
<li>Report2</li>
<li>Report3</li>
</ul>
</li>
</ul>
</div>
I have this custom js code for basic (open/close) menu movement that was great when I used it on multi page websites, but it only closes the menu when you click the menu symbol. Now I need to implement it into a one page website and I need it to close after a user clicks on a menu item. I have very little experience in javascript so I need help solving this problem.
The js:
$(document).ready(function() {
var n = '#nav', no = 'nav-open';
$('#nav-menu').click(function() {
if ($(n).hasClass(no)) {
$(n).animate({height:0},300);
setTimeout(function() {
$(n).removeClass(no).removeAttr('style');
},320);
}
else {
var newH = $(n).css('height','auto').height();
$(n).height(0).animate({height:newH},300);
setTimeout(function() {
$(n).addClass(no).removeAttr('style');
},320);
}
});
});
The HTML:
<!-- Navigation Bar -->
<div class="nav-hold">
<div class="nav-bar">
<img src="images/logo.png" alt="logo" />
Company name
<a id="nav-menu" class="nav-menu-symbol">☰<!-- menu symbol --></a>
<a class="nav-menu">Menu</a>
<ul class="nav-list" id="nav">
<li>Top</li>
<li>About us</li>
<li>Services</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
</div>
</div>
</div>
change
$('#nav-menu').click(function() {
if you want that your menu close only by clicking on the li element
$('#nav li').click(function() {
or if you want to close menu with both li and menu icon
$('#nav-menu, #nav li').click(function() {
That's because you only bind the click function to the menu symbol. I'm not sure why you separate the symbol and text, but I would prefer to wrap it in single element. Also you can use jQuery slideToggle() to slide down or up on click. Example:
$(document).ready(function() {
$('#nav-menu').click(function() {
$('#nav').slideToggle(300);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav-hold">
<div class="nav-bar">
<img src="images/logo.png" alt="logo" />
Company name
<a id="nav-menu" class="nav-menu-symbol">
<span>☰</span>
<span>Menu</span>
</a>
<ul class="nav-list" id="nav">
<li>Top</li>
<li>About us</li>
<li>Services</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
</div>
</div>
</div>
I have my markup like this:
<div class="wrapper-header">
<div class="container">
<div class="navbar">
<ul class="nav navbar-nav">
<li class="">Show Categories</li>
</ul>
</div>
</div>
<div class="wrapper-categories">
<div class="container">
Content Here
</div>
</div>
The .wrapper-categories is display: none; by default, so it only shows once clicked with:
$(".toggle").on('click', function (event){
event.preventDefault();
$(".wrapper-categories").slideToggle("fast");
$(this).html(function(i,html) {
if (html.indexOf('Browse') != -1 ){
html = html.replace('Show','Hide');
} else {
html = html.replace('Hide','Show');
}
return html;
});
});
Now, I'd like to change that to showing on hover instead of on click, with the .wrapper-categories staying open if someone moves their mouse over and closing if it's not on the link or the content div anymore.
I tried replacing changing it to $(".toggle").hover(function() { and that worked, but it's not staying open. What else must I do?
Your code isn't working the way you desire is because the hover event of .toggle works only for itself. As soon as you try to move the mouse cursor over its contents i.e, under .wrapper-categories, the cursor goes out of the .toggle scope.
Here's a working example of how you need to implement this. You need to slightly change the structure of the menu you want to create using a simple structure of ul and li.
Here's is the FIDDLE.
HTML:
<ul class="nav navbar-nav">
<li class="menu">Show Categories
<ul>
<li>
Content Here
</li>
<li>
Content Here
</li>
<li>
Content Here
</li>
</ul>
</li>
</ul>
JS:
$(".menu").mouseover(function(){
$(this).find('ul').css('visibility', 'visible');
});
$(".menu").mouseout(function(){
$(this).find('ul').css('visibility', 'hidden');
});
CSS:
.menu > ul{
visibility:hidden;
}
.menu > ul > li:hover{
font-weight:bold;
}
Here is the solution for your problem.
https://jsfiddle.net/44wrL4g4/2/
I wrapped all in a menu class.
And I have used mouseleave() instead of mouseout(). See the Jquery documentation for these functions.
See the code for further understanding.
I am kind of confused why my code doesn't work correctly, I hope You will tell me what I've done wrong.
I want to highlight navigation tab while clicked.
HTML:
<header class="mainheader">
<!-- Obrazek tutaj-->
<nav>
<ul>
<li><a id="a-home" onclick="dodajAktywne(this)" href="index.html">Home</a></li>
<li><a id="a-omnie" onclick="dodajAktywne(this)" href="omnie.html">O mnie</a></li>
<li><a id="a-kurs" onclick="dodajAktywne(this)" href="kurs.html">Kurs</a></li>
<li><a id="a-kontakt" onclick="dodajAktywne(this)" href="kontakt.html">Kontakt</a></li>
</ul>
</nav>
</header>
JavaScript:
function dodajAktywne(elem) {
var a = document.getElementsByTagName('a')
for (i = 0; i < a.length; i++) {
a[i].classList.remove('active');
}
elem.classList.add('active');
}
CSS:
.active {
color: blue;
background-color: #cf5c3f;
}
You can simplify your JavaScript to:
Fiddle
function dodajAktywne(elem) {
// get all 'a' elements
var a = document.getElementsByTagName('a');
// loop through all 'a' elements
for (i = 0; i < a.length; i++) {
// Remove the class 'active' if it exists
a[i].classList.remove('active')
}
// add 'active' classs to the element that was clicked
elem.classList.add('active');
}
If you pass the parameter this in your HTML to:
<header class="mainheader">
<!-- Obrazek tutaj-->
<nav>
<ul>
<li><a id="a-home" onclick="dodajAktywne(this)" href="#">Home</a>
</li>
<li><a id="a-omnie" onclick="dodajAktywne(this)" href="#">O mnie</a>
</li>
<li><a id="a-kurs" onclick="dodajAktywne(this)" href="#">Kurs</a>
</li>
<li><a id="a-kontakt" onclick="dodajAktywne(this)" href="#">Kontakt</a>
</li>
</ul>
</nav>
</header>
Note: I've changed href attribute to #, you will have to change it back to your .html pages
Alternatively, you can do this without JavaScript, using CSS's :focus:
Fiddle
a:focus {
color: blue;
background-color: #cf5c3f;
}
This code will highlight the navigation tab without needing to include onclick in the HTML, though it doesn't remove the background color if another tab is clicked.
document.onclick = function(event) {
var target = event.target || event.srcElement;
target.style.background = '#cf5c3f';
};
https://codepen.io/mdmcginn/pen/BwrNaj/
var list = document.querySelector('ul');
list.addEventListener('click', function(ev) {
if (ev.target.tagName === 'LI') {
ev.target.classList.toggle('checked');
}
}, false);
I'm using the following script to generate a horizontal drop down menu on a site. It works wonderfully in Firefox and Safari, but fails in IE8 (surprise surprise). The intended behavior is that when a main menu item with a submenu is hovered over in the navigation list, the corresponding submenu will appear and any existing submenus in the .submenu div will disappear. In IE8, though, only one of the menu items will display its corresponding submenu (and then only after the link to the left of it, a link without a submenu, has been hovered), and its doing so disables the CSS hover effect on the links. Here's a live example.
I'm not experienced enough in jQuery to know why I might be running into issues, so I'm asking the good folks at StackOverflow for help. Thanks!
(Edit: I'm also running ie7.js on this particular page-- I don't know if that will effect anything or not, but I thought it would be worth mentioning)
$(document).ready(function() {
$('.submenu ul').hide(); //hide all submenus
var msec = document.location.href; //get current url
var mshref = msec.split("/"); //trim URL to include only current section
$('.submenu ul[class~='+mshref[3]+']').show(); //show submenu belonginging to current section
$('.topmenu a').hover(function(){
var msection = $(this).attr("href");
var msechref = msection.split("/");
if($('.submenu ul[class~='+msechref[3]+']').length){ //if there's a submenu belonging to this section
$('.submenu ul').hide();//hide all submenus
$('.submenu ul[class~='+msechref[3]+']').show(); //show the submenu for the section being hovered over
}
else
{
$('.submenu ul').hide();//hide all submenus
$('.submenu ul[class~='+mshref[3]+']').show();//show submenu for current section
}
});
});
And here's the HTML.
<nav><!-- top nav -->
<div class="topmenu">
<ul class="section_list">
<li><a class="active" href="http://test/">Home</a></li>
<li>About</li>
<li>ministries</li>
<li>news</li>
<li>sermons</li>
<li>contact</li>
</ul>
</div>
<div class="submenu">
<ul class="category_list about">
<li>join us</li>
<li>our beliefs</li>
<li>our staff</li>
<li>services</li>
</ul>
<ul class="category_list ministries">
<li>adults</li>
<li>children</li>
<li>preschool</li>
<li>youth</li>
</ul>
</div>
</nav><!-- end of top nav -->
EDIT - Can you try this instead of yours:
$(document).ready(function() {
var root = 'http://www.qualprnt.com/clients/fbcw/', $submenu = $('.submenu ul');
$submenu.hide();
var current = location.href.replace(root, '').split('/')[0];
if(current != '') {
$submenu.filter('.' + current).show();
}
$('.topmenu a').mouseenter(function(){
var section = this.href.replace(root, '').split('/')[0];
$submenu.hide();
if(section != '') {
$submenu.filter('.' + section).show();
}
else {
if(current != '') {
$submenu.filter('.' + current).show();
}
}
return false;
});
});
With this solution, you have to change root variable after you move the site to it's original domain. Please let me know if it works.
I will not delete my old answer, maybe it'll be useful for someone else.
OLD ANSWER:
If you're willing to change your CSS and HTML a little then this solution might be better for you.
HTML:
<nav><!-- top nav -->
<div class="topmenu">
<ul class="section_list">
<li><a class="active" href="http://test/">Home</a></li>
<li>About
<ul class="category_list">
<li>join us</li>
<li>our beliefs</li>
<li>our staff</li>
<li>services</li>
</ul>
</li>
<li>ministries
<ul class="category_list">
<li>adults</li>
<li>children</li>
<li>preschool</li>
<li>youth</li>
</ul>
</li>
<li>news</li>
<li>sermons</li>
<li>contact</li>
</ul>
</div>
</nav><!-- end of top nav -->
Javascript:
$(document).ready(function() {
$('.section_list > li').hover(
function() {
var $this = $(this);
if($this.has('ul')) {
$this.find('ul').show();
}
},
function() {
var $this = $(this);
if($this.has('ul')) {
$this.find('ul').hide();
}
}
);
});
change your script tags:
<script>
to
<script type="text/javascript">