Adding dropdown and collapse functions to mobile menu - javascript

An issue that’s been bugging me for a while is that by default in the mobile menu of my theme, ALL menu items auto expand so it makes it hard to navigate if you have a lot of sub-menu items.
I’m trying to have my sub-menu items collapse with a drop-down arrow. Something that seems fairly simple but there are no options for adjust this in WordPress.
I managed to find some code in Header.php that you will find below
Any ideas how I can modify this code to have my sub-menu items collapse with a dropdown arrow?
Thanks
Christian

You can do it easily by Bootstrap:
Bootstrap Dropdowns
or, You can also hide dropdowns in css:
li ul{
display: none;
}
and show it on arrow click using jQuery:
$("li a").click(function(){
$(this).parent().find("ul").toggle();
});
Demo:
https://codepen.io/seyyedmojtaba72/pen/VOgmdE

Pure js
let arr=[...document.querySelectorAll(".toggle")];
arr.map(a=> a.onclick = e => {
a.nextElementSibling.classList.toggle('hide');
a.innerHTML = a.innerHTML=='→' ? '↓' : '→';
});
.hide { display: none }
.toggle { cursor: pointer}
<nav>
<ul id='menu'>
<li><a class='home' href='/'>Home</a></li>
<li>
<a class='prett' href='#' >SubMenu A</a>
<span class="toggle">→</span>
<ul class='submenus hide'>
<li><a href='#' >Dropdown 1</a></li>
<li><a href='#' >Dropdown 2</a></li>
</ul>
</li>
<li>
<a class='prett' href='#' >SubMenu B</a>
<span class="toggle">→</span>
<ul class='submenus hide'>
<li><a href='#' >Dropdown 3</a></li>
<li><a href='#' >Dropdown 4</a></li>
</ul>
</li>
<li><a class='home' href='/'>Back</a></li>
</ul>
</nav>

Sorry I had a hard time figuring out how to paste code without errors. Here is my code below. Any way to modify this code to have a collapsible drop down menu on mobile devices?
<!– Toggle button for Main Navigation on mobile –>
<button class=”btn btn-primary header__navbar-toggler hidden-lg-up js-sticky-mobile-option” type=”button” data-toggle=”collapse” data-target=”#shaka-main-navigation”><i class=”fa fa-bars hamburger”></i> <span><?php esc_html_e( ‘MENU’ , ‘shaka-pt’ ); ?></span></button>
<!– Main Navigation –>
<nav class=”header__navigation collapse navbar-toggleable-md js-sticky-desktop-option” id=”shaka-main-navigation” aria-label=”<?php esc_html_e( ‘Main Menu’, ‘shaka-pt’ ); ?>”>
<?php
if ( has_nav_menu( ‘main-menu’ ) ) {
wp_nav_menu( array(
‘theme_location’ => ‘main-menu’,
‘container’ => false,
‘menu_class’ => ‘main-navigation js-main-nav js-dropdown’,
‘walker’ => new Aria_Walker_Nav_Menu(),
‘items_wrap’ => ‘<ul id=”%1$s” class=”%2$s” role=”menubar”>%3$s‘,
) );
}
?>
<?php

Related

JQuery trouble understanding event order

