Closing a menu on an outside click pure JavaScript - javascript

I'm adding a basic functionality to a menu. Whenever the button is clicked the menu toggles from showing to hiding thanks to a css class through Javascript.
However, when ever I try to use this functionality in conjunction with the window.addEventListener, to close the menu on an outside click, it doesn't function.
What is the reasoning behind it?
Here is the code.
<div class="c-wrapper">
<button type="button" class="c-btn"> Click Me</button>
<ul class="c-navigation">
<li>Hi there</li>
<li>Hello</li>
<li>Hola</li>
<li>Konichiwa</li>
</ul>
</div>
I would appriciate some help, thanks.
.c-wrapper{
position:relative;
}
.c-btn{
background-color:royalblue;
border:none;
color:white;
padding:0.5rem 2rem;
cursor:pointer;
outline:none;
}
.c-navigation{
list-style:none;
background-color:#ccc;
position:absolute;
margin:0;
padding:0;
display:none;
li{
margin-top:0.5rem;
}
a{
text-decoration:none;
color:black;
padding:1.4rem;
}
}
.is-active{
display:block;
}
Here is the Javascript I am mentioning.
var button = document.querySelector('.c-btn');
button.addEventListener('click', function(){
document.querySelector('.c-navigation').classList.toggle('is-active');
});
window.addEventListener('mouseup', function(event){
var menu = document.querySelector('.c-navigation');
if(event.target != menu && event.target.parentNode != menu){
menu.style.display='none';
}
});

Try this.
// Get the menu
var menu = document.getElementById('menu');
// When the user clicks anywhere outside of the modal, close it
window.addEventListener('click', function(event) {
if (event.target === menu) {
menu.style.display = "none";
}
})
Better avoid to manipulate styles via JS. Better add a class to menu.
menu.classList.add('hidden');
And then add a .hidden class style to CSS.
.hidden {
display: none;
}

Related

Is there a property or workaround for padding-radius?

I am using a circular button,
border-radius:50%;
And I have an element inside of my element, in order to make the entire button clickable, and not just the content inside of my element.
When I add padding to the element, it makes it so that the entire button is clickable, but due to the fact that the border-radius is 50%, the corners of the button that shouldn't be clickable, are clickable.
I hope this outlines my problem enough, I'll include a jsfiddle if possible.
https://jsfiddle.net/nmcloota/7c95q1ov/5/
add overflow: hidden; to your parent button, so child's content will be hidden
button {
height:200px;
width:200px;
background-color:gold;
border-radius: 50%;
overflow: hidden;
}
https://jsfiddle.net/nd5po7rg/1/ I updated your fiddle
EDIT:
I applied some more styles to make text more centered
take a look: https://jsfiddle.net/1fd5rksg/19/
Hi If I understand correctly, what you're looking for is something like that:
// Show an element
var show = function (elem) {
elem.classList.add('is-visible');
};
// Hide an element
var hide = function (elem) {
elem.classList.remove('is-visible');
};
// Toggle element visibility
var toggle = function (elem) {
elem.classList.toggle('is-visible');
};
// Listen for click events
document.addEventListener('click', function (event) {
// Make sure clicked element is our toggle
if (!event.target.classList.contains('toggle')) return;
// Prevent default link behavior
event.preventDefault();
// Get the content
var content = document.querySelector(event.target.hash);
if (!content) return;
// Toggle the content
toggle(content);
}, false);
.toggle-content {
display: none;
}
.toggle-content.is-visible {
display: block;
}
button {
height:200px;
width:200px;
background-color:gold;
border-radius: 50%;
cursor: pointer;
}
.with-padding {
padding:50px;
}
<button>
<a class="toggle with-padding" href="#example">
Click me to make my friend appear/disappear
</a>
</button>
<button class="toggle-content" id="example">
I am friend</button>
I hope this will help you.

Why is my JavaScript code ruining my styling?

