Handling form submission with Javascript - How to give user another chance? - javascript

My current application prevents blank and empty input from being submitted on the first attempt. If the initial input is valid, the search is executed. If it is invalid, the form becomes "unresponsive" and no other attempts can be made. How can I modify my code, ideally using plain JavaScript, to allow multiple attempts without reloading the page?
// welcome.js
function prepareEventHandlers() {
document.getElementById("new_search").onsubmit = validateForm
}
function validateForm() {
var q = document.getElementById("search_q").value;
var trimmed_q = q.trim();
if (trimmed_q.length < 1) {
return false;
} else {
return true;
}
}
window.onload = function() {
prepareEventHandlers();
}
// segment from home.html.erb
<%= form_for :search, url: {action: "results"}, html: {id: "new_search", method: "get"} do |f| %>
<%= f.text_field :q, placeholder: "Where to?", html: {id: "search_q"} %>
<%= f.submit "Search" %>
<% end %>
// rails generated html for home.html.erb -- omitted 30 lines of scripts from head
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<!DOCTYPE html>
<html>
<head>
<script src="welcome.js" type="text/javascript" charset="utf-8">
</script>
</head>
</head>
<body>
<div class="homeheader">
</div>
<div class="searchbar">
<h3 class="col-md-2"></h3>
<h3 class="col-md-10">
<form id="new_search" action="/results" accept-charset="UTF-8" method="get"><input name="utf8" type="hidden" value="✓" />
<input placeholder="Where to?" html="{:id=>"search_q"}" type="text" name="search[q]" id="search_q" />
<input type="submit" name="commit" value="Search" data-disable-with="Search" />
</form></h3>
</div>
</div>
</body>
</html>
</body>
</html>

function validateForm(f) {
var ele = document.forms[f].elements;
var allValid = true;
for (var i in ele) {
if (!isChar(ele[i]) && ele[i].type!="radio" && ele[i].type!="checkbox") {
allValid = false;
ele[i].style.borderColor = "red";
}
}
if (!allValid) {
f.reset()
}
}
This code will check each field of your form to make sure there is at least 1 character in each element, as long as it's not a checkbox or radio button. Feel free to mix and match that if statement however you see fit. In the loop, if any of the fields are not valid, it sets the allValid flag to false and upon exiting the loop and evaluating that flag for false, it resets your form. Hope this helps!

I found the problem to be that on submit, the input of type submit was given the disabled option and this what not reset after validating the data. My code is still a work in process, but here is my not yet DRY solution:
// welcome.js
function prepareEventHandler() {
document.getElementById("new_search").onsubmit = validateForm
}
function validateForm() {
var q = document.getElementById("search_q").value;
var trimmed_q = q.trim();
if (trimmed_q.length < 1) {
return false;
} else {
return true;
}
}
window.onload = function() {
prepareEventHandler();
}
// (doesn't work in older IEs)
document.addEventListener('DOMContentLoaded', function(){
document.getElementsByName("commit")[0].setAttribute("disabled", "true");
document.getElementById("search_q").onkeyup = function() {
var val = document.getElementById("search_q").value;
var trimmed_q = val.trim();
if(trimmed_q != '') {
document.getElementsByName("commit")[0].removeAttribute("disabled");
}
};
}, false);

Related

if jQuery statement | empty text boxes

