Fancybox not closing after ajax call - javascript

I'm having trouble closing my fancy box in some cases after an ajax call.
$(document).ajaxStop(function() {
function(){$.fancybox.close()};
});
$(document).ajaxStart(function() {
$("a#load_gif").trigger('click');
});
Here's my code handling the fancy box. So my problem is that if the ajax call is very brief and fast the box doesn't close, however if the call is longer it closes automatically as it should.
I have found a fix which goes along the line of this
$(document).ajaxStop(function() {
setTimeout(function(){$.fancybox.close()},500);
});
But honestly that solution is not good looking. What can I do to make the fancy box close even if the ajax call is returned very fast? The length of the ajax call is variable depending on the number of rows it has to fetch.
Any help and/or suggestions are appreciated.

It seems like you have a race condition and maybe the fancybox isn't finished being created and doesn't have it's close function defined yet when your AJAX call is attempting to fire off that close function.
I recommend a 2 step process that triggers the fancybox to close. Create 2 global variables ajaxStop = false; and fancyboxDone = false;
create a function like:
function closeFancyBox(){
if(ajaxStop && fancyboxDone){
$.fancybox.close();
ajaxStop = fancyboxDone = false;
}
}
Then change your ajax stop to :
$(document).ajaxStop(function() {
function(){
ajaxStop = true;
closeFancyBox()
};
});
And finally add an onComplete function to your fancybox that does the same as the ajax Stop but sets fancyboxDone = true instead of ajaxStop.
So now no matter which one finishes first and second they will be able to check on each other's status and fire the close appropriately.

Related

Bootstrap 3 modal doesnt always activate ajax code

I'm sure there is a simple answer to this I just don't seem to be able to resolve it.
I am using the bootstrap modal to return ajax content from specified url. (using $.removeData() between loads to remove content).
The problem comes with running JS on content from the form presented in the modal.
I am currently using (simplified) from within the final file (returned by ajax):
$('#myModalLg').on('shown.bs.modal', function(e) {
$(this).on('submit', 'form', function(ev) {
... event handler for form...
});
});
EDIT: along with other event handlers (datepicker for within modal included) but this code is only loaded once and then fails to activate again until the full page is reloaded
On close code:
$('#myModal, #myModalLg').on('hidden.bs.modal', function (e) {
$(e.target).removeData();
$(e.target).off('shown.bs.modal');
$('#myModal, #myModalLg').on('shown.bs.modal', function () {
$(this).find(':input:first')[0].focus();
});
});
I would be expecting the handlers to run each time #myModalLg is shown and then when it is closed it removed what has been entered and restores each time but doesn't seem to work like that.
you never turn off your shown.bs.modal have you looked into the One Event In JQuery:
I'm not sure if this will help but it seems like your redeclaring your shown.bs.modal multiple times you might want to change that to a one instead of on
$('#myModal, #myModalLg').one('shown.bs.modal', function () {
$(this).find(':input:first')[0].focus();
});

mockjax loader - stop from running for specific function

I am making use of Jonathan Sampson's answer for my jquery busy loader. it works 100% and detects any jquery posting or the like and shows the loader.
my problem is that most times I want the user to wait when I fetch info from the database so happy for the loader to appear.
What I want however, is for certain functions only for the loader not to show when I save info to the database.
the fiddle can be found here
for example, the below causes the loader to run. how can I modify this so mockjax knows not to run for this function only?
$(document).on("click", function(){
$.get("/mockjax");
});
Thanks for the help as always.
Short version (with code)
Click the heading - Animation
Click the paragraph - No Animation
http://jsfiddle.net/hPS2v/
$.ajax({
url: "/mockjax",
type: "GET",
global: false //This is the key
});
--
The slightly longer version
There is a great variable available in the $.ajax() method which let's you stop ajax events from firing (but not the ajax itself). This is called global. From the docs
global (default: true)
Type: Boolean
Whether to trigger global Ajax
event handlers for this request. The default is true. Set to false to
prevent the global handlers like ajaxStart or ajaxStop from being
triggered. This can be used to control various Ajax Events.
With this in mind, I have slightly changed your code a little to demonstrate how we can make this work.
1) Moved the AJAX call into a function with 2 parameters: URL and eventTrigger. Basically we want the URL to be "/mockajax", and the eventTrigger to be true or false (depending on if and when you want to show your animation)
2) I took the event handler off the $(document) and added 2 events to the heading tags and the p tags so I can demonstrate the AJAX working in 2 places with the same code (1 with and 1 without an animation)
Hope this helps!
You can use a variable as a flag which denotes your preference of not showing the loader.
//let say, showLoader, by default true
var showLoader = true;
Now, add this to your ajax setup as required.
$(document).on({
ajaxStart: function () {
// if showLoader true, then shows loading image
if (showLoader)
$body.addClass("loading");
},
ajaxStop: function () {
$body.removeClass("loading");
// set showLoader to true
showLoader = true;
}
});
Change showLoader state as required by you.
$(document).on("click", function (e) {
// if target element is anchor tag, then do not show loading image - example
if (e.target.tagName === 'A') {
showLoader = false;
}
$.get("/mockjax");
});
JSFiddle: http://jsfiddle.net/VpDUG/5177/
Hope, it helps.

Delegate and AddClass not working

