JS Menu keep menu state - javascript

I have this HTML Code:
<div id="nav">
<li>Dashboard</li>
<li><a>Contacts</a>
<ul>
<li><strong>Companies</strong></li>
<li>Add Company</li>
<li>View Company</li>
</ul>
</li>
</div>
and this JS:
<script>
$(document).ready(function () {
$('#nav > li > a').click(function(e){
if ($(this).attr('class') != 'active'){
$('#nav li ul').slideUp();
$(this).next().slideToggle();
$('#nav li a').removeClass('active');
$(this).addClass('active');
}
});
});
</script>
for my vertical menu but i cant work out how to keep the menu state when the page changes.
for example, if the is expanded, how can i keep it expanded if the page changes?
here is the CSS to:
#nav {
float: left;
margin-left:5px;
margin-top:-20px;
top:0;
left:0;
width: 100%;
list-style:none;
}
#nav li a {
display: block;
padding: 8px 10px;
margin-bottom:0;
background: #666666;
border-top: 1px solid #EEEEEE;
border-bottom: 1px solid #EEEEEE;
text-decoration: none;
color: #EEEEEE;
width:155px;
}
#nav li a:hover, #nav li a.active {
background: #F36F25;
color: #FFFFFF;
cursor:pointer;
}
#nav li ul {
display: none;
list-style:none;
}
#nav li ul li {
margin-top:0;
margin-right:0;
margin-bottom:0;
margin-left:-40px;
}
#nav li ul li a {
background: #EEEEEE;
color:#666666;
border:1px solid #EEEEEE;
}
#nav li ul li a:hover {
background: #EEEEEE;
color:#f36f25;
border:1px solid #f36f25;
}

I would suggest using sessionStorage in this scenario. It's a great tool in this case, and it is widely supported, but see http://caniuse.com/namevalue-storage to see if its suitable for your needs. What you can do is use sessionStorage to keep track (client-side) of your currently expanded menu so you can expand the correct menu on a page reload. This answer is not 100% correct in the sense that you can't just plug it in directly into your code (I would have had to guess at several things) but it should give you a fairly idea of where to go. Note that in the code below, I changed link hrefs to point to JSFiddle because that is where I made a working example, but hopefully this will get you on the right track to implement it in your own pages.
One of the main things necessary to change is to give main menu <a> tags an ID (below, they are menuDashboard and menuContacts). These would have to be consistent across your different pages, and also the scripts below would have to be included in all the pages where you want to keep the menu state. Then the basic premise is that on menu click, we store the currently expanded menu <a> ID into sessionStorage so we can access that after a page reload. Then, on page load, we look at sessionStorage to see what was previously selected by retrieving the key "activeMenuItemID", and if we find that is not undefined, we expand that menu item.
Working example: http://jsfiddle.net/VBLS8/2/show/
Note, because of how JSFiddle is built, the previous link is a link directly to JSFiddle Results iframe is. Otherwise, when clicking the links JSFiddle just breaks. The actual JSFiddle is here: http://jsfiddle.net/VBLS8/2/.
<br/>
<div id="nav">
<li>
<a id="menuDashboard">Dashboard</a>
<ul>
<li><strong>Sub Category</strong></li>
<li>Sample 1</li>
<li>Sample 2</li>
</ul>
</li>
<li>
<a id="menuContacts">Contacts</a>
<ul>
<li><strong>Companies</strong></li>
<li>Add Company</li>
<li>View Company</li>
</ul>
JavaScript:
$(document).ready(function(){
//Loop through nav items, compare to expanded item ID from sessionStorage so we can expand whichever item was previously expanded
if(sessionStorage.getItem("activeMenuItemID") != undefined){
$("#nav > li > a").each(function(){
if ($(this).attr("id") == sessionStorage.getItem("activeMenuItemID")){
expandMenuItem(this);
}
});
}
$('#nav > li > a').click(function(elem){
expandMenuItem(this);
});
});
function expandMenuItem(elem){
if ($(elem).attr('class') != 'active'){
$('#nav li ul').slideUp();
$('#nav > li > a').removeClass("active");
$(elem).addClass("active");
$(elem).next().slideToggle();
sessionStorage.setItem("activeMenuItemID", $(elem).attr("id"));
}
}

