I have a set of anchor tags that I am adding an active class to via a forEach method. How do I get it so when I add the active class to one anchor tag, it removes this active class from all other anchor tags items?
I must also have it so the 1st anchor tag starts with an active class on it (which I have done via CSS)
CodePen: https://codepen.io/emilychews/pen/gOaXdMr
var tabLink = document.querySelectorAll('.tab-link'),
tabPane = document.querySelectorAll('.tab-pane')
tabLink.forEach(function(item){
item.addEventListener('click', function(){
item.classList.add('active')
}, false)
})
.nav-tabs {
display: flex;
align-items: center;
padding: 1rem 2rem;
list-style: none;
background: lightblue;
}
.tab-link {
margin-left: 4rem;
padding: 1rem;
border-radius: 1px;
transition: .2s;
display: block;
}
.tab-link.active {
background: white;
}
<ul class="nav-tabs"role="tablist">
<li role="presentation"><a class="tab-link active" href="#html-tab" title="html tab" role="tab">HTML</a></li>
<li role="presentation"><a class="tab-link" href="#css-tab" title="css tab" role="tab">CSS</a></li>
<li role="presentation"><a class="tab-link" href="#result-tab" title="result tab" role="tab">Result</a></li>
</ul>
If you use jQuery, You can do this using few lines of code.
Vanilla JS
var tabLink = document.querySelectorAll('.tab-link');
tabLink.forEach(function(item){
item.addEventListener('click', function(){
document.querySelector('.active').classList.remove('active');
item.classList.add('active');
}, false)
})
jQuery
$(document).on('click', '.tab-link', function(){
$('.tab-link').removeClass('active'); // remove active for all first.
$(this).addClass('active'); // add active for clicked element
})
Inside the click event listener, you can simply remove all the active classes from all the children elements inside .tab-link before adding the last active class to the clicked element.
I only added three lines of code below to your original code to achieve what you wanted.
var tabLink = document.querySelectorAll('.tab-link'),
tabPane = document.querySelectorAll('.tab-pane')
tabLink.forEach(function(item){
item.addEventListener('click', function(){
tabLink.forEach(function(item) {
item.classList.remove('active')
})
item.classList.add('active')
}, false)
})
.nav-tabs {
display: flex;
align-items: center;
padding: 1rem 2rem;
list-style: none;
background: lightblue;
}
.tab-link {
margin-left: 4rem;
padding: 1rem;
border-radius: 1px;
transition: .2s;
display: block;
}
.tab-link.active {
background: white;
}
<ul class="nav-tabs"role="tablist">
<li role="presentation"><a class="tab-link active" href="#html-tab" title="html tab" role="tab">HTML</a></li>
<li role="presentation"><a class="tab-link" href="#css-tab" title="css tab" role="tab">CSS</a></li>
<li role="presentation"><a class="tab-link" href="#result-tab" title="result tab" role="tab">Result</a></li>
</ul>
so basically just give each on a different id then in the function just remove the class from each and than add the class.
var tabLink = document.querySelectorAll('.tab-link'),
tabPane = document.querySelectorAll('.tab-pane')
tabLink.forEach(function(item){
item.addEventListener('click', function(){
document.getElementById('a').classList.remove('active');
document.getElementById('b').classList.remove('active');
document.getElementById('c').classList.remove('active');
item.classList.add('active')
}, false)
})
.nav-tabs {
display: flex;
align-items: center;
padding: 1rem 2rem;
list-style: none;
background: lightblue;
}
.tab-link {
margin-left: 4rem;
padding: 1rem;
border-radius: 1px;
transition: .2s;
display: block;
}
.tab-link.active {
background: white;
}
<ul class="nav-tabs"role="tablist">
<li role="presentation"><a id='a' class="tab-link active" href="#html-tab" title="html tab" role="tab">HTML</a></li>
<li role="presentation"><a id='b' class="tab-link" href="#css-tab" title="css tab" role="tab">CSS</a></li>
<li role="presentation"><a id='c' class="tab-link" href="#result-tab" title="result tab" role="tab">Result</a></li>
</ul>
I created a second function that will be called in the click event. That function search for a item where has the class active and remove the class.
var tabLink = document.querySelectorAll('.tab-link'),
tabPane = document.querySelectorAll('.tab-pane')
function clearActiveItemMenu(){
tabLink.forEach(function(item){
if(item.classList.contains('active')){
item.classList.remove('active');
}
});
}
tabLink.forEach(function(item){
item.addEventListener('click', function(){
clearActiveItemMenu();
item.classList.add('active')
}, false)
})
.nav-tabs {
display: flex;
align-items: center;
padding: 1rem 2rem;
list-style: none;
background: lightblue;
}
.tab-link {
margin-left: 4rem;
padding: 1rem;
border-radius: 1px;
transition: .2s;
display: block;
}
.tab-link.active {
background: white;
}
<ul class="nav-tabs"role="tablist">
<li role="presentation"><a class="tab-link active" href="#html-tab" title="html tab" role="tab">HTML</a></li>
<li role="presentation"><a class="tab-link" href="#css-tab" title="css tab" role="tab">CSS</a></li>
<li role="presentation"><a class="tab-link" href="#result-tab" title="result tab" role="tab">Result</a></li>
</ul>
Related
I have a menu that uses buttons and vanilla Javascript.
When a button is clicked, it adds the class opened to the button and changes aria-expanded="false" to aria-expanded="true".
If you click another button, the original button's attribute reverts to aria-expanded="false" and the class opened is removed.
However, if you click the original button a second, consecutive time, whilst the class opened is removed, aria-expanded="true" does not change back to aria-expanded="false" and I am really struggling to understand why.
Here is the script and a mini-menu with minimum CSS (obviously, the browser's inspector is required to view the changes).
NB The original JS below was written for a multi-level menu, obviously not used in this instance.
for (const selector of [".btn-level-1", ".btn-level-2", ".btn-level-3", ".btn-level-4", ".btn-level-5", ".btn-level-6",]) {
const buttons = [...document.querySelectorAll(selector)];
for (const button of buttons) {
button.addEventListener('click', () => {
buttons.filter(b => b !== button).forEach(b => {
b.classList.remove('opened'); // this works on self and also if other button is clicked
b.setAttribute("aria-expanded", "false"); //this doesn't work on self
});
button.classList.toggle('opened');
button.setAttribute("aria-expanded", "true");
})
}}
button + ul {
display: none;
}
button.opened + ul {
display: block;
}
li {
padding: 10px;
list-style: none;
}
.sidenav {
width: 560px;
background: #eee;
}
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute;
height: 1px;
width: 0;
overflow: hidden;
white-space: nowrap;
}
.menu-toggle {
height: 44px;
width: 44px;
display: inline-block;
line-height: 44px;
font-size: 25px;
text-align: center;
text-decoration: none;
margin: 0;
}
.icon {
padding-left: 1rem;
}
<nav aria-label="Main Navigation">
<ul>
<li class="has-submenu">
Some Category
<button class="btn-level-1 menu-toggle" type="button" aria-haspopup="true" aria-expanded="false">
<span class="christmas-red"></span>
<span class="icon">+</span>
<span class="visually-hidden">
<span class="toggleText">show submenu</span> for "Some Category"</span>
</button>
<ul>
<li>Some Category Item 1</li>
<li>Some Category Item 2</li>
</ul>
</li>
<li class="has-submenu">
Another Category
<button class="btn-level-1 menu-toggle" type="button" aria-haspopup="true" aria-expanded="false">
<span class="christmas-red"></span>
<span class="icon">+</span>
<span class="visually-hidden">
<span class="toggleText">show submenu</span> for "Some Category"</span>
</button>
<ul>
<li>Some Category Item 1</li>
<li>Some Category Item 2</li>
</ul>
</li>
</ul>
</nav>
After toggling the opened class on button you need to check whether you actually added or removed it when setting the aria-expanded attribute. You can do this using classList.contains. Updated working example:
for (const selector of [".btn-level-1", ".btn-level-2", ".btn-level-3", ".btn-level-4", ".btn-level-5", ".btn-level-6",]) {
const buttons = [...document.querySelectorAll(selector)];
for (const button of buttons) {
button.addEventListener('click', () => {
buttons.filter(b => b !== button).forEach(b => {
b.classList.remove('opened');
b.setAttribute("aria-expanded", "false");
});
button.classList.toggle('opened');
// check which aria-expanded value we should set below
let ariaExpanded = button.classList.contains('opened').toString();
button.setAttribute("aria-expanded", ariaExpanded);
})
}}
button+ul{
display: none;
}
button.opened+ul{
display: block;
}
li{
padding: 10px;
list-style: none;
}
.sidenav {
width: 560px;
background: #eee;
}
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute;
height: 1px;
width: 0;
overflow: hidden;
white-space: nowrap;
}
.menu-toggle{
height: 44px;
width: 44px;
display: inline-block;
line-height: 44px;
font-size: 25px;
text-align: center;
text-decoration: none;
margin: 0;
}
.icon {
padding-left: 1rem;
}
<nav aria-label="Main Navigation">
<ul>
<li class="has-submenu">
Some Category
<button class="btn-level-1 menu-toggle" type="button" aria-haspopup="true" aria-expanded="false">
<span class="christmas-red"></span>
<span class="icon">+</span>
<span class="visually-hidden">
<span class="toggleText">show submenu</span> for "Some Category"</span>
</button>
<ul>
<li>Some Category Item 1</li>
<li>Some Category Item 2</li>
</ul>
</li>
<li class="has-submenu">
Another Category
<button class="btn-level-1 menu-toggle" type="button" aria-haspopup="true" aria-expanded="false">
<span class="christmas-red"></span>
<span class="icon">+</span>
<span class="visually-hidden">
<span class="toggleText">show submenu</span> for "Some Category"</span>
</button>
<ul>
<li>Some Category Item 1</li>
<li>Some Category Item 2</li>
</ul>
</li>
</ul>
</nav>
I want to be able to link a tab link with a tab pane via a click event.
I have the code that places/removes an active class on each tab link, but I'm struggling to match this to the relevant tab pane.
Would I do this via an e.target event and do it by matching array position? Or to use the href attribute of the tab link and match it to the #id of the tab pane?
var tabLink = document.querySelectorAll(".tab-link"),
tabPane = document.querySelectorAll(".tab-pane")
tabLink.forEach(function (item) {
item.addEventListener('click', function (e) {
// ADDS AND REMOVES ACTIVE CLASS ON TABLINKS
tabLink.forEach(function (item) {
item.classList.remove("active")
})
item.classList.add("active")
// SOMEHOW EQUATE TAB LINKS TO TAB PANES
console.log(e.target)
},false)
})
.nav-tabs {
display: flex;
align-items: center;
padding: 1rem 2rem;
list-style: none;
background: lightblue;
}
.tab-link {
margin-left: 4rem;
padding: 1rem;
border-radius: 1px;
transition: 0.2s;
display: block;
}
/*changes background of active tab link*/
.tab-link.active {
background: white;
}
/*hides tab panes*/
.tab-pane {
display: none;
}
/*shows active pane*/
.tab-pane.active {
display: block;
}
<div class="tabs-wrapper">
<ul class="nav-tabs" role="tablist">
<li role="presentation"><a class="tab-link active" href="#html-tab" title="html tab" role="tab">FIRST</a></li>
<li role="presentation"><a class="tab-link" href="#css-tab" title="css tab" role="tab">SECOND</a></li>
<li role="presentation"><a class="tab-link" href="#result-tab" title="result tab" role="tab">THIRD</a></li>
</ul>
<!-- tab panel containing tab panes -->
<div class="tab-panel">
<div class="tab-pane active" id="html-tab" role="tabpanel">
FIRST CONTENT
</div>
<div class="tab-pane" id="css-tab" role="tabpanel">
SECOND CONTENT
</div>
<div class="tab-pane" id="result-tab" role="tabpanel">
THIRD CONTENT
</div>
</div>
</div>
You need use getAttribute() function
I made a jsfiddle for you : https://jsfiddle.net/fgu1ycjo/3/
<div class="tabs-wrapper">
<ul class="nav-tabs" role="tablist">
<li role="presentation"><a class="tab-link active" target="html-tab" title="html tab" role="tab">FIRST</a></li>
<li role="presentation"><a class="tab-link" target="css-tab" title="css tab" role="tab">SECOND</a></li>
<li role="presentation"><a class="tab-link" target="result-tab" title="result tab" role="tab">THIRD</a></li>
</ul>
<!-- tab panel containing tab panes -->
<div class="tab-panel">
<div class="tab-pane active" id="html-tab" role="tabpanel">
FIRST CONTENT
</div>
<div class="tab-pane" id="css-tab" role="tabpanel">
SECOND CONTENT
</div>
<div class="tab-pane" id="result-tab" role="tabpanel">
THIRD CONTENT
</div>
</div>
</div>
var tabLink = document.querySelectorAll(".tab-link"),
tabPane = document.querySelectorAll(".tab-pane")
tabLink.forEach(function (item) {
item.addEventListener('click', function (e) {
// ADDS AND REMOVES ACTIVE CLASS ON TABLINKS
tabLink.forEach(function (item) {
item.classList.remove("active")
});
item.classList.add("active");
// SOMEHOW EQUATE TAB LINKS TO TAB PANES
let target = e.target.getAttribute('target')
let activPanel = document.querySelectorAll(".tab-pane.active");
// hide actives tabs
activPanel.forEach(function (item) {
item.classList.remove('active');
});
// show target tab
document.getElementById(target).classList.add('active');
},false)
})
I used this link from w3schools to come up with an answer. The key is to assign some type of attibute to the tab itself to let it know what the target content is. Then you can manage the display of the tab panes to reflect that.
var tabLink = document.querySelectorAll(".tab-link"),
tabPane = document.querySelectorAll(".tab-pane")
tabLink.forEach(function (item) {
item.addEventListener('click', function (e) {
// ADDS AND REMOVES ACTIVE CLASS ON TABLINKS
tabLink.forEach(function (item) {
item.classList.remove("active")
})
item.classList.add("active")
// REMOVES DISPLAY OF CONTENT AREAS
tabPane.forEach(function (tab){
tab.style.display = "none";
})
// SOMEHOW EQUATE TAB LINKS TO TAB PANES
var targetPanel = item.getAttribute("content-panel");
document.getElementById(targetPanel).style.display = "block";
},false)
})
.nav-tabs {
display: flex;
align-items: center;
padding: 1rem 2rem;
list-style: none;
background: lightblue;
}
.tab-link {
margin-left: 4rem;
padding: 1rem;
border-radius: 1px;
transition: 0.2s;
display: block;
}
/*changes background of active tab link*/
.tab-link.active {
background: white;
}
/*hides tab panes*/
.tab-pane {
display: none;
}
/*shows active pane*/
.tab-pane.active {
display: block;
}
<div class="tabs-wrapper">
<ul class="nav-tabs" role="tablist">
<li role="presentation"><a class="tab-link active" href="#html-tab" title="html tab" role="tab" content-panel="html-tab">FIRST</a></li>
<li role="presentation"><a class="tab-link" href="#css-tab" title="css tab" role="tab" content-panel="css-tab">SECOND</a></li>
<li role="presentation"><a class="tab-link" href="#result-tab" title="result tab" role="tab" content-panel="result-tab">THIRD</a></li>
</ul>
<!-- tab panel containing tab panes -->
<div class="tab-panel">
<div class="tab-pane active" id="html-tab" role="tabpanel">
FIRST CONTENT
</div>
<div class="tab-pane" id="css-tab" role="tabpanel">
SECOND CONTENT
</div>
<div class="tab-pane" id="result-tab" role="tabpanel">
THIRD CONTENT
</div>
</div>
</div>
Try this !
I added a cool fade effet
function showpane(evt, pane) {
// Declare all variables
var i, tabpane, tablinks;
// Get all elements with class="tab-pane" and hide them
tabpanes = document.getElementsByClassName("tab-pane");
for (i = 0; i < tabpanes.length; i++) {
tabpanes[i].style.display = "none";
}
// Get all elements with class="tab-link" and remove the class "active"
tablinks = document.getElementsByClassName("tab-link");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].classList.remove("active");
}
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(pane).style.display = "block";
evt.currentTarget.className += " active";
}
.nav-tabs {
display: flex;
align-items: center;
padding: 1rem 2rem;
list-style: none;
background: lightblue;
}
.tab-link {
margin-left: 4rem;
padding: 1rem;
border-radius: 1px;
transition: 0.2s;
display: block;
}
/*changes background of active tab link*/
.tab-link.active {
background: white;
}
/*hides tab panes*/
.tab-pane {
display: none;
}
/*shows active pane*/
.tab-pane.active {
display: block;
}
.tab-pane {
animation: fadeEffect 1s; /* Fading effect takes 1 second */
}
/* Go from zero to full opacity */
#keyframes fadeEffect {
from {opacity: 0;}
to {opacity: 1;}
}
<div class="tabs-wrapper">
<ul class="nav-tabs" role="tablist">
<li role="presentation"><a class="tab-link active" href="#html-tab" title="html tab" role="tab" onclick="showpane(event, 'html-tab')">FIRST</a></li>
<li role="presentation"><a class="tab-link" href="#css-tab" title="css tab" role="tab" onclick="showpane(event, 'css-tab')">SECOND</a></li>
<li role="presentation"><a class="tab-link" href="#result-tab" title="result tab" role="tab" onclick="showpane(event, 'result-tab')">THIRD</a></li>
</ul>
<!-- tab panel containing tab panes -->
<div class="tab-panel">
<div class="tab-pane active" id="html-tab" role="tabpanel">
FIRST CONTENT
</div>
<div class="tab-pane" id="css-tab" role="tabpanel">
SECOND CONTENT
</div>
<div class="tab-pane" id="result-tab" role="tabpanel">
THIRD CONTENT
</div>
</div>
</div>
var tabLink = document.querySelectorAll(".tab-link"),
tabPane = document.querySelectorAll(".tab-pane")
tabLink.forEach(function(item) {
item.addEventListener('click', function(e) {
switch (e.target.classList[0]) {
case 'one':
tabPane[0].classList.add("active");
tabPane[1].classList.remove("active");
tabPane[2].classList.remove("active");
break;
case 'two':
tabPane[0].classList.remove("active");
tabPane[1].classList.add("active");
tabPane[2].classList.remove("active");
break;
case 'three':
tabPane[0].classList.remove("active");
tabPane[1].classList.remove("active");
tabPane[2].classList.add("active");
break;
default:
// whatever you'd like
}
}, false)
})
.nav-tabs {
display: flex;
align-items: center;
padding: 1rem 2rem;
list-style: none;
background: lightblue;
}
.tab-link {
margin-left: 4rem;
padding: 1rem;
border-radius: 1px;
transition: 0.2s;
display: block;
}
/*changes background of active tab link*/
.tab-link.active {
background: white;
}
/*hides tab panes*/
.tab-pane {
display: none;
}
/*shows active pane*/
.tab-pane.active {
display: block;
}
<div class="tabs-wrapper">
<ul class="nav-tabs" role="tablist">
<li role="presentation"><a class="one tab-link active" href="#html-tab" title="html tab" role="tab">FIRST</a></li>
<li role="presentation"><a class="two tab-link" href="#css-tab" title="css tab" role="tab">SECOND</a></li>
<li role="presentation"><a class="three tab-link" href="#result-tab" title="result tab" role="tab">THIRD</a></li>
</ul>
<!-- tab panel containing tab panes -->
<div class="tab-panel">
<div class="tab-pane active" id="html-tab" role="tabpanel">
FIRST CONTENT
</div>
<div class="tab-pane" id="css-tab" role="tabpanel">
SECOND CONTENT
</div>
<div class="tab-pane" id="result-tab" role="tabpanel">
THIRD CONTENT
</div>
</div>
</div>
i want change this menu clickable to hover. When i do this doesen't work :/
I must add more text but question is simple for who known javascript well.
Sorry for my bad language.
I must add more text but question is simple for who known javascript well.
Sorry for my bad language.
I must add more text but question is simple for who known javascript well.
Sorry for my bad language.
(function($, undefined)
{
var open = [];
var opts = {
selector: '.dropdown',
toggle: 'dropdown-toggle',
open: 'dropdown-open',
nest: true
};
$(document).on('click.dropdown touchstart.dropdown', function(e)
{
// Close the last open dropdown if click is from outside the target dropdown
if ( open.length && ( ! opts.nest || ! open[ open.length - 1 ].find( e.target ).length ) )
{
open.pop().removeClass( opts.open );
}
var $this = $(e.target);
// If target is a dropdown then toggle it...
if ( $this.hasClass( opts.toggle ) )
{
e.preventDefault();
$this = $this.closest( opts.selector );
if ( ! $this.hasClass( opts.open ) )
{
open.push( $this.addClass( opts.open ) );
}
else
{
open.pop().removeClass( opts.open );
}
}
});
})(jQuery);
.Row
{
display: table;
width: 100%;
table-layout: fixed;
border-spacing: 10px;
}
.Column
{
display: table-cell;
background-color: red;
}
.dropdown {
position:relative;
min-width:100%;
background:#ccc;
display: inline-block;
}
.dropdown a {
display:block;
text-decoration:none;
color:#333;
}
/* toggle */
.dropdown .dropdown-toggle {
padding:0;
}
/* dropdown */
.dropdown-menu {
position:absolute;
top:100%;
right:0;
left:0;
display:none;
margin:0;
padding:0;
list-style-type:none;
background:#ccc;
}
/* options */
.dropdown-menu .option a {
}
.dropdown-menu .option a:hover {
background-color:#aaa;
}
/* open */
.dropdown-open {
z-index:400;
}
.dropdown-open > .dropdown-menu {
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Row">
<div class="Column">
<div id="locale" class="dropdown">
English
<ul class="dropdown-menu">
<li class="option">French</li>
<li class="option">German</li>
<li class="option">Arabic</li>
<li class="option">Chinese</li>
</ul>
</div>
</div>
<div class="Column">
<div id="locale" class="dropdown">
English
<ul class="dropdown-menu">
<li class="option">French</li>
<li class="option">German</li>
<li class="option">Arabic</li>
<li class="option">Chinese</li>
</ul>
</div>
</div>
<div class="Column">
<div id="locale" class="dropdown">
English
<ul class="dropdown-menu">
<li class="option">French</li>
<li class="option">German</li>
<li class="option">Arabic</li>
<li class="option">Chinese</li>
</ul>
</div>
</div>
</div>
Change $(document).on('click.dropdown touchstart.dropdown', function(e) to $(document).on( 'mouseenter touchstart','.dropdown', function(e) {
demo
(function($, undefined) {
var open = [];
var opts = {
selector: '.dropdown',
toggle: 'dropdown-toggle',
open: 'dropdown-open',
nest: true
};
$(document).on( 'mouseenter touchstart','.dropdown', function(e) {
// Close the last open dropdown if click is from outside the target dropdown
if (open.length && (!opts.nest || !open[open.length - 1].find(e.target).length)) {
open.pop().removeClass(opts.open);
}
var $this = $(e.target);
// If target is a dropdown then toggle it...
if ($this.hasClass(opts.toggle)) {
e.preventDefault();
$this = $this.closest(opts.selector);
if (!$this.hasClass(opts.open)) {
open.push($this.addClass(opts.open));
} else {
open.pop().removeClass(opts.open);
}
}
});
})(jQuery);
.Row {
display: table;
width: 100%;
table-layout: fixed;
border-spacing: 10px;
}
.Column {
display: table-cell;
background-color: red;
}
.dropdown {
position: relative;
min-width: 100%;
background: #ccc;
display: inline-block;
}
.dropdown a {
display: block;
text-decoration: none;
color: #333;
}
/* toggle */
.dropdown .dropdown-toggle {
padding: 0;
}
/* dropdown */
.dropdown-menu {
position: absolute;
top: 100%;
right: 0;
left: 0;
display: none;
margin: 0;
padding: 0;
list-style-type: none;
background: #ccc;
}
/* options */
.dropdown-menu .option a {}
.dropdown-menu .option a:hover {
background-color: #aaa;
}
/* open */
.dropdown-open {
z-index: 400;
}
.dropdown-open>.dropdown-menu {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Row">
<div class="Column">
<div id="locale" class="dropdown">
English
<ul class="dropdown-menu">
<li class="option">French</li>
<li class="option">German</li>
<li class="option">Arabic</li>
<li class="option">Chinese</li>
</ul>
</div>
</div>
<div class="Column">
<div id="locale" class="dropdown">
English
<ul class="dropdown-menu">
<li class="option">French</li>
<li class="option">German</li>
<li class="option">Arabic</li>
<li class="option">Chinese</li>
</ul>
</div>
</div>
<div class="Column">
<div id="locale" class="dropdown">
English
<ul class="dropdown-menu">
<li class="option">French</li>
<li class="option">German</li>
<li class="option">Arabic</li>
<li class="option">Chinese</li>
</ul>
</div>
</div>
</div>
Using css:
.dropdown:hover > ul{
display:block;
}
I tried to understand and optimize your code.
As I can't understand the necessity of the "open" variable,
I removed it and created a working snippet that achieves what you want:
(Check the comments in my snippet for more details)
(function($, undefined) {
// var open = []; // I removed that, but it could be added back
var opts = {
selector: '.dropdown',
toggle: 'dropdown-toggle',
open: 'dropdown-open',
nest: true
};
// TAKIT: Changed with below
// $(document).on('click.dropdown touchstart.dropdown', function(e) {
$('.dropdown').on('mouseenter touchstart', function(e) {
/* TAKIT: Replaced some code here */
$('.dropdown-open').removeClass(opts.open);
// If target is a dropdown then toggle it...
var $this = $(e.target);
if ($this.hasClass(opts.toggle)) {
e.preventDefault();
$this = $this.closest(opts.selector);
if (!$this.hasClass(opts.open)) {
$this.addClass(opts.open);
}
}
});
// TAKIT: Added the below
$('.dropdown').on('mouseleave touchend', function(e) {
// Close all the dropdowns
$('.dropdown-open').removeClass(opts.open);
});
})(jQuery);
.Row {
display: table;
width: 100%;
table-layout: fixed;
border-spacing: 10px;
}
.Column {
display: table-cell;
background-color: red;
}
.dropdown {
position: relative;
min-width: 100%;
background: #ccc;
display: inline-block;
}
.dropdown a {
display: block;
text-decoration: none;
color: #333;
}
/* toggle */
.dropdown .dropdown-toggle {
padding: 0;
}
/* dropdown */
.dropdown-menu {
position: absolute;
top: 100%;
right: 0;
left: 0;
display: none;
margin: 0;
padding: 0;
list-style-type: none;
background: #ccc;
}
/* options */
.dropdown-menu .option a {}
.dropdown-menu .option a:hover {
background-color: #aaa;
}
/* open */
.dropdown-open {
z-index: 400;
}
.dropdown-open>.dropdown-menu {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Row">
<div class="Column">
<div id="locale" class="dropdown">
English
<ul class="dropdown-menu">
<li class="option">French</li>
<li class="option">German</li>
<li class="option">Arabic</li>
<li class="option">Chinese</li>
</ul>
</div>
</div>
<div class="Column">
<div id="locale" class="dropdown">
English
<ul class="dropdown-menu">
<li class="option">French</li>
<li class="option">German</li>
<li class="option">Arabic</li>
<li class="option">Chinese</li>
</ul>
</div>
</div>
<div class="Column">
<div id="locale" class="dropdown">
English
<ul class="dropdown-menu">
<li class="option">French</li>
<li class="option">German</li>
<li class="option">Arabic</li>
<li class="option">Chinese</li>
</ul>
</div>
</div>
</div>
Feel free to comment if any.
Hope it helps.
Currently on my site when I have too many links, the link falls down below the navigation. See my example: https://jsfiddle.net/cn6z13n1/
Is it possible instead to have a More Links list item at the far right which will have a dropdown populated with links?
.toolkit_nav {
background:#dfdfdf;
width:100%;
height:40px;
padding:0;
}
.toolkit_nav ul {
margin:0;
}
.toolkit_nav ul .page_item {
display:inline-block;
line-height:40px;
list-style-type:none;
margin:0px;
padding:0 20px;
}
.toolkit_nav ul .page_item:first-child {
margin-left:0;
padding-left:0;
}
.page_item:hover, .current_page_item {
background:grey;
}
.page_item a {
color:black;
font-size: 0.9em;
font-weight: 400;
text-decoration:none;
}
<nav class="toolkit_nav">
<div class="row">
<div class="medium-12 columns">
<ul>
<li class="page_item page-item-1035 current_page_item">Introduction</li>
<li class="page_item page-item-1039">Digital Landscapes</li>
<li class="page_item page-item-1039">Link 4</li>
<li class="page_item page-item-1039">Link 3</li>
<li class="page_item page-item-1039">Link 2</li>
<li class="page_item page-item-1039">Link 1</li>
<li class="page_item page-item-1039">Link 5</li>
</ul>
</div>
</div>
</nav>
You would need to do this in js i suggest something like this
get the width of the row (max width for nav)
loop through the li elements and sum up there width (+ remember to add the width of a "more" element here
when sum of width > width of nav element hide the elements
add js to your "more" button which shows the hidden elements
Following code is not tested but should give you an idea:
var maxWidth = $('#nav').width();
var moreWidth = $('#more').width(); // li "more" element
var sumWidth = moreWidth;
$('#nav li').each(function() {
sumWidth += $(this).width();
if(sumWidth > maxWidth) {
$(this).addClass('hide'); // add css for hide class
}
});
$('#more').on('click', function() {
$('#nav .hide').fadeIn(100);
// You will need more code here to place it correctly, maybe append the elements in an container
});
Here an example with your fiddle:
https://jsfiddle.net/cn6z13n1/3/
Note: this is just a rough draft, you might to calc paddings etc. to make this work rly good
Edit: updated example with $(window).resize() function
https://jsfiddle.net/cn6z13n1/6/
You'll need to change you HTML slightly but this will work.
.toolkit_nav {
background: #dfdfdf;
width: 100%;
height: 40px;
padding: 0;
}
.toolkit_nav ul {
margin: 0;
}
.toolkit_nav ul .page_item {
display: inline-block;
line-height: 40px;
list-style-type: none;
margin: 0px;
padding: 0 20px;
}
.toolkit_nav ul .page_item:first-child {
margin-left: 0;
padding-left: 0;
}
.page_item:hover,
.current_page_item {
background: grey;
}
.page_item a {
color: black;
font-size: 0.9em;
font-weight: 400;
text-decoration: none;
}
/* NEW STUFF */
.sub-nav,
.sub-nav li {
box-sizing: border-box;
}
.more {
position: relative;
}
.more>ul {
display: none;
position: absolute;
left: 0;
top: 100%;
padding: 0
}
.more:hover>ul {
display: block;
}
.more>ul>li {
display: block;
width: 100%;
clear: both;
text-align: center;
}
.toolkit_nav ul.sub-nav .page_item:first-child {
padding: 0 20px;
}
<nav class="toolkit_nav">
<div class="row">
<div class="medium-12 columns">
<ul>
<li class="page_item page-item-1035 current_page_item">Introduction
</li>
<li class="page_item page-item-1039">Digital Landscapes
</li>
<li class="page_item page-item-1039">Link 4
</li>
<li class="page_item page-item-1039">Link 3
</li>
<li class="page_item page-item-1039">Link 2
</li>
<li class="page_item page-item-1039 more">More...
<ul class="sub-nav">
<li class="page_item page-item-1039">Link 1
</li>
<li class="page_item page-item-1039">Link 5
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
How to close my DropDown menu if i click body element of outside dropdown menu .
Please give me suggestion .
My code is
$(document).ready(function(){
$(document).on('click', '.top-nav-head>li>a', function(){
$(this).siblings('ul').toggle().closest('.top-nav-head>li').siblings('li').find('ul').hide();
});
});
.top-nav-head{
list-style-type: none;
padding: 0;
margin: 0;
background:blue;
float: left;}
.top-nav-head>li{
float: left;
position: relative;
}
.top-nav-head>li > a{
color: #000;
padding: 0 10px;
display: block;
line-height: 40px;
font-size: 14px;
}
.top-nav-head>li > ul{
position: absolute;
display: none;
top: 100%;
left: 0;
min-width: 140px;
right: 0;
list-style-type: none;
padding: 5px 0 5px 0;
margin: 0;
background-color: red;
}
.top-nav-head>li > ul>li{
display: block;
}
.top-nav-head>li > ul>li > a{
display: block;
color:#white;
padding: 5px 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<ul class="top-nav-head">
<li>Home</li>
<li class="active">
Admin Module
<ul>
<li><a ui-sref="av-kw-questions.empty">Questions</a></li>
<li><a ui-sref="av-wbs">WBS Elements</a></li>
<li><a ui-sref="av-lbp">Lookback planning</a></li>
<li>Form</li>
<li>Plan Component</li>
</ul>
</li>
<li>
Project Management
<ul>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
<li>Link 5</li>
</ul>
</li>
</ul>
You could attach an event handler to the document that will hide your drop down menus.
You would the need to stop the event bubbling when clicking on the menu items themselves:
$(document).ready(function () {
$(document).on('click', function () {
$('.top-nav-head > li > ul').hide();
});
$(document).on('click', '.top-nav-head>li>a', function (e) {
e.stopPropagation();
$(this).siblings('ul').toggle().closest('.top-nav-head>li').siblings('li').find('ul').hide();
});
});
JSFiddle
This will check if you have clicked on the element, just set your selector ("most" parent) and "hide" functionality:
$(document).mouseup(function (e)
{
var your_element = $('#your_element');
if(container.has(e.target).length === 0)
{
//hide your element
}
});