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

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});

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

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

JQuery: don't focus out when clicking on something

I have a div, #someDiv, on which I have some jQuery code to execute when focused on, and when focused out. But I want to achieve an action in which, if a certain other div is clicked on when div #1 is focused on, that focus remains on the div:
$(document).on("focus", "#someDiv", function() {
// Some code here to execute
}).on("focusout", "#someDiv", function() {
if (#someDiv2 was clicked on) { // DON'T focus out from #someDiv }
});
...however the issue is that jQuery is unable to distinguish that during the focus out, a click was made. How can I achieve this effect?
EDIT: Basically the idea I am trying to implement is a mock web-app in which you can customize a certain kind of div when it has focus, and upon that, an "options" div appears. I don't want the options bar to disappear when it is clicked, as otherwise none of the "options" can be chosen.
One half baked solution is to simply monitor the time for click / blur and correlate the two:
http://jsfiddle.net/ztA5F/
var lastBlur = new Date().getTime();
$("html").on("click", function() {
var now = new Date().getTime();
console.log(lastBlur);
console.log(now);
if (lastBlur >= (new Date().getTime() - 500))
$("#input").focus();
console.log("click");
});
$("#input").on("blur", function() {
lastBlur = new Date().getTime();
console.log("blur");
});
I am not certain I totally understand what you're after, but maybe this will be helpful:
var lastID;
$(document).on('click focus', function (e) {
var id = $(e.target).attr('id');
if (id === 'someDiv2' && lastID === 'someDiv') {
$('#someDiv').trigger('focus');
}
lastID = id;
});

attach an event to the body when ul is visible, then remove it when invisible

I have a <ul> that when clicked, toggles the visibility of another <ul>. How can I attach an event to the body of the page when the <ul>s are revealed so that the body will hide the <ul>.
I am new to writing these sorts things which bubble, and I cannot figure out why what I have done so far seems to work intermittently. When clicked several times, it fails to add the class open when the secondary <ul> is opened.
And of course, there may be an entirely better way to do this.
$(document).on('click', '.dd_deploy', function (e) {
var ul = $(this).children('ul');
var height = ul.css('height');
var width = ul.css('width');
ul.css('top', "-" + height);
ul.fadeToggle(50, function () {
//add open class depending on what's toggled to
if (ul.hasClass('open')) {
ul.removeClass('open');
} else {
ul.addClass('open');
}
//attach click event to the body to hide the ul when
//body is clickd
$(document).on('click.ddClick', ('*'), function (e) {
e.stopPropagation();
//if (ul.hasClass('open')) {
ul.hide();
ul.removeClass('open')
$(document).off('click.ddClick');
// }
});
});
});​
http://jsfiddle.net/JYVwR/
I'd suggest not binding a click event in a click event, even if you are unbinding it. Instead, i would do it this way:
http://jsfiddle.net/JYVwR/2/
$(document).on('click', function (e) {
if ( $(e.target).is(".dd_deploy") ) {
var ul = $(e.target).children('ul');
var height = ul.css('height');
var width = ul.css('width');
ul.css('top', "-" + height);
ul.fadeToggle(50, function () {
//add open class depending on what's toggled to
if (ul.hasClass('open')) {
ul.removeClass('open');
} else {
ul.addClass('open');
}
});
}
else {
$('.dd_deploy').children('ul:visible').fadeOut(50,function(){
$(this).removeClass("open");
})
}
});​
If you need to further prevent clicking on the opened menu from closing the menu, add an else if that tests for children of that menu.
You dont' really need all that code. All you need is jquery's toggle class to accomplish what you want. simple code like one below should work.
Example Code
$(document).ready(function() {
$('ul.dd_deploy').click(function(){
$('ul.dd').toggle();
});
});​​​​
Firstly, you are defining a document.on function within a document.on function which is fundamentally wrong, you just need to check it once and execute the function once the document is ready.
Secondly why do you want to bind an event to body.click ? it's not really a good idea.
Suggestion
I think you should also look at the hover function which might be useful to you in this case.
Working Fiddles
JSfiddle with click function
JSfiddle with hover function

Prevent click event in jQuery triggering multiple times

I have created a jQuery content switcher. Generally, it works fine, but there is one problem with it. If you click the links on the side multiple times, multiple pieces of content sometimes become visible.
The problem most likely lies somewhere within the click event. Here is the code:
$('#tab-list li a').click(
function() {
var targetTab = $(this).attr('href');
if ($(targetTab).is(':hidden')) {
$('#tab-list li').removeClass('selected');
var targetTabLink = $(this).parents('li').eq(0);
$(targetTabLink).addClass('selected');
$('.tab:visible').fadeOut('slow',
function() {
$(targetTab).fadeIn('slow');
}
);
}
return false;
}
);
I have tried adding a lock to the transition so that further clicks are ignored as the transition is happening, but to no avail. I have also tried to prevent the transition from being triggered if something is already animating, using the following:
if ($(':animated')) {
// Don't do anything
}
else {
// Do transition
}
But it seems to always think things are being animated. Any ideas how I can prevent the animation being triggered multiple times?
One idea would be to remove the click event at the start of your function, and then add the click event back in when your animation has finished, so clicks during the duration would have no effect.
If you have the ability to execute code when the animation has finished this should work.
Add a variable to use as a lock rather than is(:animating).
On the click, check if the lock is set. If not, set the lock, start the process, then release the lock when the fadeIn finishes.
var blockAnimation = false;
$('#tab-list li a').click(
function() {
if(blockAnimation != true){
blockAnimation = true;
var targetTab = $(this).attr('href');
if ($(targetTab).is(':hidden')) {
$('#tab-list li').removeClass('selected');
var targetTabLink = $(this).parents('li').eq(0);
$(targetTabLink).addClass('selected');
$('.tab:visible').fadeOut('slow',
function() {
$(targetTab).fadeIn('slow', function(){ blockAnimation=false; });
}
);
}
}
return false;
}
);
Well this is how i did it, and it worked fine.
$(document).ready(function() {
$(".clickitey").click(function () {
if($("#mdpane:animated").length == 0) {
$("#mdpane").slideToggle("slow");
$(".jcrtarrow").toggleClass("arrow-open");
}
});
});
this is not doing what your code does ofcourse this is a code from my site, but i just like to point how i ignored the clicks that were happening during the animation. Please let me know if this is inefficient in anyway. Thank you.
I toyed around with the code earlier and came up with the following modification which seems to work:
$('#tab-list li a').click(
function() {
$('.tab:animated').stop(true, true);
var targetTab = $(this).attr('href');
if ($(targetTab).is(':hidden')) {
$('#tab-list li').removeClass('selected');
var targetTabLink = $(this).parents('li').eq(0);
$(targetTabLink).addClass('selected');
$('.tab:visible').fadeOut('slow',
function() {
$(targetTab).fadeIn('slow');
}
);
}
return false;
}
);
All that happens is, when a new tab is clicked, it immediately brings the current animation to the end and then begins the new transition.
one way would be this:
$('#tab-list ul li').one( 'click', loadPage );
var loadPage = function(event) {
var $this = $(this);
$global_just_clicked = $this;
var urlToLoad = $this.attr('href');
$('#content-area').load( urlToLoad, pageLoaded );
}
$global_just_clicked = null;
var pageLoaded() {
$global_just_clicked.one( 'click', loadPage );
}
As you can see, this method is fraught with shortcomings: what happens when another tab is clicked before the current page loads? What if the request is denied? what if its a full moon?
The answer is: this method is just a rudimentary demonstration. A proper implementation would:
not contain the global variable $global_just_clicked
not rely on .load(). Would use .ajax(), and handle request cancellation, clicking of other tabs etc.
NOTE: In most cases you need not take this round-about approach. I'm sure you can remedy you code in such a way that multiple clicks to the same tab would not affect the end result.
jrh.
One way to do this to use timeStamp property of event like this to gap some time between multiple clicks:
var a = $("a"),
stopClick = 0;
a.on("click", function(e) {
if(e.timeStamp - stopClick > 300) { // give 300ms gap between clicks
// logic here
stopClick = e.timeStamp; // new timestamp given
}
});

Categories

Resources