I am making a login modal and want the content to be centered horizontally and vertically. My CSS has it centered how I want it, but when I added the JavaScript, it is only centered horizontally. What's wrong with my code? thanks!
I tried flexbox and every other centering method I know. It just doesnt make sense because if I comment out the JavaScript, the modal content is where I want it to be!
// Get the modal
var modal = document.getElementById('login-modal');
// Get the button that opens the modal
var btn = document.getElementById("login");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks on the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";}
}
#login-modal{
width:100%;
height:100%;
background-color:rgba(0, 0, 0, 0.5);
position:absolute;
top:0;
left:0;
display:flex;
justify-content: center;
align-items: center;
text-align:center;
}
.login-content{
border: 10 px solid black;
height:12%;
width:20%;
background-color:white;
display:block;
text-align:center;
}
input[type=text], input[type=password]{
display:block;
margin: 0 auto;
}
When you want to initially hide something without regard to its display type in CSS, you can create the element with an inline display attribute of style="display: none;" in its HTML tag or, if creating the element in JavaScript, with element.style.display="none".
After that, you can display an element by deleting its element.style.display property. The element reverts to whatever display type was given to it in CSS.
To hide it, add back element.style.display="none";
Using this approach, the modal should always appear as styled in CSS. However, don't try to change its display type to anything except none anywhere else in JavaSript!
To specifically answer the question, inline style attribute values have absolute priority over rules provided in CSS.

Drop down menu effects

I have this drop down menu that appears when a button is clicked and disappears when clicked again. I'm wondering how to make the menu disappear from the bottom up, instead of just instantly disappear. I'm not asking for the exact code, just need pointed in the right direction. Thank you.
let nav = document.querySelector("nav");
let icon = document.querySelector(".mobile-icon");
console.log(nav);
icon.addEventListener("click", showMenu);
function showMenu() {
if (nav.style.display == "none"){
nav.style.display = "block";
} else {
nav.style.display = "none";
}
}
My solution would be to create a class that sets the hight of the menu to 0px and then toggle this on and off using JavaScript.
I have created a small mockup in JSFiddle with some comments on the important parts.
Link to JSFiddle is - https://jsfiddle.net/gmuz2m98/
Here is the code though:
HTML -
<button> Hide/Show </button>
<ul>
<li> Link 1 </li>
<li> Link 2 </li>
<li> Link 3 </li>
<li> Link 4 </li>
</ul>
CSS -
ul {
/* Give the ul a transition to run smoothly */
transition: all .5s;
list-style:none;
padding:0;
margin:20px 0px;
background-color:#D6D6D6;
/* Make sure overflow is hidden so when the hight is droped to 0px the li elements stay hidden */
overflow:hidden;
/* Give the ul a default hight to revert to, without this the transiton won't work */
height:160px;
}
li {
padding: 10px 20px;
}
/* This is the class that will be added with JavaScript */
.hide {
height:0px;
}
JS -
// Assign the ul and the button to a variable
var ul = document.getElementsByTagName('ul')[0],
btn = document.getElementsByTagName('button')[0];
// Create a function that lets the class 'hide' be toggled on and off the ul
function dropDown(){
ul.classList.toggle('hide');
}
// Assign the function to the button with an EventListener
btn.addEventListener('click',dropDown,false);
Here is my solution, you cannot use transition for height property hence we use max-height. The problem is we need to set height in px for this solution to work, hence please use this workaround and test!
let nav = document.querySelector("nav");
let icon = document.querySelector(".mobile-icon");
icon.addEventListener("click", showMenu);
nav.querySelector("ul").style.margin = "16px 0px";
nav.style.maxHeight = nav.querySelector("ul").clientHeight + 32 + "px";
function showMenu() {
nav.classList.toggle("hideThis");
}
nav{
transition: max-height 0.5s ease-out;
height:auto;
overflow:hidden;
}
nav.hideThis{
max-height:0px !important;
}
<button class="mobile-icon">toggle</button>
<nav>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</nav>

Slide modal from top on JS command