I am trying to create a Bootstrap dropdown menu with two sub-menus. My problem is that the dropdowns are dynamically created after the document is loaded, and don't respond to how I would normally get them to work.
How I would normally go about it would be
$(document).ready(function(){
addItem(); //adds the first instance of the drop down
$('ul.dropdown-menu [data-toggle=dropdown]').on('click', function(e){
e.stopPropagation();
e.preventDefault();
$(this).siblings().removeClass("open");
$(this).parent().toggleClass("open");
});
});
But this obviously doesn't work for dynamically created content. I saw elsewhere online that this would work for dynamic content;
//still has first instance of dropdown, just later in the doc
$(document).on('click', 'ul.dropdown-menu [data-toggle=dropdown]', function(e){
e.stopPropagation();
e.preventDefault();
$(this).siblings().removeClass("open");
$(this).parent().toggleClass("open");
});
but for the life of me, I can't figure out why this doesn't work. What I'm seeing is that it is adding the open class to the sub-menu, but toggle the parent menu(not stopping propagation?) So, my question is, why doesn't the second one execute as expected, and how can I make it?
List structure for reference:
<div class="dropdown open">
<button id="select0" class="btn new-btn" data-toggle="dropdown" aria-expanded="true">Select Your Item <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a class="sub" data-toggle="dropdown">Item 1</a>
<ul class="dropdown-menu sub-menu">
<li><a data-def-cost="6">Item 1.1</a></li>
<li><a data-def-cost="8">Item 1.2</a></li>
</ul>
</li>
<li><a class="sub" data-toggle="dropdown">Item 2</a>
<ul class="dropdown-menu sub-menu">
<li><a data-def-cost="5">Item 2.1</a></li>
<li><a data-def-cost="3">Item 2.2</a></li>
</ul>
</li>
<li><a data-plu="xyz" data-def-cost="8.00">Item 3</a></li>
<li><a data-plu="xyz" data-def-cost="8.00">Item 4</a></li>
<li><a data-plu="xyz" data-def-cost="10.00">Item 5</a></li>
<li class="dropdown-header">Other Items</li>
<li><a data-plu="143">Item 6</a></li>
<li><a data-plu="xyz">Item 7</a></li>
<li><a data-plu="xyz">Item 8</a></li>
</ul>
<input type="text" class="hidden" name="input1">
<input type="text" class="hidden" name="otherinput1">
</div>
$(this).siblings() points to an ul element, however, the .open class is supposed to be added to the parent li : http://getbootstrap.com/javascript/#dropdowns-usage.
Via data attributes or JavaScript, the dropdown plugin toggles hidden content (dropdown menus) by toggling the .open class on the parent list item.
Here is a suggestion (inspired by the following code snippet : Multi-Level Dropdowns) :
$(document).ready(function () {
// this variable keeps track of the last open menus
// in order to close them when another link is clicked
// or when the entire dropdown is closed
var open;
$("#my-dropdown").on("hide.bs.dropdown", function () {
if (open) open.removeClass("open");
});
$(".dropdown-submenu > a").on("click", function (e) {
if (open) open.removeClass("open");
open = $(this).parents(".dropdown-submenu");
open.addClass("open");
e.stopPropagation();
e.preventDefault();
});
});
.dropdown-submenu {
position: relative;
}
.dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
margin-top: -1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<div class="dropdown" id="my-dropdown">
<button type="button" data-toggle="dropdown">
Dropdown trigger
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>Action 1</li>
<li>Action 2</li>
<li class="dropdown-submenu">
Submenu 1
<ul class="dropdown-menu">
<li>Action 1.1</li>
<li>Action 1.2</li>
</ul>
</li>
<li class="dropdown-submenu">
Submenu 2
<ul class="dropdown-menu">
<li>Action 2.1</li>
<li>Action 2.2</li>
<li class="dropdown-submenu">
Submenu 2.3
<ul class="dropdown-menu">
<li>Action 2.3.1</li>
<li>Action 2.3.2</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Unsure as to efficiency of my solution, but I rearranged the order a bit, and forced the parent to stay open
$(document).on('click', 'ul.dropdown-menu [data-toggle=dropdown]', function(e){
$(this).siblings().removeClass("open");
$(this).parent().addClass("open");
$(this).parent().parent().parent().addClass("open");
e.stopPropagation();
e.preventDefault();
});
and this solved my issue
use one of these below lines.
$(this).siblings('.dropdown-menu').removeClass('open');
$(this).next('.dropdown-menu').removeClass('open');

Mobile navigation with sliding dropdown menu

