I'm creating an off-canvas nav that closes on three conditions:
The user toggles the nav button
the user clicks a link inside the nav
the user clicks anywhere but the nav when the nav is open.
I've got the first two conditions working but not the third. Below is my code. What I'm trying to accomplish is essentially the following:
check for a click on the body and if that click is the (in this case) .pageContainer run a second check to see if the nav has the class "showMenu" and the flag is == true
$(document).ready(function() {
var button = $('.button');
var ocn = $('.ocn');
var test = $('.test');
var flag = false;
//toggle menu using just the button
button.click(function() {
if ( flag == false ) {
ocn.addClass('showMenu');
flag = true;
} else {
ocn.removeClass('showMenu');
flag = false;
}
});
//close the menu clicking on a link
test.click(function() {
ocn.removeClass('showMenu');
flag = false;
});
//close menu when click off canvas
/*
$('body').on('click', '.pageContainer', function(e) {
if( ocn.hasClass('showMenu') && flag == true) {
ocn.removeClass('showMenu');
flag = false;
}
});
*/
});
* {
padding: 0;
margin: 0;
}
.ocn {
position: absolute;
left: -300px;
top: 0;
width: 300px;
height: 100vh;
background-color: #ccc;
transition: left .2s ease;
z-index: 2;
border: 1px solid;
}
.showMenu {
left: 0px;
}
.pageContainer {
height: 500px;
width: 1000px;
border: 1px solid;
display: block;
margin: 0 auto;
}
.button {
height: 40px;
width: 40px;
border: 1px dashed;
display: block;
position: relative;
left: 400px;
cursor: pointer;
}
.test {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ocn">
<p class="test">here is some text for the menu</p>
</div>
<div class="pageContainer">
<div class="button"></div>
</div>
You can use the e.target property to compare what was clicked. Similar to this:
if(e.target == pageContainer[0])
You can now apply the required logic when .pageContainer was clicked.
$(document).ready(function() {
var pageContainer = $('.pageContainer');
var button = $('.button');
var ocn = $('.ocn');
var test = $('.test');
var flag = false;
//toggle menu using just the button
button.click(function() {
if (flag == false) {
ocn.addClass('showMenu');
flag = true;
} else {
ocn.removeClass('showMenu');
flag = false;
}
});
//close the menu clicking on a link
test.click(function() {
ocn.removeClass('showMenu');
flag = false;
});
//close menu when click off canvas
$('body').on('click', '.pageContainer', function(e) {
if (e.target == pageContainer[0]) {
//console.log('pageContainer was clicked')
if (ocn.hasClass('showMenu') && flag == true) {
ocn.removeClass('showMenu');
flag = false;
}
};
});
});
* {
padding: 0;
margin: 0;
}
.ocn {
position: absolute;
left: -300px;
top: 0;
width: 300px;
height: 100vh;
background-color: #ccc;
transition: left .2s ease;
z-index: 2;
border: 1px solid;
}
.showMenu {
left: 0px;
}
.pageContainer {
height: 500px;
width: 1000px;
border: 1px solid;
display: block;
margin: 0 auto;
}
.button {
height: 40px;
width: 40px;
border: 1px dashed;
display: block;
position: relative;
left: 400px;
cursor: pointer;
}
.test {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="ocn">
<p class="test">here is some text for the menu</p>
</div>
<div class="pageContainer">
<div class="button"></div>
</div>
Related
innerDiv = document.getElementById("inner");
innerDiv.onclick = function(e) {
console.log("PURPLE COLOR DIV");
}
outterDiv = document.getElementsByClassName("outter")[0];
outterDiv.onclick = function(e) {
console.log("ORANGE COLOR DIV");
};
containerDiv = document.getElementsByClassName("container")[0];
containerDiv.onclick = function() {
console.log("RED COLOR DIV");
}
setTimeout(() => document.getElementById("inner").dispatchEvent(new Event('click'), {
bubbles: true
}), 2000)
.container {
width: 260px;
height: 170px;
background-color: maroon;
padding-top: 40px;
}
.outter {
width: 200px;
height: 80px;
background: orange;
margin: 0 auto;
padding-top: 35px;
}
#inner {
background: purple;
width: 100px;
height: 50px;
margin: auto;
}
<div class="container">
<div class="outter">
<div id="inner"></div>
</div>
</div>
PROBLEM
After setTimeout causes the dispatchEvent to fire, the Orange and Red color callbacks do not execute. Why is that so if bubbles property is set to true?
In case of clicking on the UI purple div, the bubbling does its job as supposed.
Fiddle example: http://jsfiddle.net/0tko5qwe/
You need to add the options to the Event() constructor itself:
new Event('click', { bubbles: true})
innerDiv = document.getElementById("inner");
innerDiv.onclick = function(e) {
console.log("PURPLE COLOR DIV");
}
outterDiv = document.getElementsByClassName("outter")[0];
outterDiv.onclick = function(e) {
console.log("ORANGE COLOR DIV");
};
containerDiv = document.getElementsByClassName("container")[0];
containerDiv.onclick = function() {
console.log("RED COLOR DIV");
}
setTimeout(() => document.getElementById("inner").dispatchEvent(new Event('click', {
bubbles: true
})), 500)
.container {
width: 260px;
height: 170px;
background-color: maroon;
padding-top: 40px;
}
.outter {
width: 200px;
height: 80px;
background: orange;
margin: 0 auto;
padding-top: 35px;
}
#inner {
background: purple;
width: 100px;
height: 50px;
margin: auto;
}
<div class="container">
<div class="outter">
<div id="inner"></div>
</div>
</div>
On my website I have a button which will create a box when clicked. If that box is visible and the user clicks outside of it, it should be hidden. The problem I have is that the box is hidden right after it is created.
This is the piece of code I use to remove the box if the user clicks outside of it. I struggle understanding why it is triggered when I create the box, because it is not really visible yet.
function createBox(){
var output = "";
output += '<div class="single-box">';
output += '</div>';
$("#list-box").html(output);
document.getElementById('list-box').style.display = 'block';
}
$(document).click(function(event) {
if(!$(event.target).closest('.single-box').length) {
if($('.single-box').is(":visible")) {
var output = "";
$("#list-box").html(output);
document.getElementById('list-box').style.display = 'none';
}
}
});
#list-box{
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: 500;
position: fixed;
display: none;
}
.single-box{
z-index: 1000;
top: 100px;
position: fixed;
background-color: white;
overflow-y: auto;
overflow-x: hidden;
width: 500px;
height: 500px;
right: calc(50% - 250px);
box-shadow: 0px 1px 4px -1px rgba(0, 0, 0, 1);
text-align: center;
border-radius: 3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<p onclick="createBox();">
Create box
</p>
<div id="list-box"></div>
$("#somebutton").click(function () {
$("#container").append('<div class="box">Your hidden box is now visible</div>');
});
var mouse_is_inside = false;
$(document).ready(function(){
$('#container').hover(function(){
mouse_is_inside=true;
}, function(){
mouse_is_inside=false;
});
$("body").mouseup(function(){
if(! mouse_is_inside) $('.box').hide();
});
});
#container {
width:200px;
height:200px;
background:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<button id="somebutton">
Your button
</button>
<div id="container"></div>
A working solution:
let mouse_inside = false ;
$("#somebutton").click(function () {
let div = document.createElement('div');
div.className = 'box';
$("#container").append(div);
$('.box').hover(function(){
mouse_inside=true;
}, function(){
mouse_inside=false;
});
});
$(document).ready(function(){
$("body").mouseup(function(){
mouse_inside || $('.box').hide();
});
});
#container {
width:200px;
height:200px;
background:red;
}
#container .box { background-color: blue; width:40px; height:40px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="somebutton">
ADD A BOX BELOW
</button>
<div id="container"></div>
here you go try using this steps , first check the element clicked id
if the element is the button you want it to creat that box trigger your creatBox() else if element clicked is the box do nothing else empty #list-boxand hide it :
function createBox(){
var output = "";
output += '<div class="single-box">';
output += '</div>';
$("#list-box").html(output);
$('#list-box').show();
}
$(document).click(function(e) {
var target = $(e.target);
var id = target.attr('id');
var eclass = target.attr('class');
if(id == "creatbox"){
createBox();
target.prop("disabled",true);
}
else if(eclass == "single-box")
{
return;
}
else {
$("#list-box").html('');
$('#list-box').hide();
$('#creatbox').prop("disabled",false);
}
});
#list-box{
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
z-index: 500;
position: fixed;
display: none;
}
.single-box{
z-index: 1000;
top: 100px;
position: fixed;
background-color: white;
overflow-y: auto;
overflow-x: hidden;
width: 500px;
height: 500px;
right: calc(50% - 250px);
box-shadow: 0px 1px 4px -1px rgba(0, 0, 0, 1);
text-align: center;
border-radius: 3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<button id="creatbox">
Create box
</button>
<div id="list-box"></div>
In my application I have 2 toggle buttons and 3 panels. Button1 switches between panel 1 and 2. And button2 switches between panel 1 and 3. I could make it work some how by giving display: none; property to div panels. but once it only works once for each button and then it makes all sub divs to display: none;
Have a look at the sample please:
$(function () {
$("button.panel2").on("click", function() {
var visibleObj = $('.mainSection div:visible');
if ($("div.panel2").css("display") == "none") {
var inVisibleObj = $("div.panel2")
}
else {
var inVisibleObj = $("div.panel1")
}
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
})
});
$("button.panel3").on("click", function() {
var visibleObj = $('.mainSection div:visible');
if ($("div.panel3").css("display") == "none") {
var inVisibleObj = $("div.panel3")
}
else {
var inVisibleObj = $("div.panel1")
}
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
})
});
});
div.app {
margin:50px auto;
width: 400px;
height: 400px;
border-radius:10px;
overflow: hidden;
position: relative;
}
div.app > .blur {
width: 100%;
height: 100%;
background: url(http://goo.gl/0VTd9W);
-webkit-filter: blur(5px);
}
div.mainSection, div.dashboard{
position: absolute;
left: 0px;
text-align:center;
color:#fff;
font-size:20px;
}
div.mainSection{
width:100%;
height:85%;
background:rgba(0,0,0,0.5);
top:0;
}
div.dashboard{
width:100%;
height:15%;
background:rgba(255,0,0,0.5);
bottom:0;
}
div.mainSection > .panel1,
div.mainSection > .panel2,
div.mainSection > .panel3 {
width: 100%;
Height: 100%;
Background: rgba(0, 0, 0, 0.5);
position: absolute;
left: 0px;
top: 0px;
}
div.mainSection > .panel3 > p{
margin-top:80px;
}
.grid-button {
background: none;
border: none;
padding: 3px;
width: 100%;
}
.grid {
display: inline-block;
height: 4px;
position: relative;
width: 32px;
transition: all 0.3s ease-in-out;
}
.grid:after, .grid:before {
content: '';
position: absolute;
background-color: #FFF;
display: inline-block;
height: 4px;
left: 0;
width: 32px;
transition: all 0.3s ease-in-out;
}
.grid.open {
background-color: #FFF;
}
.grid.open:after {
top: 10px;
}
.grid.open:before {
top: -10px;
}
.grid.close {
background-color: transparent;
transform: scale(0.9);
}
.grid.close:after, .grid.close:before {
top: 0;
transform-origin: 50% 50%;
}
.grid.close:before {
transform: rotate(135deg);
}
.grid.close:after {
transform: rotate(45deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="app">
<div class="blur"></div>
<div class="mainSection">
<div class="panel1">
<div>panel1</div>
<div>panel1</div>
</div>
<div class="panel2" style="display: none;">
<div>panel2</div>
</div>
<div class="panel3" style="display: none;">
<p>Panel3</p>
<div>panel3</div>
<div>panel3</div>
</div>
</div>
<div class="dashboard">
<button class="panel2">button1</button>
<button class="panel3">button2</button>
</div>
</div>
As you can see, each panel has some inner divs. the first time, it shows all inner divs. but once you switch between panels, it will not show inner divs inside. I tried to disappear the panels div only but it seems it does it for every div within that panel.
So any idea to keep make it work so switching between panels will not affect the inner divs?
You need to change your javascript in this way:
$(function () {
$("button.panel2").on("click", function() {
var visibleObj = $('.mainSection > div:visible');
if ($("div.panel2").css("display") == "none") {
var inVisibleObj = $("div.panel2")
}
else {
var inVisibleObj = $("div.panel1")
}
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
});
});
$("button.panel3").on("click", function() {
var visibleObj = $('.mainSection > div:visible');
if ($("div.panel3").css("display") == "none") {
var inVisibleObj = $("div.panel3")
}
else {
var inVisibleObj = $("div.panel1")
}
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
})
});
});
The problem is in your selector $('.mainSection div:visible');. This select also the child div and when you try to show the correct panel the child div are hidden. If you use $('.mainSection > div:visible'); you get only the direct child divs.
My web application is made of various panels and a dashboard that has buttons to access each panel. So each button is a toggle between the purposed panel and the main panel.
For example, if we have 3 panels, panel1 is the default one and two buttons to toggle between other two panels the the default one:
button.panel2 should switch between panel1 and panel2
button.panel3 should switch between panel1 and panel3
I have almost achieved it but my code shows both panel2 and panel3 overlapping.
$(function () {
$(".panel2").on("click", function() {
var visibleObj = $('.mainSection div:visible');
var inVisibleObj = $('.mainSection div:hidden');
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
});
});
$(".panel3").on("click", function() {
var visibleObj = $('.mainSection div:visible');
var inVisibleObj = $('.mainSection div:hidden');
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
});
});
});
div.app {
margin:50px auto;
width: 400px;
height: 400px;
border-radius:10px;
overflow: hidden;
position: relative;
}
div.app > .blur {
width: 100%;
height: 100%;
background: url(http://goo.gl/0VTd9W);
-webkit-filter: blur(5px);
}
div.mainSection, div.dashboard{
position: absolute;
left: 0px;
text-align:center;
color:#fff;
font-size:20px;
}
div.mainSection{
width:100%;
height:85%;
background:rgba(0,0,0,0.5);
top:0;
}
div.dashboard{
width:100%;
height:15%;
background:rgba(255,0,0,0.5);
bottom:0;
}
div.mainSection > .panel1,
div.mainSection > .panel2,
div.mainSection > .panel3 {
width: 100%;
Height: 100%;
Background: rgba(0, 0, 0, 0.5);
position: absolute;
left: 0px;
top: 0px;
}
div.mainSection > .panel3 > p{
margin-top:80px;
}
.grid-button {
background: none;
border: none;
padding: 3px;
width: 100%;
}
.grid {
display: inline-block;
height: 4px;
position: relative;
width: 32px;
transition: all 0.3s ease-in-out;
}
.grid:after, .grid:before {
content: '';
position: absolute;
background-color: #FFF;
display: inline-block;
height: 4px;
left: 0;
width: 32px;
transition: all 0.3s ease-in-out;
}
.grid.open {
background-color: #FFF;
}
.grid.open:after {
top: 10px;
}
.grid.open:before {
top: -10px;
}
.grid.close {
background-color: transparent;
transform: scale(0.9);
}
.grid.close:after, .grid.close:before {
top: 0;
transform-origin: 50% 50%;
}
.grid.close:before {
transform: rotate(135deg);
}
.grid.close:after {
transform: rotate(45deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="app">
<div class="blur"></div>
<div class="mainSection">
<div class="panel1">Panel1</div>
<div class="panel2" style="display: none;">Panel2</div>
<div class="panel3" style="display: none;"><p>Panel3</p></div>
</div>
<div class="dashboard">
<button class="panel2">button1</button>
<button class="panel3">button2</button>
</div>
</div>
So I want to make button1 responsible to switch between panel 1 and 2. and button2 to switch between panel 1 and 3.
Any idea how to do it?
I think you need something like this. just these jquery code will be useful.
var currentPanel = 1;
$('.panelControlBtn').on("click", function() {
var ID = $(this).attr('data-id');
if (ID != currentPanel) {
$(".panel").fadeOut('fast', function() {
$("#panel" + ID).fadeIn('fast');
});
currentPanel = ID;
}
});
How about this? https://jsfiddle.net/oez0488h/53/
$("button.panel2").on("click", function() {
var visibleObj = $('.mainSection div:visible');
if ($("div.panel2").css("display") == "none") {
var inVisibleObj = $("div.panel2")
}
else {
var inVisibleObj = $("div.panel1")
}
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
})
});
$("button.panel3").on("click", function() {
var visibleObj = $('.mainSection div:visible');
if ($("div.panel3").css("display") == "none") {
var inVisibleObj = $("div.panel3")
}
else {
var inVisibleObj = $("div.panel1")
}
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
})
});
I've got some kind of drop down menu dynamically appending to differents divs. Problem is, when someone click on "close", then style.display = "none" wont work. I can change background, opacity, size but i cant hide it.
Code looks like this:
<style>
html, body{
height: 98%;
}
#editorViewport{
width: 90%;
height: 100%;
min-width: 400px;
min-height: 300px;
position: relative;
margin: 0 auto;
border: 1px solid red;
}
#movingElementsContainer{
display: none;
top: 0px;
left: 0px;
}
#addStartingElementBtn{
width: 60px;
height: 60px;
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
}
#addStartingElementBtn:hover{
background-color: #c9eac6;
border: 1px solid grey;
cursor: pointer;
}
#elementsMenuContainer{
width: 150px;
border: 1px solid grey;
background-color: white;
min-height: 100px;
padding: 5px;
position: absolute;
z-index: 2;
display: none;
}
.elementOption{
width: 90%;
padding: 5px;
border: 1px solid grey;
}
.elementOption:hover{
border: 1px solid red;
cursor: pointer;
}
</style>
<body>
<div id="editorViewport">
<div id="addStartingElementBtn" data-Owner="starting" data-Side="starting" class="openElementsMenu">
Click!
</div>
</div>
<div id="movingElementsContainer">
<div id="elementsMenuContainer" data-Open="false" data-Owner="" data-Side="">
<div data-Kind="1" class="elementOption">
One
</div>
<div data-Kind="2" class="elementOption">
Two
</div>
<div data-Kind="3" class="elementOption">
Three
</div>
<div data-Kind="99" class="elementOption">
Close
</div>
</div>
</div>
</body>
<script type="text/javascript">
function prepareEventHandlers(){
var openElementsMenu = document.getElementsByClassName("openElementsMenu");
var event = window.attachEvent ? 'onclick' : 'click';
for(var i = 0; i < openElementsMenu.length; i++){
if(openElementsMenu[i].addEventListener){
openElementsMenu[i].addEventListener('click', elementsMenu, false);
}else{
openElementsMenu[i].attachEvent('onclick', elementsMenu);
}
}
var elementOption = document.getElementsByClassName("elementOption");
for(var i = 0; i < elementOption.length; i++){
if(elementOption[i].addEventListener){
elementOption[i].addEventListener('click', selectElementToCreate, false);
}else{
elementOption[i].attachEvent('onclick', selectElementToCreate);
}
}
}
window.onload = function(){
prepareEventHandlers();
}
var totalElements = 0;
var editorViewport = "editorViewport";
var selectedElementId = "";
var elementsMenu = function(){
var elementsMenu = document.getElementById("elementsMenuContainer")
this.appendChild(elementsMenu);
elementsMenu.style.display = "block";
elementsMenu.style.left = 61 + "px";
elementsMenu.style.top = "0px";
elementsMenu.setAttribute("data-Open", "true");
elementsMenu.setAttribute("data-Owner", this.getAttribute("data-Owner"));
elementsMenu.setAttribute("data-Side", this.getAttribute("data-Side"));
}
var selectElementToCreate = function(){
var dataKind = this.getAttribute('data-Kind');
var parentNode = document.getElementById(this.parentNode.id);
alert(dataKind)
if(dataKind == "99"){
parentNode.style.display = "none"
parentNode.setAttribute("data-Open", "false");
parentNode.setAttribute("data-Owner", "");
parentNode.setAttribute("data-Side", "");
}
}
</script>
Here is a JSFiddle
Many thanks for any advise!
var selectElementToCreate = function(e){
var dataKind = this.getAttribute('data-Kind');
var parentNode = document.getElementById(this.parentNode.id);
alert(dataKind)
if(dataKind == "99"){
console.log(parentNode);
parentNode.style.display = "none"
parentNode.setAttribute("data-Open", "false");
parentNode.setAttribute("data-Owner", "");
parentNode.setAttribute("data-Side", "");
alert("Wont Close :");
}
e.stopPropagation();
}
You are moving the element into the clicked element.
var elementsMenu = document.getElementById("elementsMenuContainer")
this.appendChild(elementsMenu);
At first the menu item's click handler is executed which sets the display property to none and as the click event bubbles then the event handler of the wrapper element is executed and sets the display property to block.
You should stop the propagation of the event using stopPropagation method of the event object.
var selectElementToCreate = function (event) {
event.stopPropagation();
var dataKind = this.getAttribute('data-Kind');
var parentNode = this.parentNode;
if (dataKind == "99") {
parentNode.style.display = "none";
// ...
}
}