Side menu in JS - javascript

I'm trying to make a side menu but it's not perfect. Take a look:
JSFiddle
HTML
<div id="content-button">
<div id="open-menu">Click</div>
</div>
<div id="content">
<nav id="side-menu">
<ul>
<li>Link</li>
<li>Link</li>
<li>Link</li>
</ul>
</nav>
</div>
Javascript
$(function() {
$("#open-menu").click(function() {
var $cache = $("#side-menu");
if($cache.is(":visible"))
{
$cache.hide("slide", {direction:"left"}, 250);
}
else
{
$cache.show("slide", {direction:"left"}, 250);
}
});
});
CSS
#content-button {
width: 100%;
height: 100px;
}
#open-menu {
width: 50px;
height: 50px;
}
#side-menu {
position: relative;
left: 0;
}
When I click on "click", the side menu appear on the left of my screen BUT :
it appears suddenly, not with slide effect
it appears at the top of div "content" and push all the content. I want it to appear at the left and push the entire content to the right
it doesn't disappear when I click a second time on "click"
I hope you understood my problem. I can't show you on JsFiddle, it doesn't work and I'm on local but I can do some screenshot if needed.

"slide" isn't a valid parameter to show/hide.
Instead, you can use animations.
$(function() {
$("#open-menu").click(function() {
var $cache = $("#side-menu");
if($cache.position().left === 0)
{
$cache.animate({
left: -300
}).then(function(){
$cache.hide();
});
}
else
{
$cache.show();
$cache.animate({
left: 0
});
}
});
});
Make sure your menu is positioned relatively.
#side-menu {
position: relative;
/* left: -300px */ /* uncomment to default hidden */
}
demo

Related

Why button function only works once

i have sidebar if i click on button and then side bar appears from left, and when i click on body side bar hides, but why it is happening only for once.
FIDDLE
HTML
<body>
<div class="site-overlay"></div>
button ☰
<nav id="menu" class="panel" role="navigation">
<ul>
<li>Home</li>
<li>The Ballad of El Goodo</li>
<li>Thirteen</li>
<li>September Gurls</li>
<li>What's Going Ahn</li>
</ul>
</nav>
</body>
JS:
$(document).ready(function() {
$('.menu-link').bigSlide({
easyClose: true
});
$('.menu-link').click(function() {
$('body').addClass('menu-open');
});
});
CSS:
a.menu-link {
float: right;
padding: 20px
}
nav#menu {
background: lightblue;
z-index: 100000000000000
}
.site-overlay {
display: none;
}
.menu-open .site-overlay {
display: block;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 9998;
-webkit-animation: fade 500ms;
animation: fade 500ms;
}
HOW CAN I MAKE IT WORK IT MANY TIMES, instead of only one time.
After the click, you're showing your overlay, but because it has z-index: 9998, the overlay is being placed on top of the button, so when you try to click the button, you're actually clicking on the overlay, not on the button.
You should make an event when the overlay is clicked to remove that class, like this:
$('.site-overlay').click(function() { $('body').removeClass('menu-open') })
This is because the added class is not removed.
You can control it by adding a toggle value for that button.
Instead of addClass put toggle.
On the way you put you will add "menu-open" once and it will never be removed.
you have more information about this here: https://www.w3schools.com/howto/howto_js_toggle_class.asp
You can do it by this JS code.
$(document).ready(function() {
$('.menu-link').bigSlide({
easyClose: true
});
$('.menu-link').click(function() {
event.stopPropagation();
$('body').addClass('menu-open');
});
$('body').click(function(){
$('body').removeClass('menu-open');
})
});

Navigation animation using JS and SCSS, can you tell me where I'm going wrong?

