Making JavaScript menu close when clicking outside - javascript

I'm basically trying to make open menu close when user click anywhere. im new and i dont know what is problem. so far i am using this code, here is my html, css and javaScript. i think problem is in my JavaScript.
thanks for help.
HTML
<div class="menu-button" style="width:23px; cursor: pointer;" onClick="show_menu()"><span style="color:#b0acac;">▼</span></div>
<div id="dropdown_menu" class="hidden_menu">
<ul id="container">
<li>Settings<br></li>
<li>Log Out</li>
</ul>
</div>
CSS
.menu-button{
position: relative;
left:1556px;
top:-43px;
}
.hidden_menu{
display:none
}
#dropdown_menu ul li {
text-decoration:none;
display: inline;
cursor: pointer;
position: relative;
left:-20px;
top:2px;
}
#dropdown_menu ul{
width:80px;
height:90px;
background-color:#efefef;
position:relative;
top:-64px;
left:1460px;
border-color:#ff0000;
border-width:2px;
}
JavaScript
<script>
function show_menu(){
var menu = document.getElementById('dropdown_menu');
if(menu.style.display == 'block'){
menu.style.display = 'none';
}else {
menu.style.display = 'block';
}
}
function hide_menu(){
var menu = document.getElementById('dropdown_menu');
if(menu.style.display == 'none'){
menu.style.display = 'block';
}
}
var cl = document.getElementById("body");
cl.addEventListener("click", hide_menu);
</script>

This can help you.
HTML Code
<div class="menu-button" style="width:23px; cursor: pointer;" ><span id="button" style="color:#b0acac;">Show Menu</span></div>
<div id="dropdown_menu" class="hidden_menu">
<ul id="container">
<li>Settings<br></li>
<li>Log Out</li>
</ul>
</div>
Css
.hidden_menu { display:none;}
JavaScript Code
var dropMenu = document.getElementById('dropdown_menu'),
menuButton = document.getElementById('button'),
dropUL = document.getElementById('container').childNodes;
function hide_menu(evt){
evt = evt || window.event; // get window.event if evt is falsy (IE)
var targetElement = evt.target || evt.srcElement; // get srcElement if target is falsy (IE)
if(targetElement === menuButton || targetElement.nodeName.toLowerCase() === 'li' ){
dropMenu.style.display = 'block'
} else {
dropMenu.style.display = 'none'
}
}
// For legacy broser(IE8 and IE7) support
function addEvent(el, type, fn){
if(typeof addEventListener !== 'undefined'){
el.addEventListener(type, fn, false)
} else {
el.attachEvent('on'+type, fn);
}
}
addEvent(document, 'click', hide_menu);
Demo

If you want plain js:
document.addEventListener('click', function(e){
console.log(e.target.id)
if(e.target.id!=="dropdown_menu")
console.log("document Clicked");
});
It is same as above function but written in javascript

Try
function hide_menu(e){
var menu = document.getElementById('dropdown_menu');
if(e.target != menu) {
menu.style.display = 'none';
}
}
document.body.addEventListener("click", hide_menu);

$('body').click(function(){
if($(this).attr('id')!='dropdown_menu' && !$(this).hasClass('menu-button'))
// code to close the menu
});
Making sure that the click is not on the div for menu

Related

Show and Hide Javascript HTML5

