I have this small form here:
<form action="prekiu-uzsakymas" method="get">
<input type="text" name="ticket" value="8888">
<input type="submit" value="Panaudoti kuponÄ…">
</form>
What I want to do is, when I click submit, the form should be hidden and only the input should appear:
<input type="text" name="ticket" value="8888">
How can I achieve this with javascript ?
Looks like you just want to remove the button. First, give the form and button an ID, then attach to the submit event, where you can do whatever you want to do before submission happens:
jQuery("#my-form-id").submit(function() {
jQuery("#my-button-id").remove(); // or .css("display", "none")
});
In Pure JavaScript, you can remove elements by using the code on the following answer by Johan Dettmar https://stackoverflow.com/a/18120786/886393
Here is a working plunker for your exact case.https://plnkr.co/edit/1HdgiSE770KKghq8DzbS?p=preview
You can define the prototypes for element and nodelist.
Element.prototype.remove = function() {
this.parentElement.removeChild(this);
};
NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
for (var i = this.length - 1; i >= 0; i--) {
if (this[i] && this[i].parentElement) {
this[i].parentElement.removeChild(this[i]);
}
}
};
Related
Does anyone have any idea to dynamically keep track of user inputs in a form? I learned how to disable a button and if users want to enable it, they would just have to fill in the input fields. While this works, if a user decides to backspace and go back to a clear field, the button is still enabled. I wanted to get some insight or ideas to keep track of user inputs dynamically.
I'm a bit new to JS so I just wanted some ideas. Is it possible to use for loops/forEach methods to iterate through the input fields? Or what approach do you recommend on taking?
HTML:
<form class="container">
<input type="text" class="input" />
<input type="email" class="input" id="input" />
<button type="submit" id="submitButton" href="index.html" disabled>
Submit
</button>
</form>
JavaScript:
document.getElementById("input").addEventListener("keyup", function() {
var inputs = document.querySelectorAll("input");
if (inputs != "") {
document.getElementById("submitButton").removeAttribute("disabled");
} else if ((inputs = "")) {
document.getElementById("submitButton").setAttribute("disabled", null);
}
});
Here is the solution of your problem.
document.addEventListener("keyup", function() {
var inputs = document.querySelectorAll("input");
var emptyFillExists = false;
for (let index = 0; index < inputs.length; index++) {
if (inputs[index].value.length === 0) {
emptyFillExists = true;
break;
}
}
if (!emptyFillExists) {
document.getElementById("submitButton").removeAttribute("disabled");
} else {
document.getElementById("submitButton").setAttribute("disabled", null);
}
});
<form class="container">
<input type="text" class="input" />
<input type="email" class="input" />
<button type="submit" id="submitButton" href="index.html" disabled>
Submit
</button>
</form>
There are a few things wrong with your codes:
You assume inputs as strings. It isn't. It's an array.
You track keyup event for only 1 input. You should track keyup event for all inputs instead.
Here's what I'd suggest you do:
Add event listener keyup for the form.
Interate through each input and check.
function areInputsValid() {
// Iterate through every input and check its value
var inputs = document.querySelectorAll('input');
for (var i = 0; i < inputs.length; i++)
if (inputs[i].value == '')
return false;
return true;
}
// Get the form element
var form = document.getElementsByTagName('form')[0];
// Add event listener
form.addEventListener('keyup', function() {
// Are the inputs valid?
if (areInputsValid())
document.getElementById("submitButton").removeAttribute("disabled");
else
document.getElementById("submitButton").setAttribute("disabled", null);
})
EDIT: as charlietfl pointed out, there are bugs in my previous answer.
I'm retrieving forms from my page, using:
DOMS = {
form: '[data-form]',
}
document.querySelectorAll(DOMS.fom).forEach(function (form, index) {
arr[index] = {};
arr[index]['DOMRef'] = form;
}
and adding them to an object. I add an event:
addEventListener('submit', function (event) {
send(event, form);
});
Later on form submit, I retrieve the form, and loop thru it:
form = arr[1];
for (i = 0; i < form.elements.length; i++) {
if (form.elements[i].type !== 'submit') {
data = data + form.elements[i].name + '=' + form.elements[i].value;
}
}
Above, I'm creating an Ajax request data. The problem is that I always retrieve the first value(without refresh).
If I change the value of a form field, is ignored, I presume because I call it from the object, and not again from DOM. Something like refresh form.
But also I don't want if is possible to call the form DOM everytime.
You are making copies of your forms somewhere, being called from object shouldn't affect.
document.addEventListener('submit', function (e) {
collectFormData(e);
});
let formsArr = document.querySelectorAll("form");
let formsObj = {fArr: formsArr};
function collectFormData(e){
e.preventDefault();
//event.target
var currForm = e.target;
for(i=0; i<currForm.elements.length; i++){
if(currForm.elements[i].type !== 'submit')
console.log(currForm.elements[i].value);
}
//array
for(j=0; j<formsArr[0].elements.length; j++){
console.log(formsArr[0].elements[j].value);
}
//object
for(k=0; k<formsObj.fArr[0].elements.length; k++){
console.log(formsObj.fArr[0].elements[k].value);
}
}
<form name="myForm" id="myform" action="" method="POST" enctype="multipart/form-datam">
<input type="text" class="val1" name="val1" id="val1" />
<input type="text" class="val2" name="val2" id="val2" />
<input type="text" class="val3" name="val3" id="val3" />
<button type="submit">submit</button>
</form>
PS. But also I don't want if is possible to call the form DOM everytime The value of the input field is in(side) the DOM. You can't get the gift without touching the package.
I'm having trouble getting the match to bind to the oninput property of my text input. Basically I want my submit button to be enabled only when the regular expression is matched. If the regex isn't matched, a message should be displayed when the cursor is over the submit button. As it stands, typing abc doesn't enable the submit button as I want it to. Can anyone tell me what I'm doing wrong? Thank you.
<div id="message">
</div>
<form method="POST">
<input type="text" id="txt" oninput="match()" />
<input type="submit" id="enter" value="enter" disabled />
</form>
<script>
var txt = $("#txt").value();
var PATTERN = /abc/;
var REQUIREMENTS = "valid entries must contain the string 'abc'";
// disable buttons with custom jquery function
jQuery.fn.extend({
disable: function(state) {
return this.each(function() {
this.disabled = state;
});
}
});
$('input[type="submit"]).disable(true);
var match = function(){
if (txt.match(PATTERN)){
$("#enter").disable(false)
}
else if ($("#enter").hover()){
function(){
$("#message").text(REQUIREMENTS);
}
}
</script>
Your code would be rewrite using plain/vanille JavaScript.
So your code is more clean and better performance:
<div id="message"></div>
<form method="POST">
<input type="text" id="txt" oninput="match()" />
<input type="submit" id="enter" value="enter" disabled />
</form>
<script>
var txt;
var enter = document.getElementById('enter');
var message = document.getElementById('message');
var PATTERN = /abc/;
var REQUIREMENTS = "valid entries must contain the string 'abc'";
function match() {
txt = document.getElementById('txt').value;
if (PATTERN.test(txt)) {
enter.disabled = false;
} else if (isHover(enter)) {
enter.disabled = true;
message.innerHTML = REQUIREMENTS;
} else {
enter.disabled = true;
}
}
function isHover(e) {
return (e.parentElement.querySelector(':hover') === e);
}
</script>
If you wanted to say that you want handle the events in different moments, your code should be the following.
Note: the buttons when are disabled doesn't fired events so, the solution is wrapper in a div element which fired the events. Your code JavaScript is more simple, although the code HTML is a bit more dirty.
<form method="POST">
<input type="text" id="txt" oninput="match()" />
<div style="display: inline-block; position: relative">
<input type="submit" id="enter" value="enter" disabled />
<div id="buttonMouseCatcher" onmouseover="showText(true)" onmouseout="showText(false)" style="position:absolute; z-index: 1;
top: 0px; bottom: 0px; left: 0px; right: 0px;">
</div>
</div>
<script>
var txt;
var enter = document.getElementById('enter');
var message = document.getElementById('message');
var PATTERN = /abc/;
var REQUIREMENTS = "valid entries must contain the string 'abc'";
function match() {
txt = document.getElementById('txt').value;
if (PATTERN.test(txt)) {
enter.disabled = '';
} else {
enter.disabled = true;
}
}
function showText(option) {
message.innerHTML = option ? REQUIREMENTS : "";
}
</script>
Two problems here:
The variable txt is defined once outside the function match, so the value is fixed to whatever the input with id txt has when the script/page is loaded.
You should move var txt = $("#txt").val(); into the match function.
Notice I changed the function value() to val().
Problems identified:
jQuery events don't happen on disabled inputs: see Event on a disabled input
I can't fix jQuery, but I can simulate a disabled button without it actually being disabled. There's other hacks you could do to get around this as well, for example, by overlaying a transparent element which actually captures the hover event while the button is disabled.
Various syntactical errors: format your code and read the console messages
.hover()){ function() { ... } } is invalid. It should be .hover(function() { ... })
else doesn't need to be followed by an if if there's no condition
.hover( handlerIn, handlerOut ) actually takes 2 arguments, each of type Function
$('input[type="submit"]) is missing a close '
Problems identified by #Will
The jQuery function to get the value of selected input elements is val()
val() should be called each time since you want the latest updated value, not the value when the page first loaded
Design issues
You don't revalidate once you enable input. If I enter "abc" and then delete the "c", the submit button stays enabled
You never hide the help message after you're done hovering. It just stays there since you set the text but never remove it.
https://jsfiddle.net/Lh4r1qhv/12/
<div id="message" style="visibility: hidden;">valid entries must contain the string 'abc'</div>
<form method="POST">
<input type="text" id="txt" />
<input type="submit" id="enter" value="enter" style="color: grey;" />
</form>
<script>
var PATTERN = /abc/;
$("#enter").hover(
function() {
$("#message").css('visibility', $("#txt").val().match(PATTERN) ? 'hidden' : 'visible');
},
$.prototype.css.bind($("#message"), 'visibility', 'hidden')
);
$('form').submit(function() {
return !!$("#txt").val().match(PATTERN);
});
$('#txt').on('input', function() {
$("#enter").css('color', $("#txt").val().match(PATTERN) ? 'black' : 'grey');
});
</script>
I am using a default value script (jquery.defaultvalue.js) to add default text to various input fields on a form:
<script type='text/javascript'>
jQuery(function($) {
$("#name, #email, #organisation, #position").defaultvalue("Name", "Email", "Organisation", "Position");
});
</script>
The form looks like this:
<form method="post" name="booking" action="bookingengine.php">
<p><input type="text" name="name[]" id="name">
<input type="text" name="email[]" id="email">
<input type="text" name="organisation[]" id="organisation">
<input type="text" name="position[]" id="position">
<span class="remove">Remove</span></p>
<p><span class="add">Add person</span><br /><br /><input type="submit" name="submit" id="submit" value="Submit" class="submit-button" /></p>
</form>
I am also using a script so that users can dynamically add (clone) rows to the form:
<script>
$(document).ready(function() {
$(".add").click(function() {
var x = $("form > p:first-child").clone(true).insertBefore("form > p:last-child");
x.find('input').each(function() { this.value = ''; });
return false;
});
$(".remove").click(function() {
$(this).parent().remove();
});
});
</script>
So, when the page loads there is one row with the default values. The user would then start adding information to the inputs. I am wondering if there is a way of having the default values show up in subsequent rows that are added as well.
You can see the form in action here.
Thanks,
Nick
Just call .defaultValue this once the new row is created. The below assumes the format of the columns is precticable/remains the same.
$(".add").click(function() {
var x = $("form > p:first-child");
x.clone(true).insertBefore("form > p:last-child");
x.find('input:not(:submit)').defaultvalue("Name", "Email", "Organisation", "Position");
return false;
});
You should remove ids from the input fields because once these are cloned, the ids, classes, everything about the elements are cloned. So you'll basically end up with multiple elements in the DOM with the same id -- not good.
A better "set defaults"
Personally I would remove the "set defaults plugin" if it's used purely on the site for this purpose. It can easily be re-created with the below and this is more efficient because it doesn't care about ordering of input elements.
var defaults = {
'name[]': 'Name',
'email[]': 'Email',
'organisation[]': 'Organisation',
'position[]': 'Position'
};
var setDefaults = function(inputElements)
{
$(inputElements).each(function() {
var d = defaults[this.name];
if (d && d.length)
{
this.value = d;
$(this).data('isDefault', true);
}
});
};
Then you can simply do (once page is loaded):
setDefaults(jQuery('form[name=booking] input'));
And once a row is added:
$(".add").click(function() {
var x = $("form > p:first-child");
x.clone(true).insertBefore("form > p:last-child");
setDefaults(x.find('input')); // <-- let the magic begin
return false;
});
For the toggling of default values you can simply delegate events and with the help of setDefault
// Toggles
$('form[name=booking]').delegate('input', {
'focus': function() {
if ($(this).data('isDefault'))
$(this).val('').removeData('isDefault');
},
'blur': function() {
if (!this.value.length) setDefaults(this);
}
});
Fiddle: http://jsfiddle.net/garreh/zEmhS/3/ (shows correct toggling of default values)
Okey, first of all; ids must be unique so change your ids to classes if you intend to have more then one of them.
and then in your add function before your "return false":
var
inputs = x.getElementsByTagName('input'),
defaults = ["Name", "Email", "Organisation", "Position"];
for(var i in inputs){
if(typeof inputs[i] == 'object'){
$(inputs[i]).defaultvalue(defaults[i]);
}
}
I'm trying to figure out what would be the simplest way to validate required fields without having to do an if statement for each element's name. Perhaps just with a loop and verify its class.
What I'm trying to accomplish is to check only the ones that have the class name as "required"
<input name="a1" class="required" type="text" />
<input name="a2" class="" type="text" />
<input name="a3" class="required" type="text" />
Thanks
I'm not at all against the libraries suggested by others, but I thought that you may want some samples of how you could do it on your own, I hope it helps.
This should work:
function validate() {
var inputs = document.getElementsByTagName("input");
for (inputName in inputs) {
if (inputs[inputName].className == 'required' && inputs[inputName].value.length == 0) {
inputs[inputName].focus();
return false;
}
}
return true;
}
Also lets say your inputs are in a form named "theForm":
function validate() {
for (var i = 0; i < theForm.elements.length; i++) {
if (theForm.elements[i].className == "required" && theForm.elements[i].value.length == 0) {
theForm.elements[i].focus();
return false;
}
}
return true;
}
Of course you would trim the value and/or add the appropriate validation logic for the application, but I'm sure you can get the idea from the sample.
You can also store arbitrary data on the input itself and read it using the getAttribute() method on the element. For example you could have this element in your html (regex requires a 3 digit number):
<input name="a1" validate="true" regex="[0-9]{3}" type="text" />
you could use this method to run the regex in the validation routine.
function validate() {
for (var i = 0; i < theForm.elements.length; i++) {
var elem = theForm.elements[i];
if (elem.getAttribute("validate") == "true") {
if (!elem.value.match(elem.getAttribute("regex"))) {
elem.select();
return false;
}
}
}
return true;
}
Hope this helps.
I use the jQuery validation plugin. Works really well and fits your stated desire to only need class attributes.
$(document).ready( function() {
$('form').validate();
});
Is all it takes to set up the validation once you have your required fields marked.
I would recommend you to use this javascript based css selector wich will get all elements of a specific class. Validating the form just like the way you mentioned.
A pattern for this that I have been using for a long time and has served me well is wrapping the control with a DIV, or P and marking that as required.
<div class="form-text required">
<label for="fieldId">Your name</label>
<input type="text" name="fieldName" id="fieldId" value="" />
</div>
This means that I can pick out the required fields to validate easily with a CSS selector.
.required input, .required select
In jQuery, you can test input with something like this:
$('form').submit(function(){
var fields = $(this).find('input, textarea, select'); // get all controls
fields.removeClass('invalid'); // remove
var inv = $(this).find('input[value=""], select[value=""]'); // select controls that have no value
if (inv.length > 0) {
inv.addClass('invalid'); // tag wrapper
return false; // stop form from submitting
}
// else we may submit
});
In plain Javascript it would be more than I care to type out, but along the lines of:
var badfields = [];
var fields = theForm.getElementsByTagName('input');
for (var i=0; i< fields.length; i++ ) {
if ( fields[i] && fields[i].parentNode && fields.value == '' &&
/(^| )required( |$)/.test( fields[i].parentNode.className ) ) {
badfields.push( fields[i] );
}
}
// badfields.length > 0 == form is invalid
The most immediate benefit of wrapping the label and input (and optionally: hint text, error...) as a control "set" in this way is that you can apply CSS styles on the input and label together.
.required input, .required select {
border : 1px solid red;
}
.required label {
color : #800;
}
.invalid input, .invalid select {
background-color : #f88;
}
I recommend using a ready made solution for your form validation as things can quickly add on: How will you validate checkboxes? Can checkboxes be required? (EULA?) What about radio buttons, how will you check those?
Most validation solutions will also provide sugar such as verifying correct data (say, email addresses) rather than just checking if it's there.
I'm a little surprised that no one mentioned YUI.
You can easily use getElementsByClassName method of Dom class in the following manner:
var aElements = YAHOO.util.Dom.getElementsByClassName('required', 'input');
for (var i = 0; i < aElements.length; i++)
{
// Validate
}
More method information is available here and more general info is here