I am having a problem with getting this piece of code to work. Its built to allow for a user to click on one row to "select" it by highlighting via a different class. If another row is clicked, that one is highlighted and the current one is cleared. If one that is already highlighted is clicked again, it will be cleared back to normal.
This is within an ajax call to refresh the page, so everytime the call finishes and inserts the html for the table, this function below is then called. For some reason, every other reload of the table, this works. Ive tracked down the the line that is not functioning to be $(this).addClass(selectedUserClass) at the end of the function. The debug console log I put in there works, with the right class, but the next section does not add the class for some reason.
In firebug, the line changes from .. to , but it doesn't change? I've been looking at this for hours and I can't figure it out. Thanks for any help!
function loadUserListener(style) {
if (style == "normal") {
selectedUserClass = 'selectedUser';
selectedJQueryClass = '.selectedUser';
} else {
selectedUserClass = 'selectedUserInverted';
selectedJQueryClass = '.selectedUserInverted';
}
console.log('setting');
$("#selectuser").delegate("tr", "click", function () {
if ($(this).hasClass(selectedUserClass)) {
$(selectedJQueryClass).removeClass(selectedUserClass);
} else if ($(selectedJQueryClass)[0]) {
console.log('another');
$(selectedJQueryClass).removeClass(selectedUserClass);
$(this).addClass(selectedUserClass);
} else {
console.log(selectedUserClass);
$(this).addClass(selectedUserClass);
}
});
}
adeneo pointed out some things for me, mainly that the listener is still there even though the table is refreshed, so after every ajax call, a listener is being put on another which results in the functionality that only works on 'even' calls.
I used the 'off' function from jquery to clear the event handler every time this listener loading function is called. I also switched delegate to on to be more correct.
I essentially did this:
$('.selectuser').off("click");

Jquery bind()/live() within a function

I wrote a little pager which removes and rewrites content. I have a function called after loading the page, it shall be executed after changing the page as well. Because I do not wat to implement the function twice (on initialisation and after changing the page) I tried bind()/live() and a simple function.
The function looks like this:
jQuery('.blogentry').each(function (){
jQuery(this).click(function(){
//Clicking on the element opens a layer, definitely works - I tested it
});
});
It is executed after initialisation, for executing it after page changes as well I tried the following:
jQuery('.nextPage, .prevPage').click(function changePage(){
// Changing page and rewriting content
showEntry();
});
//...
showEntry();
//...
function showEntry(){
jQuery('.blogentry').each(function (){
jQuery(this).click(function(){
//Clicking on the element opens a layer, definitely works - I tested it
});
});
}
But the function is not executed if put inside a function (lol) and called via showEntry();
Afterwards I tried to bind the function...
jQuery('.nextPage, .prevPage').click(function changePage(){
// Changing page and rewriting content
jQuery('.blogentry').bind("click", showEntry);
});
//...
jQuery(this).click(function showEntry(){
//Clicking on the element opens a layer, definitely works - I tested it
});
Did not work either. Code after the bind()-line would not execute as well.
I thought maybe it's a problem to bind to an event function, if an event is already given via the parameter so i also tried this:
jQuery('.nextPage, .prevPage').click(function changePage(){
// Changing page and rewriting content
jQuery('.blogentry').bind("click", showEntry);
});
//...
function showEntry(){
//Clicking on the element opens a layer, definitely works - I tested it
});
}
No success at all. Maybe I cannot call the function from inside the function regarding to the bind()? Maybe I just do not understand the bind()-function at all? I also tried the live() function since it seemed to fit better, as I am rewriting the content all the time. But it had the same effect: none...
The simplest way to implement this should be
jQuery('.blogentry').live('click', function() { /* onclick handler */ });
This should bind the function to every blogentry on the page at the moment of the call and all the blogentries that are added to the page later on.
Additional notes:
In $(foo).each(function() { $(this).click(fun); }); the each is unnecessary - $(foo).click(fun); is enough.
$(foo).bind('click', fun); is functionally equivalent to $(foo).click(fun) - it does not matter which one you use.
You can use delegate or bind. don't call the function like that, just create a delegate with .blogentry and it should update even after you load a new page via ajax. It will automatically do this.
$("#blogcontainer").delegate(".blogentry", "click", function(){ //open layer });
This should work for you
$(body).delegate(".blogentry", "click", function(){
showEntry();
});
alternaltivly you can use event delegation
$(document).ready(function () {
$('#blogcontainer').click( function(e) {
if ( $(e.target).is('.blogentry') ) {
// do your stuff
}
});
});
hence, no need to bind each blogentry at creation or reload, and it's (slightly) faster.

jquery ajax call and hide function

I have the following script that works ok on the first page load. I am then calling a page again and the hide function does not work, and certain formatting is lost..
Any ideas. Is there a way using jquery live or delegate for instance.
$(document).ready( function() {
// Hide all subfolders at startup
$(".php-file-tree").find("UL").hide();
// Expand/collapse on click
$(".pft-directory A").click( function() {
$(this).parent().find("UL:first").slideToggle("medium");
if( $(this).parent().attr('className') == "pft-directory" ) return false;
});
});
How do I execute find("UL").hide(); again on ajax call.
In the ajax success handler just execute the below line
$(".php-file-tree").find("UL").hide();

Categories