jQuery form.submit() not always called - javascript

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

Related

Jasmine: Expecting a Form Submission

I have a jasmine test I am writing for a form validation function.
function checkTotalWeight(){
if(//some condition){
return false;
}
else{
document.Weight.submit();
}
}
I have successfully written tests for my return false conditions, however, I am having trouble getting my test to
See that a submission was made
Prevent the submission from actually happening (ie. "message": "Some of your tests did a full page reload!"
I've tried
var form = $('form');
var submitCallback = jasmine.createSpy().and.returnValue(false);
form.submit(submitCallback);
var check = checkTotalWeight();
expect(submitCallback).toHaveBeenCalled();
which gives me "Expected spy unknown to have been called."
Also, I've tried
$('form').on('submit', function () {
return false;
});
var check = checkTotalWeight();
spyOn(document.Weight, 'submit');
expect(document.Weight.submit).toHaveBeenCalled();
Which gives me "Expected spy submit to have been called."
I haven't had much luck finding anything online along with the lines of "Expecting a form submission with jasmine".
Unfortunately, I cannot change the source code being tested or I would.
Does anyone have any direction?

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.
});
});

window.location only seems to work if I return false on the function

I have a javascript function being called by an input type="image" tag that generates a url and assigns it to window.location.
The problem is that unless I have a return false out of the function AND I actually break into the code and step to the return, it won't work.
So literally, if I let the code run, it refreshes the page but doesn't redirect to the new url (url has been verified correct). But if I put a breakpoint in the javascript at window.location = 'url', and step to the "return false;" statement, it will work.
In firebug in NET, when it doesn't redirect, it shows the GET for that call spinning and never completing.
<input type="image" runat="server" id="btnFind" src="images/search.png" align="top" name="Go" onclick="ValidateAndRedirectSearchResults()"/>
I am setting runat to server because I am setting the src in the code behind as well as the
CausesValidation property to false.
Any suggestions?
function ValidateAndRedirectSearchResults() {
var text = document.getElementById('<%=someTextBox.ClientID %>').value;
var url;
if (ValidateSearchBoxContent(text)) {
var criteria = ConvertStringToAscii(text);
var tempUrl = document.getElementById('<%=tempUrl.ClientID %>').value;
url = tempUrl + encodeURIComponent(criteria)
//if I break here and step to return statement it works
//I have tried window.location.href = url as well
window.location = url;
}
return false;
}
Should be onclick="return ValidateAndRedirectSearchResults()" although this is a horrible way to attach event handlers. JavaScript belongs in .js files in the same way that CSS belongs in .css files
An "image" input is like a "submit" input. That's why returning false makes it work: it cancels the form submission.
You could also prevent the default action via the event itself. (In fact I think returning false doesn't work necessarily in all browsers anyway.)
function ValidateAndRedirectSearchResults(ev) {
ev = ev || window.event;
if (ev.preventDefault)
ev.preventDefault();
else
ev.returnValue = false; // IE
// ...
}
(Make sure you bind the event handler in such a way as to ensure that the event is passed as a parameter in browsers where that makes sense.)

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

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();

Categories