Show current section's heading in a fixed position on side - javascript

For a one-page layout website I would need the current section's heading to display in a fixed position on the left side of the screen in order to show the user where he currently is.
The heading will probably have an icon on its left side. I would like the floating heading to be only visible when the user is scrolling on the page, thus disappear when he halts, while the icon stays visible all the time. Is that possible?

This is possible, and most easily done in JQuery. In CSS using
position: fixed;
Will allow you to position a element, then it'll stick where it is on the screen, regardless of the user scrolling up and down the page. Using this JQuery code:
$(window).scroll(function(){
}
Will detect when the user scrolls then will run whatever is inside of the function. If you put this inside of the function:
$("#scrollerbar").css({"display": "block"});
clearTimeout($.data(this, 'scrollTimeout'));
$.data(this, 'scrollTimeout', setTimeout(function() {
$("#scrollerbar").css({"display": "none"});
}, 250));
With this HTML:
<div id="scrollerbar">You're scrolling</div>
And the following CSS:
#scrollerbar{
display: none;
position: fixed;
top: 50px;
left: 0;
}
This will create and position the div scrollerbar 50px down the page and set it to be invisible. Then whenever the user scrolls, it will set the scrollerbar to display: block (which makes it visible). Then stops the timeout "scrollTimeout" (if it's running). Then create the timeout "scrollTimeout" what will wait 250 milliseconds then set scrollerbar to invisible again.
Here's a JSFiddle: http://jsfiddle.net/Xanco/5q6oq8tm/
Please contact me if you have some questions.
EDIT
In order to answer the first part of your question, I've updated the JSFiddle: http://jsfiddle.net/Xanco/5q6oq8tm/2/
The scrollerbar contains a set of list items, each will be bound to a div:
<li id="1read">Reading 1</li>
<li id="2read">Reading 2</li>
<li id="3read">Reading 3</li>
<li id="4read">Reading 4</li>
There's also a new class name:
.active{
font-weight: bold;
}
I've created a function that will remove all "active" class names from the list items in the scrollerbar:
function removeActive(){
$("#1read").removeClass("active");
$("#2read").removeClass("active");
$("#3read").removeClass("active");
$("#4read").removeClass("active");
}
And now whenever the user scrolls, JavaScript will check what the user is currently reading and add the "active" class to the appropriate list items in the scrollerbar:
if ($("#1").is(":hover")) {
removeActive();
$("#1read").addClass("active");
}
if ($("#2").is(":hover")) {
removeActive();
$("#2read").addClass("active");
}
if ($("#3").is(":hover")) {
removeActive();
$("#3read").addClass("active");
}
if ($("#4").is(":hover")) {
removeActive();
$("#4read").addClass("active");
}
EDIT 2
Now, the JavaScript will take the innerText of a child of the hovered div with the ID "articleheader" instead of using a non-standard attribute, as demonstrated by this line of code:
$("#displayaArticleName").text($(this).children("#articleheader")[0].innerText);
Here is the JSfiddle: http://jsfiddle.net/5q6oq8tm/6/
Please note that there are no set of attributes that can only be used, you may use custom attributes, as demonstrated here: http://jsfiddle.net/5q6oq8tm/4/

Related

bubbling in a simple menu using html, css and javascript

In the code below for a simple menu, if the sub-menu is expanded/showing, then I need the sub-menu to collapse on several conditions:
When the main menu or sub-menu LI is clicked
When the viewport is larger than the defined minimum width
When a click happens anywhere else on the screen
Number 2 works and number 1 works as long as I don't declare the addEventListener for the mainMenuID element. For some reason, when I add that event listener for any mainMenuID element, it takes precedence over anything else thus clicking on a main menu item other than Portfolio or its sub-menu items, expands and collapses the menu, but clicking on the submenuID or the ulID does nothing. As soon as I remove the eventlistener for mainMenuID, clicking on submenuID or ulID expand/collapse the sub-menu.
The second question is, how do I add a click event listener to the rest of the page so that if the sub-menu is showing, the click collapses the sub-menu.
Thank you!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
</head>
<style media="screen">
body{
background-color: black;
}
nav ul {
position: relative;
text-align: left;
}
nav ul li {
display: block; /* WHAT???? REMOVING THIS ACTUALLY MAKES TEXT-DECORATIONS REAPPEAR.... WHY???*/
}
nav a {
text-decoration: none;
}
/* Hide dropdowns by default */
nav ul ul {
position: relative;
display: none;
left: 0;
}
/* Display Dropdowns on Click */
nav ul li.showSubmenu > ul {
display: block;
position: relative;
width: 30%;
}
.menu a {
text-decoration-style: none;
text-decoration: none;
background-color: black;
color: white;
}
.menu a:hover{
background-color: white;
color: black;
}
</style>
<body>
<nav id="mainMenuID" class="menu">
<ul>
<li class="menuItem">Home</li>
<li class="menuItem">About</li>
<li id="submenuItem" class="submenu_class"><span id="submenuID">Portfolio ▼</span>
<ul id="ulID">
<li>Landscape</li>
<li>Architecture</li>
<li>Animal</li>
<li>Other</li>
</ul>
</li>
<li class="menuItem">Information</li>
<li class="menuItem">Contact</li>
</ul>
</nav>
<script>
function openSubmenu() {
if (document.getElementsByClassName('showSubmenu').length == 0){
document.getElementById("submenuItem").classList.toggle("showSubmenu");
document.getElementById("submenuID").textContent = "Portfolio ▲";
} else {
document.getElementById("submenuItem").classList.toggle("showSubmenu");
document.getElementById("submenuID").textContent = "Portfolio ▼";
}
}
function resetSubmenu() {
var submenuElements = document.getElementsByClassName('submenu_class showSubmenu');
for (var i = 0; i < submenuElements.length; i++) {
submenuElements[i].setAttribute('class', 'submenu_class');
document.getElementById("submenuID").textContent = "Portfolio ►";
}
}
function screenWidthFunction(x) {
if (x.matches) {//if it's a narrow screen
document.getElementById("submenuID").textContent = "Portfolio ▼";
document.getElementById("ulID").addEventListener("click", openSubmenu, true);
document.getElementById("submenuID").addEventListener("click", openSubmenu, true);
document.getElementById("mainMenuID").addEventListener("click", openSubmenu, true);
} else {
resetSubmenu();
document.getElementById("submenuID").textContent = "Portfolio ►";
document.getElementById("ulID").removeEventListener("click", openSubmenu);
document.getElementById("submenuID").removeEventListener("click", openSubmenu);
document.getElementById("mainMenuID").removeEventListener("click", openSubmenu);
}
}
var x = window.matchMedia("(max-width: 480px)");
screenWidthFunction(x);
x.addListener(screenWidthFunction);
</script>
<>
Hi Robidu, I had this menu working using just CSS, but I was led to use JS for some of its functionality, which stopped most of the CSS from working.
So at glacier speeds, I’ve been trying to learn JS on the fly. Believe it or not, learning from videos, W3Schools, etc…. I’ve been writing, re-working, and kludging this menu into existence for the better part of 5 or 6 weeks. Totally ridiculous.
It seems you understand and are readily familiar with JS. It would take me many more weeks of trying to figure out how to implement all of your advice, and along the way, I would very likely destroy what already works. Is there any way I could kindly ask you to please save me that pain by providing me with either the code snippets for where they need to go, or just more specific advice.
I’ve excerpted below the parts of your text about which I have questions (because of the character limits on comments, I have to split them across multiple comments):
“…you should use CSS to hide the submenu since I think that this
is to be the default.”
q. Yes, it is the default. I thought I was already doing this in “nav
ul li.showSubmenu > ul {…}” in my CSS.
“…implement an initialization stage that fires on DOMContentReady
to set up a support infrastructure.”
q. This, I would never know how to figure out myself.
“…need a flag that indicates whether or not the menu is open so
that the handler can react accordingly…spare yourself the problem
with "toggle"…have the menu's state at hand…”
q. I thought the “toggling” of the class “showSubmenu” was serving as that kind of ‘flag’. How and where would I use the variable in place of the toggle?
“…spare yourself…repeatedly attaching and removing event
listeners.”, and later on “If the menu is hidden, it doesn't get any
events at all.”
q. Are you saying to assign the listeners to variables anywhere in the JS code? Would I not still need to refer to those variables in the same places where I use the listeners now and in the same manner?
“…attach an event listener that checks for mouse events to the
the item that opens the submenu here.”
q. You mean other than the listener I have on id=“submenuID”? What would be different about what you are advising?
“…attach a resize event handler to the window that performs this
check...”
q. I cropped the screen width code from W3’s examples. How/where would using innerWidth/innerHeight be different?
“…set the bubbling stage to true to intercept the event”.
q. I haven’t been able to find any explanation about bubbling works if you apply one kind to the items in a menu system, and another kind to other elements on a page, etc. I understand the basics, but couldn’t figure out why it wasn’t working on this simple menu when all three listeners were used.
“Collapsing the menu when a menu item is clicked…attach an event
handler to each individual menu item (the best spot would be the links inside the menu”.
q. Would I have to assign an ID to each LI?
Overall question: I used a NAV element with ULs and LIs because
I was told it’s the most accessible for screen readers. Is there a
better way to do what I’m trying to do with this menu or am I sort
of on the right track?
I sincerely apologize for all the follow-up questions/clarifications, but I’m sincerely spinning my wheels on this, going in circles, in rough seas, wearing a blindfold…. and any other analogy you can throw into the mix.
I would truly appreciate any specific coding you can provide to demonstrate the specifics of your advice. (or even point me to examples so that I can try and figure them out).
A bit of retooling should do the trick here.
First of all, you should use CSS to hide the submenu since I think that this is to be the default. Furthermore you should implement an initialization stage that fires on DOMContentReady to set up a support infrastructure. This way you spare yourself the hassle with repeatedly attaching and removing event listeners. You would want to attach an event listener that checks for mouse events to the item that opens the submenu here. You would also need a flag that indicates whether or not the menu is open so that the handler can react accordingly (this way you spare yourself the problem with "toggle" and the likes, plus you immediately have the menu's state at hand if you need to do any additional checks). A simple variable should do the trick here.
The plus side: If the menu is hidden, it doesn't get any events at all.
If you are interested in the window size, I'd recommend that you switch to window.innerWidth / window.innerHeight instead, because that is a numeric value that you get and which can easily be compared to the minimum size that you require. Just attach a resize event handler to the window that performs this check, and you are set. If the window size cuts below your minimum, just force the menu to collapse.
As far as collapsing the menu if the user clicks anywhere within the document, attaching an event listener looking for mouse clicks / key presses to the document object does the trick here (set the bubbling stage to true to intercept the event before anything else can happen).
Collapsing the menu when a menu item is clicked can best be achieved by attaching an event handler to each individual menu item (the best spot would be the links inside the menu - set the bubbling stage to false) that merely closes the menu.
EDIT:
I have done some tinkering now by taking your HTML and CSS, and this is what I have come up with (please note that I have also transformed the file to XHTML - but that's up to you whether or not you want to do that):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xml:lang="en">
<head>
<title>Submenu Test Case</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style type="text/css">
body {
background-color: black;
color: white;
}
aside {
width: 15em;
float: left;
}
nav ul {
position: relative;
text-align: left;
list-style: none; /* Kills any list decoration */
}
nav ul ul {
position: relative;
left: 0;
}
nav a {
text-decoration: none;
}
/* This ARIA attribute can greatly improve accessibility and can also be used
to actually hide elements just by tying "display: none;" to it... */
[aria-hidden="true"] {
display: none;
}
.menu a {
color: white;
}
.menu a:hover, .menu span:hover {
background-color: white;
color: black;
}
/* Style definitions that override settings for mobile devices go here! */
#media screen and (min-width: 480px)
{
/* Reposition the submenu if it's on a sufficiently wide window... */
nav ul li > ul {
position: absolute;
margin-top: -1.2em;
left: 7em;
}
}
</style>
<script type="application/javascript">
/* <![CDATA[ */
var submenu_open = false; // Has the submenu been opened?
var need_mobile = false; // Are we on a narrow window?
// Takes care of hiding and showing the submenu
function ToggleMenu(p_event)
{
// Do not activate e. g. on a right click...
if(p_event.button != 0)
return;
if(submenu_open)
{
// If the submenu has previously been open, close it (and adjust the
// controlling menu item if necessary)
document.getElementById('sub1').setAttribute('aria-hidden', 'true');
if(window.innerWidth < 480)
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▼';
}
else
{
// If the submenu has previously been closed, open it (and adjust the
// controlling menu item if necessary)
document.getElementById('sub1').setAttribute('aria-hidden', 'false');
if(window.innerWidth < 480)
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▲';
}
// This prevents the document's root node (i. e. the document object) from
// seeing the event when clicking on the superordinate item for the submenu...
p_event.stopPropagation();
submenu_open = !submenu_open;
}
// Triggered upon clicking anywhere inside of the document...
function CloseMenu(p_event)
{
if(!submenu_open)
return;
document.getElementById('sub1').setAttribute('aria-hidden', 'true');
if(window.innerWidth < 480)
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▼';
submenu_open = false;
}
function CheckWindowSize(p_event)
{
if(window.innerWidth < 480)
{
if(need_mobile)
return;
// On a mobile device, insert the submenu into the main one...
if(submenu_open)
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▲';
else
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▼';
}
else
{
if(!need_mobile)
return;
// If the window is wide enough, we can display the submenu next to the main
// one...
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ►';
}
need_mobile = !need_mobile;
}
// Initialization sequence (adds a few event handlers)
document.addEventListener('DOMContentLoaded', function (p_event) {
document.getElementById('sub-item1').addEventListener('click', ToggleMenu, false);
window.addEventListener('resize', CheckWindowSize, false);
document.addEventListener('click', CloseMenu, false);
// If we are on a mobile device, adjust the text of the menu item.
if(window.innerWidth < 480)
{
need_mobile = true;
document.getElementById('sub-item1').childNodes[0].childNodes[0].data = 'Portfolio ▼';
}
}, false);
/* ]]> */
</script>
</head>
<body>
<header><h1>Submenu Test Case</h1></header>
<aside>
<nav class="menu">
<ul>
<li class="menuItem">Home</li>
<li class="menuItem">About</li>
<!-- Assume normal operation here (window width >= 480 pixels) so the
text is set accordingly...
Please note that I have removed some extraneous elements and
attributes. -->
<li class="submenu" id="sub-item1"><span>Portfolio ►</span>
<ul id="sub1" aria-hidden="true">
<li>Landscape</li>
<li>Architecture</li>
<li>Animal</li>
<li>Other</li>
</ul>
</li>
<li class="menuItem">Information</li>
<li class="menuItem">Contact</li>
</ul>
</nav>
</aside>
<main />
</body>
</html>
Please see the annotations in the (X)HTML for details on what's going on there.
By working on this I have discovered that I could greatly simplify the method that I have mentioned yet again so it just boils down to three events:
Resize: Switches the menu layout when the window width undercuts a certain threshold
Mouse click on menu item: Opens or closes the submenu
Mouse click anywhere else: Closes the menu
As for your questions...
ad 1.: I have done a bit of retooling of the CSS that you have provided. I have tossed some definitions out and have tied hiding any elements to the aria-hidden attribute (if that is set to true, the element is not displayed). Said attrtibute also helps a lot in improving accessibility. In this example, if you cannot see it on the screen, a screenreader won't display it, either.
ad 2.: It's rather simple to set up. Just include document.addEventListener('DOMContentLoaded', function (p_event) { }, false);
in the main execution path and add anything that needs to be set up into the function. This is crucial especially for so-called unobtrusive JavaScript (that is, JavaScript that itself attaches hooks to the document where needed instead of hard-coding them into the (X)HTML).
ad 3.: You can get that done with a simple variable (a boolean that indicates whether the menu is open). You can then quickly check on the menu's state without having to query the DOM.
ad 4.: That is extremely tedious and costly at best so handlers are only attached once. The rest should be up to the control logic whether any events are silently ignored (by just returning if certain conditions aren't met).
ad 5.: It takes a handler of the sort that you have implemented, but I have simplified it a bit to avoid calling the DOM where unnecessary (it resorts to the aforementioned flag), plus it also takes into account the window's width for adjusting the text.
ad 6.: innerWidth / innerHeight are numeric values that can easily be returned by the DOM. I don't know about your method, but by my reckon it seems to be a bit expensive, plus when you store the value in a variable, you can perform multiple checks on it (e. g. if you need to check for different widths/heights), which just requires simple comparisons. Your approach would require you to reset the matching condition.
ad 7.: I need to correct myself here, because by chewing on your problem I found that everything (i. e. the third parameter to addEventListener) should be set to false. Otherwise the order of execution is messed up, or some links don't see the event in the first place.
ad 8.: Turned out to be unnecessary as well. I had derived my initial answer from a context menu that I have implemented in JavaScript, but because of its nature I had to resort to these handlers to close it. Here things are a little different so things can be simplified just by omitting these handlers.
ad 9.: You actually have picked the best way here. When implementing a navigation, I'm also using this approach.
I hope I could turn some of your question marks into exclamation marks. However, if you still have questions, by all means, please ask. There's nothing worse than questions left unanswered.

Prevent browser from re-positioning focused elements navigated to via tabbing

When you navigate through form elements or anchors using the tab key (and shift + tab) the browser automatically scrolls to that focused element. If the element is not viewable because it is a part of an overflown content where overflow is set to be hidden, it moves (or scrolls) the content's container to reveal the focused element. I want to either stop or find a way to negate this behavior
Here's something I put together to showcase the issue. I reproduced it in Chrome.
https://jsfiddle.net/charlieko/wLy7vurj/2/
var container = $("#container")
var cur = 0;
function go(increment) {
var next = cur + increment;
if (next < 0) next = 4;
else if (next > 4) next = 0;
cur = next
var newX = cur * 500;
container.css({
transform: 'translate(-' + newX + 'px, 0)'
})
}
$("#left").click(function(e) {
go(-1);
});
$("#right").click(function(e) {
go(1);
});
body {
overflow: hidden;
}
#container {
width: 2600px;
overflow: none;
transition: transform 0.4s;
transform: translate(0, 0);
overflow: hidden;
margin: 0;
}
li {
width: 500px;
text-align: center;
list-style-type: none;
float: left;
margin: 0;
padding: 0;
}
a {
color: black;
font-size: 2.0rem;
}
#ui {
position: fixed;
top: 200px;
}
#ui span {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<ul>
<li>Link 1 | ABCD EFG</li>
<li>Link 2 | HIJK LMNO</li>
<li>Link 3 | PQRSTU VW</li>
<li>Link 4 | XYZA BC</li>
<li>Link 5 | DEFG HI</li>
</ul>
</div>
<div id="ui">
<div>
<span id="left">Left</span>
|
<span id="right">Right</span>
</div>
<p>
Use left and right to move. Issue: Use tab key (and shift+tab) to navigate to any of the links. The container of the links shift to show the focused link. Notice the content is decentered when it happens.
</p>
</div>
The issue is that now there are two ways to slide the contents: via interacting with the left|right buttons and via tabbing through the links. When the user chooses to navigate using the tabs it messes up the sliding logic. The content is de-centered, and the index I saved in a variable no longer represents what's visible on the screen. I can handle the accessibility issue programmatically using an onFocus event, so this automatic behavior isn't helping anything.
Is there a way to stop this behavior? I already tried preventDefault() method on onFocus events on the anchor elements.
I was able to figure out a solution. What the browser does is that it scrolls the direct parent of the overflowing content to the position so that the focused element is right in the center. Simply modifying scrollLeft property of the parent element did the trick. So in the onFocus event of the link:
function onFocus (e) {
document.getElementById('content-parent').scrollLeft = 0;
// Code for repositioning the content itself using transform with transition animation
}
Overflow:hidden is usually good for content which is intended to scroll and move, so preventing that will be difficult. If you want the Tab control to stay only on things which are visible (including any buttons or links that update your slider), then you'll need a different method of hiding your content in addition to (or instead of) overflow.
Try display:none on your list items until they are within the open/visible part of div#container. That removes them from the DOM (and therefore from keyboard focus) until you're ready. If you create a class called 'hidden' with just display:none in it, then the only script you'll need is to add/remove the class from the list item when the Left/Right controls are used. I'd edit your code sample to demonstrate but I'm on a tiny screen right now.
The problem then is that your keyboard users can't reach the Left/Right controls. If you change those to button or link elements, then they'll have keyboard support by default in every browser. And then all your users are relying on your Left/Right controls no matter whether they're using a mouse or the keyboard, which gives you more control over how it looks at each stage.
You could just set tabindex to -1 for the links to avoid focusing.
You could set tabindex="-1" for elements that are off the screen. This is suggested by MDN.
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex

jScrollPane zero height on dropdown menus

I have some content displayed as a list within a div. By default, the div is hidden, but becomes visible once it's parent has the class ".open":
<li class="dropdown">
<a>Options</a>
<div class="dropdown-menu">
<div class="menu-scroll">
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
</div>
</div>
</li>
What happens is when I click the anchor within the list item, the list item receives the ".open" class, which enables displaying the ".dropdown-menu" . Now my problem is that I want that menu to have a max-height of say 200px, after which it should initialize the scroll. Considering that each of it's list items are 50px tall, we would have these scennarios:
2 list items, height of 100px, no scroll
3 list items, height of 150px, no scroll
4 list items, height of 200px, no scroll
5+ list items, height of over 200px and SCROLL
This means I can't set a fixed height for .menu-scroll, since I want it to scale until reaching that height. What I do is set:
max-height: 200px;
height: auto;
It works perfect the first time I trigger the dropdowns but afterwards it renders everything wrong, like this:
What I've tried:
Initializing jScrollpane when clicking the anchor that toggles the .open class.
Initializing jScrollpane on document ready and only reinitializing the object when clicking the same anchor.
The results are the same everytime, as shown in the illustration above. I've searched the documentation, FAQ, StackOverflow, Google Groups but to no avail. Does anyone have any clues on this?
EDIT: This is the code I use to trigger the dropdown and initialize the scroll:
$('.dropdown-toggle').on("click", function() {
$(this).parent('.dropdown').toggleClass('open').find('.dropdown-menu').jScrollPane();
});
What the .open class does is add
.dropdown.open .dropdown-menu {
display: block;
}
to the otherwise hidden .dropdown-menu:
.dropdown.dropdown-menu {
display: none;
}
if you get it right on first trigger and then it fails after that implies you have to check your script. Can you post your script here?

Make Menu have a slideToggle Effect and push below elements down

I'm using a nice Mega Menu from CODROPS and I'm trying to customize it to have:
1) a slideToggle effect
2) When the menu is opened to push the below div element down (IE: not overlapping the below elements)
Here is my JS FIDDLE
This is what I've done so far:
1) I know very basic jquery and usually I know how to apply a slideToggle effect but I can't seem to get it right with their javascript code, so I'm left guessing where to place it but having no success. I've tried researching online but can't find a solution.
2) To make the element below the menu get pushed down, I know to make the position relative in the css below but that just breaks the menus float when it's activated.
/* sub-menu */
.cbp-hrmenu .cbp-hrsub {
display: none;
position: absolute;
background: #47a3da;
width: 100%;
left: 0;
}
It would be nice to have the elements below pushed down but the slideToggle effect is a bit more important to me...
You'll have to refactor this a bit to get it to work the way you want it to.
The .cbp-hrsub element containing the sub text is positioned absolutely, overlaying any text below. You would need to remove position:absolute to revert to the browser default position:static.
However, as the .cbp-hrsub element is part of each menu <li>, this pushes the other <li> elements down.
I'd suggest splitting the HTML out so that your menu <li> elements are separate to your sub text elements. Contain the subtext elements in a new <ul> and get these to slide down on click of the associated menu item link.

