My code below selects forms with both POST and GET methods. But I want to select forms with GET form method attribute only. How can I use selector/filters to retrieve only those form elements that set form method as GET
const jsdom = require('jsdom');
const { JSDOM } = jsdom;
{
const {
document
} = (new JSDOM(data)).window;
var all = document.getElementsByTagName("FORM");
for (var i = 0, max = all.length; i < max; i++) {
var aform = document.getElementsByTagName("FORM")[i];
// log aform.outerHTML
}
}
You can use querySelectorAll to match more complex rules than just the element type.
A type selector can filter by forms, then attribute selectors can examine the method attribute.
You need to be careful because GET is the default value so you need to test for the case where there is no method attribute at all (with a :not() pseudo-class) and where it is set to GET
const get_forms = document.querySelectorAll("form:not([method]), form[method='get']")
console.log(get_forms.length + " matching forms");
<form method="GET"></form>
<form method="POST"></form>
<form></form>
CSS Selectors
Document.querySelectorAll()
let getform = document.querySelectorAll("form[method=GET]")[0].id;
console.log(getform)
let postform = document.querySelectorAll("form[method=POST]")[0].id;
console.log(postform)
let omittedform = document.querySelectorAll("form")[2];
if (!omitted.getAttribute("method")) {
console.log(omitted.id)
}
[...document.querySelectorAll("form")].forEach(form => {
if (!form.getAttribute("method") || form.getAttribute("method") === "GET") {
console.log("Form with id " + form.id + "is GET")
} else if (form.getAttribute("method") === "POST") {
console.log("Form with id " + form.id + "is POST")
}
});
<form method="GET" id="get">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname">
</form>
<form method="POST" id="post">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname">
</form>
<form id="omitted">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname">
</form>
And as comment suggested, if form method is omitted you would need to check if method attribute exists in HTML, if not, you can treat it as GET.
!omitted.getAttribute("method")
As we don't see your HTML, you would need use examples above to write your own logic suitable for your use case.
Or you can check it all like this:
[...document.querySelectorAll("form")].forEach(form => {
if (!form.getAttribute("method") || form.getAttribute("method") === "GET" ) {
console.log("Form with id " + form.id + "is GET")
} else {
console.log("Form with id " + form.id + "is POST")
}
});
You can do it with javascript variable for which switch between form methods
let formMethod = undefined
let getForms = document.querySelectorAll(`form[method=${formMethod || 'GET'}]`)
formMethod = "POST"
let postForms = let forms = document.querySelectorAll(`form[method=${formMethod || 'GET'}]`)
you can do it also with a function
function findForms(method) {
return document.querySelectorAll(`form[method=${method || 'GET'}]`)
}
let postForms = getForms("POST")
let getForms = getForms("GET")
let firstGetForm = getForms[0]
let firstGetFormId = firstGetForm.id
let secondGetForm = getForms[1]
let secondGetFormId = secondGetForm.id
Related
I have created five input fields and a submit button to validate that fields but somehow it is not validated on submit.
In my JS I print the error dynamically. I have debugged by code and I get the proper values and errors, but it doesn't displays dynamically.
function seterror(id, error) {
// set error
var element = document.getElementById(id);
debugger;
console.log(element);
element.getElementsByClassName('ferror')[0].innerHTML = error;
}
function validateForm(e) {
e.preventDefault();
var returnval = true;
var name = document.forms['myForm']['fname'].value;
if (name.length < 5) {
seterror("uname", "abc");
returnval = false;
}
return returnval;
}
.ferror {
color: red;
}
<h1>Form Validation Demo</h1>
<form onsubmit="return validateForm()" name="myForm">
Name*: <input type="text" id="uname" name="fname"><b><span class="ferror"></span></b><br> Password*: <input type="password" id="pass" name="fpass"><b><span class="ferror"></span></b><br> Confirm Password*: <input type="password" id="cpassword" name="fcpass"><b><span class="ferror"></span></b> <br> Email*: <input type="email" id="uemail" name="femail"><b><span class="ferror"></span></b> <br> Phone*:
<input type="phone" id="uphone" name="fphone"><b><span class="ferror"></span></b> <br>
<input type="submit" class="btn" value="submit">
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
Given all the comments under the question, here's my suggestion for a more flexible remake:
Don't use IDs for your fields
Use an additional <label> as wrapper
Don't bloat HTML with useless empty <span> error elements - create them using JS
Use a proper addEventListener() and use its Event in the Validation function
Use an errors array to store all the errors during each part of the validation
Only at the end, if the errors Array has items in it (meaning something is invalid) - in that case use Event.preventDefault() to prevent the form being submitted.
// Utility functions:
const EL = (sel, parent) => (parent || document).querySelector(sel);
const ELS = (sel, parent) => (parent || document).querySelectorAll(sel);
const ELNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
// Form validation script:
const EL_form = EL("#myForm");
const validateForm = (evt) => {
// Remove old errors
ELS(".ferror", EL_form).forEach(el => el.remove());
// Prepare an array to hold your errors
const errors = [];
// Get the desired fields:
const EL_fname = EL('[name="fname"]', EL_form);
const EL_fpass = EL('[name="fpass"]', EL_form);
const EL_fcpass = EL('[name="fcpass"]', EL_form);
const EL_femail = EL('[name="femail"]', EL_form);
const EL_fphone = EL('[name="fphone"]', EL_form);
// Validation and errors:
if (EL_fname.value.trim().length <= 4) {
errors.push({name: "fname", text: "Name is too short (min 4 chars)"});
}
if (EL_fpass.value.trim().length <= 8) {
errors.push({name: "fpass", text: "Password is too short (min 8 chars)"});
}
if (EL_fpass.value !== EL_fcpass.value) {
errors.push({name: "fcpass", text: "Passwords do not match"});
}
if (!/^.+#.+\./.test(EL_femail.value)) {
errors.push({name: "femail", text: "Invalid Email address"});
}
if (EL_fphone.value.trim().replace(/\D/g, "").length <= 6) {
errors.push({name: "fphone", text: "Invalid telephone number"});
}
// Show errors:
errors.forEach(err => {
const EL_error = ELNew("span", {
className: "ferror",
textContent: err.text,
});
EL(`[name="${err.name}"]`, EL_form).closest("label").append(EL_error);
});
// Prevent Form subnit on any error
if (errors.length) {
evt.preventDefault();
}
};
EL_form.addEventListener("submit", validateForm);
form label {
display: block;
}
.ferror {
color: red;
font-weight: 700;
}
<form id="myForm">
<label>Name: <input name="fname" type="text"></label>
<label>Password: <input name="fpass" type="password"></label>
<label>Confirm Password: <input name="fcpass" type="password"></label>
<label>Email: <input name="femail" type="email"></label>
<label>Phone: <input name="fphone" type="phone"></label>
<br>
<input type="submit" class="btn" value="Submit">
</form>
I asked a question earlier with answers which didn't help, I still haven't been able to figure out where my issue is. Originally I thought it was because I had two IDs named the same but this was not the issue.. The form submits and there are no errors but it does not update the values in localStorage?
Edit: After changing const idx to const i the value at position [2] (or final value) would update for every booking (regardless of index). I thought of maybe changing the i value to below but it gives error i is defined before it is initialised?
bookings.findIndex(booking => bookings[i].fname == fname && bookings[i].lname == lname);
Here's what I have (updated code):
// ~~~ add bookings to localStorage
var bookings = JSON.parse(localStorage.getItem("bookings")) || [];
window.onload = showBooking();
$("#submit").click(function() {
var newBookings = {
fname: $('#fname').val(),
lname: $('#lname').val()
}
bookings.push(newBookings);
var json = JSON.stringify(bookings);
window.localStorage.setItem("bookings", json);
showBooking();
});
// ~~~ edit bookings in localStorage
$(document).on('click','#edit',function (e) {
e.preventDefault();
var parent_form = $(this.form);
var fname = parent_form.find('.input:eq(0)').val();
var lname = parent_form.find('.input:eq(1)').val();
const i = bookings.findIndex(booking => bookings.fname == fname && bookings.lname == lname);
deleteBooking(i);
bookings.push({
fname,
lname
});
var json = JSON.stringify(bookings);
window.localStorage.setItem("bookings", json);
// showBooking();
});
// ~~~ display bookings in browser
function showBooking() {
var bookingResult = document.getElementById("result");
var ul = document.createElement("ul");
// var bookingItems = JSON.parse(localStorage.getItem("bookings")) || [];
bookingResult.innerHTML = "";
for (let i = 0; i < bookings.length; i++) {
bookingResult.innerHTML += `<div class="card card-body bg-light m-4">
<h3>${bookings[i].fname + " " + bookings[i].lname}
<button onclick="deleteBooking(${i})" class="btn btn-danger text-light ">Delete</button>
<button onclick="editBooking(${i})" class="btn btn-danger text-light ">Edit</button>
</h3>
</div>`;
}
}
// ~~~ edit bookings in browser
function editBooking(i) {
// $('#regForm').hide();
$('#result').hide();
var currentItem = document.getElementById("currentItem");
var editBooking = document.getElementById("editAppt");
currentItem.innerHTML += `<div class="card card-body bg-light m-4">
<h3>${bookings[i].fname + " " + bookings[i].lname} </h3>
</div>`;
editBooking.innerHTML = `<input type="text" class="input" id="fname_${i}" placeholder="${bookings[i].fname}" name="${bookings[i].fname}" value="${bookings[i].fname}" required>
<input type="text" class="input" id="lname_${i}" placeholder="${bookings[i].lname}" name="${bookings[i].lname}" value="${bookings[i].lname}" required>
<input id="edit" type="submit" value="Edit">`;
}
// ~~~ delete bookings from localStorage
function deleteBooking(i) {
bookings.splice(i, 1);
localStorage.setItem("bookings", JSON.stringify(bookings));
showBooking();
}
My HTML form:
<form id="regForm" name="regForm" action="" class="col-sm-6">
<div class="row">
<input type="text" class="input" id="fname" placeholder="First Name" name="fname" required>
<input type="text" class="input" id="lname"placeholder="Last Name" name="lname" required>
<input id="submit" type="submit" value="Submit">
</div>
</form>
<div id="result" class="row"></div>
<div id="currentItem" class="row"></div>
<div id="editAppt" class="row"></div>
There are several changes you need to consider
You have bookings AND bookingItems
You do some changes (I assume there will be some destination change) but do not save them
You parse the localStorage far too often. Not needed. Only read once and write when modified
You cannot have duplicate IDs so you need to delegate and use class names
Be consistent and use jQuery to create elements and to add events- for example the delete button should be d er legates and remove its closest form element
Here is how to find the booking based on names
const idx = bookings.findIndex(booking => bookings.fname == fname && bookings.lname == lname);
I would like to fill the input value for host_name with the value that is entered into the first_name and last_name fields so the full name will appear in the host_name field. These fields are on the same page. Jquery or pure JS.
<label for="first_name">First Name</label
<input id="first_name" type="text" name="first_name">
<label for="last_name">Last Name</label
<input id="last_name" type="text" name="first_name">
<label for="host_name">Host Name</label
<input id="host_name" type="text" name="host_name">
let firstName = document.getElementById("first_name");
let lastName = document.getElementById("last_name");
let hostName = document.getElementById("host_name");
firstName.addEventListener("change", (event) => {
hostName.setAttribute("value", event.target.value);
});
lastName.addEventListener("change", (event) => {
let firstValue = hostName.getAttribute("value");
let lastValue = event.target.value;
hostName.setAttribute("value", firstValue + " " + lastValue);
});
I hope this is what you're looking for.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<form method="POST" class="form-group">
<label>First Name</label><input type="text" name="FName" class="form-control">
<label>Last Name</label><input type="text" name="LName" class="form-control"><br>
<label>I am Ready</label><input type="checkbox" name="ch"><br><br>
<label>Address</label><input type="text" name="Address" class="form-control">
</form><br><br>
<form method="POST" class="form-group">
<label>Same as Above</label><input type="checkbox" name="chd"><br><br>
<label>First Name</label><input type="text" name="FName" class="form-control">
<label>Last Name</label><input type="text" name="LName" class="form-control"><br>
<label>I am Ready</label><input type="checkbox" name="ch"><br><br>
<label>Address</label><input type="text" name="Address" class="form-control">
</form>
when we checked the checkbox named 'same as the above' then the second form will have to take same values that are in the first form fields.
you can use jQuery like suppose you have 2 input fields and a checkbox
if you click on checkbox it has to get value from first input and assign it to second like
$(function(){
("#checkbox").click(function(){
if($(this).is(':checked')){
var input1=$("#input1").val();
$("#input2").val(input1);
}
});
});
You need to start listening on proto form fields changes if "same as above" checked and stop listening if unchecked. And when value of any field changes then just proxy values of all proto form fields to surrogate form fields
(function($) {
var $forms = $('form');
var $protoForm = $forms.eq(0);
var $surrogateForm = $forms.eq(1);
var proxyValues = function(name) {
var $fields = $protoForm.find('input');
if (typeof name === 'string') {
$fields = $fields.filter('[name="' + name + '"]');
}
$fields.each(function() {
var field = $surrogateForm.find('[name="' + name + '"]').get(0);
if (field.type === 'checkbox') {
field.checked = this.checked;
} else {
field.value = this.value;
}
});
};
var startValuesProxy = function() {
proxyValues();
$protoForm.on('change.valuesProxy', 'input', function(e) {
proxyValues(e.target.name);
});
};
var stopValuesProxy = function() {
$protoForm.off('.valuesProxy');
};
$surrogateForm.on('change', '[name="chd"]', function(e) {
if (e.target.checked) {
startValuesProxy();
} else {
stopValuesProxy();
}
});
})(jQuery);
1) When You check the checkbox, which would mean you would need to create a hidden field on your Address form, and have the results of the address form fields that you require passed to the hidden fields on the address form.
2) On Checked Box Checked Event. Example
Hope Its Work !!!
In my experience you can just disable the controls - seems to be that way on other sites - then in your submit method - if the checkbox is clicked - send that to the controller and use the 'above' values there too..
$(function() {
$('#chkSameAsAbove').on('change', function() {
var otherControls = $(this).parent().find('input:not(#chkSameAsAbove)');
if($(this).is(':checked')) {
otherControls.prop('disabled', true);
} else {
otherControls.prop('disabled', false);
}
});
});
https://jsfiddle.net/7xv5bv4h/
Get all the inputs in javascript.
Let's say you have two input fields and one checkbox, if checkbox is checked both field will have same value, if not user will enter second value in second input.
so lets try this code:
var input1 = document.getElementById("input1");
if (document.getElementById('checkbox_field_ID').checked) {
$('#input2').append(input1);
}
I hope it helps :)
let us say that there is 5 input field for page (A)
<form class="classesName" action="action.php" method="POST">
<input type="text" name="class1" placeholder="Class Name1?" required="">
<input type="text" name="class2" placeholder="Class Name2?" required="">
<input type="text" name="class3" placeholder="Class Name3?" required="">
<input type="text" name="class4" placeholder="Class Name4?" required="">
<input type="text" name="class5" placeholder="Class Name5?" required="">
</form>
I want the user to fill all the fields BUT it must be unique class name for each field
so he can't fill
class a
class b
class a < this one is duplicated so it should display an error message
class c
class d
I think I can make if statement in the action.php page to check is there a duplication in the submitted field or not
but I don't want all the other values to be lost when I reload this page again to display the error for him
is there like a property in html5 or anything like that ?
thanks
No, this cannot be done with HTML5 alone. You'll have to write some JavaScript to make this happen. The JavaScript code should check all the values and if any two are identical prevent the form from submitting successfully.
In this case you could use javascript to validate the fields every time the user fills out a textbox. Here is an example:
$('input[type=text]').on('change',function(){
var arr = [];
$siblings = $(this).siblings();
$.each($siblings, function (i, key) {
arr.push($(key).val());
});
if ($.inArray($(this).val(), arr) !== -1)
{
alert("duplicate has been found");
}
});
JSFiddle: http://jsfiddle.net/x66j3qw3/
var frm = document.querySelector('form.classesName');
var inputs = frm.querySelectorAll('input[type=text]');
frm.addEventListener('submit', function(e) {
e.preventDefault();
var classArr = [];
for(var i = 0; i < inputs.length; i++) {
if(classArr.indexOf(inputs[i].value) != -1) {
inputs[i].style.backgroundColor = "red";
return false;
}
else
classArr.push(inputs[i].value);
}
frm.submit();
});
jsfiddle DEMO