So, I'm doing my designer-portfolio in html and I wanted to have a menu that only shows when this character is pressed...
But I'm new on programming and my codes are very simple, so I'm using this:
function toggle_visibility(id) {
var e = document.getElementById(id);
if(e.style.visibility == 'hidden')
e.style.visibility = 'visible';
else
e.style.visibility = 'hidden';
}
function untoggle_visibility(id) {
var e = document.getElementById(id);
if(e.style.visibility == 'visible')
e.style.visibility = 'hidden';
else
e.style.visibility = 'visible';
}
<div id="openmenu" style="visibility: visible;" onclick="toggle_visibility('menu'); onclick=toggle_visibility('closemenu');">openmenu</div>
<div id="closemenu" style="visibility: hidden;" onclick="untoggle_visibility('menu'); onclick=untoggle_visibility('closemenu');">closemenu</div>
<div id="menu" style="visibility: hidden;">...</div>
The problem is it only works once...
When I click on #openmenu it shows the #menu and the #closemenu, and when I click on #closemenu it hiddes the #menu and the #closemenu.
BUT it only works once, so if I press #openmenu after #closemenu, it won't work...
Your code is wrong.
onclick="toggle_visibility('menu'); onclick=toggle_visibility('closemenu');"
So what happens with the above code is it runs once. And when it runs it reassigns onclick because you have onclick=functionCall
So after it runs you basically have <div onclick=undefined> because the function did not run.
function toggle_visibility(id) {
var e = document.getElementById(id);
if (e.style.visibility == 'hidden')
e.style.visibility = 'visible';
else
e.style.visibility = 'hidden';
}
function untoggle_visibility(id) {
var e = document.getElementById(id);
if (e.style.visibility == 'visible')
e.style.visibility = 'hidden';
else
e.style.visibility = 'visible';
}
<div id="openmenu" style="visibility: visible;" onclick="toggle_visibility('menu');toggle_visibility('closemenu');">openmenu</div>
<div id="closemenu" style="visibility: hidden;" onclick="untoggle_visibility('menu');untoggle_visibility('closemenu');">closemenu</div>
<div id="menu" style="visibility: hidden;">...</div>
How would most people code it? By toggling a class.
function toggle_visibility(ids) {
ids.forEach( function (id) {
var elem = document.getElementById(id);
elem.classList.toggle('visibilityHidden')
})
}
.visibilityHidden {
visibility: hidden;
}
/* use hidden if you do not want it to take up space */
.hidden {
display: none;
}
<div id="openmenu" onclick="toggle_visibility(['menu','openmenu','closemenu']);">openmenu</div>
<div id="closemenu" class="visibilityHidden" onclick="toggle_visibility(['menu','openmenu','closemenu']);">closemenu</div>
<div id="menu" class="visibilityHidden">...</div>
Most developers would not use inline event handlers either, but that is a different question.

jquery focus to sibling without focusing out from parent

