function inside if statement executing multiple times - javascript

I have a container element that is being loaded multiple times to show variable content on a click event through an Ajax request and upon ajax Complete i have some functions being called including a function (A) inside an if statement.
My problem is when function (A) finally gets called, it gets called multiple times depending on how many times the container had been loaded before the if statement is true.
Here is simple version of my code:
$(".button").on("click", function(){
loadContainer();
});
var loadContainer = function(){
$(".container").load(url, function(){
var x = $(".x");
if(x.length>0){
A();
};
});
};
x is an element $(".x") that will be loaded in the container and the function (A) should only be called when that element gets loaded. i.e. $(".x").length>0
if (x.length>0) is true after say 3 times of loading the container then function (A) will be called 3 times then.
is there a way around this or a way to make sure function (A) gets called only once??
Edit:
My full code:
ajaxBtn.on("click", function(e) {
loadContainer(url, curtain, mainContainer, body, links);
});
var loadContainer = function(url, curtain, maincontainer, body, links) {
$(".main-container").load(url + " .main-container > *", function() {
$("#logo").css({
"z-index": "400"
});
mainFun();
curtain.removeClass("full");
links.removeClass("here");
body.removeClass("no-scroll");
clearInterval(timer);
getFlexIndex();
position = 0;
if (vidContainer.length > 0) {
youTubeLazyLoad();
}
});
};
please assume that all the variables are already defined.

It sounds like you are adding the same button click listener numerous times
You should look into how this occurs as there is not enough shown for us to know why. Is it embedded inside another event handler perhaps? Or in a function that gets called numerous times?
A workaround is to remove the click listener before adding a new one
Change
$(".button").on("click"...
to
$(".button").off('click').on("click"...

Related

Execute a second .click() event after the first is done

I would like to "chain" two .click() calls but cannot get it to work.
The code does work when I debug the JS code in my browser (so with a delay it seems to work)
I somehow need the first .click() to load the page (that's what the first event does) and only if that is done, I want the second .click() to execute.
My Code:
$.post("settings?type=mail&nr=" + nr, function(data){
if(data != ""){
alert(unescape(data));
// First click event -> realoads the page
$("#change_settings").click();
// Second click event -> navigates to a tab
// inside the page loaded by the first click event
$("#tab_mail_header" + nr + "").click();
}
});
EDIT: More Code
function load_change_settings_view(e){
e.preventDefault();
$("#content").empty();
// load settings.jsp in a div (test) inside the mainpage
$("#content").load("settings.jsp #test", function(){
// In here are a couple of .click() & .submit() functions but nothing else
});
});
$("#change_settings").click(function(e){
load_change_settings_view(e);
});
EDIT: I currently have this code:
$("#change_settings").click();
window.setTimeout(function () {
$("#tab_mail_header" + nr + "").click();
}, 1000);
I dont really like it though, as it is a timed delay and it may be the case (on a slow client) that that 1 second timeout will not be enough. I don't want to set the timeout too high as this slows down the workflow for users with a faster client...
I looked though a couple of post like these:
JQuery .done on a click event
Wait for a user event
How to wait till click inside function?
Wait for click event to complete
Does anyone have an idea on how to get this to work?
after a few more attempts I ended up with the following solution:
Code Snippet#1
$.post("settings?type=mail&nr=" + nr, function(data){
if(data != ""){
alert(unescape(data));
// create event object
var evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, false);
// call method manually (not called by actual button click like its supposed to be)
// - pass event object
// - additional parameter to specify the tab the user is viewing
load_change_settings_view(evt, "tab_mail_header" + nr);
}
});
Code Snippet#2
function load_change_settings_view(e, p_tab){
e.preventDefault();
$("#content").empty();
// load settings.jsp in a div (test) inside the mainpage
$("#content").load("settings.jsp #test", function(){
// Go to previous tab (if one was selected)
var prev_tab = p_tab;
if(typeof prev_tab != 'undefined'){
$("#" + prev_tab).click();
}
// In here are a couple of .click() & .submit() functions but nothing else
});
});
feel free to comment if you have a better idea on how to solve this problem or if you have any other suggestions