Ok so i have been literally trying to figure this out for the past hour, its such a simple thing that i never have a problem with. So the input 'username_input' has a jQuery if state that is
if($('#username_input').val() == 0) {
alert('Empty');
} else {
alert('Not empty');
}
After that it moves onto the 'password_input' if statement which is the same thing, but it keeps alerting 'empty'. Why?
<!doctype html>
<html>
<head>
<title> Awflicks </title>
<meta name=viewport content="width=device-width, initial-scale=1">
<link type="text/css" rel="stylesheet" href="index.css">
</head>
<body>
<div id="body_div">
<form action="" method="post">
<div id="username_div"> Username: <input type="text" name="username" id="username_input"> </div>
<div id="password_div"> Password: <input type="password" name="password" id="password_input"> </div>
<div id="retype_password_div"> Retype password: <input type="password" name="retype_password" id="retype_password_input"> </div>
<div type="submit" id="submit_button"> Create Account </div>
</form>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>
var $username = $('#username_input').val();
var $password1 = $('#password_input').val();
var $password2 = $('#retype_password_input').val();
function create_account() {
if($username == 0) {
alert('empty');
} else {
alert('not empty')
}
}
$('#submit_button').click(function() {
create_account();
document.forms[0].submit();
})
</script>
</body>
</html>
Because the variable with the value does not get updated when the value changes. It is the value when it is read. You need to read the value when you want it or set the variable onchange.
Also not sure how the value would be zero since there is no value set. Shouldn't you be checking the length? And you are going to want to return a Boolean from your validation function so you know to cancel the form submission.
You can directly use this without defining variables
if(!$('#username_input').val()) // or if(!$('#password_input').val()) for password input
{
alert('empty');
} else {
alert('not empty')
}
You need to refactor as follows to ensure that $username will only store the value once an input has been committed (e.g. once submit has been pressed)
function create_account() {
var $username = $('#username_input').val();
var $password1 = $('#password_input').val();
var $password2 = $('#retype_password_input').val();
if($username == 0) {
alert('empty');
} else {
alert('not empty')
}
}
After you make the changes suggested by the other answers, you are going to have an issue with your form always getting submitted even when the alert shows "Empty". In fact, it will get submitted twice when the alert shows "Not empty". That is because your "submit_button" has type="submit" so it submits the form. You could change to type="button", but my preference is to bind the handler to the form's submit-event, instead of the button's click-event.
$('form').submit(function(event) {
event.preventDefault(); // Stop the form from getting submitted.
var username = $('#username_input').val();
var password1 = $('#password_input').val();
var password2 = $('#retype_password_input').val();
var isValid = true;
if (username == '') {
alert('Empty');
isValid = false;
}
if (isValid) {
this.submit(); // Now submit the form.
}
});

JavaScript form validation in Ruby on Rails - Got JS working, but where do I put it?

