I've a button/link which opens my sidebar, calling the relative function onclick. It's something like
<a id="menu-toggle" href="javascript:void(0);" onclick="event.stopPropagation(); opensidebar();" type="button">
<i class="sprite-t-toggle-side"></i>
</a>
which calls this function
function opensidebar() {
var $menu = $("#sidebar-wrapper");
$menu.toggleClass("active");
};
and closes on document click like
$(document).click(function(){
$('#sidebar-wrapper').removeClass("active");
});
It works but the problem is that the sidebar closes even if I click inside it. I'd like to keep it open because I have dropdown menus there.
How can I achieve it? Thanks.
You can do it like this
$('#open').click(function() {
$('.sidebar').toggleClass('active')
})
$(document).click(function(e) {
var sidebar = $(".sidebar, #open");
if (!sidebar.is(e.target) && sidebar.has(e.target).length === 0) {
sidebar.removeClass('active')
}
});
body, html {
margin: 0;
padding: 0;
}
.sidebar {
transform: translateX(-120%);
display: inline-block;
height: 100vh;
background: lightblue;
transition: all 0.3s ease-in;
width: 200px;
}
.active {
transform: translateX(0);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidebar">Sidebar</div>
<button id="open">Toggle</button>
Related
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');
})
});
I built a navbar a few weeks back and just realised I did not set an .active class on it. Now, I built the navbar and the links dynamically in JS and would now like to give whichever one is active the according CSS.
This is how I built the navbar in JS:
let womensNav = document.createElement("ul");
womensNav.classList.add("womensNav");
const el1 = document.createElement("li");
el1.innerHTML = "<a>Jeans</a>";
el1.addEventListener("click", (e) => {
document.location.href =
"https://www.martadolska.com/product-category/women/womens-jeans";
});
womensNav.appendChild(el1);
document.querySelector(".ast-woocommerce-container").appendChild(womensNav);
I have more than one link, but for this purpose I don't need to show it all. So now the goal is to build a generic function that gives the active element within the navbar the according class.
document.querySelectorAll("#womensNav li").forEach(function (ele) {
ele.addEventListener("click", function (e) {
e.preventDefault();
document
.querySelectorAll("#womensNav li a.active")
.forEach((ele) => ele.classList.remove("active"));
ele.parentNode.classList.toggle("active");
});
});
And this is what my CSS looks like:
.womensNav li a:hover {
color: var(--main-text-color);
text-decoration: line-through darkred solid;
}
.womensNav li a::before {
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 7px;
left: 0;
background-color: #b22222;
visibility: hidden;
transform: scaleX(0);
transition: all 0.3s ease-in-out 0s;
}
.womensNav li a:hover::before {
visibility: visible;
transform: scaleX(1);
}
.womensNav li a:active::before {
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 10px;
left: 0;
background-color: #b22222;
}
// up until this point everything works
.active {
text-decoration: line-through darkred solid;
}
I am guessing there is something missing/not completely right in the second snippet of the JS code since nothing is happening when my link is active. I get the animation that I would like to get, but then it disappears once the user is redirected to that specific link, so you wouldn't know which sub-page you are on.
this is wrong
ele.parentNode.classList.toggle("active");
"ele" is the <li>, you are adding the "active" class to the <ul> via the parentNode, might be better to use the "e" event from the click and use e.target and then try and set the active class on the <a> or use childNode/children to get at your <a>
I have a page which has multiple CSS only pop-ups implemented.
The popups work fine & close when the 'X' is clicked. However I wish for them to be closed when user clicks anywhere on the page. For that I implemented a short javascript code, which does close them on any click, but they dont open again (until page is refreshed). I am guessing the state is being saved as "none". How do i fix this?
The code:
window.onclick = function(event) {
if (event.target.className === "overlay") {
event.target.style.display = "none";
}
}
<div class="editbutton">
<a class="btn btn-link" href="#popupedit">Edit</a></div>
<div id="popupedit" class="overlay">
<div class="popup10">
<a class="close" href="#"></a>
........
</div>
</div>
<div class="editbutton">
<a class="btn btn-link" href="#popupedit1">Edit</a></div>
<div id="popupedit1" class="overlay">
<div class="popup10">
<a class="close" href="#"></a>
........
</div>
</div>
<div class="editbutton">
<a class="btn btn-link" href="#popupedit2">Edit</a></div>
<div id="popupedit2" class="overlay">
<div class="popup10">
<a class="close" href="#"></a>
........
</div>
</div>
The CSS code:
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
z-index: 2000;
}
.overlay:target {
visibility: visible;
opacity: 1;
}
.popup10 {
margin: 70px auto;
padding: 20px;
background: #fff;
border-radius: 5px;
width: 50%;
position: relative;
transition: all 5s ease-in-out;
}
.popup10 h2 {
margin-top: 0;
color: #333;
font-family: Tahoma, Arial, sans-serif;
}
.popup10 .close {
position: absolute;
top: 8px;
right: 10px;
transition: all 200ms;
font-size: 30px;
font-weight: bold;
text-decoration: none;
color: #333;
}
.popup10 .close:hover {
color: #06D85F;
}
.popup10 .content {
max-height: 30%;
overflow: auto;
}
Here is the code you should update in javascript.
window.onclick = function(event) {
if (event.target.className === "btn btn-link") {
document.getElementById('popupedit').style.display = "block";
}
if (event.target.className === "overlay") {
event.target.style.display = "none";
}
}
Why the popup is not opened again is that you set the overlay part display: none when clicking the part, but no process to set back to display: block.
So you should set the popup layout back to display: block again when clicking the edit button.
Please see the result working : https://jsfiddle.net/254xmyv7/3/
Hope this would be helpful. :)
Although #Kevin Lee's code works, adding a long list of elements with getElementById isn't recommended. If you remove one of the popup elements or add one, you have to go back and manually change the code. You should consider instead looping through all the existing elements with the class 'overlay' and applying the property with a single line of code rather than 10 separate ones:
window.onclick = function(event) {
var popups;
if (event.target.className === "btn btn-link") {
popups = document.getElementsByClassName('overlay');
console.log(popups[i]);
for (let i = 0; i < popups.length; i++) {
popups[i].style.display = "block";
}
}
if (event.target.className === "overlay") {
event.target.style.display = "none";
}
};
This will save you a lot of time and potentially aggravation down the road. Working fiddle here: https://jsfiddle.net/Vanadu/u7n30Lra/24/
In your javascript, the window element gets the click, finds the element with the class 'overlay' and sets its style.display property to 'none'. Then, when you click the element to open the popup, that click is 'bubbling up' the DOM tree to the window, and the window then sets the display property to 'none' again before the popup can open.
One approach might be to prevent the click on the elements from 'bubbling up' and use the same class on the window level to control the popup that you use on the element level.
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
Apologies for the long winded question but any help would be much appreciated!
I have a navigation div on a website that disappears when the screen gets smaller to be replaced by a menu button, using a media query. The menu button uses JavaScript to show and hide the menu.
This all works apart from one small bug that I can't figure out, it's a bit hard to explain so I'll bullet point it -
1) Open small browser window so button shows.
2) Open and close menu using button.
3) Maximise screen.
4) The button disappears (which it should) but the menu doesn't reappear.
You can see a live example here - http://andrewbruce.me
I'll put relevant code below -
var clicks = 0;
function decide(x) {
if (clicks == 0) {
document.getElementById("nav").style.visibility = "visible";
document.getElementById("nav").style.opacity = "1";
x.classList.toggle("change");
clicks = 1;
}
else if (clicks == 1) {
document.getElementById("nav").style.visibility = "hidden";
document.getElementById("nav").style.opacity = "0";
x.classList.toggle("change");
clicks = 0;
}
}
#nav {
height: 100%;
width: 22%;
text-align: center;
box-shadow: 2px 2px 5px #888888;
visibility: visible;
opacity: 1;
transition: all .3s ease-in-out;
background-color: #1b1d1f;
float: left;
position: fixed;
z-index: 2;}
#media handheld, screen and (max-width: 1000px) {
#nav {width: 40%; visibility: hidden; opacity: 0;}
.menuButton {visibility: visible;}
}
<div class="menuButton" onclick="decide(this);">
<div id = "bar1"></div>
<div id = "bar2"></div>
<div id = "bar3"></div>
</div>
Try this.
I hope helps.
#media (min-width: 1000px){
#nav{
opacity:1!important;
visibility: visible!important;
}
}
You should not change style by this method document.getElementById("nav").style, it will add inline style and override your properties. Instead create a class with those properties, then use scripts to toggle it.
For example:
CSS
.nav-hidden {
visibility: hidden;
opacity: 0;
}
JS
element.classList.add("nav-hidden");
element.classList.remove("nav-hidden");
use below JS
window.addEventListener("resize", menuChange);
function menuChange() {
if (window.innerWidth > 999){
document.getElementById("nav").style.visibility = "visible";
document.getElementById("nav").style.opacity = "1";
x.classList.toggle("change");
}
}
So I am having 2 issues here and maybe this is just a poor execution in general so please point me in the right direction.
1.) Regardless of how many black boxes there are the last one always works correctly, meaning I click the black box and it opens then a red box appears, I can close the box by clicking the dark area surrounding the red box or the red box itself. The issue comes when I click any boxes before the last box, it opens as expected but when I try to close it by clicking the red box it opens another instance of the dark background, I don't want that to happen.
2.) So I think the deeper issue is when I click a black box it is adding the class "fart" to ALL .testthree divs instead of just the one for the area I am clicking AND when I click the red box it is also adding the class "open" to all of the other test divs.
So my question is, Is there a way to contain the classes that are added ONLY to the initial place that I click? What I want to happen is:
I click workImg, test gets the class of open, and testthree gets the class of fart, ONLY for the workImg that i click on. Then when I click anywhere it all closes nicely.
Link to fiddle:
http://jsfiddle.net/dkarasinski/L6gLLyko/
HTML:
<div class="workCont">
<div class="workBlock">
<div class="workImg">
<div class="test one">
<div class="testthree"></div>
</div>
<img src="/assets/images/piece1.jpg" />
</div>
<div class="workName">Project</div>
</div>
<div class="workBlock">
<div class="workImg">
<div class="test one">
<div class="testthree"></div>
</div>
<img src="/assets/images/piece1.jpg" />
</div>
<div class="workName">Project</div>
</div>
</div>
CSS:
.workImg {
background:#151515;
width:330px;
height:201px;
display:inline-block;
position: relative;
}
.test {
position: fixed;
top: 50%;
left: 50%;
z-index:100;
width: 0;
height: 0;
-webkit-transition-duration: 300ms;
-webkit-transition-property: all;
-webkit-transition-timing-function: ease-in-out;
text-align: center;
background: white;
color: white;
font-family: sans-serif; /* Just 'cos */
}
.test.open {
top: 0;
left: 0;
width: 100%;
height: 100%;
position:fixed;
color:black;
background-color: rgba(0, 0, 0, 0.8);
}
.testthree {
width:0;
height:0;
background-color: red;
margin:auto;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.testthree.fart {
width:50%;
height:300px;
}
.testthree.close {
display:none;
}
.workName {
text-align:center;
margin-top:17px;
}
JQuery / Javascript:
$(document).ready(function(){
$(".workImg").click(function() {
$(this).find(".test").toggleClass("open");
if ($(this).find(".test").hasClass("one")) {
if($('.testthree').hasClass("fart")) {
$(".testthree").removeClass("fart");
}
else {
setTimeout(function(){
$( ".testthree" ).addClass( "fart" );
}, 500);
}
}
});
});
Replace all your code in else block with this:
var scope=$(this);
setTimeout(function(){
scope.find('.testthree').addClass('fart');
},500);
You needed a scope to work within and not apply fart class to all of the .testthree elements. Hope you find it useful.
Update: Your complete code may look like:
$(document).ready(function () {
$(".workImg").click(function () {
var scope = $(this);
var test = scope.find('.test');
var testthree = scope.find('.testthree');
test.toggleClass('open');
if (test.hasClass('one')) {
if (testthree.hasClass('fart')) {
testthree.removeClass('fart');
} else {
setTimeout(function () {
testthree.addClass('fart');
}, 500);
}
}
});
});
Hope this helps.
Why don't you just ignore the whole fart and close classes.
And make .testthree invisible by default..
.testthree {
width:50%;
height:300px;
background-color: red;
margin:auto;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display:none;
}
Then just do...
$(document).ready(function(){
$(".workImg").click(function() {
var test = $(this).find(".test");
test.toggleClass("open");
setTimeout(function(){
test.find(".testthree").toggle();
},100);
});
});
JSFIDDLE HERE
Try below code
$(document).ready(function(){
$(".workImg").click(function() {
$(this).find(".test").toggleClass("open");
if ($(this).find(".test").hasClass("one")) {
if($(this).find('.testthree').hasClass("fart")) {
$(this).find(".testthree").removeClass("fart");
}
else {
setTimeout(function(){
$(this).find( ".testthree" ).addClass( "fart" );
}, 500);
}
}
});
});