stopping a nested javascript function running more than once

I'm trying to get a javascript function to run only once. I've seen this question has been asked before, e.g. Function in javascript that can be called only once, but I can't get the solutions in here to work. I'm not sure if it's because I've got nested functions, or whether there's something I'm missing. Essentially, I'm trying to run a function which, when a webpage is scrolled, it:
- runs a little animation on a canvas in the header
- reduces the size of the header
- leaves it at that
But when there is any subsequent scrolling, the animation keeps re-running. Here's a summarised version of the non-working code:
$(document).on("scroll",function(){
var arrange_title = function(){
//some code
};
if($(document).scrollTop()>0){
arrange_title();
arrange_title = function(){};
setTimeout(function(){
$("header").removeClass("large").addClass("small");
},1000);
}
});
I've also tried declaring a global variable, setting it to "false" in a "window.onload" function, then set it to true in an if function that runs the animation (the if function running only if the variable is false), but that doesn't stop it either. Thoughts?
What you're looking for is something along the lines of listenToOnce where the listener fires the one time, but never again. This could be modified to a number of calls, but the logic is like so:
Register the listener.
Then once the listener fires, remove it.
See .off
$(document).on("scroll",function(){
var arrange_title = function(){
//some code
};
if($(document).scrollTop()>0){
arrange_title();
arrange_title = function(){};
setTimeout(function(){
$("header").removeClass("large").addClass("small");
// $(document).off('scroll'); // or here
},1000);
}
$(document).off('scroll'); // remove listener, you can place this in the setTimeout if you wish to make sure that the classes are added/removed
});
Don't use a time out. That is why you are getting in trouble. Declare a variable outside of your function using var, that will make it global. Your code should be inside of a check for that variable. Before executing your code the first time but inside of the check, change that variable so that the code will never run again.
Try avoid setTimeout. Almost all animation can be watched for end.
function doHeaderAnimation() {
return $('header').animate();
}
function makeHeaderSmall() {
$("header").removeClass("large").addClass("small");
}
function handleScroll(event) {
if ($(document).scrollTop() > 0) {
doHeaderAnimation().then(makeHeaderSmall);
$(document).off("scroll", handleScroll);
}
}
$(document).on("scroll", handleScroll);

Calling jQuery function too many times in Rails app