I created a real estate calculator in Ruby for my final project in a graduate school class. The project is due in about 24 hours (on Monday) so I really appreciate the help.
The app runs great but I need to add client side form validation using JS. I got the JS to work just like I want it to in a basic html form but now I need to apply this JS functionality to the form that our group's been using in the Ruby on Rails environment.
I'm not sure how to merge these two forms exactly and where to put the JS so that the init functions do not overwrite each other or cause an error. I would assume that all the JS code goes in the App/assets/javascript folder but I'm a bit confused about how the JS links correctly to each form I'm creating because I have to do this for three forms because I have three entities: an investor entity, a property entity and a mortgage entity.
I got all the JS validation working locally for each of these three entities and I pasted the one for mortgage below. They're each in their own separate folders when I created and tested the JS validations locally, but on the ruby git repo, I think all the JS code shares the same JS folder in a way that... well I don't know much about JS in RoR yet, but I assume that all the JS in that assets/js folder is active.
I'm worried because if I throw all of my JS validation code in that folder or combine it into a single file, then would there be a conflict if all three of the entities are calling a function with the same name ("initPage")?
So... hmmm.. I guess if I just rename this initPage() to 3 separate functions, like this:
initInvestorPage()
initMortgagePage()
initPropertyPage()
QUESTIONS:would this be the correct way to go or how else would it know which initPage() to call?
how do the traditional html form and the Ruby form_for merge gracefully?
I pasted below all the JS code needed to work but actually only the warning definitions and the one function initPage() are different for each entity. I would assume the utils.js can just be placed in the assets/js folder but how about the other JS code for the three entities?
Do I (?):
option 1) combine it all into one custom.js file and rename the initPage into three separate functions.. OR
option 2) keep the js files separate and somehow call them separately depending on which form is calling
option 3) go some other way with it...
option 4) take a long walk off a short pier the day before final's week
Thx!!
Mortgage form in Ruby that I need to add JS validation: (sorry for all the markup that's from using Bootstrap)
<% provide(:title, 'Create mortgage') %>
<div class="container">
<div class="page-header">
<h1>Create mortgage</h1>
</div>
<div class="row">
<%= render 'layouts/sidebar' %>
<div class="col-md-9">
<%= form_for(#mortgage) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="col-md-12">
<div class="col-md-6">
<fieldset class="property_create_group">
<label for="mortgage_name">Mortgage name</label>
<%= f.text_field :name, :class => "form-control" %>
</fieldset>
</div>
<div class="col-md-2 clear-both1">
<fieldset class="property_create_group">
<label for="mortgage_amount">Amount</label>
<%= f.number_field :amount, :class => "form-control" %>
</fieldset>
</div>
<div class="col-md-2">
<fieldset class="property_create_group">
<label for="mortgage_terms">Term (yr)</label>
<%= f.number_field :terms, :class => "form-control" %>
</fieldset>
</div>
<div class="col-md-2">
<fieldset class="property_create_group">
<label for="mortgage_interestRate">Interest</label>
<%= f.number_field :interestRate, :class => "form-control" %>
</fieldset>
</div>
</div>
<div class="col-md-4 col-md-offset-1">
<%= f.submit "Create mortgage", class: "btn btn-large btn-success" %>
</div>
<% end %>
</div><!-- /col-md-9-->
</div><!-- /row-->
</div><!-- /container-->
Mortgage.html:
<head>
<link rel="stylesheet" type="text/css" href="css/forms.css" />
<script src="scripts/utils.js" type="text/javascript"></script>
<script src="scripts/mortgage.js" type="text/javascript"></script>
</head>
<body>
<div id="content">
<form action="#" method="post">
<fieldset><label for="mname">Mortgage name</label>
<input name="mname" id="mname" type="text" /></fieldset>
<fieldset><label for="amount">Amount</label>
<input name="amount" id="amount" type="text" /></fieldset>
<fieldset><label for="terms">Terms</label>
<input name="terms" id="terms" type="text" /></fieldset>
<fieldset><label for="interestRate">Interest Rate</label>
<input name="interestRate" id="interestRate" type="text" /></fieldset>
<input type="submit" id="createMortgage" value="Create Mortgage" disabled="disabled" />
</fieldset>
</form>
</div>
</body>
</html>
Mortgage.js:
window.onload = initPage;
var warnings = {
"mname" : {
"required": "Please enter a name for your mortgage.",
"err" : 0
},
"amount" : {
"required": "Please enter the amount of the mortgage.",
"numbers" : "Only numbers are allowed in the mortgage amount.",
"err" : 0
},
"terms" : {
"required": "Please enter the terms (in years) of the mortgage. ",
"numbers" : "Only numbers (in years) can be given for the mortgage terms.",
"err" : 0
},
"interestRate" : {
"required": "Please enter the amount of the interest rate.",
"numbers" : "Only numbers are allowed in the interest rate.",
"err" : 0
}
}
function initPage() {
addEventHandler(document.getElementById("mname"), "blur", fieldIsFilled);
addEventHandler(document.getElementById("amount"), "blur", fieldIsFilled);
addEventHandler(document.getElementById("amount"), "blur", fieldIsNumbers);
addEventHandler(document.getElementById("terms"), "blur", fieldIsFilled);
addEventHandler(document.getElementById("terms"), "blur", fieldIsNumbers);
addEventHandler(document.getElementById("interestRate"), "blur", fieldIsFilled);
addEventHandler(document.getElementById("interestRate"), "blur", fieldIsNumbers);
}
function fieldIsFilled(e) {
var me = getActivatedObject(e);
if (me.value == "") {
warn(me, "required");
} else {
unwarn(me, "required");
}
}
function fieldIsLetters(e) {
var me = getActivatedObject(e);
var nonAlphaChars = /[^a-zA-Z]/;
if (nonAlphaChars.test(me.value)) {
warn(me, "letters");
} else {
unwarn(me, "letters");
}
}
function fieldIsNumbers(e) {
var me = getActivatedObject(e);
var nonNumericChars = /[^0-9]/;
if (nonNumericChars.test(me.value)) {
warn(me, "numbers");
} else {
unwarn(me, "numbers");
}
}
function warn(field, warningType) {
var parentNode = field.parentNode;
var warning = eval('warnings.' + field.id + '.' + warningType);
if (parentNode.getElementsByTagName('p').length == 0) {
var p = document.createElement('p');
field.parentNode.appendChild(p);
var warningNode = document.createTextNode(warning);
p.appendChild(warningNode);
} else {
var p = parentNode.getElementsByTagName('p')[0];
p.childNodes[0].nodeValue = warning;
}
document.getElementById("createMortgage").disabled = true;
}
function unwarn(field, warningType) {
if (field.parentNode.getElementsByTagName("p").length > 0) {
var p = field.parentNode.getElementsByTagName("p")[0];
var currentWarning = p.childNodes[0].nodeValue;
var warning = eval('warnings.' + field.id + '.' + warningType);
if (currentWarning == warning) {
field.parentNode.removeChild(p);
}
}
var fieldsets =
document.getElementById("content").getElementsByTagName("fieldset");
for (var i=0; i<fieldsets.length; i++) {
var fieldWarnings = fieldsets[i].getElementsByTagName("p").length;
if (fieldWarnings > 0) {
document.getElementById("createMortgage").disabled = true;
return;
}
}
document.getElementById("createMortgage").disabled = false;
}
Utils.js:
function createRequest() {
try {
request = new XMLHttpRequest();
} catch (tryMS) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (otherMS) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = null;
}
}
}
return request;
}
function getActivatedObject(e) {
var obj;
if (!e) {
// early version of IE
obj = window.event.srcElement;
} else if (e.srcElement) {
// IE 7 or later
obj = e.srcElement;
} else {
// DOM Level 2 browser
obj = e.target;
}
return obj;
}
function addEventHandler(obj, eventName, handler) {
if (document.attachEvent) {
obj.attachEvent("on" + eventName, handler);
} else if (document.addEventListener) {
obj.addEventListener(eventName, handler, false);
}
}
You can try having a lok at client_side_validation gem. It is no longer maintained, but it should make your life easier without writing any additional js. https://github.com/bcardarella/client_side_validations