I am trying to create a nav that contains 2 elements (left and right). I would like both elements to move in from their respective edges of the screen, meeting in the middle to create a full screen nav. Could anyone shed some light on where I'm going wrong?
So far I have managed to get each box to move individually but not both at the same time. I gave them both separate ID's within their nav class thinking this would allow me to manipulate their postioning in different ways when the function is called that toggles 'expanded' but again this hasnt worked.
This is my HTML Structure:
<div class="nav-toggle">
<div class="nav-toggle-bar"></div>
</div>
<nav id="left" class="nav">
</nav>
<nav id="right" class="nav">
<ul>
<li>Portfolio</li>
<li>Services</li>
<li>Contact</li>
</ul>
</nav>
Here is an part of my SCSS:
.nav {
background: $nav-background;
color: $nav-color;
cursor: pointer;
font-size: 2rem;
height: 100vh;
padding: 6rem 2rem 2rem 2rem;
position: fixed;
top: 0;
width: $nav-width;
z-index: $z-nav;
ul {
#include center-vertically;
list-style: none;
margin: 0;
padding: 0;
}
}
#right{
#include transition(right 0.5s ease);
right: -$nav-width;
&.expanded { right: 0; }
}
#left{
#include transition(left 0.5s ease);
left: -$nav-width;
&.expanded { left: 0; }
}
And this is my JS:
(function() {
var hamburger = {
navToggle: document.querySelector('.nav-toggle'),
nav: document.querySelector('nav'),
doToggle: function(e) {
e.preventDefault();
this.navToggle.classList.toggle('expanded');
this.nav.classList.toggle('expanded');
}
};
hamburger.navToggle.addEventListener('click', function(e) { hamburger.doToggle(e); });
}());
This is the codepen I have been working on: https://codepen.io/matthewoproctor/pen/YmxZPQ
Thanks in advance for any help.
Your approach with the two IDs and the shared classname is perfect, as is your SCSS. The problem here is actually pretty simple: hamburger.nav is using document.querySelector, which only selects the first element with the nav class. Instead, you should use document.querySelectorAll. Then you just have to tweak the doToggle function to loop through all elements with the nav class.
(function() {
var hamburger = {
navToggle: document.querySelector('.nav-toggle'),
nav: document.querySelectorAll('nav'),
doToggle: function(e) {
e.preventDefault();
this.navToggle.classList.toggle('expanded');
this.nav.forEach(n => n.classList.toggle('expanded'));
}
};
hamburger.navToggle.addEventListener('click', function(e) {
hamburger.doToggle(e);
});
}());

jQuery page animation makes button jump

So I was busy on a site, and I made a menu button with a menu which is hidden on the right side of the page as shown below:
When I press the red button, which is used to open the menu, the button jumps like 15px to the left.
As you can see, the button jumps, I would recommend using the black header to measure.
The button stays in its new position until I refresh the page.
Here is my jQuery:
$("#zijmenu-knop").click(function()
{
if($("#zijmenu").css('right') == '0px')
{
controlZijmenu('dicht');
}else if($("#zijmenu").css('right') == '-300px')
{
controlZijmenu('open');
}
});
function controlZijmenu(controller)
{
if(controller == 'dicht')
{
$("#zijmenu").stop(true).animate(
{
right : '-300px'
}, 500);
$("#mainSite, #zijmenu-knop").stop(true).animate(
{
right : '0px'
}, 500);
}else if(controller == 'open')
{
$("#zijmenu").stop(true).animate(
{
right : '0px'
}, 500);
$("#mainSite, #zijmenu-knop").stop(true).animate(
{
right : '300px'
}, 500);
}
}
Does anybody see any mistakes? Also, if more code is needed, please comment.
EDIT:
My CSS:
#zijmenu-knop {
width: 40px;
height: 40px;
cursor: pointer;
background-image: url(../img/menuknopje.png);
background-repeat: no-repeat;
z-index: 101;
position: fixed;
margin-top: -45px;
margin-right:3%;
margin-left:97%;
}
#zijmenu {
background: #DD5C65;
height:100%;
width:305px;
position: fixed;
z-index: 100000;
overflow: hidden;
right: -300px;
}
#mainSite{
width:100%;
position: fixed;
z-index: 1000;
right: 0px;
overflow: auto;
}
My HTML:
<div id="zijmenu">
<p class="zijmenu-titel">GH 24Hourz</p>
<div id="zijmenu-nieuwtjes">
<div class="zijmenu-shouts">
Open de verzoeklijnen
</div>
<a><div class="zijmenu-twitter"></a>
Open de twitter feed
</div>
</div>
</div>
<div id='mainSite'>
<header></header>
<div class="shadow">
<div id='zijmenu-knop'></div>
</div>
The #zijmenu-knop already has a margin-right property.
When opening the menu, #zijmenu-knop has right value of 300px along with the margin-right of 3%.
So, the total distance from right increases making it move to the left a little more. All you have to do is replace the margin-right property of #zijmenu-knop to right and it becomes :
#zijmenu-knop{
right: 3%;
}
By doing this, when the menu opens, the above rule of right is replaced by 300px which makes the distance from right side correct.
To make the position from right better, I would suggest to increase the right value from 300px to 315px, because the width of #zijmenu is 305px.