In my Rails app, I am committing a single UI action (changing a select value), but the corresponding function is being called twice. The function is below.
// doc.js
$(document).on("change", "select.class", (function(){
if ($("select.otherSelect").find(":selected").is( ":disabled" ) == false) {
$.ajax({
//Ajax call
});
console.log("Selector was changed")
}
}));
I know the function is being called multiple times because the text "Selector was changed" appears more than once in the JS console when I change the select element only once. Before writing this, changing the select element six times in succession caused the function to be called once, then twice, then four times, then eight times, then sixteen times, then thirty-two times.
Why is this?
I fixed the issue. To start, I had an entire page whose elements were bound by functions in $(document).ready(function() {. This became problematic because I was using the select to asynchronously replace many elements in the page with new elements that needed to be bound by those functions (but weren't, since the binding only happens once).
To get around this, I copied all the content in $(document).ready(function() { into a function docReady() and then called docReady() both inside $(document).ready(function() { and whenever I asynchronously reloaded the content of the page. This strategy caused my error; now I was binding every element of the page, including the select itself!
Now, I've called the binding functions for the select only once in $(document).ready(function() { and I call the binding functions for the asynchronously generated elements once every time select changes its value.
You can try like this:
$(document).on("change", "select.class", (function(){
if($(this).data('clicked')) {
return;
}
if ($("select.otherSelect").find(":selected").is( ":disabled" ) == false) {
$.ajax({
//Ajax call
});
console.log("Selector was changed")
}
$(this).data('clicked', true);
}); //removed here was extra )

jquery after ajax complete /done , to call a function, the function will execute more and more times. why?

I've been stuck on this issue for about 2 days. My code (JSFiddle here) is thus:
var foo = function(){
// The code in here will be execute more and more and more times
$(element).hover(function() {
console.log("buggie code run")
})
}
var sliderShow = $(secondElement).bxSlider({
onAfterSlide:function(currentSlideNumber) {
$.ajax("/echo/html/").done(function() {
foo();
})
}
})
My problem is the code will run more than once. For example, when you hover over the element it will fire the function once, but second time it will fire twice. The third time it will fire 3 times, and so on. Why is this happening? Am I making a basic logic error, or is this JavaScript doing something?
This means you are registering the event more than once, probably on each load. You should do so only once!
Hovering itself calls the function twice once on entry and once on exit.. try
var foo = function(){
$(element).hover(function() {console.log("IN")},function() {console.log("OUT")});
}
But then as ThiefMaster pointed out you are also registering the eventhandler multiple times. In you slider, the second time you will add the event handler again and so on and on.
Look at http://docs.jquery.com/Namespaced_Events

Unable to get setTimeout to work in javascript

I am using jquery to slide up an down a div.
For some reason setTimeout is not working (looks like a function scope issue).
Not able to figure out what is wrong with the below code.
(both functions are inside $(document).ready(function(){ } )
$('.slider-thumb').click(function(){
var source = $(this).attr("src");
$('#image_view').css('background-image',"url("+source+")");
$('#image_view').slideDown(1000, calbck);
initiate_timeout();
function calbck(){}
});
function initiate_timeout(){
var time_out = setTimeout(function() {
$('#image_view').slideUp(1000, calbck);
},2000);
}
Indenting the source code shows that you indeed have some scoping issue. The calbck function is private to the click handler function, and is thus not visible to initiate_timeout function. Either make calbck a top-level function, or make initiate_timeout a function local to the click handler function.
$('.slider-thumb').click(function() {
var source = $(this).attr("src");
$('#image_view').css('background-image',"url("+source+")");
$('#image_view').slideDown(1000, calbck);
initiate_timeout();
function calbck(){}
});
function initiate_timeout(){
var time_out = setTimeout(function() {
$('#image_view').slideUp(1000, calbck);
}, 2000);
}
You have some JS errors and scoping issues. Why would you ever have debugging turned off when trying to troubleshoot an error? Change your code to this:
$('.slider-thumb').click(function(){
var source = $(this).attr("src");
$('#image_view').css('background-image',"url("+source+")");
$('#image_view').slideDown(1000);
setTimeout(function() {
$('#image_view').slideUp(1000);
},2000); // will start 2 seconds after slideDown starts (which is 1 second after it completes)
});
or even better, use the completion function of the first animation to set the timer:
$('.slider-thumb').click(function(){
var source = $(this).attr("src");
$('#image_view').css('background-image',"url("+source+")");
$('#image_view').slideDown(1000, setTimeout(function() {
$('#image_view').slideUp(1000);
},1000)); // will stay open for 1 second before sliding up again
});
Or, even better, using jQuery's delay/queuing, you can do this:
$('.slider-thumb').click(function(){
var source = $(this).attr("src");
$('#image_view').css('background-image',"url("+source+")");
$('#image_view').slideDown(1000).delay(1000).slideUp(1000); // delay 1 sec between effects
});
The calbck you were trying to pass to slideUp was not defined in the scope you were using it (inside of initiate_timout()). It was private to your click handler.
jQuery probably has better ways to chain effects than using your own timer, but I see no reason why this code shouldn't work if it matches your HTML.
Note: if your background image wasn't already pre-cached, it may not be loaded right away when your slideDown starts.
Are you getting any errors? You're passing an undefined value as calbck to slideUp in the setTimeout function.
It works for me (with my modified organization): http://jsfiddle.net/v3cjG/1/
And when I run your exact code ( http://jsfiddle.net/v3cjG/2/ ) I get an error for "Can't find variable calbck"--the var I said you were passing without defining.

Categories