Gmail-like Sign out

I have a Gmail-like Signout mechanism, such that when you hover on the username (on the top right), it slides down a menu that includes a "sign out" link. The username is on a floated list, while the menu that slides out is on an inner list (not floated). The sliding out/in is performed using jQuery.
This is what it's supposed to do:
The inner menu slides down (becomes visible) when username is hovered on;
if the mouse goes to the inner menu, the inner menu should remain visible;
if the mouse hovers elsewhere, the inner menu should slide back up (becomes invisible).
This is what it currently does:
The inner menu slides down when the username is hovered on;
when the cursor is off the username, the menu slides up - regardless of where the cursor is.
Perceived solution: I believe there should be an if clause somewhere that checks if the cursor is on the inner list and keep the inner list open, and that's the part that gets me stumped.
EDIT: Here is the current code:
HTML:
<ul id="user_spot">
<li><span class="username">username
<ul id="user_spot_links">
<li>Sign Out</li> <br />
</ul>
</li>
</ul>
CSS:
ul#user_spot li {
float:left;
position:relative;
}
ul#user_spot_links {
position:absolute;
top:20px;
display:none;
}
ul#user_spot_links li {
float:none;
clear:both;
}
JS:
$('ul#user_spot li a').hover(function() {
$('ul#user_spot_links').slideDown('slow');
return false;
}, function() {
// this is where I believe the needed code should be"
$('ul#user_spot_links').slideUp('slow');
});
You don't need JS for that.
Check this fiddle: http://jsfiddle.net/PaKnc/
Basically the UL that slides down is a child of the LI you hover over. You can manipulate the CSS properties of a child in CSS.
For example:
#parent #child {
style1;
}
#parent:hover #child {
style2;
}
Here, style1 and style2 can be totally different. In our case we take advantage of this by altering the display property.
The problem is that when you need to exit the username anchor to hover over the dropdown. The simple solution is to just change the hover selector to be the li instead of the a. Then, you will not exit it even while you remain hovered over the dropdown.

Categories