Need help closing sidebar/pull navigation menu when menu item is clicked - javascript

I have a responsive website that contains a navigation slider that is closed (off-screen) by default. This includes a vertical push/pull bar that is always visible on the screen to open and close the menu. The entire navigation slider is fixed on the page with a scrollbar on the menu.
When the menu is open on smaller devices, it takes up 100% of the viewport width. To accommodate this, I also add a top margin to the body content of 100vh to push it off the bottom. When a user clicks a menu item, it should take them to the link and automatically close the menu. I'm attempting to do this with an event listener on the menu items. If clicked, it removes the active class that controls the display when the menu is open. Currently, it takes the user to the link, but does not close the menu.
I know that the event listener works (to some degree) because if I change the body to display:none instead of margin-top:vh, clicking the menu item closes the menu, but, of course, it does not take the user to the link. I am aware that this is because the body content was displayed until after the link was clicked, which is why I'm trying to handle this with margin-top instead of display.
What am I missing? I've searched for an answer to this, but I can't seem to find anything that addresses this particular issue. I am pretty inexperienced in JavaScript, so any help is greatly appreciated.
$(document).ready(function() {
var mquery = window.matchMedia("(max-width:767.98)");
$('#toggle-bar').on('click', function() {
$('#sidebar').toggleClass('active');
});
if (mquery.matches) {
$('.menu-item').on('click', function() {
$('#sidebar').removeClass('active');
});
}
});
.sidebar {
display: flex;
width: 100%;
position: fixed;
max-height: 100vh;
margin-left: calc(-100% + 25px);
/*to keep .sidebar-toggle in the view*/
}
.sidebar.active {
margin-left: 0;
}
.sidenav {
overflow-y: scroll;
}
.sidebar-toggle {
width: 25px;
}
.sidebar #navpush {
display: none;
}
.sidebar.active #navpush {
display: inline;
}
.sidebar.active #navpull {
display: none;
}
.body-content {
padding: 15px;
}
.sidebar.active~.body-content {
margin-top: 100vh;
}
<div class="container body-wrapper">
<aside class="sidebar" id="sidebar">
<nav class="sidenav">
<ul id="main-nav">
<li>Section 1</li>
<li>Section 1
<ul id="sect1nav" class="collapse submenu">
<li>Section 2A</li>
<li>Section 2B</li>
</ul>
</li>
<li>Section 3</li>
</ul>
</nav>
<div class="toggle-bar" id="toggle-bar">
<div id="nav-toggle">
<span id="navpush">«</span>
<span id="navpull">»</span>
</div>
</div>
</aside>
<div class="container body-content">
<div id="section1">
<h2>Section 1 Title</h2>
<div>
<!-- Content -->
</div>
</div>
<div id="section2">
<h2>Section 2 Title</h2>
<div id="section2a">
<h3>Section 2A Title</h3>
<div>
<!-- Content -->
</div>
</div>
<div id="section2b">
<h3>Section 2B Title</h3>
<div>
<!-- Content -->
</div>
</div>
</div>
<div id="section3">
<h2>Section 2 Title</h2>
<div>
<!-- Content -->
</div>
</div>
</div>
</div>