Disable/Enable submit button and running this javascript every 1 second onload

I need to disable the submit button when the required fields are not filled. But the script is not working. If anybody can help, thanks in advance.
Html :
<input type="submit" value="Submit" name="sub1" id="submit1">
Javascript :
<script language="JavaScript">
function form_valid() {
var u1=document.getElementById("#user1").value;
var p1=document.getElementById("#pass1").value;
var p2=document.getElementById("#pass2").value;
var s1=document.getElementById("#school1").value;
if ((u1 == null)&&(p1 != p2)&&(s1 == null))
{
document.getElementById("#submit1").disabled = true;
document.getElementById("#submit1").setAttribute("disabled","disabled");
}
else
{
document.getElementById("#submit1").disabled = false;
document.getElementById("#submit1").removeAttribute("disabled");
}
}
function form_run() {
window.setInterval(function(){form_valid();}, 1000);
}
</script>
Body tag (HTML) :
<body bgcolor="#d6ebff" onload="form_run();">
var u1=document.getElementById("#user1").value;
Dont use #, you have many times in your code
var u1=document.getElementById("user1").value;

stopping form submit if the validation fails.

I am validating the dates in below function. If the validation fails, then the form should not get submitted. I tried returning false in form onsubmit but it still gets submitted. However, Validation is working fine and getting the alert that I put in the function. Any help to stop submitting the form if validation fails.
<script>
function dateCheck()
{
start = document.getElementById('name3').value;
end = document.getElementById('name4').value;
compare(start, end);
document.getElementById('name4').focus();
}
function compare(sDate, eDate)
{
function parseDate(input) {
var parts = input.match(/(\d+)/g);
return new Date(parts[2], parts[0]-1, parts[1]); // months are 0-based
}
var parse_sDate = parseDate(sDate);
var parse_eDate = parseDate(eDate);
parse_sDate.setFullYear(parse_sDate.getFullYear() + 1);
if(parse_eDate >= parse_sDate)
{
alert("End date should not be greater than one year from start date");
return false;
}
return true;
}
</script>
</head>
<body>
<form onsubmit="return dateCheck()">
<table>
<tr>
<td><input type="text" name="soname3" id="name3" size="15" readonly="readonly">
<img src="../Image/cal.gif" id="" style="cursor: pointer;" onclick="javascript:NewCssCal('name3','MMddyyyy','dropdown',false,'12')" /></td>
<td><input type="text" name="soname4" id="name4" size="15" readonly="readonly">
<img src="../Image/cal.gif" id="" style="cursor: pointer;" onclick="javascript:NewCssCal('name4','MMddyyyy','dropdown',false,'12'); " /> </td>
</tr>
</table>
<input type="submit" value="Submit">
</form>
Just a comment:
If your listener passes a reference to the form, you can access the controls by name or ID:
<form onsubmit="return dateCheck(this)">
then:
function dateCheck(form) {
var start = form.name3.value;
...
}
Note that you should declare variables, otherwise they will become global at the point they are assigned to. Also, you should check the values in the controls before passing them to the compare function (and display a message asking the user to enter a valid value if they aren't).
function dateCheck(form) {
var start = form.name3.value;
var end = form.name4.value;
var valid = compare(start, end);
if (!valid) form.name4.focus();
return false;
}
I appreciate all contributions above. I have just applied the suggestions above to solve my challenge & it works fine. Keeping it simple I use the following:
<form id="newuser" action="newuser.php" onsubmit="return pswderr(this)">
For the button I have
<input id='submit' type="submit" value="Login" onClick="return pswderr();">
My script is:
<script>
function pswderr() {
var pswd1 = document.getElementById("newuserpswd").value;
var pswd2 = document.getElementById("rptpswd").value;
if (pswd1 !== pswd2) {
document.getElementById("alarm").innerHTML = "Password and password
verification do not match. Retry";
return false;
} else {document.getElementById("alarm").innerHTML = "";
return true;
}
}
</script>
use return on the onclick attribute in the form tag attribute onsubmit="return validateForm()" , if you return false in your validation function in javascript if the input is incorrect then you have to add return to your onclick attribute in order for it to execute .Hope it helped someone!
<script>
function validateForm(){
var validation = false;
var phonenumber = document.forms["enqueryForm"]["phonenumber"].value;
if(phonenumber != 11) {
alert("phonenumber is incorrect");
//e.preventDefault();
return false;
}
}
</script>
<form class="form-style-5" action="BookingForm.php" method="post" id="bookingForm" onsubmit="return validateForm()" name="enqueryForm">
<input type="tel" name="phonenumber" placeholder="your no.">
<input type="submit" name="submit" value="submit">
</form>
return is not going to stop the form from submit if its called in a subfunction e.g. compare(sDate, eDate)
so change your function to this
function dateCheck(e){
var start = document.getElementById('name3').value;
var end = document.getElementById('name4').value;
if(compare(start, end)) {
// no error submit i guess
// return true ?
} else {
// error with date compare
return false;
}
end.focus();
}
In my case i used pattern in input field and also gave maxlength.
What worked with me was, remove Length attribute from input field
you can achieve the same thing using jQuery Form Plugin.
$(document).ready(function() {
$('#your_form_id').ajaxForm( { beforeSubmit: dateCheck } );
});
- I hope this will help you : Just write this code on your Html/jsp page
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
- **Don't forget to add this on your html page**
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type='text/javascript'>
$(document).ready(function() {
//option A
$("regF").submit(function(e) { //regF is form id
alert('submit intercepted');
e.preventDefault(e);
});
});
</script>
</html>

Using jquery validate with multiple fields of the same name

I am trying to get jquery validate to work on multiple fields. Reason being I have dynamically generated fields added and they are simply a list of phone numbers from none to as many as required. A button adds another number.
So I thought I'd put together a basic example and followed the concept from the accepted answer in the following link:
Using JQuery Validate Plugin to validate multiple form fields with identical names
However, it's not doing anything useful. Why is it not working?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/validate/lib/jquery.delegate.js"></script>
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/validate/jquery.validate.js"></script>
<script>
$("#submit").click(function(){
$("field").each(function(){
$(this).rules("add", {
required: true,
email: true,
messages: {
required: "Specify a valid email"
}
});
})
});
$(document).ready(function(){
$("#myform").validate();
});
</script>
</head>
<body>
<form id="myform">
<label for="field">Required, email: </label>
<input class="left" id="field" name="field" />
<input class="left" id="field" name="field" />
<input class="left" id="field" name="field" />
<input class="left" id="field" name="field" />
<br/>
<input type="submit" value="Validate!" id="submit" name="submit" />
</form>
</body>
</html>
This: $("field").each(function(){
Should be: $("[name=field]").each(function(){
Also your IDs should be unique, you'll get unpredictable behavior when this isn't true. Also, you should move the rule adding inside the document.ready, like this (this is now all your script):
$(function(){
$("#myform").validate();
$("[name=field]").each(function(){
$(this).rules("add", {
required: true,
email: true,
messages: {
required: "Specify a valid email"
}
});
});
});
#pratik
JqueryValidation maintaining rulesCache, You need to modify core library.
elements: function() {
var validator = this,
rulesCache = {};
// select all valid inputs inside the form (no submit or reset buttons)
return $(this.currentForm)
.find("input, select, textarea")
.not(":submit, :reset, :image, [disabled]")
.not(this.settings.ignore)
.filter(function() {
if (!this.name && validator.settings.debug && window.console) {
console.error("%o has no name assigned", this);
}
// select only the first element for each name, and only those with rules specified
if (this.name in rulesCache || !validator.objectLength($(this).rules())) {
return false;
}
rulesCache[this.name] = true;
return true;
});
},
Just comment the rulesCache[this.name] = true;
elements: function() {
var validator = this,
rulesCache = {};
// select all valid inputs inside the form (no submit or reset buttons)
return $(this.currentForm)
.find("input, select, textarea")
.not(":submit, :reset, :image, [disabled]")
.not(this.settings.ignore)
.filter(function() {
if (!this.name && validator.settings.debug && window.console) {
console.error("%o has no name assigned", this);
}
// select only the first element for each name, and only those with rules specified
if (this.name in rulesCache || !validator.objectLength($(this).rules())) {
return false;
}
// rulesCache[this.name] = true;
return true;
});
},
If you don't want to change in core library file. there is another solution. Just override existing core function.
$.validator.prototype.checkForm = function (){
this.prepareForm();
for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
if (this.findByName( elements[i].name ).length != undefined && this.findByName( elements[i].name ).length > 1) {
for (var cnt = 0; cnt < this.findByName( elements[i].name ).length; cnt++) {
this.check( this.findByName( elements[i].name )[cnt] );
}
}
else {
this.check( elements[i] );
}
}
return this.valid();
};

Categories