How to remove a class with delay after a button is pressed? - javascript

I have a full page navigation on my website. To make sure the page can't scroll when the navigation is opened, the body get's the 'no-scroll' class with overflow hidden. This also removes the scrollbar when the nav is opened.
When the nav button is pressed again and the nav closes, the class 'no-scroll' is removed from the body, revealing the scrollbar immediately. The navbar takes 1.05s to fully close. What I tried to achieve is to have the class 'no-scroll' not be removed immediately, but with a delay. Is there any way to do this?
This is the code I currently have to add and remove the class on button click:
<script>
// when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
// on .nav-menu-button click
document.querySelectorAll('.nav-menu-button').forEach(trigger => {
trigger.addEventListener('click', function(){
this.x = ((this.x || 0) + 1)%2;
if(this.x){ // 1st click
document.querySelectorAll('body').forEach(target => target.classList.add('no-scroll'));
}
else{ // 2nd click (toggle)
document.querySelectorAll('body').forEach(target => target.classList.remove('no-scroll'));
}
});
});
});
</script>
Thanks in advance!

You could use setTimeout function. Here I've used 5 seconds delay:
setTimeout(function(){
document.querySelectorAll('body').forEach(target => target.classList.remove('no-scroll'));
},5000);

You can use setTimeout Function from WebAPI which helps in such cases. It registers approximate(minimum) timeout (in milliseconds, your case is 1050), after which specified function will be executed. In the end code will look like this:
setTimeout(() => {
document.querySelectorAll('body').forEach(
(target) => target.classList.remove('no-scroll')
);
}, 1050);

The code from Ann Francis solved it!
<script>
// when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
// on .nav-menu-button click
document.querySelectorAll('.nav-menu-button').forEach(trigger => {
trigger.addEventListener('click', function(){
this.x = ((this.x || 0) + 1)%2;
if(this.x){ // 1st click
document.querySelectorAll('body').forEach(target => target.classList.add('no-scroll'));
}
else{ // 2nd click (toggle)
setTimeout(function(){
document.querySelectorAll('body').forEach(target => target.classList.remove('no-scroll'));
},900);
}
});
});
});
</script>

You should try .add() and .remove() instead of classList.add() and classList.remove():
document.querySelectorAll('body').forEach(target => target.remove('no-scroll'));

Related

How to make an action on first click and another action on second click

My goal is to move a div element to the right side of the page on the first click and move it back to the left if I click it again and so on. How can I do this in javascript?
As enhzfelp said in their comment, the best solution would be to create a css class which moves your element to the right side of the page and to add / remove it with javascript.
If your goal is actually to perform one action and on next event call perform another, you can simply change a variable whenever the event is called.
Example code:
let right = false;
someElement.on('click', () => {
right = !right;
if (right) moveRight();
else moveLeft();
});
function moveRight() { ... }
function moveLeft() { ... }
You can also do this
<script>
var clickCount = 0;
function checkClick() {
if ( clickCount % 2 == 0 ) {
alert("first click");
} else {
alert("Second click");
}
clickCount++
}
</script>
<button onclick="checkClick()">Click me</button>
So, as I understood, you want to make so on click, the div element move to the opositive direction of left or right.
You can make this with an event listener, that listens to the click event and execute whatever you want on every click.
document.addEventListener('click', function(event) {
// your code that executes on every click
});
This event listener listens the click on all your webpage, so if you want to only listen the click when the use click your div, you need to get the div. There are several ways, but I recomend you to add an id to the div.
<div id="iAmYourElement"></div>
And then get the element in JavaScript
const element = document.getElementById("iAmYourElement");
element.addEventListener('click', function(event) {
// your code that executes on every click
});
Now that we have the way to deal with the click event, let's talk about the code that goes inside the listener.
One way to do this is creating two CSS classes, one is your div on the left and another whe div on your right. So, if we need the element to be on the right, we add the right-class, and if we need the div to be to the left, we add left-class and remove right-class.
Final javascript code will looks like that:
const element = document.getElementById("iAmYourElement");
let isDivOnLeft = true;
element.addEventListener('click', function (event) { // executes if you click on the div
isDivOnLeft = !isDivOnLeft // We negate the value of isDivOnLeft, so if it was true, it will now be false and vice versa.
if (isDivOnLeft) {
elementToRight()
} else {
elementToLeft()
}
});
function elementToRight() {
element.classList.remove("left-class")
element.classList.add("right-class")
}
function elementToLeft() {
element.classList.remove("right-class")
element.classList.add("left-class")
}
Hmm,
my English is kinda weak so I'll try my best to explain.
Let's assume that we have a div with id moveable
<div id="moveable"></div>
And we have button
<button id="move">Move</div>
And our goal is to move the div to the right in the first click, and in the second click, we will move it back to the right.
let button = document.getElementById("move");
let div = document.getElementById("moveable");
button.addEventListener("click", function () {
const dataMovedAttribute = div.getAttribute("data-moved");
if (dataMovedAttribute && dataMovedAttribute === "true") {
div.setAttribute("data-moved", "false");
div.style.float = "left";
} else {
div.setAttribute("data-moved", "true");
div.style.float = "right";
}
});
Checkout this example:
https://codesandbox.io/s/vigilant-rosalind-176by

