I have a automatically rendered HTML form which uses a index for the input fields.
for quantity:
<input id="id_orderline_set-0-orderline_quantity" name="orderline_set-0-orderline_quantity" onkeyup="orderlineTotal()" type="number" value="120">
for product price;
<input id="id_orderline_set-0-orderline_product_price" name="orderline_set-0-orderline_product_price" onkeyup="orderlineTotal()" type="number" value="22">
for total line price;
<input id="id_orderline_set-0-orderline_total_price" name="orderline_set-0-orderline_total_price" tag="orderline_total_price" type="number" value="2640">
For the following lines the index of the id and name are increased, only quantity example shown;
<input id="id_orderline_set-1-orderline_quantity" name="orderline_set-1-orderline_quantity" onkeyup="orderlineTotal()" type="number" value="55">
I would like to use the following JavaScript to calculate the total line price;
function orderlineTotal()
{
var orderlineTotalPrice = 0;
var theForm = document.forms["orderform"];
var orderlineQuantityField = theForm.getElementsByName["orderline_quantity"];
var orderlineProductPriceField = theForm.getElementsByName["orderline_product_price"];
var orderlineTotalPriceField = theForm.getElementsByName["orderline_total_price"];
for (var i = 0; i < orderlineQuantityField.length; i ++) {
orderlineTotalPrice = orderlineQuantityField[i].value * orderlineProductPriceField[i].value;
orderlineTotalPriceField[i].value = orderlineTotalPrice;
}
}
Offcourse this wont work because the name of the elements do not match. Can i lookup the name of the element by using a partial name? If not, how should i loop through the input boxes to calculate the line total?
You tagged jQuery so if you want to use jQuery you can use ends with selector:
$("input[name$='orderline_quantity']")
ends with
there's also
starts with
$("input[name^='id_orderline_set-0']")
and contains
$("input[name*='orderline_']")
Maybe you could use static names. Set the equal input names for inputs of the same type and then use this function:
var elements = document.getElementsByName('name');
for (var i=0; i<elements.length; i++) {
doSomething(elements[i]);
}
where name matches name of input.
Example
Instead of:
name="orderline_set-0-orderline_total_price"
use:
name="orderline_total_price"
and then:
var orderlineTotalPriceField = theForm.getElementsByName["orderline_total_price"];
and so on...
Related
I basically have an input of type number
<input type="number" id="no_pi" name="" onkeyup="des()">
<div id="extract"></div>
and function
function des() {
var ext = document.getElementById('extract');
var va = Number(document.getElementById('no_pi').value);
for (var i = 0; i = va; i++) {
ext.innerHTML = "<input type='number' name='' class='form-control'><div class='input-group-text'>cm</div>";
}
}
I just want to instantly generate x number of inputs in div based on user input.
When the user input any number, the page just crashes down. I think the page is going in infinite loop, but I think it is not the case.
Any idea how to achieve this
There's several errors :
In your loop : i = va (this is why it crashes)
You erase the content of the div ext each time you iterate, instead of adding content
By listening on keyup event, you add some content on each key hit. Finally if the user submit 12, it will generate 1 + 12 elements. You should pass the value using a form (by doing this you can also add easily the value control in the input element).
As perfectly mentionned by #Andy in the comments, innerHTML += is a very bad idea. You should generate your elements using document.createElement or insertAdjacentHTML.
Some advices :
Use an event listener instead of the onkeyup attribute
Avoid this kind of variable names, be more explicit
Use const and let instead of var
Here's a version which fixes all that issues :
document.getElementById('elementsNumberForm').addEventListener('submit', event => {
event.preventDefault();
const targetElement = document.getElementById('extract');
const inputValue = document.getElementById('no_pi').value;
for (let i = 0; i < inputValue; i++) {
targetElement.insertAdjacentHTML('beforeEnd', '<input type="number" name="" class="form-control" /><div class="input-group-text">cm</div>');
}
});
<form id="elementsNumberForm">
<input type="number" id="no_pi" min="1" />
<input type="submit" />
</form>
<div id="extract"></div>
Your key issue is how you're using your loop. i = va isn't going to accomplish what you want. It should be a check that the index in the iteration is less than the number represented by the value in your input. It should be i < va.
The other issue is that you're not adding to the HTML, just ensuring that the HTML is just one input.
I've adjusted the code in your question to remove the inline JS and use addEventListener instead, and also to use an array to store the HTML built from the loop which can then be applied to the extract element.
// Cache the elements outside of the loop
// and attach a change listener to the noPi element
const extract = document.getElementById('extract');
const noPi = document.getElementById('no_pi');
noPi.addEventListener('change', des, false);
function des() {
const limit = noPi.value;
// Check that we haven't gone into
// negative numbers
if (limit >= 0) {
// Create an array
const html = [];
// Loop, pushing HTML into the array, until
// we've reached the limit set by the value in noPi
for (let i = 0; i < limit; i++) {
html.push('<input type="number" class="form-control"><div class="input-group-text">cm</div>');
}
// `join` up the array, and add the HTML
// string to the extract element
extract.innerHTML = html.join('');
}
}
<input type="number" id="no_pi" />
<div id="extract"></div>
Additional information
join
I see that you want to use an input field to insert the number of inputs to create.
I see a better way to start learning insert the number of inputs with a prompt, and then scale the project.
You can start like this: (hope it make sense to you)
<div style="height: 300px; background-color: #ccc;" class="container"></div>
we have this div that is going to be filled with the inputs
Then we have the script:
const container = document.querySelector('.container');
const runTimes = prompt("How many inputs wnat to create?");
for(let i = 0; i < runTimes; i++){
let newInput = document.createElement('input');
newInput.innerHTML = "<input type='number' name='' class='form-control'>";
container.appendChild(newInput);
}
In the for loop, we create the element input, then with the .innerHTML we add the HTML we want. to end the loop, we need to append the created input element to the div we have.
hope it makes sense to you, :)
when you get the idea with the prompt , I´ve done this project more pro jaja.
<div style="height: 300px; background-color: #ccc;" class="container"></div>
<input type="text" class="numberTimes" onkeyup="getValue()">
we add an event listener to the input with the function getValuue, and the script like this:
const container = document.querySelector('.container');
function getValue(){
let runTimes = document.querySelector('.numberTimes').value;
document.querySelector('.numberTimes').value= "";
for(let i = 0; i < runTimes; i++){
let newInput = document.createElement('input');
newInput.innerHTML = "<input type='number' name='' class='form-control'>";
container.appendChild(newInput);
}
}
This line document.querySelector('.numberTimes').value= ""; is to reset the input field.
So whenever insert a value on the input it creates that number of inputs in the container and cleans the input field :)
Amongst n input text boxes having ids with an incremented integer. Example
first textbox is text_box_1_name and 10th is text_box_10_name.
I need to get the value from these textboxes using a for loop.
function exportCSV(filename)
{
var csv = [];
var number_of_names = document.getElementById("text_no_of_names").value;
csv.push(number_of_names)
var temp = document.getElementById("text_box_2_name")
// Value is available in temp var if id is written directly
for (var i = 0 ; i < number_of_names ; i++) {
var temp =document.getElementById("text_box_"+i+"name").value
// How to increment such id
csv.push(temp)
}
downloadCSV(csv.join("\n"), filename); // Function ahead to download csv
}
use querySelectorAll to select the inputs which id's start with text_box and loop through them with .forEach():
function exportCSV(filename)
{
var csv = [];
[...document.querySelectorAll('input[id^="text_box"]')].forEach(function(e){
csv.push(e.value);
});
downloadCSV(csv.join("\n"), filename); // Function ahead to download csv
}
here's an example of that :
function exportCSV()
{
var csv = [];
[...document.querySelectorAll('input[id^="text_box"]')].forEach(function(e){
csv.push(e.value);
});
console.log(csv.join(",")); // Function ahead to download csv
}
exportCSV();
<input type="text" id="text_box_1" value="first"/>
<input type="text" id="text_box_2" value="second" />
<input type="text" id="another_text_box" value="third" />
<input type="text" id="another_text_box_2" value="fourth" />
<input type="text" id="text_box_3" value="fifth" />
<input type="text" id="text_box_4" value="sixth" />
var textBoxArr = document.getElementsByTagName("input");
for(i=0; i<textBoxArr.length; i++) {
//store textbox value here;
alert("value is: "+textBoxArr[i].value);
}
The above code snippet will iterate through all input type = "text" and get corresponding value ; which we can as: csv.push(textBoxArr[i].value) no need to work based on ID
Im trying to create a list of input ID's and use it in array, to make them readOnly - but the result is error -> "cannot read property 'readOnly' of null".
Can you give me a hint what I should change?
script language="javascript" type="text/javascript">
$(document).ready(function () {
$(function(){
var index, len;
$.get('/SomeList.txt', function(data){
var SomeList = data.split('\n');
for (index = 0, len = SomeList.length; index < len; index++) {
document.getElementById(SomeList[index]).readOnly = true;
}
});
});
});
</script>
and txt file contains name of input ID:
TextFieldName
TextFieldEmail
TextFieldDepartment
TextFieldOffice
Assuming you have some elements with the given IDs you must check if the element exists first before doing
document.getElementById(SomeList[index]).readOnly = true;
so replace that line with
var myElement = document.getElementById(SomeList[index]);
if(myElement == null) {
return;
}
myElement.readOnly = true;
That should work like following example where the IDs come from an array and the second one will not mach because of xxxxx so it's not readonly. But all the others are.
var dataArray = [
'TextFieldName',
'TextFieldEmailxxxxx',
'TextFieldDepartment',
'TextFieldOffice'
];
dataArray.forEach(function(id){
var myElement = document.getElementById(id);
if(myElement == null) {
return;
}
myElement.readOnly = true;
});
<input id="TextFieldName" type="text">
<input id="TextFieldEmail" type="text">
<input id="TextFieldDepartment" type="text">
<input id="TextFieldOffice" type="text">
var id_array=["email","country"];
for (i = 0; i <id_array.length; i++) {
document.getElementById(id_array[i]).readOnly = true;
}
Email: <input type="text" id="email" value="test#mail.com"><br>
Country: <input type="text" id="country" value="Norway" >
it is working fine in my case.
i think there may be whitespace in your array items because your are reading them from file.so try to trim array items.
and make sure you assign id's to input elements
<input type="number" name="quantity" id="quantity">
<span id="price">4000</span>
<input type="text" value="" id="total" readonly>
<input type="button" value="calculate Total Price" onClick="calculate()">
I need values from field name="quantity" and id="price" above and calculate using javascript function and to display it in field id="total" only when I click calculate button. I tried the javascript function below but the result is showing as NaN.
function calculate(tot) {
var quan = document.getElementsByName('quantity').value;
var pri = document.getElementById('price');
var pr = parseInt(pri);
var tot = quan * pr;
document.getElementById("total").value = tot;
}
Whenever you see a method in plural, such as getElementsByName it gets multiple elements, or what we call a nodeList, and even if there's only one matching element, you still get a nodeList, and a nodeList has no value, you can access a nodeList like an array and get the first element in the list like :
var quan = document.getElementsByName('quantity')[0].value;
Also, getElementById gets an element, not a number, you'd have to get the innerHTML
var pri = document.getElementById('price').innerHTML;
and remember the radix for parseInt
parseInt(pri, 10)
not that you really need to parse it when you're multiplying
FIDDLE
You will need a for loop and iterate over every individual value and put that in a value. Like this:
for(i=0; i<quan.length; i++) {
var total+= quan[i];
}
How is repeated code HTML for five times?
like repeated(echo) a input <input type="text" name="ok"> with a js code five times.
I mean this is that, a input by a js code echo five times
I want after run jQuery code output is this (5 input):
<input type="text" name="ok">
<input type="text" name="ok">
<input type="text" name="ok">
<input type="text" name="ok">
<input type="text" name="ok">
how is it?
Your question isn't totally clear, do you mean this?
for (var i = 0; i<5;i++) {
$("body").append("<input type='text' name='ok'>");
}
function EchoInput(html, count) {
var result = [];
for (var i = 0; i < count; i++)
result.push(html);
return result.join("");
}
To use this function, you could do something like this:
document.write(EchoInput("<input type='text' name='ok'>", 5));
var body = $('body');
for(var i = 0; i < 5; i++) {
body.append('<input type="text" name="ok">');
}
http://jsfiddle.net/ucbsh/1/
Instead of creating HTML, you can create elements directly.
Here is a way that let you set different names on each input field. Right now all five have the name "ok", but you can change that in the array:
// use ready event so that the page is loaded:
$(document).ready(function(){
// decide where to add the elements:
var container = $('body');
// loop over an array of names:
$.each(['ok','ok','ok','ok','ok'], function(idx, name) {
// create an element and add to the container:
container.append($('<input/>', { type: "text", name: name }));
});
});