When the page changes, the click handler gets bound, but there is no statement handling the initial state of the menu.
So...
$(document).ready(function() {
//original click handler
//$('#nav a').click
//but also this piece of code, that will display all the lists having an .active link inside
$('#nav ul').has('a.active').show();
});
Regards and good luck!
A quick but a little dirty solution to keep track of your currently active page is to compare the src attribute of your target frame with the href attribute of your links.
Edit: The following fiddle might help you a bit: fiddle

Related

How to stay the Jquery function when the page is reload

How can I stay the Jquery functions when it leaves the page?
The code below is running good when the link is blank/#, but When I change the # and make it the path link, the jquery seems not running properly. I click it, it change the background but when it goes to the link the background was gone, is there something I miss in the code?
$(document).ready(function(e){
$('#main-menu li a').click(function(e) {
$('#main-menu li a').removeClass('active');
$(this).addClass('active');
});
});
#main-menu li {
display: inline-block;
font-family: 'Raleway', sans-serif;
padding: 17px 25px;
}
#main-menu li a {
color:#333333;
font-size:15px;
}
#main-menu li.active a {
color:#0198cf;
}
#main-menu li:last-child {
padding-right: 0;
}
.active{
background-color:#ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="topnav" id="main-menu">
<li ></i> Home</li>
<li></i> Home2</li>
<li></i> Home3</li>
<li></i> Home4</li>
</ul>
Add this script:
$(function () {
var url = window.location.pathname,
urlRegExp = new RegExp(url.replace(/\/$/, '') + "$");
$('#main-menu li a').each(function () {
if (urlRegExp.test(this.href.replace(/\/$/, ''))) {
$(this).addClass('active');
$(this).parent().previoussibling().find('a').removeClass('active');
}
});
});
You need to stop default behavior of a element. You should call preventDefault function for your a click event:
$(document).ready(function(e){
$('#main-menu li a').click(function(e) {
e.preventDefault();
$('#main-menu li a').removeClass('active');
$(this).addClass('active');
});
});
If the user is traveling off of the current page, the styles modified by jQuery will be gone permanently, as they are not saved anywhere.
However, using javascript you can store cookies, and if that cookie exists, you can add the background style you desire.
See https://www.w3schools.com/js/js_cookies.asp for more insight into storing cookies.

Trigger completely separate div based on hover of other div

Is it possible to trigger changes to CSS of an element that is completely unrelated to the hovered div?
I have a CSS hover effect on a dropdown menu, that I also want to trigger the opacity of a div right at the bottom of the page to create a background overlay effect.
This is the CSS I'm using:
#overlay {
background:rgba(0,0,0,0.5);
position:absolute;
top:120px;
left:0;
z-index:0;
height:120%;
width:100%;
visibility:hidden;
opacity:0;
}
#menu-main-menu li.menu-parent-item:hover ul.sub-menu,
#menu-main-menu li.menu-parent-item:hover #overlay {
visibility:visible;
opacity:1;
}
The hover of the sub menu works fine, but the div #overlay is right at the bottom of the page, and doesn't get called when it's hovered.
I've tried all kinds of alternatives such as :hover > #overlay, :hover + #overlay, but nothing seems to trigger it. I also can't seem to find a definitive answer to the question.
Is it possible?
Yes. You can load this style in a php file and then use jQuery to apply the css when your div has been hovered on.
No there is no way to select parent element in css and that means that you cannot move up in hierarchy.
<ul class="hover-parent">
<li></li>
</ul>
<div>Something here</div>
<div class="target"></div>
From this point :
.hover-parent li:hover you cannot go up (to ul or div).
Selectors which you tried to use are "next":
A>B - This will select only direct B children of A
A+B This will select B immediately preceded by A
Here you can find W3C documentation of CSS selector
http://www.w3.org/TR/CSS2/selector.html#adjacent-selectors
And demos:
http://code.tutsplus.com/tutorials/the-30-css-selectors-you-must-memorize--net-16048
Notice that it will be really confusing for user that different part off app/page is changing when he is hovering something else. Bad UX idea.
You're going to have to use JavaScript to do this.
Your posted selector #menu-main-menu li.menu-parent-item:hover #overlay is looking for #overlay somewhere inside of an ancestor element of li.menu-parent-item that is somewhere inside of an ancestor element with an id of #menu-main-menu.
Using the child selector > will not work as the overlay element is not a child of the list element you're hovering in your menu from what you have described and from comment responses.
As #Paulie_D has pointed out the two target elements, the element to be hovered and the overlay element, need to adjacent siblings to use the sibling selector +. From what you have described and the comment responses they are not adjacent siblings.
I have setup a basic example for you using jQuery. This example displays the overlay as long as you are hovering any element in the .main-menu element.
HTML
<ul class="main-menu">
<li>Item One</li>
<li>Item Two</li>
<li>Item Three
<ul class="sub-menu">
<li>Sub Item One</li>
<li>Sub Item Two</li>
<li>Sub Item Three</li>
<li>Sub Item Four</li>
<li>Sub Item Five</li>
</ul>
</li>
</ul>
<main>
Content here.
</main>
<footer>
<div class="overlay">This is my overlay.</div>
</footer>
CSS
body {
margin: 25px auto;
width: 500px;
}
ul,
li {
margin: 0;
padding: 0;
}
main {
min-height: 300px;
}
footer,
.overlay {
height: 50px;
}
footer {
position: realative;
background-color: yellow;
}
.main-menu {
list-style: none;
height: 50px;
}
.main-menu > li {
float: left;
padding: 0 10px;
position: relative;
}
.main-menu > li:hover .sub-menu {
display: block;
}
.sub-menu {
display: none;
list-style: none;
position: absolute;
left: 10px;
width: 150px;
}
.overlay {
display: none;
text-align: center;
}
jQuery
$overlay = $('.overlay');
$('.main-menu > li').hover(
// when hovered
function() {
$overlay.css('display','block');
},
// when NOT hovered
function() {
$overlay.css('display','none');
}
);
jsFiddle: http://jsfiddle.net/ednf2pzq/
Edit
You could simplify the jQuery hover selector to .main-menu.
jQuery
$('.main-menu > li').hover(
// same code as before
);
jsFiddle: http://jsfiddle.net/ednf2pzq/1/