toggle div content when click anywhere on the page

I have simple slider which I open/close on click event.
$('#tab1-slideout span').click(function () {
manageToggleStateTab1();
});
function manageToggleStateTab1() {
if (tab1ToggleState == 'collapsed') {
$('#tab1-content').slideToggle('slow');
$('#tab1-slideout span').addClass('active');
tab1ToggleState = 'expanded';
});
and on page load I set this tab1ToggleState with initial value
var tab1ToggleState = 'collapsed';
this works great but I want to expand this further in order to allow toggling state on click event anywhere outside #tab1-content container div.
I tried to wire click event anywhere on page except the one with toggle content
$(document).not($('#tab1-content')).click(function () {
manageToggleStateTab1();
});
but this not gives me desired result, div immediately slide down after it slide up.
you can use this function
// hide some divs when click on window
function actionwindowclick(e , el , action){
if (!$(el).is(e.target) // if the target of the click isn't the container...
&& $(el).has(e.target).length === 0) // ... nor a descendant of the container
{
action();
}
}
in click event
$(document).click(function (e) {
actionwindowclick(e , '#tab1-content' , function(){
// do action here
});
});
simply this function says if the element is not a target do the action
Working Demo
and while you use $(document).click(... you will need event.stopPropagation()
so for example
$('#tab1-slideout span').click(function (event) {
event.stopPropagation();
manageToggleStateTab1();
});
Working Example

Onclick toggle DIV class

So I have a button that is a div class, lets call it "login-button-arrow".
I want to set up a javascript method, so when this div gets clicked on, a little javascript box can pop up.
How do I go about doing this?
I have tried something like this:
login-button-arrow.onclick{alert('xyz')}
but I guess it does not work like that.
// Get #popup element:
const popup = document.querySelector("#popup");
// Function to toggle popup (toggles .active)
const togglePopup = () => {
console.log( "xyz" );
popup.classList.toggle("active");
};
// Get buttons elements from DOM
const buttons = document.querySelectorAll('.login-button-arrow');
// Assign event listener with callback to every button:
buttons.forEach((btn) => {
btn.addEventListener("click", togglePopup);
});
$('.login-button-arrow').on('click', function() { alert('xyz'); });
var login-button-arrows = document.getElementsByClassName('login-button-arrow');
login-button-arrows.forEach(function(obj){
obj.addEventListener('click', function(){
alert('xyz');
});
});
using Jquery :
$('#login-button-arrow').on('click', function(){ alert('xyz'); });

Click function into click function

I thought that if I put one click function into click function it was only proceeding the second click function if it was clicked, but when I click the first the codes for second one is running... I thought that if i clicked the second one it should have run the codes.
I mean when I clicked the second one then the codes are visible and doing as they should do, but If click like first function 3 times without to click the second and suddenly click on the second, it is behaving like the codes have run three times.
$(".click1").click(function () {
alert("hej");
$(".click2").
function ({
alert("bye");
});
});
My intention is to only make the second click to run when it is really clicked and not run the codes if I click the first one!
To be more clear. When I click first, it says hej and if I click three time then it will say hej 3x but when I suddenly click click2 it showing bye three times but I only clicked once.
Can anyone explain me why this is happening? and How i can prevent this to happen?
Thanks for the help!
EDIT!!
function click_back() {
current_question_for_answer.splice(0,1);
$("#tillbaka_question").fadeTo("slow", 0.2);
$("#tillbaka_question").off("click");
$(".questions").hide();
$(".containing_boxes").show();
$(".answered_box").remove();
var numbers_of_answered_question = history.length - 1;
for (var i = numbers_of_answered_question; i > -1; i--) {
current_question.push(i);
$(".containing_boxes").prepend('<div class="answered_box">'+i+'</div>');
$("div.containing_boxes > div:nth-child("+history.length+")").css("background-color", "green");
$(".containing_boxes").hide();
$(".containing_boxes").fadeIn(100);
}
$("div.containing_boxes > div").not(":last-child").click(answered_box);
$("div.containing_boxes > div:nth-child("+history.length+")").click(function () {
$("div.containing_boxes > div:nth-child("+history.length+")").click(function () { }) this function should only work if I click it. I can not seperate this code in two new function. If I do it, then the whole system will stop working.....
Because you clicked on click1 3 times, the click event on click2 is 3x created. Thats why it will alert 'bye' 3 times.
You should Unbind click event before binding New click event
$(".click1").click(function () {
alert("hej");
$(".click2").unbind('click');
$(".click2").bind('click',function (){
alert("bye");
});
});
Live Demo
The first click is attaching another click handler which means the second click will fire multiple times, so every time you click it you will get a lot of "bye"s. To avoid this, you can simply set a variable like var isClicked = 0 on load, and then before attaching the handler to click2, check if isClicked == 0, if true then set isClicked = 1 so it only works once
var isClicked = 0;
$(".click1").click(function () {
alert("hej");
if ( isClicked == 0 ) {
isClicked = 1;
$(".click2").
function ({
alert("bye");
});
}
});
I think, his is what you are after:
$(".click1").click(function () { alert("hej"); });
$(".click2").click(function () { alert("bye"); });
Try this:
var click1 = false;
$(".click1").click(function () {
alert("hej");
click1 = true;
});
$(".click2").click(function() {
if (click1 === true) {
alert("bye");
click1 = false;
}
});
Every time you click 1st button, You are registering click event for the 2nd button, so if you click 1st button 5x then 2nd button click event will be registered 5x
The solution is that
You make sure that every time you click 1st button you unregister click event for 2nd button, then register it again

Prevent 'click' event from firing multiple times + issue with fading

Morning folks. Have an issue with a simple jQuery gallery i'm making. It lets the user cycle through a collection of images via some buttons and at the same time, rotates through these images on a timer. My problem is that the user is able to click the button multiple times which queues up the fade in animation and repeats it over and over, e.g. user clicks button 5 times > same image fades in/out 5 times > gallery moves to next image.
I've tried using:
$('#homeGalleryImage li a').unbind('click');
After the click event is fired and then rebinding:
$('#homeGalleryImage li a').bind('click');
After it's done but this simply removes the click event after pressing a button once and never rebinds to it?
I've also tried disabling the button via:
$('#homeGalleryImage li a').attr('disabled', true);
To no avail... ?
There is a secondary issue where if you manage to click a button while the image is in a transition, the next image appears 'faded' as if the opacity has been lowered? Very strange... Here is the code for button clicks:
var i = 1;
var timerVal = 3000;
$(function () {
$("#homeGalleryControls li a").click(function () {
var image = $(this).data('image');
$('#galleryImage').fadeOut(0, function () {
$('#galleryImage').attr("src", image);
});
$('#galleryImage').fadeIn('slow');
$('.galleryButton').attr("src", "/Content/Images/Design/btn_default.gif");
$(this).find('img').attr("src", "/Content/Images/Design/btn_checked.gif");
i = $(this).data('index') + 1;
if (i == 4) {
i = 0;
}
timerVal = 0;
});
});
Here is the code that cycles through the images on a timer:
//Cycle through gallery images on a timer
window.setInterval(swapImage, timerVal);
function swapImage() {
$('#galleryImage').fadeOut(0, function () {
var imgArray = ["/Content/Images/Design/gallery placeholder.jpg", "/Content/Images/Design/1.jpg", "/Content/Images/Design/2.jpg", "/Content/Images/Design/3.jpg"];
var image = imgArray[i];
i++;
if (i == 4) {
i = 0;
}
$('#galleryImage').attr("src", image);
$('#galleryImage').fadeIn('slow');
});
var currentButton = $('#homeGalleryControls li a img').get(i - 1);
$('.galleryButton').attr("src", "/Content/Images/Design/btn_default.gif");
$(currentButton).attr("src", "/Content/Images/Design/btn_checked.gif");
}
I realise it might be a better idea to use a plugin but I'm very new to jQuery and I'd like to learn something rather than using some ready made code.
Any help at all, is much appreciated.
Thankyou
You could always try adding something to the element to cancel the click event?
For example
$(".element").click(function(e) {
if ( $(this).hasClass("unclickable") ) {
e.preventDefault();
} else {
$(this).addClass("unclickable");
//Your code continues here
//Remember to remove the unclickable class when you want it to run again.
}
}):
In your case you could try adding a check on the click.
$('#homeGalleryImage li a').attr('data-disabled', "disabled");
Then inside your click event
if ( $(this).attr("data-disabled" == "disabled") {
e.preventDefault();
} else {
//Ready to go here
}
Edit
Here is a working example showing the element becoming unclickable. http://jsfiddle.net/FmyFS/2/
if you want to make sure that the registered event is fired only once, you should use jQuery's one :
.one( events [, data ], handler ) Returns: jQuery
Description: Attach a handler to an event for the elements. The handler is executed at most once per element per event type.
see examples:
using jQuery: https://codepen.io/loicjaouen/pen/RwweLVx
// add an even listener that will run only once
$("#click_here_button").one("click", once_callback);
using vanilly JS: https://codepen.io/loicjaouen/pen/gOOBXYq
// add a listener that run only once
button.addEventListener('click', once_callback, {capture: true, once: true});

Categories

Resources