How to access html form values from nested inputs - javascript

I'm trying to validate input from this form:
<form id = "mpath" name = "mpath" action = './../cgitest.cgi' method="POST" onsubmit = "return validateForm(this)">
Total Time (in ms): <input type = "text" name = "ttime">
Number of Cars (1-10): <input type = "text" name = "carnum">
Initial Speed (fps): <input type = "text" name = "initspeed"><br>
<!--extraRowTemplate will be repeated for every change in the accleration of the
head car -->
<p class = "extraRowTemplate" name = "extraRowTemplate">
Change:
<select name="change">
<option value="acc">Acceleration</option>
<option value="dec">Deceleration</option>
</select>
Start time: <input type = "text" name="starttime">
End time: <input type = "text" name="endtime">
Amount (in fps): <input type = "text" name="amount"><br>
</p>
<div id = 'container'></div>
<i class="icon-plus-sign"></i>Add Change<br>
<input type="submit" value="Load Head Car">
</form>
Using this function (I haven't written any of the actual validation):
<script type="text/javascript">
function validateForm(form){
var tt = document.forms[0].ttime.value;
var cn = document.forms[0].carnum.value;
var is = document.forms[0].initspeed.value;
var sta = form.elements[4].value;
console.log(tt);
console.log(cn);
console.log(is);
console.log(sta);
if(tt == ""){
alert("starttime must be filled out");
return false;
}
//return false;
}
</script>
But when I try to submit values, it only finds the values for ttime, carnum, and initspeed, and not the value of starttime, endtime, or amount. Also, the value of change is always "acc", even if I set it to "deceleration".
For those wondering why I don't simply remove extraRowTemplate, I need to have those input options in a nested section because I have an option to duplicate them.
I've tried to pass the form as an argument to the function (as shown) as well as just use document.forms[0] to access it. Neither produce the correct result.
Also, when I remove the .value from the form.elements[4].value and set:
var sta = form.elements[4];
The console prints out:
<input type = "text" name = "starttime">
Does anyone know how I can access the value of the nested inputs?
I suppose I should also say that the form works correctly in every other way, and when I send it to the cgitest.cgi, I can access all inputs. I just don't want to validate the inputs on the server side.
EDIT:
If instead of using an onsubmit function (validateForm in my case), I use an event listener:
<script type="text/javascript">
var button = document.querySelector('input[type=submit]')
button.addEventListener('click', function onClick(event) {
var ttime = document.querySelector('input[name=ttime]')
var carnum = document.querySelector('input[name=carnum]')
var initspeed = document.querySelector('input[name=initspeed]')
var change = document.querySelector('select[name=change]')
var starttime = document.querySelector('input[name=starttime]')
var endtime = document.querySelector('input[name=endtime]')
var amount = document.querySelector('input[name=amount]')
console.info('ttime', ttime.value)
console.info('carnum', carnum.value)
console.info('initspeed', initspeed.value)
console.info('change', change.value)
console.info('starttime', starttime.value)
console.info('endtime', endtime.value)
console.info('amount', amount.value)
event.preventDefault()
})
</script>
With the input ttime = 1, carnum = 2, initspeed = 3, change = "acc", starttime = 4, endtime = 5, amount = 6, I get the following console output:
(index):70 ttime 1
(index):71 carnum 2
(index):72 initspeed 3
(index):73 change acc
(index):74 starttime
(index):75 endtime
(index):76 amount
As can be seen, all values beyond initspeed (everything inside extraRowTemplate) are empty. Like I said before, they are not empty when sent to the form action url.

Can you try removing the extraRowTemplate and submit. If it's working, than you can try generating the elements inside with the different ids, because now you have duplicated items with no distinction.

You are currently accessing the elements in a bit of a roundabout way, using document.forms[0]. Also I don't see any code to get the value of the starttime input. You are testing tt in the if, but that was assigned the value of ttime.
document.querySelector
Might I suggest accessing the form elements by name directly, using document.querySelector? This method accepts a CSS selector and returns the first element that matches. Using a simple CSS3 selector we can select elements by name and assuming those names are unique on the page, we will get the right inputs. You could also use form.querySelector if the names are only unique within the form.
Example
var myInput = document.querySelector('input[name=ttime]')
I find document.querySelector and document.querySelectorAll (which gets all elements matching the CSS selector) very useful and use them all the time.
Runnable code snippet
Run this snippet and press the form submit button to print the values of the inputs. Try it and see how it works.
var button = document.querySelector('input[type=submit]')
button.addEventListener('click', function onClick(event) {
var ttime = document.querySelector('input[name=ttime]')
var carnum = document.querySelector('input[name=carnum]')
var initspeed = document.querySelector('input[name=initspeed]')
var change = document.querySelector('select[name=change]')
var starttime = document.querySelector('input[name=starttime]')
var endtime = document.querySelector('input[name=endtime]')
var amount = document.querySelector('input[name=amount]')
console.info('ttime', ttime.value)
console.info('carnum', carnum.value)
console.info('initspeed', initspeed.value)
console.info('change', change.value)
console.info('starttime', starttime.value)
console.info('endtime', endtime.value)
console.info('amount', amount.value)
event.preventDefault()
})
<form id = "mpath" name = "mpath" action = './../cgitest.cgi' method="POST" onsubmit = "return validateForm(this)">
Total Time (in ms): <input type = "text" name = "ttime">
Number of Cars (1-10): <input type = "text" name = "carnum">
Initial Speed (fps): <input type = "text" name = "initspeed"><br>
<!--extraRowTemplate will be repeated for every change in the accleration of the
head car -->
<p class = "extraRowTemplate" name = "extraRowTemplate">
Change:
<select name="change">
<option value="acc">Acceleration</option>
<option value="dec">Deceleration</option>
</select>
Start time: <input type = "text" name="starttime">
End time: <input type = "text" name="endtime">
Amount (in fps): <input type = "text" name="amount"><br>
</p>
<div id = 'container'></div>
<i class="icon-plus-sign"></i>Add Change<br>
<input type="submit" value="Load Head Car">
</form>

I can access the value of your "starttime" field in Firefox/Chrome/Opera using either
var sta = document.forms[0][4].value
or
var sta = document.forms[0].starttime.value

I was able to figure out what was going wrong. In my css I set:
.extraRowTemplate {
display: none;
}
which was preventing the input values from being sent. Once I removed this my problems went away. Setting "visibility : hidden" is a good alternative that allowed the values to be submitted and the template not visible.

Related

How to read input box line by line in Javascript and return various values depending on input?

I am trying to create a function in Javascript which can read an input box line by line and return different values depending on the input.
For example, if someone enters several protein mutations on separate lines with the format Arg86Lys, I want the function to read the first three and last three letters to get Arg Lys. Then, if I have a value stored for Arg Lys (let's say 100), I want the output to be a textbox which prints out the value 100 (and prints out the rest of the values on separate lines).
I am stuck on how to read the input box value line by line, and only extract the first three and last three letters from each line. I also do not understand how I can store values (like Arg Lys = 100) and return said values when a certain input is found.
So far I have created a multiline textbox (in HTML) and tried to make a function that reads line by line:
<body>
<form action = "/cgi-bin/hello_get.cgi" method = "get">
Enter mutations on separate lines with format Arg86Lys
<br>
<textarea rows = "5" cols = "60" name = "description">
</textarea><br>
<input type = "submit" value = "submit" />
</form>
<script>
var lines = document.getElementById('textareaId').innerHTML.split('\n');
for(var i = 0;i < lines.length;i++){
\\
}
</script>
</body>
textarea is an input, so its value is going to be stored in its value property, and passed along with the form submission. Here is an answer I found that goes over how to intercept the submit event for the form:
Intercept a form submit in JavaScript and prevent normal submission
Once you've intercepted the form submission event, pull the value from the description input, and do with it what you want from there
let form = document.getElementById("form");
let data = {"Arg Lys":100}; // store data like this
form.addEventListener("submit",function(e){
e.preventDefault();
var lines = document.getElementById('textareaId').value.split('\n');
document.getElementById('textareaId').value = '';
for(var i = 0;i < lines.length;i++){
let val = lines[i].substring(0,3);
let lastval = lines[i].substring(lines[i].length - 3)
document.getElementById('textareaId').value += val+' '+lastval + ' - ' +data[val+' '+lastval]+'\n';
}
})
<body>
<form id="form" action = "/cgi-bin/hello_get.cgi" method = "get">
Enter mutations on separate lines with format Arg86Lys
<br>
<textarea id="textareaId" rows = "5" cols = "60" name = "description"></textarea><br>
<input type = "submit" value = "submit" />
</form>
</body>
Are you looking for something like that?

Which API I need to use instead of serializeArray to get the custom attributes of fields?

I'm using serializeArray() to retrive the form attributes. When I try to get the attributes, I'm receiving name and value for all the fields.
I have checked the documentation https://api.jquery.com/serializeArray/. I understood it will return the name and value of all the fields.
Now I have few custom attributes for some fields. I want to retrieve them using those custom attributes.
How can i achieve this?
Here is my logic.
var data = $('form').serializeArray();
var newData = {};
var queue = {};
data.forEach(function(field) {
if( field.customField != undefined && field.customField.indexOf("true")>=0 ) {
queue[field.name] = frm.value
} else {
newData[frm.name] = frm.value;
}
});
I need to get that customField attribute, I'm adding that to the HTML field attribute.
May not be the best, but you can do like this.
Let's say you have set of text boxes, text areas and so on with custom data attributes in it. What I am doing here is adding a class to those fields that you need to get value / data attributes in it.
Let's take the following HTML as an example.
HTML
<form id="frm">
<input class="serialize" type="text" name="title1" value="Test title 1" data-test1="test AAA" data-test2="test BBB" /><br/>
<input class="serialize" type="text" name="title2" value="Test title 2" data-test1="test CCC" data-test2="test DDD" /><br/>
<textarea class="serialize" data-test1="textarea test 1">TEST 22 TEST 11</textarea>
<button id="btn" type="button">Serialize</button>
</form>
What I am doing here is iterating through fields which has class .serialize and putting value, name, data attributes and so on to an array.
jQuery
$(document).ready(function(){
$('#btn').on('click', function(e) {
var dtarr = new Array();
$(".serialize").each(function(){
var sub = new Array();
sub['name'] = $(this).attr('name');
sub['value'] = $(this).val();
//data attribute example
sub['data-test1'] = $(this).data('test1');
sub['data-test2'] = $(this).data('test2');
dtarr.push(sub);
});
// This will give you the data array of input fields
console.log(dtarr);
});
});
Hope this helps.

Change value of <input> to include a superscript, using Javascript

The following code works correctly for me, in HTML.
<input type = "text" name = "var_1" id = "i_var_1" value = "x&sup8">
The following, using Javascript, also works:
<p id = "p1"><input type = "text" name = "var_1" id = "i_var_1" value = "0"></p>
<script....>
q1 = document.getElementById("p1");
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value = "x&sup8">';
</script>
However I need to add in the superscript when a button is pressed. So I have something like:
<p id = "p1"><input type = "text" name = "var_1" id = "i_var_1" value = "0"></p>
<input type = "button" id = "i_button" value = "Add the superscript" onclick="Add_Superscript()";>
<script.....>
function Add_Superscript()
{
q1 = document.getElementById("p1");
b1 = document.getElementById("i_var_1");
c1 = b1.value.toString() + "&sup8";
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value = c1.value>';
}
</script>
The above code does not reproduce the superscript properly.
Anyone any ideas? Thanks in advance for comments.
Not sure this is what you want, but it adds &sup8 to whatever is in the input box.
function Add_Superscript() {
q1 = document.getElementById("p1");
b1 = document.getElementById("i_var_1");
c1 = b1.value.toString() + "&sup8";
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value = "' + c1 + '">';
}
<p id="p1">
<input type="text" name="var_1" id="i_var_1" value="0">
</p>
<input type="button" id="i_button" value="Add the superscript" onclick="Add_Superscript()" ;>
I don't know what you're trying to do but maybe it's because of the c1.value ! Try:
q1.innerHTML = '<INPUT TYPE = "text" name = "var_1a" id = "i_var_1a" value =' + c1 + '>';
You have several typos in your code and a lot of unnecessary code as well. You just need to set up a click event handler on the button that populates the value of the pre-existing input. No need to create a new input.
A few notes:
When you were trying to create the new input element (which it turns out you don't need to do in the first place), you had the entire thing as a string. You need to inject the dynamic value into that string, by terminating the string, concatenating the new value in and then concatenating the closing of the string, like this:
q1.innerHTML = '<input type="text" name="var_1a" id="i_var_1a" value=' + c1.value + '>';
Next, it's best to use good naming conventions for elements and variables. Prefix an id and name with something that describes the "type" of thing the element is. Use btn (button), txt (textbox), chk (checkbox), rad (radio button), etc. And don't use _ (that's a very old convention). Instead use "camelCase". Further, with form elements, you need to give them a name for form submission purposes, but it is also a good idea to give them and id for CSS and JavaScript purposes. Use the same id that you used for name so that you don't have two different names for the same thing.
Lastly, don't configure your HTML elements to event handlers via HTML attributes (onclick, onmouseover, etc.). Doing this creates global anonymous functions that alter the this binding in the callback function, it creates "spaghetti code" that is hard to scale and debug and it doesn't follow the W3C DOM Event specification. Instead, do all the work in JavaScript and use .addEventListener() to connect functions to events.
// Get references to the relevant DOM elements
var btn = document.getElementById("btnGo");
var input = document.getElementById("txtInput");
// Set up a click event handling function
btn.addEventListener("click", add_Superscript);
function add_Superscript(){
// Create a new value that is the old value plus a "superscript" value
var newVal = input.value + "&sup8";
// Update the input with the new value:
input.value = newVal;
}
<p>
<input type="text" name="txtInput" id="txtInput" value="0">
</p>
<input type = "button" id="btnGo" value="Add the superscript">

Generating additional rows in PHP form with alternative id and name

I am looking for a way to add the following row of inputs using a button (and I've found plenty of examples) BUT most of them renames the name of html element (e.g. name = 'price1', name = 'price2') but my javascript references the element's id, making it erroneous when new rows are added. Some helps are appreciated.
JS Fiddle just to see the rows
https://jsfiddle.net/n4h5uwvk/
the HTML code
<form action = "" method = "POST">
<label>Item : </label>
<select id = 'item_name' name = 'item_name' onChange = 'listMatch(this);fieldCheck();'
>
<option value = "" disabled = "disabled" selected="selected">Please Select</option>
<?php
while($row = mysqli_fetch_assoc($result)){
echo "<option value = '".$row['PRODUCT_ID']."' data-price ='
".$row['UNIT_PRICE']."' >".$row['PRODUCT_NAME']."</option>";
}
?>
</select>
<label>Price : </label>
<input type = 'text' id = 'item_price' name = 'item_price' value = '' disabled/>
<label>Quantity : </label>
<input type = "number" id = 'quantity' name = 'quantity' max = "150" min = "0" onChange = 'multiplier(value)' disabled/>
<label>Sub-Total : </label>
<input type = "number" id = 'sub-total' name = 'sub-total' disabled value = ''/>
and the Javascript
<script>
//lists the price according to selected item
function listMatch(product){
var x = product.options[product.selectedIndex].getAttribute('data-price');
document.getElementById('item_price').value = x;
}
//un-disable quantity field after item is selected
function fieldCheck(){
document.getElementById('quantity').removeAttribute('disabled');
}
//var z = quantity*price
function multiplier(value){
var x = document.getElementById('item_price').value;
var y = value;
var z = x*y;
document.getElementById('sub-total').value = z.toFixed(2);
}
//clone fields on 'add field' button click
Updated :
I found a code to clone my forms well, but I encounter another problem. The clone will always duplicate values of the first row, I want to create child rows that have empty values. Any ways around this code?
//global variable for duplication identification
var count = 1;
//clone form for multiple entries
(function() {
$('#add').click(function() {
var source = $('form:first'),
clone = source.clone();
clone.find(':input').attr('id', function(i, val) {
return val + count;
});
clone.insertBefore(this);
count++;
});
})();
As you know id has to be unique and adding numbers to the cloned form elements to keep the ids unique seems overdoing it.
Names don't have to be unique though, so you can have different forms with elements with the same name. And they can be accessed easily by their names:
<form name="form_1">
<input name="firstName" type="text" />
<input name="lasttName" type="text" />
</form>
<form name="form_2">
<input name="firstName" type="text" />
<input name="lasttName" type="text" />
</form>
You can use the form name to access specific element, to access the input with name="firstName" in form_1 and form_2 you can use:
var firstName1 = document.form_1.firstName;
var firstName2 = document.form_2.firstName;
So it will be easy to distinguish between different forms, although their elements have the same structure and names. You just create a new form with name="form_X" and use innerHTML to add the cloned elements.
And to clone an element you can use .cloneNode(true); (or jQuery's clone()).
EDIT:
You still seem to think of it that you need to store everything in a variable, here's an example to do it all, and you can see it's much simpler than you think. I give these forms class="contactForm" to separate them from other forms there might be. we can clone 10 .contactForm and have 100 other forms in the page as well.
To get number of forms you can use $('form.contactForm').length
To empty text inputs inside new form you can use: newForm.find('input[type=text]').val("");
jsfiddle DEMO

Get id value using <input> with javascript and php

First example:
var dbSelected = "File selected: ";
var filenamePanel = document.getElementById('filenamePanel');
filenamePanel.textContent = dbSelected + files[0].name;
var postLink = files[0].link;
document.getElementById('postLink').value = postLink;
var postName = files[0].name;
document.getElementById('postName').value = postName;
If I use <input type="hidden" name="postName" id="postName"> to send the value to another page via POST with PHP, it works.
Second example:
function onSuccessCallback(Blob){
document.getElementById('postName').textContent = Blob.filename;
document.getElementById('postLink').textContent = Blob.url;
document.getElementById('results').textContent = JSON.stringify(Blob);
};
Now, If I use <input type="hidden" name="postName" id="postName"> on the second example to send the 'postName' id value to another page, the value is empty.
What changes are necessary, on the second example, so that I can send the 'postName' id value to another page using a hidden <input> field?
Use .value instead of .textContent to store the data in the hidden input field:
document.getElementById('postName').value= Blob.filename;

Categories