Change color <li>

I'm building a survey and what I'm trying to do now is that when someone clicks an answer (for example: 8) in my list, the background of that answer changes color. This has to work for each seperate answer (there are 60 questions).
The list html/css code:
<div class="answers">
<ul>
<li class="liFirst">1</li>
<li class="liMiddle">2</li>
<li class="liMiddle">3</li>
<li class="liMiddle">4</li>
<li class="liMiddle">5</li>
<li class="liMiddle">6</li>
<li class="liMiddle">7</li>
<li class="liMiddle">8</li>
<li class="liMiddle">9</li>
<li class="liLast">10</li>
</ul>
</div>
.answers {
float: right;
width: 400px;
height: auto;
margin: 0;
background: #DFE5E3;
}
.answers ul {
display: inline-block;
}
.answers li {
float: left;
padding: 0 auto;
font-weight: bold;
}
I've already researched it a bit but can't seem to find a solution that works. I suppose I have to do this in JS/jQuery?
Tried this solution: link! but didn't seem to work for me
add an active class
.active{
background:#000;
color:#FFF;
}
and in jquery toggle class
$('ul li').on('click',function(){
$(this).toggleClass('active');
});
if he wants to choose only one answer
$('ul li').on('click',function(){
$(this).toggleClass('active').siblings().removeClass('active');
});
You can do this with the following:
JQuery
$(document).on('click', '.answers ul li', function(){
$(this).toggleClass('selected').siblings().removeClass('selected');
});
CSS
.answers li.selected {
background: yellow;
}
You probably want to remove the selected background effect one other <li>s once you click on one.
DEMO
If you want to stay strictly CSS based, this checkbox hack may be your best bet... http://css-tricks.com/the-checkbox-hack/
Which can also be implemented with radio buttons to ensure only one answer can be chosen.
jQuery
$( "ul" ).on( "click", "li", function() {
$("li").removeClass("selected");
$(this).addClass("selected");
});
CSS
.selected { background-color:lime;}
JSFiddle Demo

