I have a navigation given by an nested ul list like this
<ul id='mainNav'>
<li> Some Stuff!
<ul>
<li>Page 1</li>
<li>Page 2</li>
</ul>
</li>
<li> Hover here to login!
<ul >
<li>
<div class='login'>
<p>Login</p>
<input type='password'>
<button>Okay</button>
</div>
</li>
</ul>
</ul>
and I use jQuery to show the menu on hover
$('ul#mainNav > li').hover(function() {
$(this).addClass("showMenu");
},
function(){
$(this).removeClass("showMenu");
}
);
This works fine, except for the input box for the login. In the moment where one moves the mouse pointer from the input box to a browser proposal entry, jQuery thinks that one left the li element and removes the class showMenu so that the submenu disappears.
So when I hover over the li element the login form opens
And as soon as I hover over the browser proposal the li element dissapears except for the browser proposal
I also created a jFiddle.
How can I tell jQuery to keep hovering if I move over the browser proposal from the input element?
As a solution You can remove the class .showMenu if event.target is not input
Also blur the input when the dropdown becomes hidden
$('ul#mainNav > li').hover(function(e) {
$(this).addClass("showMenu");
},
function(e) {
if (!$(e.target).is('input')) {
$(this).removeClass("showMenu");
$('input').blur();
}
});
#mainNav>li {
border: 3px solid #08C;
background-color: #FFF;
display: inline-block;
}
#mainNav li {
margin: 0;
padding: 0;
}
#mainNav,
#mainNav ul {
list-style: none;
margin: 0;
padding: 0;
}
#mainNav li>ul {
position: absolute;
display: none;
z-index: 1;
min-width: 200px;
padding: 0px;
margin: 0px;
text-align: left;
background-color: #FFF;
box-sizing: border-box;
}
#mainNav li.showMenu>ul {
display: block
}
.login {
border: 3px solid #08C;
padding: 20px;
margin: 0
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form method>
<ul id='mainNav'>
<li> Hover here to login!
<ul>
<li>
<div class='login'>
<p>Login</p>
<input type='password'>
<button>
Okay
</button>
</div>
</li>
</ul>
</ul>
</form>
https://jsfiddle.net/dzt87zbk/
Related
I'm completely new to JavaScript in frontend development, and I've got a really basic question I can't seem to figure out... I'm making a tabular navigation bar where the active element is highlighted.
I know there are other ways to accomplish the desired result, but what is wrong with my script here?
function navTabsClick(child) {
getElementsByClassName("active")[0].classList.remove("active");
child.getElementsByTagName("li")[0].className = "active";
}
ul{
display: flex;
list-style-type: none;
}
a{
text-decoration: none;
}
a:link, a:visited{
color: black;
}
a:hover{
cursor: pointer;
}
li{
margin: 0;
padding: 10px 30px;
background-color: lightgray;
}
li:hover{
background-color: darkgray;
}
li.active{
background-color: red;
}
<nav>
<ul>
<a onclick="navTabsClick(this)">
<li class="active">1</li>
</a>
<a onclick="navTabsClick(this)">
<li>2</li>
</a>
<a onclick="navTabsClick(this)">
<li>3</li>
</a>
</ul>
</nav>
If I remove the top line of my JavaScript function, I can get other tabs to highlight, but as is I get the following error:
Uncaught ReferenceError: getElementsByClassName is not defined
What am I missing?
Also, as a secondary question, is there a better way to handle navbar JavaScript than this?
Try doing document.getElementByClassName
function navTabsClick(child) {
document.getElementsByClassName("active")[0].classList.remove("active");
child.getElementsByTagName("li")[0].className = "active";
}
ul{
display: flex;
list-style-type: none;
}
a{
text-decoration: none;
}
a:link, a:visited{
color: black;
}
a:hover{
cursor: pointer;
}
li{
margin: 0;
padding: 10px 30px;
background-color: lightgray;
}
li:hover{
background-color: darkgray;
}
li.active{
background-color: red;
}
<nav>
<ul>
<a onclick="navTabsClick(this)">
<li class="active">1</li>
</a>
<a onclick="navTabsClick(this)">
<li>2</li>
</a>
<a onclick="navTabsClick(this)">
<li>3</li>
</a>
</ul>
</nav>
The function is document.getElementsByClassName, i.e.:
function navTabsClick(child) {
document.getElementsByClassName("active")[0].classList.remove("active");
child.getElementsByTagName("li")[0].className = "active";
}
ul {
display: flex;
list-style-type: none;
}
a {
text-decoration: none;
}
a:link,
a:visited {
color: black;
}
a:hover {
cursor: pointer;
}
li {
margin: 0;
padding: 10px 30px;
background-color: lightgray;
}
li:hover {
background-color: darkgray;
}
li.active {
background-color: red;
}
<nav>
<ul>
<a onclick="navTabsClick(this)">
<li class="active">1</li>
</a>
<a onclick="navTabsClick(this)">
<li>2</li>
</a>
<a onclick="navTabsClick(this)">
<li>3</li>
</a>
</ul>
</nav>
You are missing the document before getElementsByClassName
Others have pointed out that getElementsByClassName must be called on an element, but that does not address the second part of your question.
Is there a better way to handle navbar JavaScript than this?
Right now, you are setting an event listener on each menu item which is unnecessary. The click event exposes the element that was clicked in the target property. You can set a single event listener on the menu itself and use this property to determine which item was clicked.
This also allows you to remove the a tags around your menu items. I assume those will cause issues with screen readers. Edit: As pointed out by Scott, the click event could have been set directly on the li tag originally.
Here's a modified example with a single event for the menu.
function navClicked(nav, item) {
/* Do not attempt to set the nav
menu itself to the active item */
if (nav === item) return;
/* Do not change the active item if the
item that was clicked is already active */
if (item.classList.contains("active")) return;
/* Remove the class from all nav items */
Array.from(nav.children)
.forEach(child => child.classList.remove("active"));
/* Add the class to the item that was clicked */
item.classList.add("active");
}
ul {
display: flex;
list-style-type: none;
}
a {
text-decoration: none;
}
a:link,
a:visited {
color: black;
}
a:hover {
cursor: pointer;
}
li {
margin: 0;
padding: 10px 30px;
background-color: lightgray;
}
li:hover {
background-color: darkgray;
}
li.active {
background-color: red;
}
<nav>
<ul onclick="navClicked(this, event.target)"> <!-- 'this' is the ul element, 'event.target' is the li element that was clicked -->
<li class="active">1</li>
<li>2</li>
<li>3</li>
</ul>
</nav>
I want to start by apologizing for such a long question, I just hope I wont make it difficult to understand as a result.
I have created a side bar with three Menu elements in an UL which expand to show child elements, change background color and remove hover effect when clicked. I did this by defining a function that adds and remove classes containing relevant properties when the menu element is clicked.
The four specific things that I want the sidebar to do but cant seem to get it to do are as follows;
only one selected/clicked item to expand at a time while all the
rest of the unselected menu elements are collapsed. That means if I
click the first item, it expands and when I click the second one,
the first one collapses while the one I clicked expands etc.
The selected/clicked element changes its background color to
indicate it's selected.
The selected/clicked element has no hover effect on the text while
the unselected elements have a hover effect of text color change on
them.
I also want the selected menu element be able to toggle the
expansion on and off not affecting the other elements in the UL.
I think where I'm having most trouble with my code is in the adding and removal of classes especially given that the <a>Tags which are nested inside the <li> Tags (clicked elements) are where the "hover" class needs to be added/removed, as well as the <ul>Tags that expand are also nested inside the clicked elements.
function toggleMenu(e) {
var kids = document.querySelector("#menuList").children;
var unselectedLink = document.querySelectorAll(".unselected a");
var unselectedDropdown = document.querySelectorAll(".unselected ul");
//adds "unselected" class to all elements exept the selected one
for (var i = 0; i < kids.length; i++) {
kids[i].className = "unselected";
}
//adds "menuHover" class to all elements exept the selected element
for (var i = 0; i < unselectedLink.length; i++) {
unselectedLink[i].className = "menuHover";
}
for (var i = 0; i < unselectedDropdown.length; i++) {
unselectedDropdown[i].classList.remove("show")
}
//adds "selected" class, removes "menuHover" class and adds "toggle" to the selected element
e.className = "selected";
document.querySelector(".selected a").classList.remove("menuHover");
document.querySelector(".selected ul").classList.toggle("show");
}
.sidebar {
position: fixed;
width: 250px;
height: 100%;
left: 0px;
top: 0;
background: #1b1b1b;
font-family: sans-serif;
}
.menu-bar {
background: #1b1b1b;
height: 60px;
display: flex;
align-items: center;
padding-left: 42px;
}
.side-text {
color: #C5C5C5;
font-weight: bold;
font-size: 20px;
}
nav ul {
background: #1b1b1b;
height: 100%;
width: 100%;
list-style: none;
margin-left: 0;
padding-left: 0;
}
nav ul li {
line-height: 40px;
}
nav ul li a {
position: relative;
color: #C5C5C5;
text-decoration: none;
font-size: 14px;
padding-left: 43px;
font-weight: normal;
display: block;
width: 100%;
}
nav ul ul {
position: static;
display: none;
}
nav ul ul li a {
font-family: sans-serif;
font-size: 13px;
color: #e6e6e6;
padding-left: 80px;
font-weight: lighter;
}
.submenu-item:hover {
background: #1e1e1e!important;
}
/*...........selected and show..................*/
.selected {
background-color: #255DAA;
}
.show {
display: block;
}
/*...........unselected and hover..................*/
.unselected {
color: #1e1e1e;
}
.menuHover:hover {
color: #255DAA;
}
<nav class="sidebar">
<div class="menu-bar">
<label class="side-text">MENU</label>
</div>
<ul id="menuList">
<li class="selected" onclick="toggleMenu(this)">
Staff
<ul>
<li>New Staff</li>
<li>View Staff</li>
</ul>
</li>
<li class="unselected" onclick="toggleMenu(this)">
Notes
<ul>
<li>New Note</li>
<li>Edit Notes</li>
</ul>
</li>
<li class="unselected" onclick="toggleMenu(this)">
Tasks
<ul>
<li>New Tasks</li>
<li>Edit Task</li>
</ul>
</li>
</nav>
I am quite close but somehow, logically I am doing things the wrong way with the JavaScript, so any adjustments to the code to make it reach all four of the above goals will be much appreciated. thanks
A simple way to do this:
If the element was selected, just unselect it
If it wasnt, unselect all elements and select the clicked element
function toggleMenu(el) {
if (el.classList.contains("selected")) {
el.classList.remove("selected");
el.classList.add("unselected");
}
else {
for (const child of document.getElementById("menuList").children) {
child.classList.remove("selected");
child.classList.add("unselected");
}
el.classList.remove("unselected");
el.classList.add("selected");
}
}
Edit 1
You can use the following css to unhide the submenu of a selected menuitem:
.selected ul {
display: block;
}
Edit 2
I went to the trouble of actually implementing it.
function toggleMenu(el) {
if (el.classList.contains("selected")) {
el.classList.remove("selected");
el.classList.add("unselected");
}
else {
for (const child of document.getElementById("menuList").children) {
child.classList.remove("selected");
child.classList.add("unselected");
}
el.classList.remove("unselected");
el.classList.add("selected");
}
}
.sidebar {
position: fixed;
width: 250px;
height: 100%;
left: 0px;
top: 0;
background: #1b1b1b;
font-family: sans-serif;
}
.menu-bar {
background: #1b1b1b;
height: 60px;
display: flex;
align-items: center;
padding-left: 42px;
}
.side-text {
color: #C5C5C5;
font-weight: bold;
font-size: 20px;
}
/* menu */
.menu {
background: #1b1b1b;
height: 100%;
width: 100%;
list-style: none;
margin-left: 0;
padding-left: 0;
}
.menu-item {
line-height: 40px;
}
.menu-item a {
position: relative;
color: #C5C5C5;
text-decoration: none;
font-size: 14px;
padding-left: 43px;
font-weight: normal;
display: block;
width: 100%;
}
/* submenu */
.submenu {
position: static;
display: none;
list-style: none;
}
.submenu-item a {
font-family: sans-serif;
font-size: 13px;
color: #e6e6e6;
padding-left: 80px;
font-weight: lighter;
}
.submenu-item:hover {
background: #1e1e1e;
}
/* selected and unselected */
.selected {
background-color: #255DAA;
}
.selected .submenu {
display: block;
}
.unselected {
color: #1e1e1e;
}
.unselected:hover a {
color: #255DAA;
}
<nav class="sidebar">
<div class="menu-bar">
<label class="side-text">MENU</label>
</div>
<ul class="menu" id="menuList">
<li class="menu-item selected" onclick="toggleMenu(this)">
Staff
<ul class="submenu">
<li class="submenu-item">New Staff</li>
<li class="submenu-item">View Staff</li>
</ul>
</li>
<li class="menu-item unselected" onclick="toggleMenu(this)">
Notes
<ul class="submenu">
<li class="submenu-item">New Note</li>
<li class="submenu-item">Edit Notes</li>
</ul>
</li>
<li class="menu-item unselected" onclick="toggleMenu(this)">
Tasks
<ul class="submenu">
<li class="submenu-item">New Tasks</li>
<li class="submenu-item">Edit Task</li>
</ul>
</li>
</ul>
</nav>
As alternative to the accepted answer, here two different approaches I was working on...
#menuList li is a container for a list of <a> menu items which have adjacent <ul> sub-menu-items. For easy selection with CSS I assigned class .menu-item to those <a>.
The CSS logic for both versions is essentially equal:
set the .menu-item adjacent ul sub-menu-items hidden by default
define :hover colors
define colors for a selected .menu-item and adjacent ul (either :focus or .selected is true)
make .menu-item adjacent ul sub-menu-items visible when a .menu-item gets selected (ditto)
Difference: for CSS only we use the :focus selector, for CSS with Javascript we use class .selected.
CSS only (automatic focus and blur)
An <a> gets focus when clicked (like button, input, etc. :focus is true). When the user clicks/taps outside the focussed element it automatically loses focus again (gets blurred and :focus is false, as in :not(:focus) = 'blur'). We can use the CSS :focus selector to handle user clicks and modify elements, MDN: ':focus'.
CSS with Javascript (focus and blur on request)
The OP wants a selected .menu-item and its adjacent ul sub-menu-items to stay visible until the user specifically deselects it again. This cannot be done with the :focus selector, so we ignore that selector and use class .selected instead to handle focus and blur requirements ourselves, MDN: HTMLElement.blur().
The Javascript logic is fairly straightforward:
Attach a 'click'-eventListener (MDN: Element: click event) to main container #menuList handling:
when a .menu-item gets selected and it is the currently .selected then blur it (menuItemBlur())
otherwise
when we have a previously selected .menu-item open, blur that first (menuItemBlur())
and then focus the newly selected .menu-item (menuItemFocus())
Changes to OP code
removed unneeded CSS
removed unneeded class attributes from HTML
changed href="#" in <#menuList li a> to href="javascript:void(0)" to prevent it from creating an entry in the browser history (sub-menu-items will still create an entry).
The below snippet is heavily commented and should be self-explanatory.
'use-strict';
var activeItem; // Holds the currently '.selected''.submenu' (null/undefined if none)
// Attach 'click' event listener to the #menuList
document.getElementById('menuList')
.addEventListener('click', function(e) { menuItemToggle(e.target) });
function menuItemToggle(el) {
if (el.classList.contains('menu-item2')) { // When a '.menu-item' gets clicked (not its kids)
if (el.classList.contains('selected')) { // and it is the '.selected''.menu-item'
menuItemBlur(el); // then close it and remove focus()
}
else {
if (activeItem) // When there is a currently selected '.menu-item'
menuItemBlur(activeItem); // then deactivate it
menuItemFocus(el); // Now activate the clicked `.menu-item`
};
};
function menuItemBlur(el) {
el.classList.remove("selected"); // Set the '.menu-item' to not '.selected'
activeItem = null; // and remove the reference to it
el.blur(); // Remove focus from element for CSS ':focus'
// ...extend with other 'Blur' stuff...
};
function menuItemFocus(el) {
el.classList.add("selected"); // Set the '.menu-item' to '.selected'
activeItem = el; // and save a reference to it
// ...extend with other 'Focus' stuff...
};
};
.sidebar {
position: fixed;
width: 250px;
height: 100%;
left: 0px;
top: 0;
background: #1b1b1b;
font-family: sans-serif;
}
.menu-bar {
background: #1b1b1b;
height: 60px;
display: flex;
align-items: center;
padding-left: 42px;
}
.side-text {
color: #c5c5c5;
font-weight: bold;
font-size: 20px;
}
nav ul {
background: #1b1b1b;
height: 100%;
width: 100%;
list-style: none;
margin-left: 0;
padding-left: 0;
}
nav ul li {
line-height: 40px;
}
nav ul li a {
position: relative;
color: #c5c5c5;
text-decoration: none;
font-size: 14px;
padding-left: 43px;
font-weight: normal;
display: block;
width: 100%;
}
nav ul ul {
position: static;
display: none;
}
nav ul ul li a {
font-family: sans-serif;
font-size: 13px;
color: #e6e6e6;
padding-left: 80px;
font-weight: lighter;
}
/*************/
/* ADDED CSS */
/*************/
/* All classes starting with "menu-item" */
[class^="menu-item"] + ul { display: none } /* hide adjacent UL */
[class^="menu-item"]:hover { color: #255daa } /* hover color */
a + ul li a:hover { color: #c5c5c5; background-color: #1b1b1b }
/*
menu-item adjacent sub-menu-items hover colors
Here the generic form is used, but it would
probably be more clear to be specific and use:
- either .menu-item1:focus + ul li a:hover
- or .menu-item2.selected + ul li a:hover
*/
/*
':focus' version
This version uses the CSS ':focus' without any Javascript.
Main difference with the '.selected' version below is that when the
user clicks outside the '.menu-item', the '.menu-item' looses focus
and therefore gets hidden again (as :focus is no longer true).
*/
.menu-item1:focus,
.menu-item1:focus + ul { color: #e6e6e6; background-color: #255DAA } /* focus colors */
.menu-item1:focus + ul { display: block } /* show adjacent UL */
/*
'.selected' version, with Javascript.
Basically the same CSS, but now using class '.selected' instead of ':focus'.
Closing occurs only on user specific 'click'.
*/
.menu-item2.selected,
.menu-item2.selected + ul { color: #e6e6e6; background-color: #255DAA } /* focus colors */
.menu-item2.selected + ul { display: block } /* show adjacent UL */
/*********************/
/* for demo use only */
/*********************/
nav h3 {
color: rgba(100, 149, 237,.9); /* CornflowerBlue */
font-style: italic;
padding-left: 43px;
}
.anchor {
color: white;
padding-left: 43px;
}
.content {
font-size: 1.5rem;
margin: 5rem 300px;
}
/* preferred globals */
html,body { box-sizing: border-box; width: 100%; max-width: 100% }
*::before,*::after, * { box-sizing: inherit }
body { margin: 0 }
<nav class="sidebar">
<div class="menu-bar">
<label class="side-text">MENU</label>
</div>
<h3>test</h3>
<a class="anchor" href="javascript:void(0)">some '.sidebar' <a></a>
<ul id="menuList">
<h3>:focus version</h3>
<li>
<a class="menu-item1" href="javascript:void(0)">Staff</a>
<ul>
<li>New Staff</li>
<li>View Staff</li>
</ul>
</li>
<li>
<a class="menu-item1" href="javascript:void(0)">Notes</a>
<ul>
<li>New Note</li>
<li>Edit Notes</li>
</ul>
</li>
<li>
<a class="menu-item1" href="javascript:void(0)">Tasks</a>
<ul>
<li>New Tasks</li>
<li>Edit Task</li>
</ul>
</li>
<h3>.selected version</h3>
<li>
<a class="menu-item2" href="javascript:void(0)">Staff</a>
<ul>
<li>New Staff</li>
<li>View Staff</li>
</ul>
</li>
<li>
<a class="menu-item2" href="javascript:void(0)">Notes</a>
<ul>
<li>New Note</li>
<li>Edit Notes</li>
</ul>
</li>
<li>
<a class="menu-item2" href="javascript:void(0)">Tasks</a>
<ul>
<li>New Tasks</li>
<li>Edit Task</li>
</ul>
</li>
</ul>
</nav>
<div class="content">
<h3><b>Note</b></h3>
<p>
This demo uses two different approaches interchangeably creating a quirky behaviour,
which under normal circumstances would not exist.
</p>
<p>To reproduce:</p>
<ul>
<li>select a <i>':focus version'</i> menu item first
<li>then select a <i>'.selected version'</i> menu item
</ul>
<p>
As you can see, the selected <i>':focus version'</i> loses focus and a second
'click' is needed to activate the <i>'.selected version'</i> menu item.
This is because the first click event of the <i>'.selected version'</i> gets consumed by the blur event
of the <i>':focus version'</i>.
</p>
<p>Just so you know...</p>
</div>
Here is my fiddle: http://jsfiddle.net/2tBGE/209/
I just want to open a div with animation after a user clicked on a menu item.
For example, when clicking on the second item, clicked item and previous item should push to the top of the page and below item should push to the bottom of the page.
jQuery(document).ready(function($) {
$('ul li a').on('click', function(){
$(this).parent().next().css({
'display':'block'
})
})
});
ul{
list-style: none;
background: #eee;
padding: 0;
margin: 0;
position: fixed;
bottom: 0;
width: 100%;
height: 200px;
}
.js_item{
display:none;
}
li a{
position: relative;
display: block;
padding: 10px 15px;
text-decoration: none;
}
a:hover{
background: #9c0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="main">
<li>main menu1</li>
<div class="load_content_for_menu_1 js_item">1</div>
<li>main menu2</li>
<div class="load_content_for_menu_2 js_item">2</div>
<li>main menu3</li>
<div class="load_content_for_menu_3 js_item">3</div>
<li>main menu4</li>
<div class="load_content_for_menu_4 js_item">4</div>
<li>main menu5</li>
<div class="load_content_for_menu_5 js_item">5</div>
</ul>
Note: I've made a small edit to your html structure so that each .toggled_content <div> is the child of each <li>.
With the following jQuery methods you can achieve this.
slideToggle()
Display or hide the matched elements with a sliding motion.
toggleClass()
Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence or the value of the state argument.
find()
Get the descendants of each element in the current set of matched elements, filtered by a selector, jQuery object, or element.
var allContent = $("li");
allContent.find(".toggled_content").hide();
$(".toggler").on("click", function() {
var $thisParent = $(this).parent();
if (!$thisParent.hasClass('open')) {
$thisParent
.parent()
.find(".open")
.toggleClass("open")
.find(".toggled_content")
.slideToggle();
}
$thisParent
.toggleClass("open")
.find(".toggled_content")
.slideToggle();
});
ul {
list-style: none;
background: #eee;
padding: 0;
margin: 0;
}
li a {
display: block;
padding: 10px 15px;
text-decoration: none;
}
a:hover {
background: #9c0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="main">
<li>
main menu1
<div class="toggled_content">1</div>
</li>
<li>
main menu2
<div class="toggled_content">2</div>
</li>
<li>
main menu3
<div class="toggled_content">3</div>
</li>
<li>
main menu4
<div class="toggled_content">4</div>
</li>
<li>
main menu5
<div class="toggled_content">5</div>
</li>
</ul>
Edit:
Or just use the jquery-ui accordion widget.
$("#accordion").accordion({
heightStyle: "fill",
active: 3
});
$("#accordion").on("accordionactivate", function(event, ui) {
const offset = ui.newHeader[0].offsetTop;
$([document.documentElement, document.body]).animate({
scrollTop: offset
}, 200);
});
body {
margin: 0;
}
.ui-accordion {
height: 200vh; /* simulate height with content */
background: #eee;
}
.ui-accordion-header {
margin: 0;
padding: 10px 15px;
font-weight: normal;
}
.ui-accordion-header:hover {
background: #9c0;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js"></script>
<div id="accordion">
<h3>main menu 1</h3>
<div>1</div>
<h3>main menu 2</h3>
<div>2</div>
<h3>main menu 3</h3>
<div>3</div>
<h3>main menu 4</h3>
<div>4</div>
</div>
This might be a little more complex than it appears, because you probably do not want any of the DIVs to be made full-screen. Rather, you want the headings of all the DIVs to remain visible, and the contents of any one content div to fill all remaining vertical space.
jQueryUI does this for you, using their accordion tabs widget. You can either include jQueryUI in your project and use their functionality, or you can examine their code and see how they did it, then modify their code to work in your own project.
To incorporate jQueryUI is simple: just add it the same way you would add jQuery, right after the call to jQuery (that is, you also need jQuery for jQueryUI to work, and the link to jQueryUI must follow the link for jQuery) See this link for a code example.
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.9.2/themes/base/jquery-ui.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js"></script>
Instead of adding .css() I have added .show(). It basically does the same by adding display:block
Try adding blow
jQuery(document).ready(function($) {
$('ul li a').on('click', function() {
$('.js_item').hide('slow')
$(this).parent().next().show('slow')
})
});
ul {
list-style: none;
background: #eee;
padding: 0;
margin: 0;
position: fixed;
bottom: 0;
width: 100%;
height: 200px;
}
.js_item {
display: none;
}
li a {
position: relative;
display: block;
padding: 10px 15px;
text-decoration: none;
}
a:hover {
background: #9c0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<ul class="main">
<li>main menu1</li>
<div class="load_content_for_menu_1 js_item">1</div>
<li>main menu2</li>
<div class="load_content_for_menu_2 js_item">2</div>
<li>main menu3</li>
<div class="load_content_for_menu_3 js_item">3</div>
<li>main menu4</li>
<div class="load_content_for_menu_4 js_item">4</div>
<li>main menu5</li>
<div class="load_content_for_menu_5 js_item">5</div>
</ul>
Hope this helps!
I need some help with both JS and CSS. I am using JS to hide and show subsections from one specific navigation bar on the website. First problem is, that I would like the JS code to specifically only work for that navigation bar and not the many others on the same site. Below is the JS code:
$('a').click(function(){
$('section').hide();
$($(this).attr('href')).show();
});
And below is the HTML code. I was wondering if I could somehow use the "navigation" class to select only this navigation bar in the JS code?
<ul class="navigation">
<li class="link">Tab1</li>
<li class="link">Tab2</li>
<li class="link">Tab3</li>
</ul>
Next problem has to do with the CSS. I would like to have the #content1, Tab1 be default when the site loads - and would like to have the text in it set to a color that is different from the rest (red or whatever). When tab2 is selected I would like that to change color while tab1 switches to black like the others etc. However I can't get the :active method to work in CSS (I guess because the JS really doesn't set it active.) Can anybody help me with that? Below is my CSS code (not all is relevant).
section {
display: none;
}
section:first-of-type {
display:block;
}
.navigation {
list-style: none;
}
li {
display: inline-block;
}
.nav2 {
display: inline-block;
width: 100px;
margin-right: 25px;
margin-bottom: 25px;
padding: 5px 5px 5px 5px;
background-color: #ffffff;
border: 1px;
border-style: solid;
border-color: #000000;
text-align: center;
text-decoration: none;
color: #000000;
}
Thank you very much in advance!
Create a CSS class that will be in charge of styling the active element. For this example we will use the class .active. It's important to notice that this is not a Pseudo-Class.
We will use a simple HTML markup for the tabs:
<ul class="tabs">
<li>
my tab
</li>
</ul>
Here follows a minimalist example of a tab style:
.tabs a { // represents the tabs
border: 1px solid #000;
}
.tabs a.active { // represents the active tabs
background: #f00;
}
Next step is creating a script to handle the clicks on the tabs. We want the script to remove the class .active from every other tabs and assign it to the tab that just got clicked. For that we can create an script that looks like:
$('.tabs').on('click', 'a', function () {
var $this = $(this), $ul = $this.parents('ul');
$ul.find('a').removeClass('active');
$this.addClass('active');
});
Example
$('.tabs').on('click', 'a', function() {
var $this = $(this),
$ul = $this.parents('ul');
$ul.find('a').removeClass('active');
$this.addClass('active');
});
body {
margin: 25px;
}
ul.tabs {
margin: 0 0 30px 0;
padding: 0;
list-style: none;
}
ul.tabs li {
display: inline-block;
}
ul.tabs li a {
margin: 0 2px;
padding: 5px 10px;
box-shadow: 0 0 4px rgba(0, 0, 0, .4);
text-decoration: none;
background: #eee;
color: #888;
text-transform: uppercase;
border-radius: 4px;
}
ul.tabs li a:hover {
box-shadow: 0 0 4px rgba(0, 0, 0, .4), 0 0 8px rgba(0, 0, 0, .8);
}
ul.tabs li a.active {
background: #aaa;
color: #fff;
}
<ul class="tabs">
<li>
tab 1
</li>
<li>
<a class="active" href="javascript:void(0)">tab 2</a>
</li>
<li>
tab 3
</li>
<li>
tab 4
</li>
<li>
tab 5
</li>
</ul>
<ul class="tabs">
<li>
tab 1
</li>
<li>
<a class="active" href="javascript:void(0)">tab 2</a>
</li>
<li>
tab 3
</li>
<li>
tab 4
</li>
<li>
tab 5
</li>
</ul>
<ul class="tabs">
<li>
tab 1
</li>
<li>
<a class="active" href="javascript:void(0)">tab 2</a>
</li>
<li>
tab 3
</li>
<li>
tab 4
</li>
<li>
tab 5
</li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
Ok so lets cover css first
If you want link be active by default just modify it to
<ul class="navigation">
<li class="link">Tab1</li>
<li class="link">Tab2</li>
<li class="link">Tab3</li>
and then style it with css
.active { your css }
And then you can handle rest via JS , use .find to select element only in navigation and .addClass and .removeClass to change a to active
$(".navigation a").click(function() {
$(".navigation").find('a').removeClass('active');
$(this).addClass('active');
});
jQuery selection strings use the same syntax as CSS. Therefore to select only anchor tags that are children of navigation, you can use descendent selectors.
$('.navigation a')
And for your CSS issue, no need to use the :active selector. Simply add or remove classes to your target element.
$('.navigation a').click(function () {
// make tabs default color
$('.navigation a').removeclass('fancy-colors')
// make clicked tab fancy
$(this).addClass('fancy-colors')
})
Check out the jQuery toggleclass docs http://api.jquery.com/toggleclass/
Setting default on page load simply means adding your class in the markup.
<a class="fancy-colors">
I followed a great example of how to make a sub-menu appear/disappear on click here and made it work. Quite an accomplishment since I'm just starting with javascript. But just as I made it work a few other problems came up, I'll try to explain:
1.- I have a vertical main menu and one of the options, 'Products' has a sub-category that opens on hover below the parent item. When selecting one of its sub-categories, a bigger menu shows up in a new div to the right of the main menu. When this happens, the selected sub-category changes color and displays a bullet so the user knows which sub-category they are viewing. I was doing this using PHP to detect the current page and assign an "active" id. But when I had it like that the sub-menu show/hide didn't work and all the options were showing when first entering the page. So I changed the link reference from "page.php" to "#" ---which makes more sense since that option is not meant to be a link rather than just display another sub-menu but had to include it for the sake of displaying the 'active' id--- and now the show/hide works except after I click a sub-category, the menu to the right opens, but the previously selected sub-category that opens on hover closes and the php detect function doesn't work because I changed the reference to "#" and the link doesn't show an 'active' status; in fact, the 'home' option stays selected even when the second div is already showing.
It sounds confusing, I know. Here's the example, I hope it's clear what I'm trying to do. I'd appreciate if anyone knows a way around this.
2.- Once I can get this fixed, is there a way to make the second div slide from left to right instead of fading in?
Thanks in advance :)
See my update to your code.. http://jsfiddle.net/Jaybles/tkVfX/4/
CSS
.mainNav {
float: left;
width: 200px;
height: 100%;
min-width: 150px;
background-color: #e21a22;
}
.active{
font-weight:bold;
}
.mainSide {
font-size: 14px;
list-style: none;
font-family: Helvetica,"Helvetica Neue",Arial,sans-serif;
padding-top: 40px;
width: 143px;
margin-right: auto;
margin-left: auto;
}
.mainSide li a, .mainSide li {
color: #fff;
width: 143px;
display: block;
padding: 2px 0 2px 0;
text-decoration: none;
}
.mainSide ul li a {
width: 125px;
list-style: none;
padding: 6px 0 2px 18px;
}
.mainSide li a:hover {
color: #fdb046;
}
.mainSide li a#active, .mainSide ul li a#active {
color: #fdb046;
background: url("../img/bullet.jpg") right center no-repeat;
}
#subNavSys, #subNavApp, #subNavAcc {
float: left;
width: 200px;
height: 100%;
min-width: 150px;
background-color: #414143;
display:none;
}
#subSideSys, #subSideApp, #subSideAcc {
font-size: 14px;
list-style: none;
font-family: Helvetica,"Helvetica Neue",Arial,sans-serif;
padding-top: 163px;
width: 143px;
margin-right: auto;
margin-left: auto;
}
#subSideSys li a, #subSideSys li, #subSideApp li a, #subSideApp li, #subSideAcc li a, #subSideAcc li {
color: #fff;
width: 143px;
display: block;
padding: 2px 0 2px 0;
text-decoration: none;
}
#subSideSys li a:hover, #subSideApp li a:hover, #subSideAcc li a:hover {
color: #fdb046;
HTML
<div class="mainNav">
<img id="top" src="img/metal.jpg" width="143" height="43" alt="Index" />
<ul class="mainSide">
<li>Home</li>
<li>About us</li>
<li>Products
<ul>
<li>By system</li>
<li>By application</li>
<li>Accesories</li>
</ul>
</li>
</ul>
</div>
<div id="subNavSys">
<ul id="subSideSys">
<li>Sub-menu-1.1</li>
<li>Sub-menu-1.2</li>
<li>Sub-menu-1.3</li>
</ul>
</div>
<div id="subNavApp">
<ul id="subSideApp">
<li>Sub-menu-2.1</li>
<li>Sub-menu-2.2</li>
<li>Sub-menu-2.3</li>
</ul>
</div>
<div id="subNavAcc">
<ul id="subSideAcc">
<li>Sub-menu-3.1</li>
<li>Sub-menu-3.2</li>
<li>Sub-menu-3.3</li>
</ul>
</div>
JS
$(document).ready(function(){
$("#sys").click(function() {
$("#subNavApp").hide();
$("#subNavAcc").hide();
$("#subNavSys").fadeIn(800);
$('*').removeClass('active');
$(this).addClass('active');
});
$("#app").click(function() {
$("#subNavSys").hide();
$("#subNavAcc").hide();
$("#subNavApp").fadeIn(800);
$('*').removeClass('active');
$(this).addClass('active');
});
$("#acc").click(function() {
$("#subNavSys").hide();
$("#subNavApp").hide();
$("#subNavAcc").fadeIn(800);
$('*').removeClass('active');
$(this).addClass('active');
});
});