I am intercepting form submissions so that I can reroute them in my single page app (I'm not using a framework, just plain Javascript). Some of my code has multiple buttons with the same name. The following code works on Chrome/Desktop, but does not work on iOS. Specifically, in the following sample code, using document.activeElement doesn't work on iOS. How can I determine which button was pressed on iOS so that I only pass the correct button name/value?
Ideally, the solution would not involve modifying the existing form (other than the 'submit' event listener).
<html>
<body>
<span id="app">
<form method="POST" action="/test">
<input type="hidden" name="id" value="123">
<input name="email" id="email" class="form-control" type="text">
<button name="action" value="one">One</button>
<button name="action" value="two">Two</button>
<button name="action" value="three">Three</button>
<button name="action" value="four">Four</button>
</form>
</span>
<script>
document.getElementById("app").addEventListener("submit", myfunc);
function myfunc(e) {
e.preventDefault()
let action = e.target.getAttribute("action");
console.log("action:", action);
let ae = document.activeElement;
console.log("ae:", ae);
// On iOS btnname and btnval are null. They should be the name
// and value of the button that did the form submittion.
let btnname = ae.getAttribute('name');
let btnval = ae.getAttribute('value');
console.log("btnname:", btnname);
console.log("btnval:", btnval);
let elements = e.target.elements;
for (i=0; i<elements.length; i++) {
let ele = elements[i];
if (ele.type == "submit") {
if (btnval == undefined) {
console.log("skipping:", ele.value)
continue;
}
if (ele.name == btnname) {
if (ele.value != btnval || btnval == undefined) {
console.log("skipping:", ele.value)
continue;
}
console.log("found pressed button: ", btnval)
}
}
console.log("submitting: ", ele.name)
console.log("submitting: ", ele.value)
}
}
</script>
</body>
The solution I came up with involves adding a click event handler. click handlers always fire before submit event handlers. With the click event handler, I record the name and value of the button that was clicked. Then, I can use those in the submit handler, ignoring all elements of type submit. Here is sample code, that also handles check boxes and radio buttons.
<!DOCTYPE html>
<html lang="en-US">
<body>
<span id="app">
<form method="POST" action="/test">
<input type="hidden" name="id" value="123">
<input name="email" id="email" class="form-control" type="text">
<button name="action" value="one">One</button>
<button name="action" value="two">Two</button>
<button name="action" value="three">Three</button>
<button name="action" value="four">Four</button>
<input type="checkbox" name="check1" value="checkvalue1">
<input type="checkbox" name="check2" value="checkvalue2" checked>
<input type="radio" name="radio" value="radio1">
<input type="radio" name="radio" value="radio2" checked>
<input type="radio" name="radio" value="radio3">
click me!
</form>
</span>
<script>
var submitName;
var submitValue;
// click events fire before submit events
document.getElementById("app").addEventListener("submit", myfunc);
document.getElementById("app").addEventListener("click", setSubmit);
function myfunc(e) {
e.preventDefault()
let action = e.target.getAttribute("action");
console.log("action:", action);
let elements = e.target.elements;
if (submitName != "") {
console.log("submitting: ", submitName)
console.log("submitting: ", submitValue)
}
for (i=0; i<elements.length; i++) {
let ele = elements[i];
if (ele.type == "submit") {
} else if (ele.type == "checkbox" || ele.type == "radio") {
if (ele.checked == false) {
continue
}
}
console.log("submitting: ", ele.name)
console.log("submitting: ", ele.value)
}
}
function setSubmit(e)
{
console.log("type:", e.target.type);
if (e.target.type != "submit") {
return;
}
// record the name/value of the button that was pressed
submitName = e.target.name;
submitValue = e.target.value;
}
</script>
</body>
So, I am making something where the user has to fill in their username and password in the beginning and in the end they can submit their score. I want the button to be disabled when the wrong data is filled in and to enable the button when the correct data is filled in. I cant get it to work. I have the name and password stored in the localStorage.
HTML
<button id="submit" class="register_button" type="submit" value="submit">Submit</button>
JavaScript
if (document.getElementById('name2') == localStorage.getItem('name') && document.getElementById('password2') == localStorage.getItem('password')) {
document.getElementById("submit").disabled = false;
} else {
document.getElementById("submit").disabled = true;
};
your expression is wrong you need to add .value after document.getElementById('name2') you are comparing the whole element not it's value
below is the working example
<input type="text" name="" id="name2">
<input type="text" name="" id="password2" onkeydown="validateData();">
<button id="submit" class="register_button" disabled type="submit" value="submit">Submit</button>
<script>
localStorage.setItem('name', "fazal")
localStorage.setItem('password', "pwd")
function validateData() {
//alert(document.getElementById('name2').value);
if (document.getElementById('name2').value == localStorage.getItem('name') && document.getElementById('password2').value == localStorage.getItem('password')) {
document.getElementById("submit").disabled = false;
} else {
document.getElementById("submit").disabled = true;
};
}
</script>
I know nothing about Angular but I was asked to create a validation for the new google map input. All I want to do is have the #lugar_continuar button stay disabled until the input #ciudad is filled in, but the button isn't disabled for some reason.
index.php, input to validate
<div class="">
<input id="ciudad" name="ciudad" class="ciudad" type="text"
placeholder="Ciudad" value="" required ng-model="ciudadSet">
<div id="map"></div>
<input type="hidden" id="distance" size="31" value="31">
</div>
Input type button that should stay disabled
<input id="lugar_continuar" name="lugar_continuar" type="button" onClick="_gaq.push(['_trackEvent', 'Reserva', 'Continuar', 'preciohome'])" value="Continuar" ng-disabled="validacion2() && ciudadSet" ng-click="from_precio = true" >
Using ng-model doesn't work. I also tried with JS, in main.js:
var ReservasApp = angular.module('Reservas',['rzModule']);
ReservasApp.controller('ReservasController',function($scope){
$scope.ciudad = "";
$scope.validacionCiudad = function() {
var disabled = false;
if( $scope.ciudad != null && $scope.ciudad != "" )
{
disabled = false;
}
else
{
disabled = true;
}
}
}
index.php
<input id="lugar_continuar" name="lugar_continuar" type="button" onClick="_gaq.push(['_trackEvent', 'Reserva', 'Continuar', 'preciohome'])" value="Continuar" ng-disabled="validacion2() && validacionCiudad()" ng-click="from_precio = true" >
I also tried using only JS:
var validacionCiudad = function() {
var ciudad = document.getElementById('ciudad');
var btn = document.getElementById('lugar_continuar');
if (ciudad.value == "") {
btn.setAttribute("disabled", "disabled");
} else {
btn.removeAttribute("disabled");
}
}
validacionCiudad();
I have tried many ways to achieve this but nothing is working!
you can try this: ng-disabled = "ciudadSet == ''", since ng-disabled is valid when the expression equals true. If you must call function validacionCiudad to judge this, you have to return bool value in your function. May this will help.
Change $scope.ciudad ="" to $scope.ciudad = undefined;
change your ng-model to:
ng-model="ciudad"
and your ng-disabled to:
ng-disabled="!ciudad"
that shall work
You can validate it like this.
<div ng-controller="MyCtrl">
<form name="userForm" ng-submit="submitForm(userForm.$valid)" novalidate>
<input name="name" ng-model="name" type="text" required >
<br>
<button type="submit" ng-disabled="userForm.$invalid" >Enviar</button>
</form>
</div>
https://jsfiddle.net/ivanm07/y2t88817/
I have a form containing various fields.
See jsFiddle demo.
My aim is to enable the submit button only when the user has filled in all fields.
So far, I'm able to force the title field to have content before submit button is enabled. How do I make it so that all other fields need to be filled too before submit button is enabled.
jQuery("input[type='text']").on("keyup", function () {
if (jQuery(this).val() != "" ) {
if (jQuery("#titlenewtide").val() != '')
{
jQuery("#subnewtide").removeAttr("disabled");
}
} else {
jQuery("#subnewtide").attr("disabled", "disabled");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post" id="new_tide">
Title: <input id="titlenewtide" type="text" name="title" required> <br>
Description: <textarea name="description" id="description"></textarea> <br>
Tag: <input id="newtag" type="text" name="newtag" required> <br>
Category: <input type="radio" name="category" value="19" required> Animation
<button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>
</form>
Note that I am loading the JavaScripts in my footer.
Make the changes take effect after changing inputs values:
On each input change, test the values of other inputs and checked state of radio, if all inputs has been entered it will make the submit button enabled:
var validateInputs = function validateInputs(inputs) {
var validForm = true;
inputs.each(function(index) {
var input = $(this);
if (!input.val() || (input.type === "radio" && !input.is(':checked'))) {
$("#subnewtide").attr("disabled", "disabled");
validForm = false;
}
});
return validForm;
}
inputs.change(function() {
if (validateInputs(inputs)) {
$("#subnewtide").removeAttr("disabled");
}
});
Demo:
var inputs = $("form#myForm input, form#myForm textarea");
var validateInputs = function validateInputs(inputs) {
var validForm = true;
inputs.each(function(index) {
var input = $(this);
if (!input.val() || (input.type === "radio" && !input.is(':checked'))) {
$("#subnewtide").attr("disabled", "disabled");
validForm = false;
}
});
return validForm;
}
inputs.change(function() {
if (validateInputs(inputs)) {
$("#subnewtide").removeAttr("disabled");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post" id="myForm">
Title:
<input id="titlenewtide" type="text" name="title" required>
<br>Description:
<textarea name="description" id="description"></textarea>
<br>Tag:
<input id="newtag" type="text" name="newtag" required>
<br>Category:
<input type="radio" name="category" value="19" required>Animation
<button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>
</form>
Also it uses the form id="myForm", so you can use it to validate only specific forms in your pages.
Note: This is tested and working on Chrome, Firefox and IE.
EDIT:
Make the changes take effect when we type in the inputs:
In the previous code we are using onchange event handler to call the function so it's only called when we click outside a given input (after change).
To perform the call automatically when the user enters a character in a field (the last one) we need to use the onkeyup event so we don't need to click outside of it.
This is the changed code you need :
var inputs = $("form#myForm input, form#myForm textarea");
var validateInputs = function validateInputs(inputs) {
var validForm = true;
inputs.each(function(index) {
var input = $(this);
if (!input.val() || (input.type === "radio" && !input.is(':checked'))) {
$("#subnewtide").attr("disabled", "disabled");
validForm = false;
}
});
return validForm;
}
inputs.each(function() {
var input = $(this);
if (input.type === "radio") {
input.change(function() {
if (validateInputs(inputs)) {
$("#subnewtide").removeAttr("disabled");
}
});
} else {
input.keyup(function() {
if (validateInputs(inputs)) {
$("#subnewtide").removeAttr("disabled");
}
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post" id="myForm">
Title:
<input id="titlenewtide" type="text" name="title" required>
<br>Description:
<textarea name="description" id="description"></textarea>
<br>Tag:
<input id="newtag" type="text" name="newtag" required>
<br>Category:
<input type="radio" name="category" value="19" required>Animation
<button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>
</form>
Use this code below. On each input, it will check all the form fields by using this function validate().
jQuery("input[type='text'], textarea").on("input", function () {
var isValid = validate();
if (isValid) {
jQuery("#subnewtide").removeAttr("disabled");
} else {
jQuery("#subnewtide").attr("disabled", "disabled");
}
});
function validate() {
var isValid = true;
$('input, textarea').each(function() {
if ($(this).val() === '')
isValid = false;
});
return isValid;
}
Fiddle
Update
To make it validate if the form has id="new_tide" and fix about the radio button.
$("input[type='text'], textarea").on("change input", function() {
validate($(this));
});
$("input:radio[name='category']").on("change", function() {
validate($(this));
});
function validate(self) {
if (self.parents("form:first").attr("id") == "new_tide") {
var isValid = true;
$('input[type="text"], textarea').each(function() {
if ($(this).val() === '')
isValid = false;
});
if (!$("input:radio[name='category']").is(':checked'))
isValid = false;
if (isValid) {
$("#subnewtide").removeAttr("disabled");
} else {
$("#subnewtide").attr("disabled", "disabled");
}
}
}
Fiddle
Here's how you can do it:
$(document).ready(function () {
var $inputs = $("#new_tide input:not([type=hidden]), #new_tide textarea");
$inputs.on("input change", function () {
valid = true;
$inputs.each(function () {
valid *= this.type == "radio" ? this.checked : this.value != "";
return valid;
});
$("#subnewtide").prop("disabled", !valid);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<form action="#" method="post" id="new_tide">
Title: <input id="titlenewtide" type="text" name="title" required> <br>
Description: <textarea name="description" id="description"></textarea> <br>
Tag: <input id="newtag" type="text" name="newtag" required> <br>
Category: <input type="radio" name="category" value="19" required> Animation
Hidden: <input type="hidden">
<button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>
</form>
Try utilizing .siblings() , .map() to compile values of form elements , Array.prototype.every() to return Boolean representation of input , textarea values , set disabled property of form input[type=submit] element
$("form *[required]").on("input change", function(e) {
$(this).siblings("[type=submit]").prop("disabled"
, !$(this).siblings(":not([type=submit])").add(this).map(function(_, el) {
return el.type === "radio" ? el.checked : el.value
}).get().every(Boolean)
);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<form action="#" method="post" id="new_tide">
Title: <input id="titlenewtide" type="text" name="title" required> <br>
Description: <textarea name="description" id="description" required></textarea> <br>
Tag: <input id="newtag" type="text" name="newtag" required> <br>
Category: <input type="radio" name="category" value="19" required> Animation
<button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>
</form>
By far the easiest, would be to rely on the HTML5 validation you're already using.
You'd have to add required to all form controls if you want to require all of them, and that can easily be done by using jQuery's :input selector and setting the property, like so
$(':input:not(#subnewtide)').prop('required', true)
We'll exclude the submit button, as that doesn't have to be required, obviously, not that it would matter in this case.
Then we'll listen for the input event, which covers all sorts of inputs, like typing, pasting etc, and the change event as well to cover the radio button.
Using form.checkValidity() tells us if the form is valid, and returns a boolean, so we could use it directly to set the disabled property of the submit button.
All together it looks like this, and that's all you need, a few lines of really simple code
$(':input:not(#subnewtide)').prop('required', true).on('input change', function() {
$('#subnewtide').prop( 'disabled', !this.form.checkValidity() );
});
FIDDLE
If you have to support old browsers that don't have HTML5 validation, you can use the H5F polyfill
My solution is base on standard JavaScript.
HTML form
<form action="#" method="post" id="new_tide" name="form1">
Title: <input onkeyup="myBtnActivator(1)" id="titlenewtide" name="title" type="text" required> <br>
Description: <textarea onkeyup="myBtnActivator(2)" id="description" name="description"></textarea> <br>
Tag: <input id="newtag" onkeyup="myBtnActivator(3)" name="newtag" type="text" required> <br>
Category: <input name="category" onchange="myBtnActivator(4)" type="radio" value="19" required> Animation
<button id="subnewtide" name="subnewtide" type="submit" value="Submit">Submit</button>
</form>
JavaScript
<script>
document.getElementById("subnewtide").disabled = true;
var input1 = false;
var input2 = false;
var input3 = false;
var input4 = false;
function myBtnActivator(i) {
switch (i) {
case 1:
input1 = true;
if (document.form1.title.value == "")
input1 = false;
break;
case 2:
input2 = true;
if (document.form1.description.value == "")
input2 = false;
break;
case 3:
input3 = true;
if (document.form1.newtag.value == "")
input3 = false;
break;
case 4:
input4 = true;
if (document.form1.subnewtide.value == "")
input4 = false;
break;
}
trigger();
}
function trigger() {
if (input1 == true && input2 == true && input3 == true && input4 == true) {
document.getElementById("subnewtide").disabled = false;
} else {
document.getElementById("subnewtide").disabled = true;
}
}
</script>
Why don't you use jquery validate . It's a good plugin .
The logic works like, any change in the form it will check the form is valid or not. And also using the errorplacement function it will disable the default error message also.
$().ready(function() {
// validate signup form on keyup and submit
$("#contactForm").validate({
rules: {
title: "required",
description: {
required: true
},
newtag: {
required: true
},
category: {
required: true
}
},
errorPlacement: function(error, element) {
return true;
},
submitHandler: function() {
}
});
$('#contactForm').change(function() {
if ($("#contactForm").valid()) {
$("#subnewtide").removeAttr("disabled");
}
});
});
Fiddle
There's actually a pretty easy approach. I'm using native JavaScript, but I think it is applicable in jQuery as well:
var form = document.getElementById("new_tide");
form.onchange = function onChange() {
var enable = true;
var inputs = form.getElementsByTagName("input");
var textareas = form.getElementsByTagName("textarea");
for (var i in inputs) {
enable = enable && inputs[i].value != "";
}
for (var i in textareas) {
enable = enable && textareas[i].value != "";
}
enable = enable && textarea.value != "";
document.getElementById("subnewtide").disabled = !enable;
}
The change event on form is always called, when any input or textarea element was changed (click in element, type, click somewhere else or lose focus).
Edit:
Regarding hidden fields, you can exclude them by surrounding the enable calculation with an if-condition:
if (!inputs[i].hidden) {
enable = enable && inputs[i].value != "";
}
Note:
This will work in any browser (even Internet Explorer 5.5). Check on MDN:
for ..in Loop
element.getElementsByTagName()
document.getElementById()
Thought I might chip in. Assuming as little as possible.
jQuery("input, textarea").on("keyup click", function () { // going vanilla after easy-mode attach
var sub = document.getElementById('subnewtide');
if (require_all(find_form(this))) {
sub.removeAttribute('disabled');
sub.disabled = false;
} else {
sub.setAttribute('disabled', 'disabled');
sub.disabled = true;
}
});
function concat(a, b) { // concating Array-likes produces Array
var slice = [].slice; // not assuming Array.prototype access
return [].concat.call(
slice.call(a, 0),
slice.call(b, 0)
);
}
function find_form(e) { // shim input.form
if (e) do {
if (e.tagName === 'FORM') return e;
} while (e = e.parentNode);
return null;
}
function require_all(form, dontIgnoreHidden) { // looks at textareas & inputs (excluding buttons)
var inp = concat(form.getElementsByTagName('input'), form.getElementsByTagName('textarea')),
rad = {}, // not assuming Object.create
i, j,
has = {}.hasOwnProperty; // not assuming Object.prototype access
for (i = 0; i < inp.length; ++i) {
switch ((inp[i].type || '').toLowerCase()) {
default: // treat unknown like texts
case 'text':
if (!inp[i].value) return false; break;
case 'checkbox':
if (!inp[i].checked) return false; break;
case 'radio':
j = inp[i].getAttribute('name');
if (!rad[j]) rad[j] = inp[i].checked;
break;
case 'hidden':
if (dontIgnoreHidden && !inp[i].value) return false; break;
case 'button':
case 'submit':
break;
}
}
for (j in rad) if (!has || has.call(rad, j)) // not assuming hasOwnProperty
if (!rad[j]) return false;
return true;
}
Here is a quick way to accomplish that. It involves attaching a change event listener to :radio and :checkbox elements and an input event listener to other elements. These can both use a common predefined handler that will count the number of unfilled element each time each of these events fires on the appropriate element.
function checkForm() {
//define and initialize variables
var unfilled = 0,
form = $(this.form);
//disable submit button if enabled
$(':submit', form).prop('disabled', true);
//count number of unfilled elements
$(':input', form).each(function() {
if( $(this).is(':radio,:checkbox') ) {
$('input[name=' + this.name + ']:checked').length || unfilled++;
} else {
$('[name=' + this.name + ']').val() || unfilled++;
}
});
//enable submit button if no unfilled element is found
unfilled || $(':submit', form).prop('disabled', false);
}
//set up event listeners to fire above handler
$(':text,textarea,select').on('input', checkForm);
$(':radio,:checkbox').on('change', checkForm);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form action="#" method="post" id="new_tide">
Title: <input id="titlenewtide" type="text" name="title" required> <br>
Description: <textarea name="description" id="description"></textarea> <br>
Tag: <input id="newtag" type="text" name="newtag" required> <br>
Category: <input type="radio" name="category" value="19" required> Animation
<button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>
</form>
var inputs = $("form#myForm input, form#myForm textarea");
var validateInputs = function validateInputs(inputs) {
var validForm = true;
inputs.each(function(index) {
var input = $(this);
if (!input.val() || (input.type === "radio" && !input.is(':checked'))) {
$("#subnewtide").attr("disabled", "disabled");
validForm = false;
}
});
return validForm;
}
inputs.each(function() {
var input = $(this);
if (input.type === "radio") {
input.change(function() {
if (validateInputs(inputs)) {
$("#subnewtide").removeAttr("disabled");
}
});
} else {
input.keyup(function() {
if (validateInputs(inputs)) {
$("#subnewtide").removeAttr("disabled");
}
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post" id="myForm">
Title:
<input id="titlenewtide" type="text" name="title" required>
<br>Description:
<textarea name="description" id="description"></textarea>
<br>Tag:
<input id="newtag" type="text" name="newtag" required>
<br>Category:
<input type="radio" name="category" value="19" required>Animation
<button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>
</form>
Use this html<br>
HTML:
<br>
<pre>
<form action="#" method="post" id="">
Title: ##<input id="titlenewtide" type="text" name="title" required>
Description: <textarea name="description" id="description"></textarea>
Tag: <input id="newtag" type="text" name="newtag" required>
Category: <input type="checkbox" onclick="validate()" name="category" id="cate"value="19" required > Animation
<button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>
</form>
</pre>
validation code:<br>
//on each key up function intiate the function validate
<pre>
jQuery("input[type='text']").on("keyup", function () {
validate();
});
jQuery("#description").on("keyup", function () {
validate();
});
function validate(){
jQuery("input[type='text']").each(function(){
if (jQuery(this).val() != "" )
{
if((jQuery("#description").val() !="") && (jQuery("#cate").is(':checked')))
{
jQuery("#subnewtide").removeAttr("disabled");
}
else {
jQuery("#subnewtide").attr("disabled", "disabled");
}
}
});
}
</pre>
you can find the fiddle in : https://jsfiddle.net/s8uv2gkp/
Maytham Fahmi's relatively easy solution can be made even easier by passing this.name.
<form action="#" method="post" id="new_tide" name="form1">
<input onkeyup="myBtnActivator(this.name)" name="title" type="text" required> <br>
<textarea onkeyup="myBtnActivator(this.name)" name="description"></textarea> <br>
<input id="newtag" onkeyup="myBtnActivator(this.name)" name="newtag" type="text" required> <br>
<input name="category" onchange="myBtnActivator(this.name)" type="radio" value="19" required> Animation
<button id="subnewtide" name="subnewtide" type="submit" value="Submit">Submit</button>
</form>
this refers to the DOM object that called the function. So the switch can just directly take the name, or the value, or anything else you can pass with DOM.
myBtnActivator(n)
{
switch(n)
{
case "title":
break;
case "description":
break;
case "newtag":
break;
case "category":
break;
}
}