Jquery Drop Down menu blinks only on IE

I am starting a Jquery drop down menu for a new project and it is working as expected on Google Chrome, Firefox, Safari but of course it is giving me some headache on Internet Explorer.
here's the thing,
See this page
http://www.universidadedoingles.com.br/dev/index.ASP
on mouse over the menu HOME, the drop down appers, when you move over the links in IE you see some flashes of the background, which doesn't happens on Chrome and ETC.
here's the js coda I am using to do the dd menu.
<script type="text/javascript">
$(document).ready(function() {
$("ul.mainmenu li.menuhome").mouseover(function(){
$(".arrow-spacer").show(); //When mouse over ...
//Following event is applied to the subnav itself (making height of subnav 150px)
$(this).find('.submenu').show().animate({height: '150px', opacity:'1'},{queue:false, duration:300})
});
$("ul.mainmenu li.menuhome").mouseout(function(){ //When mouse out ...
//Following event is applied to the subnav itself (making height of subnav 0px)
$(this).find('.submenu').hide().animate({height:'0px', opacity:'0'},{queue:false, duration:200})
});
//menu itembackground color animation
$("li").hover(function() {
$(this).animate();},
function() {
$(".arrow-spacer").hide();
});
});
</script>
That's it, I guess it may be simple, but it's been weeks and I still can't get it to work.
Thanks a lot.
I noticed that the anchor <a> tags have a margin on them. My first thing would be to try using padding instead. IE doesn't treat a hover in the margin the same way as other browsers.
in some cases it helps to set a z-index on elements that should placed in top of other elements.
In your case I would try to set the z-index on <ul class="submenu">
No blinks anymore! I changed one word hide() to stop (), now there is no blinking on iE. but...
After you show the menu 1 time, everytime you get your mouse below the link or close the link, the menu shows up again.
check this
www.universidadedoingles.com.br/dev
you'll be able to see its behavior
The thing is that the focus to <li> is lost when you mouse over an <a> element.
Here is something you could use to overcome this. I avoided using the <a> tag, instead I used a JavaScript function to send the user to the preferred location. I used JavaScript rather than jQuery hoping to make it more self-explanatory.
<script type="text/javascript" src="jquery.js" ></script>
<script type='text/javascript'>
$(document).ready(function() {
$('#n li').hover(function() {
$('ul', this).slideDown(200);
$(this).children('a:first').addClass('h');
}, function() {
$('ul', this).slideUp(200);
$(this).children('a:first').removeClass('h');
});
});
function gotoPage(pnumber){
var goto;
if(pnumber==1){
goto="home.html";
}else if(pnumber==2){
goto="watsnew.html";
}else if(pnumber==3){
goto="aboutus.html";
}else if(pnumber==4){
goto="contactus.html";
}
window.location.href=goto;
}
</script>
<style type="text/css">
#n {
padding: 0;
list-style: none;
padding-left: 15px;
padding-right: 15px;
width:5em;
}
#n li {
/*display:inline;*/
background: none;
position: relative;
z-index: 1;
font-weight:bold;
margin: 0 auto;
}
#n li .h {
background-color: #fff;
border-left: 1px solid #CF3;
border-right: 1px solid #CF3;
color: #576482;
height:20px; }
#n ul {
position: absolute;
display: none;
margin: 0; padding: 0;
list-style: none
padding-bottom: 3px;
width:200px;
}
#n ul li {
list-style-type:none;
padding:10px;}
#n ul li:hover {
background:#960;}
</style>
<div>
<ul id="n">
<li>MENU
<ul >
<li value="1" onclick="gotoPage(this.value)">HOME</li>
<li value="2" onclick="gotoPage(this.value)">WATS NEW</li>
<li value="3" onclick="gotoPage(this.value)">ABOUT US</li>
<li value="4" onclick="gotoPage(this.value)">CONTACT US</li>
</ul>
</li>
<ul>
</div>

