I use jquery-ujs for ajax requests (data-remote="true"). My problem is, that the first request is okay, and while the second is running, it breaks. Whenever I call in the events $('#modal').empty() or $('#modal').text('') or $('#modal').html(''), no more events are going to be called.
To be clear, here's the code:
$(document).on('ajax:beforeSend', function () {
console.log('beforeSend');
$('#modal').empty().modal('show');
});
$(document).on('ajax:send', function () {
console.log('send');
});
$(document).on('ajax:success', function (e, xhr) {
console.log('success');
$('#modal').html(xhr).drags({ handle: '.modal-header' }).modal('show');
if (typeof doWork === 'function') {
doWork();
}
});
$(document).on('ajax:complete', function () {
console.log('complete');
});
And the console output:
beforeSend
send
success
complete
beforeSend
If I move $('#modal').empty().modal('show'); to the send event, then it is going to be called, but the success method is never called anymore (neither error neither complete, nothing more).
This problem annoys me for more hours now... Thank you for your help.
How about to move empty() to the ajax:complete?
In this case, when your modal closes, it opens empty for the next use and is ready for reuse.
I suggest that you put this command in the last step so that it does not cause any problems. Like the following:
$(document).on('ajax:complete', function () { console.log('complete'); . . . . $('#modal').empty(); });
I believe that this is not the best solution and there are definitely other solutions. But I hope this solution will solve your problem.
$('#modal').on('hidden.bs.modal', function () {
$(this).empty()
})
My workaround was to avoid using jquery-ujs events and using global ajax events, so my final working code is:
$(document).ajaxSend(function () {
$('#modal').empty().modal('show');
});
$(document).ajaxSuccess(function (e, xhr) {
$('#modal').html(xhr.responseText).drags({ handle: '.modal-header' }).modal('show');
if (typeof doWork === 'function') {
doWork();
}
});
Related
I have this code for make a Ajax call:
$.post($form.attr('action'), $form.serialize(), 'json').done(function (data, textStatus, jqXHR) {
// Some logic here for done callback
// Redirect to another URL after 5 seconds
window.setTimeout(function () {
window.location = data.redirect_to;
}, 5000);
}).fail(function () {
// Some logic here for fail callback
})
That code works fine. Now I need to attach a "loader" to this Ajax call. I knew that I can attach this to $(document) as of jQuery 1.8+ docs expose (also found the same on this topic) so I have done the following:
$(function () {
// a bunch of logic here
}).ajaxStart(function () {
$('#loaderModal').modal('show');
$('#loaderModal').on('show.bs.modal', function (e) {
$('#loaderDiv').loader();
})
}).ajaxStop(function () {
$('#loaderModal').modal('hide');
$('#loaderModal').on('hidden.bs.modal', function (e) {
$('#loaderDiv').loader('destroy');
})
});
And once again that works but happens that I have other Ajax calls on the page (for validation purposes on some fields) and every time any of them run then the loader is show which is not correct since I need to attach only to the code shown above (the first piece of code). How I can accomplish this?
As a second part, an related to this post, some of the logic on done and fail callback trigger a Bootstrap Growl message and as you must have noticed I'm using the Twitter Bootstrap Modal component in which the loader is contained, so I'm fear that the call made to run the loader block in some way the second call when the callback for done is invoked, is that even possible? how fast is the execution of these events?
PS: If any of yours have a better solution to this then say and thanks in advance
Instead of using the global event handlers, show/hide the loader for the current ajax request like
//show the loader before the request
showLoader();
$.post($form.attr('action'), $form.serialize(), 'json').done(function (data, textStatus, jqXHR) {
// Some logic here for done callback
// Redirect to another URL after 5 seconds
window.setTimeout(function () {
window.location = data.redirect_to;
}, 5000);
}).fail(function () {
// Some logic here for fail callback
}).always(hideLoader) //hide the loader after the ajax request
function showLoader() {
$('#loaderModal').modal('show');
$('#loaderModal').on('show.bs.modal', function (e) {
$('#loaderDiv').loader();
})
}
function hideLoader() {
$('#loaderModal').modal('hide');
$('#loaderModal').on('hidden.bs.modal', function (e) {
$('#loaderDiv').loader('destroy');
})
}
Why not put your loading scripts into a function so you can call them at will? That way they fit into the logic of your code instead of running every time.
function startLoad() {
.ajaxStart(function () {
$('#loaderModal').modal('show');
$('#loaderModal').on('show.bs.modal', function (e) {
$('#loaderDiv').loader();
})
})
}
function stopLoad() {
.ajaxStop(function () {
$('#loaderModal').modal('hide');
$('#loaderModal').on('hidden.bs.modal', function (e) {
$('#loaderDiv').loader('destroy');
})
});
}
In my angular code, I load some data in ajax which fill my template, so far so good...
Then, once the data are loaded, I want to call a javascript function.
I couldn't find a way to have callback once the template is rendered. I have try several events but none are working.
My solution is to call the javascript method after a timeout:
$http.post('url').success(function (data) {
$timeout(function () {/* process data */ }, 200);
});
It seems to work, but that's a timeout, nothing guarantee me that at the end of the timeout everything is rendered. Maybe it is working only because my PC is fast...
Is there an event based solution? Or any solution better than this one...
The jsfiddle of my solution : http://jsfiddle.net/ZCT4K/5/
You need to $watch() your data. So you could try the following:
$http.post('url')
.success(function (data) {
$scope.postData = data;
});
//Watch the value of postData
$scope.$watch('postData', function () {
if ($scope.postData === undefined || $scope.postData === null || $scope.postData === "") {
return;
}
/*Else process your data*/
});
I tried to create a simple solution for ordering problem in async calls on a project I'm working on.
The best solution I found was this:
I attach an event that check if the pre-requirements are done, if so I remove the event listener and perform the function.
Each function calls the event once its done and that way everyone will be waiting until the can run.
This is the code:
$(function() {
$(document).on('bmadone',function() {
if(beepmeapp.done_arr['fb-init']){
$(document).off('bmadone','#bma-root',this);
getBMAUserRoutes();
}
});
});
The function (for the test) is doing this:
function getBMAUserRoutes(){
$.ajax({
url : '/bma/users/fb',
type : 'GET',
data : {
access_token: 'abc'
},
success : function( data ) {
console.log('getBMAUser: success');
beepmeapp.done_arr['user-init'] = true;
$('#bma-root').trigger('bmadone');
},
error : function( xhr, err ) {
console.log('getBMAUser: error');
}
});
}
It works great but the problem I have is that it gets into a loop that never ends.
Don't know why but it looks like:
$(document).off('bmadone','#bma-root',this);
Doesn't remove the listener...
I'm a true newbie in JS / Jquery and all of this client side development so I guess I'm probably missing something basic.
You have to pass the same (sub)set of parameters to .off that you passed to .on. I.e. in your case it would be $(document).off('bmadone').
You never passed '#bma-root' to .on and this does not refer to the event handler (the function you pass to .on), so by passing those you won't remove the correct event handler.
If you need to remove only that specific handler, you can use a named function instead:
function handler() {
if(beepmeapp.done_arr['fb-init']){
$(document).off('bmadone', handler);
getBMAUserRoutes();
}
}
$(document).on('bmadone', handler);
// or as a named function expression
$(document).on('bmadone', function handler() {
if(beepmeapp.done_arr['fb-init']){
$(document).off('bmadone', handler);
getBMAUserRoutes();
}
});
or use namespaced events.
I seem to have problem with jQuery bind() and unbind() functions. They seem to not get executed at all. Here's the code I have so far:
$(function() {
var init = function() {
$.get('test.php', function(j) {
if(j.r && j.r == 'error') {
console.log("1");
$('#far').bind('click', function() {
console.log("2"); return false;
});
} else {
//getData();
}
})
}();
var getData = function() {
$('#far').unbind('click', false);
};
$('#far').click(function() { ... });
});
Console only shows me 1 and no errors. I have no idea what I'm doing wrong since there are no errors and jQuery docs and StackOverflow has given me the same answer. I'm using jQuery 1.4.4
What am I doing wrong?
By calling your getData() function at the end of the $.get() function you are unbinding the event as soon as you bind it. Try commenting out the getData() call in the $.get() function and see if that helps.
As I see you're binding event before it's created, so use live instead.
I have a big problem writing a small piece of code using JS/jQuery (don't know which of these is causing the problem). Anyhow, here we go:
$('#themePicker').unbind().click(function() {
var t = $(this);
modalwindow2(t, function() {
console.log(1);
}, function(w) {
console.log(w);
});
return false;
});
and the function itself:
function modalwindow2(w, callbackOnSHow, callbackOnHide) {
if (typeof(callbackOnSHow) == 'function') {
callbackOnSHow.call();
}
// do some stuff //
$('form').submit(function() {
ajaxSubmit(function(data) {
if (typeof(callbackOnHide) == 'function') {
console.log('---------------');
console.log(data);
console.log('---------------');
callbackOnHide.call(data);
}
});
return false
});
}
The function is called modalwindow2 and I want to call a function when the modal is shown and another function when the modal will be hidden.
The first is not a problem.
The second… Well… Let's just say it's a problem. Why?
I want a parameter sent to the second function. The paramenter is an ajax response, similar to other jQuery stuff (ajax action, sortable, etc).
I hope I made myself clear enough.
Thanks!
Edit:
I'm using jQuery 1.1.2 (or 1.1.3) and upgrading or using jQuery UI is NOT a solution. I have some dependencies (interface is one of them) and i don't have enough time (nor motivation) to upgrade to 1.3 & UI 1.7.
I noticed that you have a typo on .submit:
$('form').submti(function(){
Was that just an entry error to SO?
EDIT:
Ok, so after looking at your code and doing a short test, I've come up with this (pardon the pun):
function modalwindow2(w, callbackOnShow, callbackOnHide) {
if(typeof callbackOnShow == 'function') {
callbackOnShow.call();
}
$('form').submit(function() {
if(typeof callbackOnHide == 'function') {
callbackOnHide.call(this, "second");
}
});
}
$(document).ready(function (){
$('#themePicker').click(function(){
var t=$(this);
modalwindow2(t, function() { alert("first"); }, function(x) { alert(x); });
return false;
});
});
It looks like you may have just been missing the "this" in your call() statement. Try using callbackOnHide.call(this, data);
Let me know if that works any better!
I understand what you are trying to do, but you will need to store the newly created window so that you can access it on the close callback function.
You might want to look at jQuery UI Dialog. It provides some really basic functionality for dialog windows (modal and otherwise) and handles some of the callback implementation.