i'm trying to create a seperate mobile navigation for a website i'm creating. this is the basic html layout right now
<nav class="mobile-navigation">
<ul class="header-mobile">
<li>
<i class="fa fa-bars" aria-hidden="true"></i>
</li>
<li>
<img src="{$WEB_ROOT}/templates/{$template}/img/logo/logo.svg" alt="logo">
</li>
<li>
<ul>
<li><span class="icon icon-nav-account"></span></li>
<li>
<a href="{$WEB_ROOT}/cart.php?a=view">
<span class="icon icon-cart"></span>
<span class="notification-amount">{$cartitemcount}</span>
</a>
</li>
</ul>
</li>
</ul>
</nav>
<div class="row">
<ul class="nav-mobile">
<li>About us</li>
<li>Services</li>
<li>Domains</li>
<li>Support</li>
</ul>
</div>
with a simple script to toggle the menu
$('.fa-bars').click(function(evt) {
$('.nav-mobile').slideToggle('down');
});
Now i'm trying to create something where if a list item is chosen, the dropdown is displayed like the images below.
first list -->
second list with selected item
anyone an idea how i achieve this?
First of all you should change your arrow's direction and position. or create two of them one on left and one on right then when user clicks on a li toggle class clicked or something else to that li element(if you want others to collapse you should remove clicked class). Then in css
li > ul{
display:none;
}
li .left-arrow{
display:none;
}
li.clicked > .left-arrow{
display:inline;
}
li.clicked > ul{
display: block;
}
should do the trick

Accordion menu with rotating arrows