Starting point for my question, this Codepen
I have been looking for a way to get a slide on page that would be triggered by a JS call. Looking around, the pen above seems to be what I am looking for, but instead of a JS function, the animation is triggered by a checkbox.
One of my options would be to make the button invisible and trigger the checking using jQuery like this
$("#toggle")[0].checked = !($("#toggle")[0].checked)
While this line works, I am trying to find here a more JS/jQuery animation solution, if that makes sense.
The option of hide check and trigger the checkbox will work ... other thing you can do is add -- remove a classname but you need to change the CSS.
If you want just simple Jquery you can use slideUp / Down ...
$('.container').click(function(){
$('.message').slideToggle(500)
})
* {
margin:0;
padding:0;
}
.container {
padding:50px;
}
h1 {
font-size:40px;
font-weight:bold;
color:#191919;
}
h2 {
font-weight:normal;
font-size:20px;
color:#888;
padding:5px 0;
}
.message {
background:#181818;
color:#FFF;
height: 150px;
padding: 20px;
display:none;
}
.message h1 {
color:#FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="message">
<h1> hello, I'm a hidden message. You found it.</h1>
</div>
<div class="container">
<h1>Jquery Slide Down Toggle Demo</h1>
<h2> Click here to Toggle the hidden mesage.</h2>
</div>

jquery fadeIn acting funny?

this is what I'm working on right now
http://www.dsi-usa.com/yazaki_port/hair-by-steph/
as you can see when you click the tabs the fade in and fade outs look extremely funny. I'm wondering if anyone can take a look at the code and tell me what I'm doing wrong. I'm extremely new to Jquery and Javascript (like yesterday new) so I apologize if the code is messy. I'm wondering if 1. there was an easier way to write this and 2. if there's a way to just have the sections fade into each other/any other cool ideas anyone has.
the html structure (pulled out all of the content for space purposes)
<div id="main">
<div id="display_canvas">
</div>
<div id="nav">
<ul>
<li><a class="btn" title="contact">CONTACT</a></li>
<li><a class="btn" title="resume">RESUME</a></li>
<li><a class="btn" title="portfolio">PORTFOLIO</a></li>
<div class="clear"></div>
</ul>
<div class="clear"></div>
</div>
<div id="resume">
//contents here
</div>
<div id="contact">
//contents here
</div>
</div>
the css
*
{
margin:0;
padding:0;
font-family:verdana, helvetica, sans-serif;
}
#main
{
width:1200px;
margin:0 auto;
}
#display_canvas
{
height:700px;
background-color:#fefea8;
box-shadow:5px 5px 5px #888888;
-moz-box-shadow:5px 5px 5px #888888;
-webkit-box-shadow:5px 5px 5px #888888;
display:none;
}
.clear
{
clear:both;
}
#resume
{
clear:both;
float:right;
width:100%;
background-color:#000000;
background-image:url("../imgs/resume_back.png");
background-position:300px 0px;
background-repeat:no-repeat;
height:200px;
text-align:left;
display:none;
}
#contact
{
clear:both;
float:right;
width:100%;
background-color:#000000;
background-image:url("../imgs/contact_back.png");
background-position:left;
background-repeat:no-repeat;
height:200px;
text-align:left;
display:none;
}
#nav
{
margin:1em 0 0 0;
text-align:right;
}
#nav ul
{
list-style-type:none;
}
#nav li
{
display:inline;
}
.btn
{
margin-right:20px;
display:block;
text-align:center;
float:right;
color:#000000;
font-size:15px;
font-weight:bold;
line-height:30px;
text-decoration:none;
cursor:pointer;
width:150px;
height:30px;
}
.over
{
background-color:#888888;
color:#ffffff;
}
.active_contact
{
background-color:#000000;
color:#00a8ff;
}
.active_resume
{
background-color:#000000;
color:#9848c2;
}
.active_portfolio
{
background-color:#000000;
color:#ffffff;
}
and finally a whole mess of javascript
$(document).ready(function(){
//handles general navigation
$(".btn").hover(
function(){
$(this).addClass("over");
},
function(){
$(this).removeClass("over");
}
)
$(".btn").click(function(){
var btn = $(this);
var newClass = "active_" + btn.attr("title"); //set the new class
var section = $("#" + btn.attr("title"));
if ($("#curSection").length)
{
alert('there is a section');
var curClass = "active_" + $("#curSection").attr("title"); //get the current class active_section name
var curSection = "active"
$("#curSection").removeClass(curClass).removeAttr("id"); //remove the current class and current section attributes
btn.addClass(newClass).attr("id", "curSection"); //designate new selection
$(".currentSection").fadeOut("slow", function(){ //fade out old section
$(".currentSection").removeClass("currentSection");
section.fadeIn("slow", function(){ //fade in new section
alert('faded in');
section.addClass("currentSection"); //designate new section
});
});
}
else
{
alert('first time');
btn.addClass(newClass).attr("id", "curSection"); //designate new selection
section.fadeIn("slow", function(){
alert('faded in');
section.addClass("currentSection");
});
}
});
//handles resume navigation
$(".res-btn").hover(
function(){
$(this).addClass("res-over")
},
function(){
$(this).removeClass("res-over")
}
)
$(".res-btn[title=experience]").click(function(){
$("#scroller").stop().animate({top: "0px"}, 1000);
});
$(".res-btn[title=expertise]").click(function(){
$("#scroller").stop().animate({top: "-180px"}, 1000);
});
$(".res-btn[title=affiliates]").click(function(){
$("#scroller").stop().animate({top: "-360px"}, 1000);
});
});
if anyone has any ideas as to why this doesn't work let me know. I thought maybe it was having problems loading the content, but the content should be loaded already as they are on the screen already, just no display. I'm stumped, I saw a few posts similar to mine, so I followed some of their thinking. When I set the fadeIn() to like 5000 instead of "slow" The first 60% or so of the fadeIn is skipped and the section appears at say 60% opacity and then fades in the rest of the way. Not sure what I'm doing so thank you in advance.
Off the top of my head, I think the problem might be that you are initiating an alert dialogue box rather than a jquery Fancybox / Thickbox type of overlay lightbox which accommodates the speed at which the it animates to open or close. And in any case, I am unable to replicate the issue you are facing despite going directly to your link.
So rather than to try and resolve that chunk of codes you have picked out from different sources and since the content that you wish to display is an inline one, you might as well consider using Thickbox or Fancybox instead.
Alternatively, you could also kinda script your own lightbox without using the alert dialogue boxes if you like. It could look something like this:
HTML:
<!--wrapper-->
<div id="wrapper">
Box 1</li>
Box 2</li>
<!--hidden-content-->
<div class="box-1">
This is box 1. close
</div>
<div class="box-2">
This is box 2. close
</div>
</div>
<!--wrapper-->
CSS:
#wrapper{
background:#ffffff;
width:100%;
height:100%;
padding:0;
}
.box-1, .box-2{
display:none;
width:300px;
height:300px;
position:fixed;
z-index:3000;
top:30%;
left:30%;
background:#aaaaaa;
color:#ffffff;
opacity:0;
}
JQUERY:
$(document).ready(function(){
$(".toggle-1").click(function(){
$(".box-1").show(900);
$(".box-1").fadeTo(900,1);
});
$(".close-1").click(function(){
$(".box-1").hide(900);
$(".box-1").fadeTo(900,0);
});
$(".toggle-2").click(function(){
$(".box-2").show(900);
$(".box-2").fadeTo(900,1);
});
$(".close-2").click(function(){
$(".box-2").hide(900);
$(".box-2").fadeTo(900,0);
});
});
Well, of course there's still quite a bit of styling to be done in order for the content to appear nicely in the center of the screen, but I'm gonna be leaving that out as this is more of a question of how to control the speed of which the overlay appears.
In any case, if you wanna change the speed of which it appears or close, simply alter the "900" value to something else - a lower number means a faster animation speed and vice versa. If you have noticed, I'm applying the .hide() and .fadeTo() functions together. This is partly because I will try and enforce for the shown divs to be hidden after the Close button is clicked. This will prevent it from stacking on top of other content and thereby disabling any buttons, links or functions. You can try to play around with their "900" values as well. For e.g. when you press the close button, you can actually make .hide() execute slower in relation to the fadeTo() simply by assigning maybe 3000 to the former and 700 to the latter. This will give the illusion that it is fading only rather than fading and swinging, the latter of which is prominent when you utilize the .hide() or .show() function.
Hope this helps some how. =)

Categories

Resources