Detecting is Div Out Of Screen

I coded dropdown menu via javascript(w/ jQuery) and CSS. Dropdown menu works fine but if dropdown menu located at corner for example rightmost or leftmost of user screen then if user opens the dropdown menu, it overflows to unseen area of window and causes horizontal scroll-bar.
How can I stop overflowing ?
HTML
<ul class="dropdown">
<li class="headlink">
Menu <img src="/static/images/mini/sort_down.png" />
<ul class="arrowlist invisible">
<li>Hello 1</li>
<li>Hello 2</li>
<li>Hello 3</li>
</ul>
</li>
</ul>
CSS
.dropdown {z-index: 1}
.dropdown .headlink{border:1px solid #C7C9CF;padding:4px 6px;}
.dropdown li{}
.dropdown a{outline:none}
.dropdown ul{z-index:100;border:1px solid #C7C9CF;-moz-border-radius: 4px; -webkit-border-radius: 4px;border-radius:4px;behavior: url(/static/css3pie.php);background: #FFF url("/static/images/grey_fade_back.png") repeat-x scroll bottom;padding:8px;position:absolute;top:-1px;left:-4px}
.dropdown ul li{margin:2px;white-space:nowrap}
JS
$('.dropdown li.headlink')
.click(function() {
$(this).css('position', 'relative');
$('ul', this).slideDown(100);
});
$('.dropdown li.headlink')
.mouseleave(function(){
var headlink = this;
$('ul', this).slideUp(100, function(){
$(headlink).css('position', 'static');
})
});
I found a solution:
$('.dropdown li.headlink')
.click(function() {
$(this).css('position', 'relative');
if($('ul', this).width() + 10 > $(window).width() - $(this).offset().left) $('ul', this).css('left', 'auto').css('right', '-1px');
else $('ul', this).css('left', '-4px').css('right', 'auto');
$('ul', this).slideDown(80);
});
I think you may need to store in a var the height in px of your drop down and check its y-offset. This post might be able to point you in the right direction How to see if an element in offscreen I wish I could provide you with working code.
Try this
replace:
.dropdown .headlink{border:1px solid #C7C9CF;padding:4px 6px}
with
.dropdown .headlink{border:1px solid #C7C9CF;padding:4px 6px;position:relative}
and replace
.dropdown ul {
z-index:100;
border:1px solid #C7C9CF;
-moz-border-radius:4px;
-webkit-border-radius:4px;
border-radius:4px;
behavior:url(/static/css3pie.php);
background:#FFF url(/static/images/grey_fade_back.png) repeat-x scroll bottom;
position:absolute;
top:-1px;
left:-4px;
padding:8px;
}
with
.dropdown ul {
z-index:100;
border:1px solid #C7C9CF;
-moz-border-radius:4px;
-webkit-border-radius:4px;
border-radius:4px;
behavior:url(/static/css3pie.php);
background:#FFF url(/static/images/grey_fade_back.png) repeat-x scroll bottom;
position:absolute;
left:-4px;
padding:8px;
}
Hope it helps
The general solution to a problem like this is to, using either CSS or JavaScript, add a class to the first or last dropdown menu element so that it's alignment is corrected. In this specific case, with absolute positioning, changing the left and right property should do.
A simple example, for when the menu is right aligned and the right-most dropdown protrudes out of the screen, is to add a class with JavaScript which will shift the menu from the been aligned to the left side of the menu item to the right:
.dropdown ul {
left: 0;
}
.dropdown ul.last {
right: 0;
left: auto;
}
A simple demo of this can be found here: http://www.jsfiddle.net/yijiang/HyXuy/1/

Categories