The issue is caused by lack of units in the media query:
Fixed code (note the addition of "px" at the end):
var mquery = window.matchMedia("(max-width:767.98px)");
Pre-edit: Your HTML markup does not contain elements with ID "sidebar" (#sidebar) or "toggle-bar" (#toggle-bar).

Related

Match div to window size with css or javascript

I have an element which drops down when I toggle my menu bars.
I can make the element as large or as small as I like but can't make it fit to screen so it doesn't scroll and no page shows underneath. It's a WordPress site and I started off with an an i class fa-bars. It wasn't possible to animate font awesome so I replaced it with this.
<div class="module widget-handle mobile-toggle right visible-sm visible-xs">
<a id="mobile-nav" href="#">
<div class="container1"
onclick="myFunction(this)">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
</a>
<script>
function myFunction(x) {
x.classList.toggle('change');
}
</script>
</div>
This worked to toggle the menu amd make it drop but it didn't cover the screen. The element controlling the dropdown area was too small so I enlarged it by increasing height, like so:
#media (max-width: 768px) {
.collapse {
position: absolute;
height: 775px;
background-color: white;
z-index: 99999 !important;
top: 75px;
left: -50px;
line-height: 10px;
}
}
This made it too high but making it any lower would show the page underneath.
Is there a way I can modify my existing javascript or css to make it fit to screen exactly, responsively with no scroll and no page showing underneath?
It's located in my header.php so it would go there I'm assuming, if there's a way to modify what i already have. If not, what's a good way to approach this?
here on mobile
Html dropdown.
<div class="module-group right">
<div class="module left">
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul id="menu" class="menu">
<li id="menu-item-15050"
class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-15050 dropdown">
<a title="Contact" href="url">Contact
<ul role="menu" class="dropdow n-menu">
</ul>
</a>
</li>
</ul>
</div>
</div>
</div>
I've tried applying min-height to element collapse max- height and 100% None worked.
Here's a pen https://codepen.io/adsler/pen/bGVXNVM
You can used position: fixed to size the element with respect to the frame:
.your-selector {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
This will make it take up the entire window. It's not clear if you're wanting it to cover the window in all dimensions, but you can choose where the top/bottom/left/right anchor selectively.
If you're also wanting to make the body (or if it's not the body some other scrollable element) non-scrollable, set the overflow style to hidden.

How to undo javascript function

I have a function like so which toggles my dropdown menu.
<div class="module widget-handle mobile-toggle right visible-sm visible-xs">
<a id="mobile-nav" href="#">
<div class="container1" onclick="myFunction(this)">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>.
</div>
</a>
</div>
<script>
function myFunction(x) {
x.classList.toggle('change');
document.body.style.overflow ='hidden'
}
</script>
The last part of it
document.body.style.overflow = 'hidden'
Keeps the page from overflowing at the top when the dropdown menu is open. The problem is that when I click on my menu bars, whilst the overflow disappears, clicking on the bars again reveals the page but locks it due to the overflow being hidden.
I'd like to undo
document.body.style.overflow = 'hidden'
When the menu is closed and the closest I've got to understanding it is the function doBack. Can I somehow add doBack to my existing function?
Mobile page here
It's a WordPress site and the javascript above toggles the dropdown by pressing on the bars. In order to extend the dropdown, I made the class collapse bigger, like so.
#media (max-width: 768px) {
.collapse {
position: absolute;
height: 775px;
background-color: white;
z-index: 99999 !important;
top: 75px;
left: -50px;
line-height: 10px;
}
}
HTML:
<div class="module-group right">
<div class="module left">
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul id="menu" class="menu">
<li id="menu-item-15050" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-15050 dropdown">
<a title="Contact" href="url">Contact
<ul role="menu" class="dropdow n-menu">
</ul>
</a>
</li>
</ul>
</div>
</div>
</div>
You can eliminate the style attribute by using:
document.body.style.overflow = null
You can simply add a new CSS class:
.body-overflow {
overflow: hidden;
}
and in your javascript function add another .classList.toggle() but this time on the body:
function myFunction(x) {
x.classList.toggle('change');
document.body.classList.toggle('body-overflow');
}

jQuery adding and removing classes dynamically when the user clicked

