Disable submit button until Ajax Completes - ajax

I'm trying to disable a submit button until an ajax function is completed.
Right now, I have only been able to figure out how to disable the button for a specified time when the user is typing.
How can I disable the submit button until the ajax data loads? Thank you.
<script>
$('#comment_comment').keyup(function() {
$("#new_comment_button").attr("disabled", true);
setTimeout(function() { $("#new_comment_button").removeAttr("disabled"); }, 2000);
});
$('#comment_comment').preview({ key:'my key',
selector : {type:'rich'},
preview : {
submit : function(e, data){
$.ajax({
dataType: 'script',
url: this.form.attr('action'),
type: 'POST',
data: data
});
},
},
autoplay : 0,
maxwidth : 350,
display : {display : 'rich'}
});
</script>

Disable the button when starts the AJAX with simple JS and enable it when the AJAX request finishes.
It would be something like this
$.ajax({...
success: function(){
submitButton.enable(); // Pseudo-code
},
...
});
You can do several things with the AJAX request. See this post for more information
EDIT: If you want to prevent the double submit request, there is a way to do it but I can't remember :/ and I didn't found it on google.
This is a way to do it, but I don't like it

Related

Selectors not working on ajax response

I'm using ajax to submit pages and return content blocks based on user action for an onboarding sequence.
If have a page which loads and get 1 content element, the user then clicks Yes or No, which loads the next content element into the same space (via ajax).
For some reason my selectors don't seem to be working on that ajax loaded html.
Here is my ajax function which gets the form:
$.ajax({
beforeSend: function() {
$("#loader").toggleClass('progress');
},
type: 'POST',
dataType: 'json',
data: data,
url: baseUrl+'welcome/user_confirmation_form',
complete: function( response ) {
$("#loader").toggleClass('progress');
},
success: function( response ) {
console.log(response);
$("div.welcome-page > .col").html(response.response);
},
error: function( response ) {
$("#next-steps").html(response.response);
}
});
I'm then trying to access the submit button (have tried doing it as a ahref and button type=submit but nothing seems to be selecting the event.
$('div.welcome-page').on('submit', "user_complete", function(e) {
e.preventDefault();
console.log('FOund form');
var user = $(this).serializeArray();
console.log(user);
});
If I view source, the ajax returned HTML is not even in the dom, but it is when viewing the UI normally.
I'm guessing this has something to do with it?
How can I select all the form data?
Any time I click on the button or ahref it just fires the same page again.
If user_complete is a class you are assigning on your submit button in your loaded html, then you are missing a .
$('div.welcome-page').on('submit', ".user_complete", function(e) {
But this will only work if you're using a submit action as this is listening for a submit event. Maybe you want to listen for a click event?
You need to bind the events to your handlers for your newly added HTML elements. Your original call to
$('div.welcome-page').on('submit' ...
Only bound the event handler for the elements that were on the page at that point in time.
You can put your handler into a function ...
var myHandler = function(e) {
e.preventDefault();
var user = $(this).serializeArray();
}
And then after you load the new HTML you need to bind the handler to the event. So, on success with the AJAX you would ...
success: function( response ) {
$("div.welcome-page > .col").html(response.response);
$('div.welcome-page').on('submit', "user_complete", myHandler);
},

AJAX loading image barely visible

I have a simple issue. I am posting data from a form to my DB using an AJAX request. I have coded in a loading GIF using the beforeSend and complete commands in my AJAX request.
<script>
$(function(){
//email the link
$("##emailTicket#get_active_tickets.ticket_id#").submit(function(){
// prevent native form submission here
$.ajax({
type: "POST",
data: $('##emailTicket#get_active_tickets.ticket_id#').serialize(),
url: "actionpages/email_dashboard_ticket.cfm",
beforeSend: function(){
$('.loader').show()
},
complete: function(){
$('.loader').hide();
},
success: function() {
$("##emailTicketResponse#get_active_tickets.ticket_id#").html("");
$("##emailTicketResponse#get_active_tickets.ticket_id#").append( "Ticket successfully sent." );
}
});
return false;
});
});
</script>
Everything seems to be working correctly however the loading GIF only flashes for a split second because the request doesn't take long at all to complete. Sometimes you can't even see it and users are confused if clicking the submit button actually did anything.
Is there a way to delay the 'complete' part of the function so that the animated GIF appears on the screen longer?
complete: function(){
$('.loader').hide();
},
I was able to achieve this by modifying my complete code in my function and adding a delay in milleseconds:
complete: function(){
$('.loader').hide(3000);
},

replacement for async:false in $.ajax

I have a form that submits data to the database and then gets submitted to google docs.
I am using jquery ajax to achieve this.
javascript:
var name ="a";
var company = "b";
var phone = "1";
...
$.ajax({
async: false,
url: "view/templates/includes/abc.php",
//type: 'POST',
//timeout: 10000,
data: {
"name": name,
"company": company,
"phone": phone,
"email": email,
"comments": comments
},
success: function(data) {
//called when successful
alert(data);
//alert('success');
$('#php-code').html(data);
},
error: function(e) {
// alert(e.message);
//called when there is an error
//console.log(e.message);
}
});
return true;
}
abc.php is where lies my code to insert data into the DB.
Now the issue is I don't wanna use async:false since I read it should never be used because it may cause browser hangs and it destroys the purpose of using ajax. However, if I dont use async:false the form gets submitted before my ajax response comes and so it always goes to the error function.
What could I do to not to use async:false?
You may calling ajax function on submit.
You may want to stop submitting form at your event(click of button may be).
And in the ajax success method, explicitly submit the form.
(can be done using jQuery - $('#id_of_form').submit())
EX. can follow the steps,
$('#id_button_submit').click(function(event){
// this will prevent form to be submitted
event.preventDefault();
// call the function of ajax
serviceCall();
});
In the success method of ajax
success: function(data) {
$('#id_of_form').submit();
// rest of your code
},
Or A jQuery plugin http://malsup.com/jquery/form/#ajaxSubmit may be useful to you

Load Ajax Content to Hidden Tab - Instead of Current Tab

I have a dashboard UI that utilizes a jQuery tabs script. Each tab loads its content via separate Ajax requests.
Here's the issue I'm having:
A user will open multiple tabs, one right after the other
Each tab is created and an Ajax request is made for each
The last tab to be created is currently open and each tab's content is displayed on this tab once the requests are complete
Once a user clicks on any tab, the content is set as it should be.
Basically, if the user opens a new tab ahead of a recent tab's Ajax request completing, both Ajax requested contents display on the current open tab until the user clicks on any tab and then everything is displayed as it should be.
I've tried setting the Ajax calls to async: false which solves the issue as it forces the ajax requests to complete and load on the current tab before allowing the user to open another tab, however the user feedback has been negative in that users think that the dashboard froze (which it has).
I've also set a timeout function to load the tab with a loading .gif and then make the async: false Ajax request. The user feedback as been the same, even with the timeout function as the loading gif stops it's animation once the Ajax request is made.
The Ajax requests looks like this:
$.ajax ({
url: report,
cache: false,
success: function(html) {
$("#loading").hide();
$("#tabcontent").append('<div id="c'+count+'" class="tabContentContainer">'+html+'</div>');
},
error: function(x, status, error) {
$.ajax ({
url: 'admin/error_notification.php',
type: "POST",
data:{
error: error
}
});
},
async:true
});
Keep track of the last request in some way and abort it when creating another request:
var jqxhr = {abort: function () {}};
/* various other code */
function loadTabOrWhatever() {
jqxhr.abort();
jqxhr = $.ajax({
/* ajax call in your question */
I would suggest having a separate tabcontent div that is paired with each tab (not just one #tabcontent div), and show/hide those when switching tabs. Then if a previous ajax call comes back later, and populates a tabcontent div that is now hidden, there's no harm done.
function loadTab(tabName) {
// Hide all tab content panes, then just show the one we want
$(".tab-pane").hide();
$("#tab-" + tabName).show();
$.ajax ({
...
success: function(html) {
$("#loading").hide();
$("#tab-" + tabName).append('<div id="c'+count+'" class="tabContentContainer">'+html+'</div>');
<snip>
Create your content panes like:
<div class="tab-pane" id="tab-firsttab"></div>
And trigger links would be something along the lines of:
First Tab
I believe it would make it harmless then for users to quickly click on multiple tabs, firing off multiple ajax calls, since each ajax call will only load the content into it's own content pane.
I figured out that if I create the tabContentContainer div prior to the Ajax request, then the tab selector has a object to then hide when another tab opens. Then, once the Ajax response is loaded, the visibility of it has already been set. See below:
$("#tabcontent").append('<div id="c'+count+'" class="tabContentContainer"></div>');
$.ajax ({
url: report,
cache: false,
success: function(html) {
$("#loading").hide();
$("#c"+count+"").html(''+html+'');
},
error: function(x, status, error) {
$("#tabcontent").append('<div id="c'+count+'" class="tabContentContainer"><div class="alert alert-error" style="margin-top:70px;"><button type="button" class="close" data-dismiss="alert">×</button><strong>Don\'t worry… It\'s not you, it\'s us.</strong> We were unable to connect to your data and deliver results. We are looking into this now.</div></div>');
$.ajax ({
url: 'admin/error_notification.php',
type: "POST",
data:{
error: error
}
});
},
async:true
});
I have such a setup. You call the function below indicating what tab you're loading into. I make sure each new tab has a unique ID (UUID) and that the function gets that ID to load the page.
There is a snag, however - I have found that if the sub pages loaded contain javascript code, that needs to initialize objects internally to the page,
they may be confused by the fact that the page is 'hidden'. Sometimes when
I get back to the tab with such elements, I would find they have a 'small' size.
This function also store the data submitted to the backend, so that you easily can create a 'reload' button.
function LoadView(ident, view, data) {
var img = $('<img>', {
src : '/images/ajax-loading.gif'
});
$('#' + ident).html(img);
data.view = view;
data.viewid = ident;
// console.log(data);
$.ajax({
url : '/cgi-bin/browser.cgi',
data : data,
type : 'GET',
dataType : 'html',
timeout : 30000000,
success : function(result) {
$("#" + ident).html(result);
// set data on view
$("#" + ident).data('data', data);
},
error : function(xhr, status, error) {
var img = $('<img>', {
src : '/images/exclamation_micro.png'
});
$('#' + ident).html(img.html() + error);
// alert("Error processing request " + error);
},
timeout : function() {
var img = $('<img>', {
src : '/images/exclamation_micro.png'
});
$('#' + ident).html(img.html() + ' Timeout');
// alert("Timeout processing request");
}
});
}
function ReloadView(view, ident) {
// Retrieve the data for the view
var data = $('#' + ident).data('data');
// Reload the view
LoadView(ident, data.view, data);
}

AJAX avoid repeated code

I'm using Symfony2.1 with Doctrine2.1
I'd like to use AJAX for many features on my site , editing a title , rate an article , create an entity on the fly , etc.
My question is simple :
Do I need to create a JQuery function for each functionnality , like this :
$('#specific-functionality').bind('click', function(e){
var element = $(this);
e.preventDefault();
// the call
$.ajax({
url: element.attr('href'),
cache: false,
dataType: 'json',
success: function(data){
// some custom stuff : remove a loader , show some value, change some css
}
});
});
It sounds very heavy to me, so I was wondering if there's any framework on JS side, or a specific method I can use to avoid this. I was thinking about regrouping items by type of response (html_content , boolean, integer) but maybe something already exists to handle it nicely !
From what I understand, you are asking for lighter version of JQuery ajax method. There are direct get/post methods instead of using ajax.
$.get(element.attr('href'), {'id': '123'},
function(data) {
alert(data);
}
);
To configure error function
$.get(element.attr('href'), {'id': '123'}, function(data) {alert(data);})
.error(function (XMLHttpRequest, textStatus, errorThrown) {
var msg = jQuery.parseJSON(XMLHttpRequest.responseText);
alert(msg.Message);
});
Also, you can pass callback function to do any synchronous operations like
function LoadData(cb)
{
$.get(element.attr('href'), { 'test': test }, cb);
}
And call
LoadData(function(data) {
alert(data);
otherstatements;
});
For progress bar, you use JQuery ajaxStart and ajaxStop functions instead of manually hiding and showing it. Note, it gets fired for every JQuery AJAX operation on the page.
$('#progress')
.ajaxStart(function () {
//disable the submit button
$(this).show();
})
.ajaxStop(function () {
//enable the button
$(this).hide();
});
Instead of $('#specific-functionality').bind('click', function(e){, try this:
$(".ajax").click(function(){
var url = $(this).attr("href") ;
var target = $(this).attr("data-target") ;
if (target=="undefined"){
alert("You forgot the target");
return false ;
}
$.ajax(....
And in html
<a class="ajax" href="..." data-target="#some_id">click here </a>
I think it is the simplest solution. If you want some link to work via ajax, just give it class "ajax" and put data-target to where it should output results. All custom stuff could be placed in these data-something properties.

Resources