I have created a simple accordion with rotating arrows on click. It works fine with one exception :
I have a few collapsible item and if I click the first one it works ok. But clicking the other one do not rotate the previous icon to the default state.
How to make arrow to come back to the default state when clicking the other collapsible item?
$(function() {
$('.arrow-r').on('click', function() {
$(this).find('.fa-angle-down').toggleClass('rotate-element');
})
})
.rotate-element {
#include transform (rotate(180deg));
}
.fa-angle-down {
&.rotate-icon {
position: absolute;
right: 0;
top: 17px;
#include transition (all 150ms ease-in 0s);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="collapsible collapsible-accordion">
<li><a class="collapsible-header arrow-r"> Menu 1<i class="fa fa-angle-down rotate-icon"></i></a>
<div class="collapsible-body">
<ul>
<li><a>Item 1</a>
</li>
<li><a>Item 2</a>
</li>
</ul>
</div>
</li>
<li><a class="collapsible-header arrow-r"> Menu 2<i class="fa fa-angle-down rotate-icon"></i></a>
<div class="collapsible-body">
<ul>
<li><a>Item 1</a>
</li>
<li><a>Item 2</a>
</li>
</ul>
</div>
</li>
<li><a class="collapsible-header"> Menu 3</a>
<div class="collapsible-body">
<ul>
<li><a>Item 1</a>
</li>
<li><a>Item 2</a>
</li>
</ul>
</div>
</li>
Please try this:
$(function() {
$('.arrow-r').on('click', function() {
//Reset all but the current
$('.arrow-r').not(this).find('.fa-angle-down').removeClass('rotate-element');
//Rotate/reset the clicked one
$(this).find('.fa-angle-down').toggleClass('rotate-element');
})
})
If it helps other folks; this combination worked for me: (it's almost identical except I added the ".arrow-r" after the firs .find)
I had 4 main Accordions with multiple Accordions inside, but I only wanted the main arrow on each of the main accordions to animate. (this combination stopped all the inner accordions from triggering the main animation)
$(function() {
$('.arrow-r').on('click', function() {
//Reset all but the current
$('.arrow-r').not(this).find('.arrow-r').removeClass('rotate-element');
//Rotate/reset the clicked one
$(this).find('.fa-angle-down').toggleClass('rotate-element');
})
})
This is my actual code if it helps to see the pattern:
$(function() {
$('.accroordlite').on('click', function() {
//Reset all but the current
$('.accroordlite').not(this).find('.accroordlite').removeClass('down');
//Rotate/reset the clicked one
$(this).find('.spinOnClick').toggleClass('down');
})
})

How to add active class to nav ul li a element when it has some sub pages with it?

I am working on Drupal 8 website. In that i having a problem in assigning a active class to nav list elements.
I used the following code to set the active class, it is working for the same url.
The code look like this
<nav id="getnav">
<ul>
<li>
<a class="" data-drupal-link-system-path="user" href="/drupal/todo">Todo</a>
</li>
<li>
<a class="" data-drupal-link-system-path="user" href="/drupal/files">Files</a>
</li>
<li>
<a class="" data-drupal-link-system-path="user" href="/drupal/photos">Photos</a>
</li>
</ul>
</nav>
I used jquery function to set the active class based on the url. Using the following code.
function setActive() {
var myurl =window.location.href.substr(window.location.href.lastIndexOf("/")+1);
$("#getnav ul li a").each(function(){
if($(this).attr("href") == '/drupal/'+myurl )
$(this).addClass("active");
});
}
window.onload = setActive();
The real problem is whenever accessing the subpages like todo/page2 the active class is gone.
http://localhost/drupal/todo :::is working fine but after accessing subpage like
http://loclahost/drupal/todo/add
The class is gone.
Please give me suggestions regarding this problem.
I want to Set The Active class to all of the subpages too.after todo/*
You can do this using pure CSS. You need to add class/id to your body element and your nav li elements, and then you can define combinations of them in your css to be highlighted. For example, suppose this is your html:
< body id="todo_body">
<nav id="getnav">
<ul>
<li class="todo_dropdown">
<a class="" data-drupal-link-system-path="user" href="/drupal/todo">Todo</a>
</li>
<li class="files_dropdown">
<a class="" data-drupal-link-system-path="user" href="/drupal/files">Files</a>
</li>
<li class="photos_dropdown">
</body>
<a class="" data-drupal-link-system-path="user" href="/drupal/photos">Photos</a>
</li>
</ul>
</nav>
</body>
Now, you can use css like given below to apply highlighting styles to your 'should be active' li element:
#todo_body .todo_dropdown,
#files_body .files_dropdown,
#photos_body .photos_dropdown
{
background-color: red;
color: white;
/*Your css styles for active nav item will come here */
}
You can also add any styles to any elements contained in the should be active li element.
<ul class="nav">
<?php
$page_name = basename($_SERVER['PHP_SELF']);
?>
<!-- Main menu -->
<li class="<?php echo ($page_name=='dashboard.php')?'current':'';?>"><i class="glyphicon glyphicon-home"></i> Dashboard</li>
<li class="submenu <?php echo ($page_name=='welcome_note.php' || $page_name=='corporate_profile.php' || $page_name=='introduction_of_the_township.php' || $page_name=='location_map.php')?'current open':'';?>">
<a href="#">
<i class="glyphicon glyphicon-list"></i> Masters
<span class="caret pull-right"></span>
</a>
<!-- Sub menu -->
<ul>
<li class="<?php echo ($page_name=='welcome_note.php')?'current':'';?>">Welcome Note</li>
<li class="<?php echo ($page_name=='corporate_profile.php')?'current':'';?>">Corporate Profile</li>
<li class="<?php echo ($page_name=='introduction_of_the_township.php')?'current':'';?>">The Township</li>
<li class="<?php echo ($page_name=='location_map.php')?'current':'';?>">Location Map</li>
</ul>
</li>
</ul>

Bootstrap group element inline when navbar collapsed?

I have these two links here that act as buttons. They are basic glyphicons. This is when the navbar isn't collapsed into xs view.
But when the navbar is collapsed the links are each on one row which is the normal bootstrap comportement.
So my question is :
Is it possible to make both arrows/links inline like the in the non-collapsed navbar. If so how?
This is my code for the ul in the navbar-right section.
<ul class="nav navbar-nav navbar-right">
<li><a id="minicalendar" class="glyphicon glyphicon-calendar"></a></li>
<li><a id="linkToday">Today</a></li>
<li><a id="btnPrev" class="glyphicon glyphicon-arrow-left"></a></li>
<li><a id="btnNext" class="glyphicon glyphicon-arrow-right"></a></li>
<li><a class="glyphicon glyphicon-question-sign" type="button" id="btnHelp"></a></li>
</ul>
Demo
Something like this would do:
.menu-half {
display: inline-block !important;
width: 48%;
}
<li class="menu-half">...</li>
Demo
You can use 50% if you mash the two LI tags together. Demo

Categories

Resources