Execute .click(function () only first click - javascript

I trying to Execute given .click(function() only on first click, but it always Execute when click.
It's works when click .more-post-button it will add class loading to .main ul and show-more-post to .main li after that remove Class loading on setTimeout function 7 second.
JS:
$(".more-post-button").click(function () {
$('.main ul').addClass('loading');
$('.main li').addClass('show-more-post');
setTimeout(function(){
$('.main ul').removeClass('loading');
},7000);
});
My question is how to do this for only on first click, not every time click.
Thanks in advance.

Try:
$(".more-post-button").one("click", function () {
$('.main ul').addClass('loading');
$('.main li').addClass('show-more-post');
setTimeout(function(){
$('.main ul').removeClass('loading');
},7000);
});
http://api.jquery.com/one/
It'll handle it only once.

Why complicating things, try a simple closure on that. You won't pollute globale name space, too!
Demo goes here
(function(){
'use-strict';
var button = document.getElementsByTagName('button')[0];
var myHandler = function() {
var click = 0;
return function() {
if(click === 0) {
alert('single click');
}
click++;
}
}();
button.addEventListener('click', myHandler, false);
})();

I would use jQuery's .one() function. This attaches a handler that will only fire once.
Modified JS
$(".more-post-button").one("click", function () {
$('.main ul').addClass('loading');
$('.main li').addClass('show-more-post');
setTimeout(function(){
$('.main ul').removeClass('loading');
},1000);
});
Fiddle

Actually you can send in the addEventListener an option { once: true } to tell it to fire only once. So adding up to #fubbe and also using only javascript, it would be:
var button = document.getElementsByTagName('button')[0];
var handler = function () { alert('once click'); };
button.addEventListener("click", handler, {once: true});
Source :
MDN - addEventListener
webreflection - DOM Listener: capture, passive, and once

Use unbind in your function to remove all events
$(this).unbind();
From jQuery 1.7 .off is the recommended way
$(this).off();

save it in a variable:
var clicked = false;
$(".more-post-button").click(function () {
if(!clicked) {
clicked = true;
$('.main ul').addClass('loading');
$('.main li').addClass('show-more-post');
setTimeout(function(){
$('.main ul').removeClass('loading');
},7000);
}
});

Related

jQuery - mouseenter / mouseleave with timer not functioning

What I am trying to do is only run my code when someone has hovered on an element for 1 second.
Here is the code that I am using:
var timer;
$(".homeLinkWrap").mouseenter(function() {
timer = setTimeout(function(){
$(this).find('.homeLinkNfo').removeClass('flipOutY').addClass('flipInY').css({opacity: '1'});
console.log('in');
}, 1000);
}).mouseleave(function() {
$(this).find('.homeLinkNfo').removeClass('flipInY').addClass('flipOutY');
console.log('out');
clearTimeout(timer);
});
The first part (mouseenter) IS NOT functioning and DOESN'T remove the class and then add the new one. The second one (mouseleave) IS functioning properly and DOES remove the class and add the new one.
I am guessing it is because I am targeting $(this) which is the current element being hovered over and since it is in a timer function jQuery doesn't know which element $(this) is referring to.
What can I do to remedy this?
I think it is because you are calling $(this) inside the setTimeout function. You need to do something like this:
$(".homeLinkWrap").mouseenter(function() {
var $self = $(this);
timer = setTimeout(function(){
$self.find('.homeLinkNfo').removeClass('flipOutY').addClass('flipInY').css({opacity: '1'});
console.log('in');
}, 1000);
});
Inside the setTimeout callback, this no longer refers to the jQuery selection. You should either keep a reference to the selection:
$(".homeLinkWrap").mouseenter(function() {
var $this = $(this);
timer = setTimeout(function(){
$this.find('.homeLinkNfo').removeClass('flipOutY').addClass('flipInY').css({opacity: '1'});
console.log('in');
}, 1000);
})
Or use an arrow function (ES2015)
$(".homeLinkWrap").mouseenter(function() {
timer = setTimeout(() => {
$(this).find('.homeLinkNfo').removeClass('flipOutY').addClass('flipInY').css({opacity: '1'});
console.log('in');
}, 1000);
})
The problem here is that the this inside the callback function that you're passing to setTimeout doesn't reference to the same point that the this outside the callback does.
There are some ways of solving your problem, I'll suggest you to use Function.prototype.bind to bind your callback function to the same this you have outside:
var timer;
$(".homeLinkWrap").mouseenter(function() {
timer = setTimeout((function() {
$(this).find('.homeLinkNfo').removeClass('flipOutY').addClass('flipInY').css({ opacity: '1' });
}).bind(this), 1000);
}).mouseleave(function() {
$(this).find('.homeLinkNfo').removeClass('flipInY').addClass('flipOutY');
clearTimeout(timer);
});

Consolidate javascript timeout functions

Sorry for the basic level of the question, but js definitely isn't my area of expertise. However, it's one of those questions that's difficult to Google an answer on.
I basically want to do a couple of things when the window is resized. I have a little bit of extra code that also stops the resize event firing twice.
The issue is that I'm duplicating bits of code, that as a coder, I know is wrong. The problem is I don't know how to go about making it right. Here's my current duplicated code:
Event binding
$(window).on("resize", resizeText);
$(window).on("resize", resizeIndicator);
Functions
function resizeIndicator() {
clearTimeout(id);
id = setTimeout(updateIndicator, 200);
}
function resizeText() {
clearTimeout(id);
id = setTimeout(updateText, 200);
}
Thse are not duplicated but included for completeness:
function updateIndicator() {
$tab = $(".tabs li.focus");
if ($tab.length) {
toggleIndicator($tab, true);
}
}
function updateText() {
$tabs = $(".tabs li:not(.indicator) a");
$tabs.each(function () {
$(this).toggleClass("two-line", this.scrollWidth > $(this).outerWidth());
});
}
So you want to avoid code duplication? No problem use higher order of function to create new function.
function createResizeCallback(resizeFunc) {
var id;
return function () {
clearTimeout(id);
id = setTimeout(resizeFunc, 200);
}
}
$(window).on("resize", createResizeCallback(updateText));
$(window).on("resize", createResizeCallback(updateIndicator));
function updateIndicator() {
console.log('updateIndicator');
}
function updateText() {
console.log('updateText');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Declare your timeout id globally and use single handler.
Working demo: http://jsbin.com/nugutujoli/1/edit?js,console,output
$(window).on("resize", resizeEvent);
var timeout;
function resizeEvent() {
clearTimeout(timeout);
timeout = setTimeout(function(){
updateIndicator();
updateText();
}, 200);
}
function updateIndicator() {
console.log("update indicator fired.");
}
function updateText() {
console.log("update text fired.");
}

Add stop to setInterval on hover via jQuery

JS:
setInterval(function(){ $("#nav #nextslide").click()},10000);
HTML:
click.
I want when hover on a button, stop setInterval.
How can I do it?
UPDATED: Thank you for all answers. All soluitons working on static structure. But my a tag get via ajax. So, I think must on option. (jQuery version 2.0.3) Right?
var interval = setInterval(function(){ $("#nav #nextslide").click()},10000);
and on hover callback:
clearInterval(interval);
You can setinterval id. and later can clearInterval whenever you want to stop executing it.
ar refreshIntervalId = setInterval(function(){$("#nextslide").click()}, 10000);
/*On Hover */
$( ".gallery.form_click" ).mouseenter( function(){
clearInterval(refreshIntervalId);
})
Just give the interval function a name so you can refer to it later with .clearInterval.
Start interval function:
nameOfIntervalFunction = setInterval(function(){$("#nav #nextslide").click()},10000);
Stop interval function with hover:
$( "a.gallery.form_click" ).mouseenter( function(){
window.clearInterval(nameOfIntervalFunction)
})
clearInterval() is used to stop the interval.
Use event delegation as a is appended dynamically.
Write:
var t = setInterval(function () {
$("#nav #nextslide").click()
}, 10000);
$(document).on("hover","a",(function () {
clearInterval(t);
});
DEMO here.
try hover-in and hover-out function on your anchor tag, make your interval global so it can be stop and start:
var interval=setInterval(function(){ $("#nav #nextslide").click()},10000);
$( ".gallery" ).hover(
function() {
clearInterval(interval);
}, function() {
interval = setInterval(function(){ $("#nav #nextslide").click()},10000);
}
);
if a tag is dynamic then use jQuery on():
var interval=setInterval(function(){ $("#nav #nextslide").click()},10000);
$( ".gallery" ).on(
mouseenter: function() {
clearInterval(interval);
},
mouseleave: function() {
interval = setInterval(function(){ $("#nav #nextslide").click()},10000);
}
);
and for only stop on hover:
$('.gallery').on("hover",(function () {
clearInterval(interval);
});

disable link temporarily during quickflip

I am using on my site the plugin Quickflip with tabs on my site .
However if by exemple I click too fast on var2 and then var1 there is a bug.
That is why I am trying to put a timeout of 1s on each click of the tab so that it would wait for the flip to do.
Here is how I call the quickflip function (and tab)
$('document').ready(function () {
$('#flip-container').quickFlip();
$('#flip-navigation li a').each(function () {
$(this).click(function () {
$('#flip-navigation li').each(function () {
$(this).removeClass('selected');
});
$(this).parent().addClass('selected');
var flipid = $(this).attr('id').substr(4);
$('#flip-container').quickFlipper({}, flipid, 1);
return false;
});
});
});
Is there a solution to this please ?
I try to test your code and find out the problem that you mentioned.
[EDIT]
You want tabs can't be clicked until flip animation stop. I check the quickflip lib implementation and find out when div is flipping all the flip content display style will be set to "none". So I implement a "is animating" checking function.
Try this:
$('#flip-navigation li a').each(function () {
$(this).click(function () {
$('#flip-navigation li').each(function () {
$(this).removeClass('selected');
});
$(this).parent().addClass('selected');
var flipid = $(this).attr('id').substr(4);
var isAnimating = true;
$("#flip-container>div").each(function(index){
if($(this).css("display")!=="none"&&index<3){
isAnimating=false;
}
});
if(!isAnimating){
$('#flip-container').quickFlipper({}, flipid, 1);
}
return false;
});
});
[EDIT]
And this is the updated answer jsfiddle demo
Hope this is helpful for you.
There are few solutions that i know can solve your problem.
Have a look at Callback which is used to make another function wait to the other function to finish first before performing, and you can put it together with Unbind function or Event.Prevent
Code may look something like this:
$('document').ready(function () {
$('#flip-container').quickFlip();
$('#flip-navigation li a').each(function () {
$(this).click(function () {
$('#flip-navigation li').each(function () {
$(this).removeClass('selected');
$(this).$('#flip-navigation li a').unbind('click', handler); //Mod 1
});
$(this).parent().addClass('selected');
var flipid = $(this).attr('id').substr(4);
//Mod 2 ---- Start
$('#flip-container').quickFlipper({}, flipid, 1, function(){
$(this).$('#flip-navigation li a').bind('click', handler);
});
//Mod 2 ---- End
return false;
});
});
});
I am not entirely sure how to implement callback on the plugin, but here is a link to you that might be able to give you some idea how to implement callback on the quickflip plugin.

Prevent Double Animation in jQuery

How can I stop this function from happening twice when a user clicks too fast?
$(document).ready(function() {
$(".jTscroller a").click(function(event) {
event.preventDefault();
var target = $(this).attr("href");
$("#photo").fadeTo("fast", 0, function() {
$("#photo").attr("src",target);
$("#photo").load(function() {
$("#photo").fadeTo("fast", 1);
});
});
});
});
The issue I'm having is that if a user clicks too fast the element won't fade back in, it just stays hidden.
The issue wasn't what I thought it was. When I was clicking on the same thumbnail it would try to load in the same image and stick loading forever. The .stop() answer does fix double animation so I'm accepting that answer, but my solution was to check if the last clicked item was the currently displayed item. New script:
$(document).ready(function() {
$(".jTscroller a").click(function(event) {
event.preventDefault();
var last = $("#photo").attr("src");
var target = $(this).attr("href");
if (last != target) {
$("#photo").stop().fadeTo("fast", 0, function() {
$("#photo").attr("src",target);
$("#photo").load(function() {
$("#photo").fadeTo("fast", 1);
});
});
};
});
});
Well you use the correct word in your descripton. Use stop()
$("#photo").stop().fadeTo("fast", 0, function() {
You may use a setTimeout function to make a delay between click grabs. I mean, a second click will be processed only after sometime, after the first click. It sets an interval between clicks.
$(document).ready(function() {
var loaded = true;
$(".jTscroller a").click(function(event) {
if(!loaded) return;
loaded = false;
event.preventDefault();
var target = $(this).attr("href");
$("#photo").fadeTo("fast", 0, function() {
$("#photo").attr("src",target);
$("#photo").load(function() {
$("#photo").fadeTo("fast", 1);
loaded = true;
});
});
});
});
Keep track of its state
I believe what you are looking for is .stop()
http://api.jquery.com/stop/
$("#photo").stop(false, false).fadeTo()
I would prevent it like this:
var photo = $("#photo");
if (0 == photo.queue("fx").length) {
foto.fadeTo();
}
I differs from stop as it will only fire when all animations on this element are done. Also storing the element in a variable will save you some time, because the selector has to grab the element only once.
Use on() and off() :
$(document).ready(function() {
$(".jTscroller a").on('click', changeImage);
function changeImage(e) {
e.preventDefault();
$(e.target).off('click');
$("#photo").fadeOut("fast", function() {
this.src = e.target.href;
this.onload = function() {
$(this).fadeIn("fast");
$(e.target).on('click', changeImage);
});
});
}
});

Categories