Change a header's position dynamically when activating drop down menu

I have a drop down menu that sits inside a header that is set to position: fixed. When viewed on a mobile device, I want the header to remain fixed, but when the menu is activated, jQuery dynamically changes the header's position to relative. That works fine (see code below), but there are a few problems that I need to fix. If the menu-toggle link is clicked again (closing the menu), the header does not return to its previous state "relative". Is there a way to do this? I also notice a flicker, so let's say you scroll half way down the page, then click on the menu to open it, the page sort of jumps and does not scroll back to the top where the menu is located inside the header as it should. I would prefer a pure CSS solution, but that seems impossible. I COULD set the rules so that if it's less than 499 pixels wide, the header gets positions "relative", but then usability fails, as a user will have to scroll up to the top of the page to access the drop down menu.
Any help would be greatly appreciated.
Here is my code:
HTML
<header role="banner" class="secondary">
<em>Menu</em> <span aria-hidden="true"></span>
<nav id="nav" role="navigation">
<ul class="menu set">
<li class="subnav">
Link
<ul class="sub-menu">
<li>Link</li>
<li>Link</li>
<li>Link</li>
</ul>
</li>
</ul>
</nav>
</header>
CSS
header[role="banner"] {
width: 100%;
background: #fff;
display: block;
margin: 0 auto;
padding: 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.25);
z-index: 10000;
}
#media all and (min-width: 500px) {
header[role="banner"] {
position: fixed;
top: 0;
left: 0;
clear: both;
height: auto;
display: block;
}
}
#media all and (max-width: 499px) {
header[role="banner"] {
position: fixed;
}
}
JAVASCRIPT
$(document).ready(function() {
$('body').addClass('js');
var $menu = $('#nav'),
$menulink = $('.menu-toggle'),
$menuTrigger = $('.subnav > a');
$menulink.click(function(e) {
e.preventDefault();
$menulink.toggleClass('active');
$menu.toggleClass('active');
});
var add_toggle_links = function() {
if ($('.menu-toggle').is(":visible")){
if ($(".toggle-link").length > 0){
}
else{
$('.subnav > a').before('<span class="toggle-link">Open</span>');
$('.toggle-link').click(function(e) {
var $this = $(this);
$this.toggleClass('active').siblings('ul').toggleClass('active');
});
}
}
else{
$('.toggle-link').empty();
}
}
add_toggle_links();
$(window).bind("resize", add_toggle_links);
});
$(document).ready(function() {
$('.menu-toggle').click(function() {
if ($( document ).width() < 499)
$('header[role="banner"]').css('position', 'relative');
});
});
So you don't actually have any js code in there that will switch the position of your header between fixed and relative.
What I would do is maybe toggleClass on your header.
$(document).ready(function() {
$('.menu-toggle').click(function() {
if ($( document ).width() < 499){
$('header[role="banner"]').toggleClass('active');
}
});
});
Then in your css
header[role="banner"] {
position: fixed;
}
header[role="banner"].active {
position: relative;
}
The screen jump you're getting is probably from changing the position from fixed to relative, because relative will add the header back to the normal page flow. So to fix this, you could also toggle the class of whatever is below your header, so when active, it has a margin-top of 0, and when inactive, it has a margin-top equal to the height of the header.

Circular rotating/magnifying menu with jquery