I've a problem with the following code. I've two tabs in my navigation Tab-1 & Tab-2, when the user click on any tab, then I want to add the active class to it and at the same time I want to remove the active class from previously active tab. Also the tab which is currently active should display its content and have to hide the remaining content. It means when the user clicked on any tab it should display only its content and the other contents should be hidden. Please help me thank you.
<style>
.wrapper .tabs {
display: none;
}
.wrapper .tabs.active {
display: block;
}
</style>
<div class="wrapper">
<!-- Navigation -->
<ul class="nav">
<li class="active">Tab-1</li>
<li>Tab-2</li>
</ul>
<!-- Panel-1 -->
<div id="tab-1" class="tabs active">
<p>Tab-1 Content</p>
</div>
<!-- Panel-2 -->
<div id="tab-2" class="tabs">
<p>Tab-2 Content</p>
</div>
</div>
<!-- Script -->
<script>
$(document).ready(function () {
$('.nav li').click(function() {
$('.nav li.active').removeClass('active');
$(this).addClass('active');
});
// To display content for active class only
$('.nav li').click(function() {
$('.wrapper .tabs.active').removeClass('active');
$(this).addClass('active');
});
});
</script>
You can use .eq(), .index() at click event attached to selector "a[href^='#tab-']" which selects element where href begins with #tab-, create variable referencing elements where id begins with tab-, call event.preventDefault() within click function to prevent navigation to document fragment, .hide(), .show()
$(document).ready(function() {
var a = $("a[href^='#tab-']");
var tabs = $("[id^=tab]");
a.click(function(e) {
e.preventDefault();
tabs.hide().eq(a.index(this)).show()
})
})
#tab-1 {
display: block;
}
[id^="tab"]:not(#tab-1) {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js">
</script>
<div class="wrapper">
<!-- Navigation -->
<ul class="nav">
<li>
Tab-1
</li>
<li>
Tab-2
</li>
</ul>
<!-- Panel-1 -->
<div id="tab-1" class="tabs active">
<p>Tab-1 Content</p>
</div>
<!-- Panel-2 -->
<div id="tab-2" class="tabs">
<p>Tab-2 Content</p>
</div>
</div>

Cannot type (or even focus) in input type="text" while bootstrap modal is open

I have a jquery code that creates a dropdown menu and places it exactly where the user right-clicked. Everything works fine except one thing: I cannot type inside an input field.
The generated dropdown looks as follows:
<ul role="menu" style="display: none; position: absolute; left: 751px; top: 294px; z-index: 999999;">
<li>Link 1</li>
<li role="separator" class="divider"></li>
<li><input type="text" name="filter"></li>
<li style="height:200px;" class="scroll-container-y">
<ul class="list-unstyled gutter-left-small">
<li>Sublink 1</li>
<li>Sublink 2</li>
<li>Sublink 3</li>
</ul>
</li>
</ul>
In my idea, the input will be used to filter the Sublinks.
What I've tried (with no results):
Change z-index
Force $('input').focus()
Force $('input').get(0).focus()
Playing around with CSS to check if it was just white text over white background
Reviewed code to see if some other jQuery was interfering
Hope you guys can help.
EDIT (working example):
It appears that this is a Bootstrap problem: as you can see from this fiddle http://jsfiddle.net/2gkjb0h8/3/ the input can be entered UNTIL the bootstrap modal is opened. Still no clue on how to solve this.
EDIT 2:
Here's an image of what I want to achieve http://prnt.sc/bxbucf
In the modal, there will be a table with selectable TDs; once selected, the user can right click to open a context menu with a list of teachers (each of them is a link). This works already, the input is there to allow filtering all the possible names.
It appears that this answer would resolve your problem.
Twitter Bootstrap modal blocks text input field
The author recommends against a modal for this scenario (and I agree).
It sounds like a modal isn't the right solution to your problem here.
A modal dialog by definition shouldn't allow the user to interact with anything below it.
However, he does provide a workaround:
Bootstrap 2
$('#myModal1').on('shown', function() {
$(document).off('focusin.modal');
});
You can see this in action on an updated jsfiddle of your original solution:
http://jsfiddle.net/2gkjb0h8/4/
Bootstrap 3
It should also be noted that the event names changed in Bootstrap 3:
$('#myModal1').on('shown.bs.modal', function() {
$(document).off('focusin.modal');
});
<div id="myModal1" class="modal hide" tabindex="-1" role="dialog">
tabindex is used to define whether elements should be focusable or not within a page. You have used tabindex attribute so that focus is on modal and you can't able to enter text on text box. Just remove tabindex you can able to enter text.
<div id="myModal1" class="modal hide" role="dialog">
Click here to check on jsfiddle
Not sure if the element is in DOM when you are trying to focus on it.
You can call this once this component is visible after right click. Also use assign an id to this input element.
$('body').find('#idOfInput').focus();
You can try usind data-target to focus the input
.btn-group {
z-index: 1051;
}
ul[role="menu"]{
position: absolute;
left: 50px;
top: 400px;
z-index: 999999;
border: 1px solid black;
}
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<div class="container">
<h3>Inputting proble</h3>
<!-- Button to trigger modal -->
<div>
<a href="#myModal1" role="button" class="btn" data-toggle="modal" data-target="#text" class="test" >Launch Modal</a>
<p>
Now you are able to enter text in the input field below. Once tested, open the modal.
</p>
</div>
<!-- Modal -->
<div id="myModal1" class="modal hide" tabindex="-1" role="dialog">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Modal</h3>
</div>
<div class="modal-body">
<p>Now you will not be able to enter text in the input</p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
</div>
</div>
</div>
<ul role="menu">
<li>Link 1</li>
<li role="separator" class="divider"></li>
<li><input id="text" type="text" name="filter" ></li>
<li style="height:200px;" class="scroll-container-y">
<ul class="list-unstyled gutter-left-small">
<li>Sublink 1</li>
<li>Sublink 2</li>
<li>Sublink 3</li>
</ul>
</li>
</ul>
<style>
I had the same issue using bootstrap modal version 4.3.1. The prescribed solution to remove the focus out of the open modal was not working for me.So, I ended up removing the modal entirely from my code. And used combination of css attributes position ,z-index and display to achieve the same look as that of a modal dialog.
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.rootDivKlass {
position: relative;
width: 800px;
height: 500px;
background-color: #A64831;
}
.backGroundDivKlass {
background-color: #BEB2AF;
height:400px;
width:500px;
z-index: 1;
position: absolute;
}
.myModalLikeDivKlass {
position: absolute;
z-index: 2;
display: block;
width: 290px;
height: 200px;
margin: 100px;
background-color: white;
}
.inputDivKlass {
position: absolute;
margin-left: 550px;
margin-top: 50px;
}
</style>
</head>
<body>
<div class="rootDivKlass">
<div id="modalBackgroundDiv" class="backGroundDivKlass">
</div>
<div class="myModalLikeDivKlass">
<center><font color="blue">Put your modal content here</center>
</div>
<div class="inputDivKlass">
<input type="text"/>
</div>
</div>
</body>
</html>
Correct! Tabindex is used to define whether elements should be focusable or not within a page. You have used tabindex attribute so that focus is on modal and you can't able to enter text on text box. Just remove tabindex you can able to enter text.

Display a fixed header after scolling a specific distance in Bootstrap

I am using Bootstrap affix property to display a header after scrolling to 100px. It works fine when I set opacity property to 0.0001 etc. but when I set it to 0 or display to none. It stops working. Here is a working demo with opacity property - http://jsfiddle.net/gu33f5cm/.
One issue with setting opacity is that it still takes up space in the document and the document appears to be blank at the location of header. This is my CSS code:
CSS:
#nav.affix {
position: fixed;
top: 0;
width: 100%;
transition: 0.6s all;
}
#nav.affix-top {
opacity:0.1;
}
HTML:
<div class="container" data-spy="affix" data-offset-top="100" id="nav">
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<div class="span12"> <a class="brand" href="#">Home</a>
<ul class="nav">
<li class="active">Home
</li>
<li>Link
</li>
<li>Link
</li>
</ul>
</div>
</div>
</div>
</div>
What version of bootstrap are you using? In v3.3.5 there is a separate nav class which works as you require.
http://getbootstrap.com/examples/navbar/

Categories

Resources