I am try to iterate through all li elements in ul on keydown event by firing focus() event for next sibling li. In this process, I dont want to focus out from parent ul.
But its not happening. Even changing focus on siblings is causing focusout event on parent. I want that only when someone clicks somewhere else on the screen should focus out of parent be fired.
var KEY_DOWN=40;
$(document).on('keydown', 'li', function(e){
let keyCode = e.keyCode || e.which;
if(keyCode == KEY_DOWN)
{
if($(this).next().length != 0)
{
$(this).next().focus();
}
else
{
$(this).parent().children().first().focus();
}
return false;
}
});
$(document).on('focusout','ul', function(e)
{
console.log('focused')
});
li
{
border: 1px solid black;
}
li:focus
{
background: #999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul tabindex="-1">
<li tabindex="-1">First</li>
<li tabindex="-1">Second</li>
<li tabindex="-1">Third</li>
</ul>
In the snippet, focused in getting printed on every down key press. How to solve this situation.
Due to event bubbling, the focusout event is logging the message for you when you are focusing out of li too. You can use the event data to check from where you have focused out. (Read more here: jQuery figuring out if parent has lost 'focus')
But I would like to mention how I do it. I would rather like to detect click outside my ul.
var KEY_DOWN=40;
$(document).on('keydown', 'li', function(e){
let keyCode = e.keyCode || e.which;
if(keyCode == KEY_DOWN)
{
if($(this).next().length != 0)
{
$(this).next().focus();
}
else
{
$(this).parent().children().first().focus();
}
return false;
}
});
$(document).on('focusout','ul', function(e)
{
console.log('focused out of li');
});
$(document).click(function() {
console.log('focused out of ul');
});
$('ul').click(function(e) {
e.stopPropagation();
});
li
{
border: 1px solid black;
}
li:focus
{
background: #999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul tabindex="-1">
<li tabindex="-1">First</li>
<li tabindex="-1">Second</li>
<li tabindex="-1">Third</li>
</ul>
Only way I found was to disable focusout event on parent ul when I am trying to focus any li
var KEY_DOWN=40;
$(document).on('keydown', 'li', function(e){
let keyCode = e.keyCode || e.which;
if(keyCode == KEY_DOWN)
{
$(document).off('blur','ul', doWork);
if($(this).next().length != 0)
{
$(this).next().focus();
}
else
{
$(this).parent().children().first().focus();
}
$(document).on('blur','ul', doWork);
return false;
}
});
doWork = function(e)
{
console.log('focused')
};
$(document).on('blur','ul', doWork);
li
{
border: 1px solid black;
}
li:focus
{
background: #999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul tabindex="-1">
<li tabindex="-1">First</li>
<li tabindex="-1">Second</li>
<li tabindex="-1">Third</li>
</ul>

How to open a box on screen by clicking a link and hide it when clicked outside in JS

My goal is to have #box2 appear when I click on #box1 but when you click on something other than #box2, it will display none and only #box1 will show.
Here are my 2 boxes, they are just 2 styled divs:
var condition;
$(document).click(function() {
if (condition === 'block') {
$(":not(#box2)").click(function() {
$("#box2").hide();
});
}
})
$('#box1').click(function(e) {
$('#box2').css('display', 'block');
condition = 'block';
});
$('#box2').click(function(e) {
$('#box2').css('display', 'none');
condition = 'none';
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box1" style="width: 300px; height: 300px; background-color: red; margin-left: 100px; margin-bottom: 50px; position: absolute;">
</div>
<div id="box2" style="width: 300px; height: 300px; background-color: blue; margin-left: 150px; display: none; position: absolute;">
</div>
This current code works correctly the first time but after that, it wont run again. I am just wondering if there is a reset function or where I am going wrong?
Really what I want to do is make this work on an ipad so when the user clicks/taps away from the box, it will close. If there are better ways to do this on the Ipad tablet, please let me know!!
Any ideas?
Don't overcomplicate things. This is all the javascript you need, get rid of everything else:
$(document).click(function () {
$('#box2').hide();
});
$('#box1').click(function (e) {
e.stopPropagation();
$('#box2').show();
});
You could just filter event target at document level:
$(document).on('click', function(e) {
$('#box2').toggle(!!$(e.target).closest('#box1').length);
});
-jsFiddle-
You can listen to all click events of the document and then use the event.target to detect which element is being clicked. if the clicked element is box1 and box2 is not being shown then display it to the user. in any other condition we can hide the box2 if it's not the element being clicked. here is the vanilla JavaScript code to achieve this:
<html>
<body>
<div id='box1'>BOX ONE</div>
<div id='box2' style="display: none;">BOX TWO</div>
<script>
document.addEventListener('click', function(event) {
var secondBox = document.getElementById('box2')
if(event.target.id === 'box1' && secondBox.style.display === 'none'){
secondBox.style.display = 'block'
} else if (event.target.id !== 'box2') {
secondBox.style.display = 'none'
}
})
</script>
</body>
</html>
And if you are into DRY (Do not repeat yourself), you can define a function for this task. Take look at this modified version of the script:
function addOpenHandler(handler, target){
document.addEventListener('click', function(event) {
if(event.target === handler && target.style.display === 'none'){
target.style.display = 'block'
} else if (event.target !== target) {
target.style.display = 'none'
}
})
}
addOpenHandler( document.getElementById('box1'), document.getElementById('box2') )
$(document).click(function () {
if (condition === 'block')
{
$(":not(#box2)").click(function () {
$("#box2").hide();
});
}
})
The line $("#box2").hide(); is firing after every click

Clear all the open div's

I have a script that open's div's by doing an onclick="toogle_visibility(id)
event but how do i do when i want to close the div that is open and open
the new div ?
Javascript/jQuery:
function toggle_visibility(id) {
var e = document.getElementById(id);
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
HTML:
<div class="navBar">
Social
Följer
Bokmärken
</div>
<div id="Social">
#Liam_Rab3 - TWITTER<br>
#Liam_Rab3 - INSTAGRAM<br>
#LiamRab3- FACEBOOK<br>
#Liam_Rab3 - YOUTUBE<br>
#Liam_Rab3 - FLICKR<br>
#Liam_Rab3 - TUMBLR<br>
</div>
<div id="Foljer">
Sebbe Stakset (Kartellen)
</div>
CSS:
a:link {
color:white;
text-decoration:none;
-o-transition:.5s;
-ms-transition:.5s;
-moz-transition:.5s;
-webkit-transition:.5s;
transition:.5s;
}
a:hover {
color:white;
text-decoration:none;
font-size:100%;
}
a:visited {
text-shadow:0px 0px 0px #0066BB;
color:white;
}
#social {
display:none;
}
#Foljer {
display:none;
}
DISCLAIMER!
These links in the #social and #bokmarken links is'nt for commercial purpose.
You can use JQuery Toggle
<div id="clickme">
Click here !!!
</div>
<a href="#social" >Social</a>
$( "#clickme" ).click(function() {
$( "#social" ).toggle(); //With no parameters, the .toggle() method simply toggles the visibility of elements:
});
First choose the control you are willing to hide/show, then use that control's id as follows:
$('#<id-of-that-control>').toggle();
Now you can call that in the onclick event handler of a button or div as you wish.
How it might appear for you is:
JS
function toggle_visibility(id) {
$('#' + id).toggle();
}
HTML
<div class="navBar">
Social
Följer
Bokmärken
</div>
Update:
As pointed out by Brodie, seemingly you might always look into the solution provided by Niet the Dark Absol. As he provides you a pure JS implementation. My solution will give you insight of using a library like JQuery and it's API of toggle. Jquery provides a wide range of built-in functionality that helps you to do things quickly. What my piece of code provides you is usage of an api i.e. toggle, which when used will be same as the hide and show behavior.
Basically, you need to close all DIVs, and toggle the current one.
Try this:
var ids = ['Social','Foljer','Bokmarken'];
function toggle_visibility(id) {
var l = ids.length, i, e;
for( i=0; i<l; i++) {
e = document.getElementById(ids[i]);
if( id != ids[i])
e.style.display = 'none';
else if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
}

when double-clicking one element, another gets selected

I've written an image scroller in html/css/js, a very simple one: right button is clicked, I go through all images inside "holder"-div and change the class of the image after the one with classname="current".
But that's not where the problem lies, I think. Whenever I successively click on the left or the right button, the image in the div gets selected (blue selection box). If I successively click the left button, even the text above it gets selected.
<div class="grid_4 omega image_box">
<div id="txt_choose" class="image_txt">
this is helpful text
</div>
<div id="alt_spacer"></div>
<div id="image_content" class="image_content" onclick="chooseImageType(this)">
<div id="current" class="current"><img src="images/default1.png" /></div>
<div id="current" class="hidden"><img src="images/default2.png" /></div>
</div>
<!--- left button --->
<div class="image_btn_left" onclick="showPrev()"></div>
<!--- right button --->
<div class="image_btn_right" onclick="showNext()"></div>
</div>
and this is the css:
.image_btn_right
{
width : 20px;
height : 20px;
position : relative;
float : left;
margin-top : -170px;
margin-left : 260px;
z-index : 4;
cursor : pointer;
background-image: url('../images/right.png');
}
.image_btn_left
{
width : 20px;
height : 20px;
position : relative;
float : left;
margin-top : -170px;
margin-left : 20px;
z-index : 4;
cursor : pointer;
background-image: url('../images/left.png');
}
.image_content
{
height : 280px;
background-color: white;
margin : 10px;
}
on request, my javascript:
function showNext()
{
//vars
var shown = false;
var current;
$('#image_content > div').each(function()
{
if($(this).attr('class') == "current")
{
current = $(this);
shown = true;
}
else if($(this).attr('class') == "hidden" && shown == true)
{
current.hide();
current.attr('class', 'prev');
current.attr('id', '');
$(this).show();
$(this).attr('class', 'current');
$(this).attr('id', 'current');
shown = false;
}
});
}
Is there anyway to stop the image and the text above to be selected like that (without actually making them not selectable)?
Could it be because of the relative position of the buttons and their z-index..?
This works in your JS fiddle.
function showNext()
{
//vars
var shown = false;
var current;
window.getSelection().removeAllRanges();
$('#image_content > div').each(function()
{
if($(this).attr('class') == "current")
{
current = $(this);
shown = true;
}
else if($(this).attr('class') == "hidden" && shown == true)
{
current.hide();
current.attr('class', 'prev');
current.attr('id', '');
$(this).show();
$(this).attr('class', 'current');
$(this).attr('id', 'current');
shown = false;
}
});
}
function showPrev()
{
window.getSelection().removeAllRanges();
//vars
var prev_present = false;
var prev;
$('#image_content > div').each(function()
{
if($(this).attr('class') == "prev")
{
prev = $(this);
prev_present = true;
}
else if($(this).attr('class') == "current" && prev_present == true)
{
$(this).hide();
$(this).attr('class', 'hidden');
$(this).attr('id', '');
prev.show();
prev.attr('class', 'current');
prev.attr('id', 'current');
prev_present = false;
}
});
}
best regards
Jonas
I found the answer and it was painfully easy.. >_>
I just needed to wrap the buttons in another div, so they became more eperated from the rest of the html.
Like so:
<div>
<!--- left button --->
<div class="image_btn_left" onclick="showPrev()"></div>
<!--- right button --->
<div class="image_btn_right" onclick="showNext()"></div>
</div>

Categories

Resources