I'm trying to make a menu that contains 5 items/icons with the selected one being in the center. Clicking to the left or right of this centered icon, rotates the menu left or right, wrapping round the edges and moving whichever item was closest to the edge back in through the opposite one. Clicking on the centered item takes you to its linked URL.
The menu should also magnify in a way similar to the OS X dock except the magnification levels are set based on position not mouseover.
I've made a diagram which is easier to understand than my ramblings.
(source: yfrog.com)
I've managed to cobble together a simple jQuery version, where the items swap positions as needed, but can't figure out how to animate this movement, especially the wrap around the edges part, and change size based on position.
I'm guessing my code is probably not the best either :)
The HTML is as follows:
<div id="nav">
<div id="leftnav"></div>
<div id="rightnav"></div>
<div id="navblock1" class="navblock">
one
</div>
<div id="navblock2" class="navblock">
two
</div>
<div id="navblock3" class="navblock">
three
</div>
<div id="navblock4" class="navblock">
four
</div>
<div id="navblock5" class="navblock">
five
</div>
And the JS:
function rotateNav(direction) {
var change = (direction=='left')?(-1):(+1);
$('div.navblock').each(function() {
oldPos = parseInt($(this).attr('id').substr(9));
newPos = oldPos+change;
if (newPos == 0)
newPos = 5;
else if (newPos == 6)
newPos = 1;
$(this).attr('id','navblock'+newPos);
});
}
$(document).ready(function(){
$("#leftnav").click(function() {
rotateNav('right');
});
$("#rightnav").click(function() {
rotateNav('left');
});
});
All the .navblock elements are absolutely positionned. The #leftnav and #rightnav elements also and they have a higher z-index so float above the items/icons.
I've looked at various jQuery plugins but none seem close to what I need.
Instead of changing id attributes (which you really shouldn't do in the first place) you can change CSS classes and use jQuery UI's switchClass() method to animate the rotation.
You would also have to do a bit of clone()ing to make it look like the edge navblocks have rotated around to the other side of the widget and some queue()/dequeue()ing to handle multiple clicks.
Working Demo:
http://jsbin.com/ovemu (editable via http://jsbin.com/ovemu/edit)
Full Source:
JavaScript
function rotateNav(direction) {
if (direction === 'left') {
var change = 1;
$('.navblock5').clone()
.removeClass('navblock5')
.addClass('navblock0')
.appendTo('#nav');
}
else {
var change = -1;
$('.navblock1').clone()
.removeClass('navblock1')
.addClass('navblock6')
.appendTo('#nav');
}
$('div.navblock').each(function() {
var oldClassName = this.className.split(' ')[1],
oldPos = parseInt(oldClassName.substr(8)),
newPos = oldPos + change;
$(this).switchClass(
oldClassName,
'navblock'+newPos,
'fast',
function () {
var animated = $('.navblock:animated').length;
if (newPos === 6 || newPos === 0) {
$(this).remove();
}
if (animated === 1) {
$('#nav').dequeue();
}
}
);
});
}
$(document).ready(function(){
$("#leftnav").click(function() {
$('#nav').queue(function(){rotateNav('right');});
});
$("#rightnav").click(function() {
$('#nav').queue(function(){rotateNav('left');});
});
});
CSS
#nav {
width: 580px; height: 120px;
position: relative; left: 150px;
overflow: hidden;
}
.navblock {
height: 100px; width: 100px;
position: absolute; top: 10px; z-index: 50;
background-color: grey;
}
.navblock0 { left: -110px; }
.navblock1 { left: 10px; }
.navblock2 { left: 120px; }
.navblock3 { left: 230px; width: 120px; height: 120px; top: 0;}
.navblock4 { left: 360px; }
.navblock5 { left: 470px; }
.navblock6 { left: 590px; }
#leftnav, #rightnav {
position: absolute; z-index: 100; height: 120px; width: 228px;
}
#leftnav { left: 0; }
#rightnav { right: 0; }
/*Uncomment the following to help debug or see the inner workings */
/*
#nav { border: 1px solid green; overflow: visible; }
#leftnav, #rightnav { border: 1px solid blue; }
*/
HTML
<div id="nav">
<div id="leftnav"></div>
<div id="rightnav"></div>
<div class="navblock navblock1">one</div>
<div class="navblock navblock2">two</div>
<div class="navblock navblock3">three</div>
<div class="navblock navblock4">four</div>
<div class="navblock navblock5">five</div>
Instead of doing this yourself and wasting time on getting this to work properly I suggest you use existing solutions ones. Here a few pointers (I guess many more can be found by using google
jQuery: Mac-like Dock
Mac-like icon dock (v2)
MAC CSS Dock Menu
jQuery mimicking the OS X dock
Simple OSX-like dock with jQuery
iconDock jQuery Plugin
You seem to be on the right track. One issue is that this line
oldPos = parseInt($(this).attr('id').substr(9));
Should use 8 in the substr:
oldPos = parseInt($(this).attr('id').substr(8));

Categories

Resources