$.post() doesn't have time to run? - javascript

I'm trying to send data from a form to an external script prior to submitting the form, yet I cannot seem to get the data to reach the external script unless I return false; on the form itself.
$(document).ready(function () {
// Handle Form-Submission
$("#mainForm").submit(function () {
// Reset Error Array
errors = new Array();
/* Validation Code Removed - Not Relevant */
// Check if errors exist
if (errors.length > 0) {
return false;
} else {
$("div.errors").html("");
$.post("post.php",{
"First Name": name_first.val(),
"Last Name": name_last.val(),
"Home State": home_state.val(),
"Primary Email": email_primary.val()
});
}
return false; /* Remove this line, and the $.post won't work. */
});
});

I ran into the exact same problem today. Like Marc says, it's because the ajax call is asynchronous. The simplest fix is to make it synchronous.
Use .ajaxSetup() before any ajax calls like such:
$.ajaxSetup({async: false});

Sending to two end points
I would try something like this instead of using async: true. Though it is notably more complicated, it would not freeze the interface.:
$(document).ready(function(){
// Handle Form-Submission
$("#mainForm").submit(function(e){
e.preventDefault();
var $form = $(this);
if($form.data('submitting')) return; // Avoid double submissions
$(':submit').attr('disabled','disabled'); // Disable the submit button
// Reset Error Array
errors = new Array();
/* Validation Code Removed - Not Relevant */
// Check if errors exist
if (errors.length > 0) {;
$(':submit').removeAttr('disabled'); // Enable the submit button
return false;
} else {
$("div.errors").html("");
$form.data('submitting',true); // Flag that a submission has started
$.post("post.php",{
"First Name":name_first.val(),
"Last Name":name_last.val(),
"Home State":home_state.val(),
"Primary Email":email_primary.val()},
function(){
// remove our special handler and submit normally
$form.unbind('submit').submit();
}
);
}
});
});
Original Answer
It seems your hangup is that you want to use $.post if JavaScript is enabled, but let the form function normally with JavaScript disabled.
However, since none of your JavaScript will run if it is disabled you don't have to worry about altering behavior in the submit function.
You can just leave your return false; statement, or use
$("#mainForm").submit(function(e){
// all your existing code
e.preventDefault();
}
That will keep the form from submitting normally and will instead using your $.post method when JavaScript is enabled. If it is disabled it will submit normally.
preventDefault is preferred to return false if you want event bubbling to continue as normal, but keep the default browser action from continuing. return false is the equivalent of calling e.preventDefault(); e.stopPropagation();

Related

jQuery form.submit() not always called

I use the following javascript code to do some checks before a form is submitted:
$('form').submit(function(e){
var is_error = false;
// do certain checks and if some of them fail set is_error = true
if(!is_error)
return;
e.preventDefault();
});
This works perfectly and everything is fine actually.
However, I found out that this function is not necessarily always called on a form submit. (I was not able to reproduce this behavior by myself but I saw that on my error logs).
This is what I did to get this information:
I added an hidden input field to the form:
<input id="input-is_used_function" type="hidden" name="is_used_function" value="0" />
And i also adjusted the javascript the following way:
$('form').submit(function(e){
var is_error = false;
// do certain checks and if some of them fail set is_error = true
$('#input-is_used_function').val(1);
if(!is_error)
return;
e.preventDefault();
});
After the submit I logged all transmitted POST vars and I found out that 'is_used_function' is sometimes 0, which means that the jQuery submit function has never been called.
Does somebody has a solution for this or at least a hint on how this behavior happens?
Best,
Freddy

How do I detect an attempted submission of invalid HTML forms?

When using HTML form validation, having an invalid input value in a form will halt submission of that form. How can I detect that the user attempted a failed form submission? The form's onsubmit handler does not fire when submission is halted by validation failure.
I'm currently listening for keypress and click events on the submit button to detect submit attempts. Is there a better way of detecting a failed form submission?
A simple way to get around this is to add an event listener to each input in the form to see when it has been prevented from submitting. The 'invalid' event should do everything you need.
Example
Array.prototype.slice.call(document.querySelectorAll("[required]")).forEach(function(input){
input.addEventListener('invalid',function(e){
//Your input is invalid!
})
});
More info here
http://www.html5rocks.com/en/tutorials/forms/constraintvalidation/
I suggest you to use noValidate property. You can turn off default validation, and run it manually within onsubmit method
var form = document.getElementById("myForm");
form.noValidate = true; // turn off default validation
form.onsubmit = function(e) {
e.preventDefault(); // preventing default behaviour
this.reportValidity(); // run native validation manually
// runs default behaviour (submitting) in case of validation success
if (this.checkValidity()) return form.submit();
alert('invalid'); // your code goes here
}
you can check it here: https://jsfiddle.net/titulus_desiderio/Laon29f3/
Building on #Titulus' code above, here's how I would do it in jQuery; you can adapt this to native events if need be.
$('form-selector').on('submit', function(event) {
// Don't do anything if constraint validation isn't supported by the browser.
if (
!('checkValidity' in this) ||
// In the unlikely case this is a property but not actually a function.
// Hypothetically, a botched polyfill could do this; it pays to be careful
// and build resilient code.
typeof this.checkValidity !== 'function'
) {
return;
}
if (this.checkValidity() === true) {
// Valid values code.
} else {
// Invalid values code.
// Leave this until the last possible moment in the handler in case there's
// an error in any of the handler code to reduce the chances of a broken
// form where the submit does nothing. If an exception is thrown before
// this, the browser shouldn't get this far, (hopefully) allowing the basic
// form to still work.
event.preventDefault();
}
});
// Tell the browser to not validate automatically, as that would prevent submit
// from being triggered. We prevent the submission above if form doesn't pass
// validation. This is here in case there's an error in the preceding code, so
// this (hopefully) doesn't get applied in that case and browser validation
// takes place as a fallback.
this.noValidate = true;

How can I check the value returned by a validation function to pass along the metrics to Google Analytics?

I use a system that captures visitors information via a form. I can't edit the code of the form validation scripts. I am trying to see if I can check upon clicking on the submit button, before the form submit sends the person to the response URL if the validation was passed.
The "submit" calls the function "formSubmit()", if validation is passed myFormIsValid() is returned. If not, then return false to the form.
Like this:
function formSubmit(elt) {
if (!myFormIsValid()) {
return false;
}
I want to know if validation was passed before allowing the form to move forward and do something like setting a variable value so I can tell Google Analytics that the form was successfully submitted. Is there a way to setup a "listener" to the results of the formSubmit function before it is called? I can put the code on the header or footer and I can use jQuery.
You can handle the submit before it reaches it's destination with an event handler.
jQuery.submit()
$(function () {
$("#MyForm").submit(function (e) {
if (!$(this).valid()) {
e.preventDefault(); // prevents the form from submitting.
return;
}
// you can do things here or just let it continue submitting.
});
});

Keep Checking until True

Basically, I have a form that is handled by a CMS which I cannot edit it's javascript, but I more or less want to add in a "Loading" or "Sending" message to my users. For example.
Currently, the default form once submitted, will append a html success message to a div called 'success' once sent, but basically, I want to run a function on the submit button that keeps checking the 'success' for anything other than '' and once it isn't empty, turn off the loading symbol.
Something like this perhaps:
$('#submitBtn').click(function(){
$('#loadingDiv').show();
while (!$('#success').html() == ''){
$('#loadingDiv').hide();
}
});
Any help would be greatly appreciated. I'm just not quite sure how to write it, I'm not great with jquery or javascript
You may do this with setInterval. Something like this:
$('#submitBtn').click(function(){
$('#loadingDiv').show();
var intervalId = setInterval(function() {
if($('#success').html() != '') {
clearInterval(intervalId);
$('#loadingDiv').hide();
}
}, 100);
});
while (!$('#success').html() == '') will freeze all other operations and will last forever.
But still - it is better to double check if you really can't add some code into success callback. Possibly ajaxComplete may help you.
Maybe you could send the form's data manually with something like this?
(In this case, maybe make sure that "submitBtn" is a simple button and not a submit button to prevent the default submit)
$('#submitBtn').click(function(){
$('#loadingDiv').show();
// Send the data with post - To complete
$.post('/your_post_addr', {data_1: my_data_1, ...},
function(data) {
$('#loadingDiv').hide();
}).error(function() {
// Your error message
alert('Error');
});
});

How can I override the OnBeforeUnload dialog and replace it with my own?

I need to warn users about unsaved changes before they leave a page (a pretty common problem).
window.onbeforeunload = handler
This works but it raises a default dialog with an irritating standard message that wraps my own text. I need to either completely replace the standard message, so my text is clear, or (even better) replace the entire dialog with a modal dialog using jQuery.
So far I have failed and I haven't found anyone else who seems to have an answer. Is it even possible?
Javascript in my page:
<script type="text/javascript">
window.onbeforeunload = closeIt;
</script>
The closeIt() function:
function closeIt()
{
if (changes == "true" || files == "true")
{
return "Here you can append a custom message to the default dialog.";
}
}
Using jQuery and jqModal I have tried this kind of thing (using a custom confirm dialog):
$(window).beforeunload(function () {
confirm('new message: ' + this.href + ' !', this.href);
return false;
});
which also doesn't work - I cannot seem to bind to the beforeunload event.
You can't modify the default dialogue for onbeforeunload, so your best bet may be to work with it.
window.onbeforeunload = function() {
return 'You have unsaved changes!';
}
Here's a reference to this from Microsoft:
When a string is assigned to the returnValue property of window.event, a dialog box appears that gives users the option to stay on the current page and retain the string that was assigned to it. The default statement that appears in the dialog box, "Are you sure you want to navigate away from this page? ... Press OK to continue, or Cancel to stay on the current page.", cannot be removed or altered.
The problem seems to be:
When onbeforeunload is called, it will take the return value of the handler as window.event.returnValue.
It will then parse the return value as a string (unless it is null).
Since false is parsed as a string, the dialogue box will fire, which will then pass an appropriate true/false.
The result is, there doesn't seem to be a way of assigning false to onbeforeunload to prevent it from the default dialogue.
Additional notes on jQuery:
Setting the event in jQuery may be problematic, as that allows other onbeforeunload events to occur as well. If you wish only for your unload event to occur I'd stick to plain ol' JavaScript for it.
jQuery doesn't have a shortcut for onbeforeunload so you'd have to use the generic bind syntax.
$(window).bind('beforeunload', function() {} );
Edit 09/04/2018: custom messages in onbeforeunload dialogs are deprecated since chrome-51 (cf: release note)
What worked for me, using jQuery and tested in IE8, Chrome and Firefox, is:
$(window).bind("beforeunload",function(event) {
if(hasChanged) return "You have unsaved changes";
});
It is important not to return anything if no prompt is required as there are differences between IE and other browser behaviours here.
While there isn't anything you can do about the box in some circumstances, you can intercept someone clicking on a link. For me, this was worth the effort for most scenarios and as a fallback, I've left the unload event.
I've used Boxy instead of the standard jQuery Dialog, it is available here: http://onehackoranother.com/projects/jquery/boxy/
$(':input').change(function() {
if(!is_dirty){
// When the user changes a field on this page, set our is_dirty flag.
is_dirty = true;
}
});
$('a').mousedown(function(e) {
if(is_dirty) {
// if the user navigates away from this page via an anchor link,
// popup a new boxy confirmation.
answer = Boxy.confirm("You have made some changes which you might want to save.");
}
});
window.onbeforeunload = function() {
if((is_dirty)&&(!answer)){
// call this if the box wasn't shown.
return 'You have made some changes which you might want to save.';
}
};
You could attach to another event, and filter more on what kind of anchor was clicked, but this works for me and what I want to do and serves as an example for others to use or improve. Thought I would share this for those wanting this solution.
I have cut out code, so this may not work as is.
1) Use onbeforeunload, not onunload.
2) The important thing is to avoid executing a return statement. I don't mean, by this, to avoid returning from your handler. You return all right, but you do it by ensuring that you reach the end of the function and DO NOT execute a return statement. Under these conditions the built-in standard dialog does not occur.
3) You can, if you use onbeforeunload, run an ajax call in your unbeforeunload handler to tidy up on the server, but it must be a synchronous one, and you have to wait for and handle the reply in your onbeforeunload handler (still respecting condition (2) above). I do this and it works fine. If you do a synchronous ajax call, everything is held up until the response comes back. If you do an asynchronous one, thinking that you don't care about the reply from the server, the page unload continues and your ajax call is aborted by this process - including a remote script if it's running.
This can't be done in chrome now to avoid spamming, refer to javascript onbeforeunload not showing custom message for more details.
Angular 9 approach:
constructor() {
window.addEventListener('beforeunload', (event: BeforeUnloadEvent) => {
if (this.generatedBarcodeIndex) {
event.preventDefault(); // for Firefox
event.returnValue = ''; // for Chrome
return '';
}
return false;
});
}
Browsers support and the removal of the custom message:
Chrome removed support for the custom message in ver 51 min
Opera removed support for the custom message in ver 38 min
Firefox removed support for the custom message in ver 44.0 min
Safari removed support for the custom message in ver 9.1 min
Try placing a return; instead of a message.. this is working most browsers for me.
(This only really prevents dialog's presents)
window.onbeforeunload = function(evt) {
//Your Extra Code
return;
}
You can detect which button (ok or cancel) pressed by user, because the onunload function called only when the user choise leaveing the page. Althoug in this funcion the possibilities is limited, because the DOM is being collapsed. You can run javascript, but the ajax POST doesn't do anything therefore you can't use this methode for automatic logout. But there is a solution for that. The window.open('logout.php') executed in the onunload funcion, so the user will logged out with a new window opening.
function onunload = (){
window.open('logout.php');
}
This code called when user leave the page or close the active window and user logged out by 'logout.php'.
The new window close immediately when logout php consist of code:
window.close();
I faced the same problem, I was ok to get its own dialog box with my message, but the problem I faced was :
1) It was giving message on all navigations I want it only for close click.
2) with my own confirmation message if user selects cancel it still shows the browser's default dialog box.
Following is the solutions code I found, which I wrote on my Master page.
function closeMe(evt) {
if (typeof evt == 'undefined') {
evt = window.event; }
if (evt && evt.clientX >= (window.event.screenX - 150) &&
evt.clientY >= -150 && evt.clientY <= 0) {
return "Do you want to log out of your current session?";
}
}
window.onbeforeunload = closeMe;
<script type="text/javascript">
window.onbeforeunload = function(evt) {
var message = 'Are you sure you want to leave?';
if (typeof evt == 'undefined') {
evt = window.event;
}
if (evt) {
evt.returnValue = message;
}
return message;
}
</script>
refer from http://www.codeprojectdownload.com
What about to use the specialized version of the "bind" command "one". Once the event handler executes the first time, it’s automatically removed as an event handler.
$(window).one("beforeunload", BeforeUnload);
Try this
$(window).bind('beforeunload', function (event) {
setTimeout(function () {
var retVal = confirm("Do you want to continue ?");
if (retVal == true) {
alert("User wants to continue!");
return true;
}
else {
window.stop();
return false;
}
});
return;
});

Categories