I have an ordered list which i want to make collapsible by default and expandable when user click on the link.
https://jsfiddle.net/rkmv3rn3/17/
How can I make it work so that it works properly
With following script it collapses all Parent item then fails to open them properly.
$(window).load(function() {
prepareList();
});
function prepareList() {
$('#expList').find('li:has(ol)')
.click(function(event) {
if (this == event.target) {
$(this).toggleClass('expanded');
$(this).children('ol').toggle('medium');
}
return false;
})
.addClass('collapsed')
.children('ol').hide();
//Create the button funtionality
$('#expandList')
.unbind('click')
.click(function() {
$('.collapsed').addClass('expanded');
$('.collapsed').children().show('medium');
})
$('#collapseList')
.unbind('click')
.click(function() {
$('.collapsed').removeClass('expanded');
$('.collapsed').children().hide('medium');
});
};
.page-left-bar {
width: 200px;
background-color: #fff;
}
ol {
margin-left: 0px;
padding-left: 20px;
}
.handbook-page ol {
color: #687074;
counter-reset: item;
}
ol {
counter-reset: item;
color: #687074;
}
ol li {
display: block;
padding: 5px 0;
}
ol li a {
text-decoration: none;
color: #687074;
padding-left: 10px;
}
ol li:before {
content: counters(item, ".") " ";
counter-increment: item;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>LIST OL child list alignment</h1>
<div class="page-left-bar">
<ol id='#expList'>
<li>Home</li>
<li>News</li>
<li>Contact
<ol>
<li>Sub menu</li>
<li>Sub menu long name</li>
<li>Sub menu</li>
<li>Sub menu</li>
</ol>
</li>
<li>About
<ol>
<li>Mission</li>
<li>Vision</li>
<li>Sub menu</li>
<li>Sub menu</li>
</ol>
</li>
</ol>
</div>
If you want to toggle the visibility of your submenus. First remove the # from the id #expList in your HTML as #MoshFeu said.
<ol id='expList'>
Then you can simply do it like this.
$(document).ready(function(){
$("#expList").find("ol").hide();
$("#expList > li").click(function(){
$(this).find("ol").slideToggle();
});
});
See this fiddle
Related
I have three navigations in one page and I'm trying to show the active links for each nav. For some reason the third nav isn't working correctly. For example, if you click on "chapter 2" or "chapter 3" or "chapter 4", "chapter 1" stays active. I don't know if it's because "Chapter 1" and "sublink4" from the middle nav have the same url. I tried removing the active class of the third nav, but it's not working. Unfortunately the snipping isn't working as it is on my computer. I only used target="_blank" on the snippet, not only my local machine since you can't click on links on the snippet without restarting the snippet.Thanks
$(window).on('load', function () {
$('body').setActiveMenuItem();
$('body').setActiveMenuItem2();
$('body').setActiveMenuItem3();
});
$(document).ready(function () {
//first nav
$.fn.setActiveMenuItem2 = function () {
$.each($('.nav1').find('li'), function () {
$(this).toggleClass('active',
window.location.pathname.indexOf($(this).find('a').attr('href')) > -1);
});
}
//middle nav
$.fn.setActiveMenuItem3 = function () {
$.each($('.nav3').find('li'), function () {
$(this).toggleClass('active3',
window.location.pathname.indexOf($(this).find('a').attr('href')) > -1);
});
}
//third nav
$.fn.setActiveMenuItem = function () {
$.each($('.nav2').find('li'), function () {
$(this).removeClass('active2');
$(this).toggleClass('active2',
window.location.pathname.indexOf($(this).find('a').attr('href')) > -1);
});
}
});
li.active {
background-color: red;
}
li.active2 {
background-color: blue;
}
li.active {
background-color: yellow;
}
.nav1 ul, .nav3 ul {
display: flex;
justify-content: space-between;
}
nav {
margin-bottom: 50px;
}
.wrapper {
width: 400px;
margin: auto;
}
li {
list-style: none;
background-color: aliceblue;
padding: 10px;
}
li a {
padding: 10px;
}
li a:hover {
color: red;
background: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<nav class="nav1">
<ul>
<li> Link 1 </li>
<li><a href="/link-2" target="_blank" >Link 2</a> </li>
<li>Link 3 </li>
<li>Link 4 </li>
</ul>
</nav>
<nav class="nav3">
<ul>
<li>Subink 1</li>
<li>Subink 2</li>
<li>Subink 3</li>
</ul>
</nav>
<nav class="nav2">
<ul>
<li>Chapter 1</li>
<li>Chapter 2</li>
<li>Chapter 3</li>
</ul>
</nav>
</div>
-> replace $ to j Query
->Either replace a latest jquery
Use preventDefault to let default event handler to open new link.
window.open() will let you open links in new tabs.
Note: This code won't work in sand-boxes.
Let me know if I'm missing something?
var links = document.querySelectorAll('a');
links.forEach((node) => {
node.addEventListener("click", (evt) => {
evt.stopPropagation();
evt.preventDefault();
evt.target.classList.add('active');
window.open(evt.target.href);
});
});
li.active {
background-color: red;
}
li.active2 {
background-color: blue;
}
li.active {
background-color: yellow;
}
.nav1 ul,
.nav3 ul {
display: flex;
justify-content: space-between;
}
nav {
margin-bottom: 50px;
}
.wrapper {
width: 400px;
margin: auto;
}
li {
list-style: none;
background-color: aliceblue;
padding: 10px;
}
li a {
padding: 10px;
}
li a:hover {
color: red;
background: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<nav class="nav1">
<ul>
<li> Link 1 </li>
<li>Link 2 </li>
<li>Link 3 </li>
<li>Link 4 </li>
</ul>
</nav>
<nav class="nav3">
<ul>
<li>Subink 1</li>
<li>Subink 2</li>
<li>Subink 3</li>
</ul>
</nav>
<nav class="nav2">
<ul>
<li>Chapter 1</li>
<li>Chapter 2</li>
<li>Chapter 3</li>
</ul>
</nav>
</div>
I have two divs. When I click on 3 dots , then the div is appearing and on clicking the same 3 dots , same div is disappearing. But I want to hide the div, even if I click anywhere in the document.
There are two circles. When I click on one circle, then a div is shown and when I click on another circle, then the opened div is closing and related div is opening but when I click anywhere on the document, then none of the div are closing.
$("#discussion_declined , #discussion_pending").click(function() {
var relatedDiv = $(this).closest('.panel').find('.discussion_edit_div');
relatedDiv.toggle("fast");
$('.discussion_edit_div').not(relatedDiv).hide('fast');
});
.discussion_small_round_div {
width: 25px;
height: 25px;
border-radius: 50%;
position: relative;
background: #2d3446;
bottom: 9px;
left: 15px;
float: right;
}
.discussion_small_round_div:after {
content: '\2807';
font-size: 1.5em;
color: white;
position: absolute;
left: 9px;
top: 1px;
}
.discussion_edit_div {
background: #FFFFFF;
display: none;
position: absolute;
right: 35px;
border: thin #ced0d1 solid;
z-index: 1001;
width: 150px;
box-shadow: 0px 3px 3px #ccc;
}
ul li {
padding: 5px 15px;
list-style-type: none;
color: #838383;
}
ul li:hover {
background: #eeeded;
cursor: pointer;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="panel discussion_panel_div no_background no_box_shadow" style="position: relative;">
<div class="panel-heading no_border_radius bg-dark set_padding_0">
<div class="discussion_small_round_div pull-right cursor_pointer" id="discussion_declined"></div>
</div>
<div class="discussion_edit_div">
<ul>
<li> <span class="glyphicon glyphicon-trash"></span> Replicate</li>
<li><span class="glyphicon glyphicon-trash"></span> Delete</li>
<li><span class="glyphicon glyphicon-ban-circle"></span> Deactivate</li>
</ul>
</div>
</div>
<div class="panel discussion_panel_div no_background no_box_shadow" style="position: relative;">
<div class="panel-heading no_border_radius bg-dark set_padding_0">
<div class="discussion_small_round_div pull-right cursor_pointer" id="discussion_pending"></div>
</div>
<div class="discussion_edit_div">
<ul>
<li> <span class="glyphicon glyphicon-trash"></span> Replicate</li>
<li><span class="glyphicon glyphicon-trash"></span> Delete</li>
<li><span class="glyphicon glyphicon-ban-circle"></span> Deactivate</li>
</ul>
</div>
</div>
Praveen's answer is nice but you can also achieve the same without tweaking your HTML.
Just add this to your jQuery:
$(window).click(function() {
//Hide the menus if visible
$('.discussion_edit_div').hide('fast');
});
$("#discussion_declined , #discussion_pending").click(function(e) {
e.stopPropagation();
var relatedDiv = $(this).closest('.panel').find('.discussion_edit_div');
relatedDiv.toggle("fast");
$('.discussion_edit_div').not(relatedDiv).hide('fast');
});
And your are good to go.
This achieves one more thing which is that once you have opened one ul, then you can directly toggle to another ul by clicking once. In Praveen's answer you have to click twice in order to open the other ul.
Check the link:https://jsfiddle.net/zfqqqr1c/1/
How Bootstrap handles this is interesting. They have a mask, and the only thing you can click is the mask or the items in the menu.
$(function () {
$(".mask").hide();
$("nav > ul > li > a").click(function () {
$(this).closest("li").addClass("open");
$(".mask").show();
return false;
});
$(".mask").click(function () {
$(this).hide();
$(".open").removeClass("open");
});
});
* {font-family: 'Segoe UI'; margin: 0; padding: 0; list-style: none; line-height: 1; box-sizing: border-box;}
body {background-color: #f5f5f5;}
a {text-decoration: none; color: inherit;}
.mask {position: fixed; top: 0; bottom: 0; right: 0; left: 0; z-index: 8;}
nav > ul > li {display: inline-block; position: relative; width: 30%;}
nav > ul > li a {display: block; padding: 5px; border: 1px solid #ccc;}
nav > ul ul {position: absolute; left: 0; right: 0; z-index: 9; display: none;}
nav > ul > li.open > ul {display: block;}
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
<div class="mask"></div>
<nav>
<ul>
<li>
Main Item 1
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Sub Item 3</li>
<li>Sub Item 4</li>
<li>Sub Item 5</li>
</ul>
</li>
<li>
Main Item 2
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Sub Item 3</li>
<li>Sub Item 4</li>
<li>Sub Item 5</li>
</ul>
</li>
<li>
Main Item 3
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Sub Item 3</li>
<li>Sub Item 4</li>
<li>Sub Item 5</li>
</ul>
</li>
</ul>
</nav>
I am working on a simple vertical toggle menu but having trouble leaving the first drop level opened when its sub level is clicked. For less confusion here is fiddle , click on "Products" than on "Sites" and products will close.
But if you click on Products and than on Services it does what is needed
which is , close other subs when one is opened.
$('.vtoggle li').each(function(el) {
$(this).find('a').first().attr('href', 'javascript:;').addClass('vtoggler');
});
$('ul.vtoggle > li:has(ul)').addClass("inactive");
$('ul.vtoggle > li:has(ul) ul').css('display', 'none');
$('.vtoggler').click(function() {
var checkElement = $(this).next();
$('.vtoggle li').removeClass('active');
$(this).closest('li').addClass('active').removeClass("inactive");
if ((checkElement.is('ul')) && (checkElement.is(':visible'))) {
$(this).closest('li').removeClass('active').addClass('inactive');
checkElement.slideUp('normal');
}
if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
$('ul.vtoggle ul:visible').slideUp('normal');
checkElement.slideDown('normal');
}
if (checkElement.is('ul')) {
return false;
} else {
return true;
}
});
body {
background: #fff;
}
.vertical ul {
list-style-type: none;
padding: 0;
margin: 0;
display: block;
position: relative;
}
.vertical li {
list-style-type: none;
padding: 0;
margin: 0;
display: block;
float: none;
position: relative;
}
.vertical li a {
display: block;
height: 45px;
line-height: 45px;
padding: 0 10px;
border: 1px solid rgba(0, 0, 0, 0);
border-bottom-color: #eee;
}
/* sub menu */
.vertical ul ul {
display: none;
position: relative;
padding: 0 0 0 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="vertical">
<ul class="vtoggle">
<li>Home</li>
<li>Services +
<ul>
<li>Service 1</li>
<li>Service 2</li>
<li>Service 3</li>
</ul>
</li>
<li>Products +
<ul>
<li>Widgets</li>
<li>
Sites +
<ul>
<li>Site 1</li>
<li>Site 2</li>
</ul>
</li>
<li>Gadgets +
<ul>
<li>Gadget 1</li>
<li>Gadget 2</li>
</ul>
</li>
</ul>
</li>
<li>Contact</li>
</ul>
</nav>
A soution can be to wrap line into:
var lastUl = $('ul.vtoggle ul:visible:last');
if (lastUl.find(this).length == 0) {
$('ul.vtoggle ul:visible').each(function() {
if ($(this).find(checkElement).length == 0) {
$(this).slideUp('normal');
}
})
}
The snippet:
$(function () {
$('.vtoggle li').each(function (el) {
$(this).find('a').first().attr('href', 'javascript:;').addClass('vtoggler');
});
$('ul.vtoggle > li:has(ul)').addClass("inactive");
$('ul.vtoggle > li:has(ul) ul').css('display', 'none');
$('.vtoggler').click(function (e) {
var checkElement = $(this).next();
$('.vtoggle li').removeClass('active');
$(this).closest('li').addClass('active').removeClass("inactive");
if ((checkElement.is('ul')) && (checkElement.is(':visible'))) {
$(this).closest('li').removeClass('active').addClass('inactive');
checkElement.slideUp('normal');
}
if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {
var lastUl = $('ul.vtoggle ul:visible:last');
if (lastUl.find(this).length == 0) {
$('ul.vtoggle ul:visible').each(function() {
if ($(this).find(checkElement).length == 0) {
$(this).slideUp('normal');
}
})
}
checkElement.slideDown('normal');
}
if (checkElement.is('ul')) {
return false;
} else {
return true;
}
});
});
body {
background: #fff;
}
.vertical ul {
list-style-type: none;
padding: 0;
margin: 0;
display: block;
position: relative;
}
.vertical li {
list-style-type: none;
padding: 0;
margin: 0;
display: block;
float: none;
position: relative;
}
.vertical li a {
display: block;
height: 45px;
line-height: 45px;
padding: 0 10px;
border: 1px solid rgba(0, 0, 0, 0);
border-bottom-color: #eee;
}
/* sub menu */
.vertical ul ul {
display: none;
position: relative;
padding: 0 0 0 20px;
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<nav class="vertical">
<ul class="vtoggle">
<li>Home</li>
<li>Services +
<ul>
<li>Service 1</li>
<li>Service 2</li>
<li>Service 3</li>
</ul>
</li>
<li>Products +
<ul>
<li>Widgets</li>
<li>
Sites +
<ul>
<li>Site 1</li>
<li>Site 2</li>
</ul>
</li>
<li>Gadgets +
<ul>
<li>Gadget 1</li>
<li>Gadget 2</li>
</ul>
</li>
</ul>
</li>
<li>Contact</li>
</ul>
</nav>
Microsoft suggests using aria-haspop="true" to simulate hover on touch-enabled devices.
This is also the correct use in the W3 roles model spec.
Without including aria-haspop="true" I am unable to keep a submenu open when I click, and when I hold down a click it will fire a "right-click".
Codepen Example
HTML
<ul class="menu">
<li aria-haspopup="false">
aria-haspopup="false"
<ul class="sub-menu">
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
<li>
Menu Item 2
</li>
<li aria-haspopup="true">
aria-haspop="true"
<ul class="sub-menu">
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
</ul>
CSS
.menu > li {
display: inline-block;
position: relative;
background: #1abc9c;
}
.menu > li > a {
padding: 20px;
background: #1abc9c;
display: inline;
float: left;
}
.menu > li:hover .sub-menu {
display: block;
position: absolute;
background: #1abc9c;
top: 50px;
left: 0;
}
.menu .sub-menu {
display: none;
}
.menu .sub-menu li {
padding: 20px;
width: 140px;
}
Let's try to make the web a less accessible place. Is there any way to have the sub-menu work just as well without adding aria tags on a windows surface device? Preferably using only CSS. Javascript would be acceptable but less than ideal.
In the same Microsoft guide you linked, they recommend using the onclick event to show content.
The best practice is to not use hover to hide content that a user can interact with. Instead, consider using the onclick event to toggle the visibility.
The challenge, of course, is that your menu items are also links, and clicking on a link is likely to take you to another page. Only if they really are dead anchors that go nowhere (as in your example code) is it safe to use their onclick events to show or hide the submenus.
Here's some example code that uses onclick to show the submenus instead of using CSS :hover. Note that my example directly assigns the handlers for the sake of brevity, but better practice would be to use the addEventListener() method.
var parentMenuItems = document.querySelectorAll(".menu > li");
var len = parentMenuItems.length;
while (len--) {
parentMenuItems[len].onclick = showSubMenu;
parentMenuItems[len].onmouseenter = showSubMenu;
parentMenuItems[len].onmouseleave = hideSubMenu;
}
function showSubMenu() {
this.querySelector(".sub-menu").style.display = "block";
}
function hideSubMenu() {
this.querySelector(".sub-menu").style.display = "none";
}
.menu > li {
display: inline-block;
position: relative;
background: #1abc9c;
}
.menu > li > a {
padding: 20px;
background: #1abc9c;
display: inline;
float: left;
}
.menu > li .sub-menu {
position: absolute;
background: #1abc9c;
top: 50px;
left: 0;
}
.menu .sub-menu {
display: none;
}
.menu .sub-menu li {
padding: 20px;
width: 140px;
}
<ul class="menu">
<li aria-haspopup="false">
aria-haspopup="false"
<ul class="sub-menu">
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
<li aria-haspopup="true">
aria-haspop="true"
<ul class="sub-menu">
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
</ul>
I'm taking this CSS-Tricks article and converting it to a UL > LI instead of a DT > DD approach. I just want the pink box to reveal the sub-links when clicked.
For some reason though I cannot get it working. I've created a jsFiddle of it here (click the pink box):
//Accordion
(function($) {
var allPanels = $('ul.sub-level').hide();
$('.click-me').click(function() {
allPanels.slideUp();
alert('slide up');
// Problem line
$(this).parent().next().slideDown();
return false;
});
})(jQuery);
ul { list-style: none; padding:0; margin:0; width: 400px; }
ul li { position:relative; background: #fafafa; margin-bottom:3px; height:20px; }
ul li > ul { margin-left: 30px; background: #e3e3e3; }
.click-me { display:block; width: 20px; height: 20px; position: absolute; top:0; right:0; background: #e4f; cursor: pointer;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Link somewhere</li>
<li>Link somewhere</li>
<li class="test">
Link somewhere
<!-- I want to reveal accordion using this span tag -->
<span class="click-me"></span>
<!-- /end -->
<ul class="sub-level">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
</ul>
<li>Link somewhere</li>
</li>
</ul>
http://jsfiddle.net/ndczc728/1/
The problem line is this (I think):
// Problem line
$(this).parent().next().slideDown();
Anyone?
You don't need to use parent. Also you have to remove fixed height from li elements:
//Accordion
(function($) {
var allPanels = $('ul.sub-level').hide();
$('.click-me').click(function() {
allPanels.slideUp();
// Problem line
$(this).next().slideDown();
return false;
});
})(jQuery);
ul {
list-style: none;
padding: 0;
margin: 0;
width: 400px;
}
ul li {
position: relative;
background: #fafafa;
margin-bottom: 3px;
}
ul li > ul {
margin-left: 30px;
background: #e3e3e3;
}
.click-me {
display: block;
width: 20px;
height: 20px;
position: absolute;
top: 0;
right: 0;
background: #e4f;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Link somewhere
</li>
<li>Link somewhere
</li>
<li class="test">
Link somewhere
<!-- I want to reveal accordion using this span tag -->
<span class="click-me"></span>
<!-- /end -->
<ul class="sub-level">
<li>Link 1
</li>
<li>Link 2
</li>
<li>Link 3
</li>
<li>Link 4
</li>
</ul>
<li>Link somewhere
</li>
</li>
</ul>