I have this code in a function:
tableFields = tableFields.children;
for (item in tableFields) {
// Do stuff
}
According to a console.log of tableFields, I am getting an array back as I assume I need to do. A console.log of item within the loops returns undefined. What do I have to do to loop through tableFields and insert each object into a table?
console log of tableFields:
HTMLCollection[label, input, label, input 25, label, input, input, input Remove]
0
label
1
input
2
label
3
input 25
4
label
5
input
6
input
7
input Remove
description[]
input
hours[]
input
invoice_number
input
getlength
8
rate[]
input 25
item
item()
iterator
iterator()
namedItem
namedItem()
__proto__
HTMLCollectionPrototype { item=item(), namedItem=namedItem(), iterator=iterator()}
Here is the entire section of code as I have so far:
$this->title("Test");
$this->defaultMenu();
$select = "";
$names = Customer::getNames();
foreach ($names as $id => $name) {
$select .= '<option value="'.$id.'"';
if ($this->customerid == $id) $select .= ' selected ';
$select .= '>'.$name.'</option>';
}
$form = '
<script type="text/javascript">
var counter = 0;
function isEven(int){
int = Number(int);
return (int%2 == 0);
}
function moreLabor() {
var table = document.getElementById("editTable");
var tableFields = document.getElementById("readroot");
tableFields = tableFields.children;
console.log(tableFields);
for (item in tableFields) {
if (isEven(counter)) {
var tableRow = table.insertRow(-1);
var label = tableRow.insertCell(-1);
console.log(tableFields[item]);
label.appendChild(tableFields[item]);
} else {
var field = tableRow.insertCell(-1);
field.innerHTML = item.innerHTML;
}
counter++;
}
console.log();
var insertHere = document.getElementById("writeroot");
}
window.onload = function(){
document.getElementById(\'moreLabor\').onclick = function(){ moreLabor(); }
moreLabor();
}
</script>
<div id="readroot" style="display: none">
<tr>
<td><label for="hours">Hours:</label></td>
<td><input type="text" name="hours[]" value="" /></td>
</tr>
<tr>
<td><label for="rate">Rate:</label></td>
<td><input type="text" name="rate[]" value="25" /></td>
</tr>
<tr>
<td><label for="description">Description:</label></td>
<td><input type="text" name="description[]" value="" /></td>
</tr>
<input type="hidden" name="invoice_number" value="'.$this->number.'" />
<tr>
<td><input type="button" value="Remove"
onclick="this.parentNode.parentNode.removeChild(this.parentNode);" /></td>
</tr>
</div>
<form method="POST" class="invoice" id="edit">
<table id="editTable">
<tr>
<td><label>Work Order Number:</label></td>
<td><input type="text" name="number" value="'.$this->number.'"/></td>
</tr>
<tr>
<td><label>Customer:</label></td>
<td><select name="customerid">'.$select.'</select></td>
</tr>
<span id="writeroot"></span>
<tr>
<td><input type="button" id="moreLabor" value="Add labor"/></td>
<td><input type="submit" name="Save" value="Save" /></td>
</tr>';
if (!is_null($this->id)) {
$form .= '<input type="hidden" name="id" value="'.$this->id.'"/>';
}
$form .= '</table></form>';
$this->component($form);
The trick is that the DOM Element.children attribute is not an array but an array-like collection which has length and can be indexed like an array, but it is not an array:
var children = tableFields.children;
for (var i = 0; i < children.length; i++) {
var tableChild = children[i];
// Do stuff
}
Incidentally, in general it is a better practice to iterate over an array using a basic for-loop instead of a for-in-loop.
In ECS6, one may use Array.from() or Spread array syntax:
const listItems = document.querySelector('ul').children;
const listArray = Array.from(listItems);
// or
const listArray = [...listItems];
listArray.forEach((item) => {console.log(item)});
if tableFields is an array , you can loop through elements as following :
for (item in tableFields); {
console.log(tableFields[item]);
}
by the way i saw a logical error in you'r code.just remove ; from end of for loop
right here :
for (item in tableFields); { .
this will cause you'r loop to do just nothing.and the following line will be executed only once :
// Do stuff
Modern JS also uses the for..of to enable us to iterate DOM children objects, array, or other iterable objects. I think it is very clean and simple.
var children = tableFields.children;
for (c of children) {
console.log(c);
// Do stuff with child c
}
The backwards compatible version (IE9+) is
var parent = document.querySelector(selector);
Array.prototype.forEach.call(parent.children, function(child, index){
// Do stuff
});
The es6 way is
const parent = document.querySelector(selector);
Array.from(parent.children).forEach((child, index) => {
// Do stuff
});
Using ES6,
[...element.children].map(child => console.log(child));
In the year 2020 / 2021 it is even easier with Array.from to 'convert' from a array-like nodes to an actual array, and then using .map to loop through the resulting array.
The code is as simple as the follows:
Array.from(tableFields.children).map((child)=>console.log(child))
I’m surprised no-one answered with this code:
for(var child=elt.firstChild;
child;
child=child.nextSibling){
do_thing(child);
}
Or, if you only want children which are elements,
this code:
for(var child=elt.firstElementChild;
child;
child=child.nextElementSibling){
do_thing(child);
}
Related
I used for loop to copy the table to n times. The code below works only in first table. How can i get to work in all tables?. I am a beginner.
function copy() {
var text1 = document.getElementById("Name1").value;
document.getElementById("Name2").value = text1;
var text2 = document.getElementById("Name3").value;
document.getElementById("Name4").value = text2;
}
<td rowspan="3" style="height:100px;">Name <input type="text" name="Emp name" placeholder="enter your name" id="Name1" /><br> ID <input type="id" name="Emp Id" placeholder="enter id" id="Name3"> </td>
<tr id="p001">
<td colspan="10" style="border:1px solid #ffffff;height:150px;"><input type="button" value="Get data" onclick="copy();" /><label for="text"> Name : <input type="text" id="Name2"></label>
<label for="text"> ID : <input type="id" id="Name4"></label> </td>
</tr>
ID's should always be unique. When using duplicate ID's it will only work on the first one and ignore the rest. By pushing in the selector to the function you can reuse your function for multiple tables.
https://jsfiddle.net/m5aqdswe/
onclick="copy('Name');"
function copy(selector) {
var text1 = document.getElementById(selector + "1").value;
document.getElementById(selector + "2").value = text1;
var text2 = document.getElementById(selector + "3").value;
document.getElementById(selector + "4").value = text2;
}
Hope this helps
EDIT TO HELP WITH YOUR FIDDLE MISTAKE
After checking your code I can see that you haven't implemented my fix. You have an onclick on the button calling copy();. You're not passing in any arguments so your JS is static. So when you add another table you're creating duplicate ID's.
When searching for an ID document.getElementById("Name1") it will search through the DOM until it finds that first id="Name1" and then stop. That is why your second table never works.
To fix that we need to push in your ID name to the function so that the JS becomes dynamic. copy('Name') where "Name" is the first part of your ID. The numbers will still be used.
In the function you need to grab that arguments by passing it in to the function and calling it whatever you like. I chose 'selector' because it is most descriptive. onclick="copy(selector)"
No the function will replace all the 'selector' variables with the string you passed through, namely "Name" so document.getElementById(selector + "1") will actually be document.getElementById("Name1"). This way you can create as many clones as you like but remember to change the clone table ID's and pass in the correct argument to the onclick.
Here is your fixed fiddle. https://jsfiddle.net/3shjhu98/2/
Please don't just copy, go see what I did. You'll need to fix your clone function to use dynamic arguments instead of static ones.
function check() {
var rowCount = $('table.mytable tbody tr');
for (var index = 0; index < rowCount.length; index++) {
var tr = $('table.mytable tbody tr')[index];
var td = $(tr).find('td');
for (var j = 0; j < rowCount.length; j++) {
copy('table.mytable tbody tr[data-index=' + index + '] td[data-index=' + j + ']');
}
}
}
function copy(selector) {
var val_1 = $(selector).find('input:first').val();
$(selector).find('input:last').val(val_1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<table class="mytable">
<tbody>
<tr data-index="0">
<td data-index="0">
<input type="text" onblur="check()" />
<input type="text" />
</td>
</tr>
</tbody>
</table>
Hi. try it...
I think you need to pass table selector like [ table.className ] etc. then you find input text box and get the value this and paste into another text box.
Like this.
///it mean you pass first table row of first table data.
copy('table.className tbody tr[data-index=1] td[data-index=1]');
function copy(selector) {
var val_1 = $(selector).find('input#Name1').val();
$(selector).find('input#Name2').val(val_1);
}
I have a table set up as such:
<table id="mantab" style="cursor:pointer;" onkeypress="scan(event)">
<tr>
<td><input type='text' placeholder="Term" id='inp1' class="inp1" /></td>
<td><input type='text' placeholder="Definition" id='inp2' class="inp2" /></td>
</tr>
</table>
An action can be taken to add a row to this table, which is done by inserting a cell via the insertCell method and setting that cell's innerHTML appropriately.
What I've been trying to do is iterate through the first column of the table and add up all the values from inputs in each cell (after they've been entered) in a comma separated string. This process should be repeated for the second column.
The problem:
Everything I attempt to read is undefined
I've tried the following approaches to retrieving the contents of a cell:
document.getElementById("id").value,
document.getElementByClassName("classname").value,
table.rows[0].cells[0].value,
table.rows[0].cells[0].val(),
table.rows[0].cells[0].innerHTML,
table.rows[0].cells[0].children[0].val()
None work, some return blank, most undefined. The innerHTML one returns the input element inside the cell, but there is no actual text input data.
If a clearer picture of what I'm looking at is needed, see the following:
This should return one variable containing a string: "KeyA,KeyB,KeyC" and another with: "ValueA,ValueB,ValueC"
I'm somewhat new to javascript, but I have a basic knowledge of a couple other languages. I'm not sure why iterating through a table is posing such a challenge. Any help clarifying how I can extract these "invisible" values would be appreciated. Thanks.
Here is one of many approaches that isn't working for me:
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
if(j == 0) { //if first column
words += col.getElementsByClassName("inp1").value + ","; //inp1 refers to first column input class name
} else {
defs += col.getElementsByClassName("inp2").value + ","; //inp2 refers to second column input class name
}
}
}
In this example, words is analagous to the first variable from the image above, and defs to the second.
Update: logging the values and the element responsible for providing the values resulted in this:
The first log is blank, and the second has no value assigned, even though I typed in something.
You can do something like this using jQuery selectors
$("#bt").click(function()
{
var keys = [], values = [];
$('table tr input').each(function(i,e){
//access the input's value like this:
var $e = $(e);
if($e.hasClass('key')){
keys.push($e.val());
}else{
values.push($e.val());
}
});
keys = keys.join(',');
values = values.join(',');
console.log(keys);
console.log(values);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="mantab" style="cursor:pointer;">
<tr>
<td><input type='text' placeholder="Term" id='inp1' class="key" /></td>
<td><input type='text' placeholder="Definition" id='inp2' class="value" /></td>
</tr>
<tr>
<td><input type='text' placeholder="Term" id='inp1' class="key" /></td>
<td><input type='text' placeholder="Definition" id='inp2' class="value" /></td>
</tr>
</table>
<button id="bt">
Get Value
</button>
what about using jQuery and finding all inputs in a table:
$('table input').each(function(i,e){
//access the input's value like this:
console.log($(e).val());
});
I'm trying to do mi own serialize function (like in jQuery), I need to get inputs and selects in an array in order to serialize it.
The problem is that methods "push" and "pop" doesn't exist in DOM elements arrays (Error: "Undefined is not a function").
HTML:
<form>
<table>
<tr>
<td><label for="name">Name:</label></td>
<td><input type="text" id="name" name="name"/></td>
</tr>
<tr>
<td><label for="age">Age:</label></td>
<td><input type="number" id="age" name="age"/></td>
</tr>
<tr>
<td><label for="genre">Genre:</label></td>
<td><select name="genre" id="genre">
<option>Female</option>
<option>Male</option>
</select></td>
</tr>
</table>
</form>
Javascript:
HTMLFormElement.prototype.ownSerialize=function() {
var inputs = this.getElementsByTagName('input');
var selects = this.getElementsByTagName('select');
while(selects.length)inputs.push(selects.pop());//Breaks here
console.log(inputs);
var json = {};
for (var f=0; f<inputs.length; f++) {
json[inputs[f].id]=inputs[f].value;
}
console.log(json);
var str = "?";
for(f in json){
str+=f+"="+json[f]+"&"
}
str = str.slice(0,-1); //Delete de last "&"
console.log(str);
};
document.getElementsByTagName('form')[0].ownSerialize();
How can I achieve it?
http://jsfiddle.net/mpecdv2t/
(Hope my english is correct)
You can convert HTMLCollection (and any other array-like collection) to native array with Array.prototype.slice method:
var slice = Array.prototype.slice;
var inputs = slice.call(this.getElementsByTagName('input'));
var selects = slice.call(this.getElementsByTagName('select'));
After that inputs and selects are true javascript arrays with DOM elements as array elements.
Demo: http://jsfiddle.net/mpecdv2t/1/
I have a table in my jsp:
<table id="table">
<tr>
<th>Valor</th>
<th>Recompensa</th>
</tr>
<tr>
<td>
<input type="text" name="amount">
</td>
<td>
<input type="text" name="text">
</td>
</tr>
</table>
<input type="button" value="Send" onclick="send('table')"/>
I write something in the boxes, and press Send, and the send Javascript method is called.
Javascript send method, which iterates through rows and cells, and stores the values in an Array:
function send(tableID) {
var table = document.getElementById(tableID);
var array= new Array();
for (var i = 1;i<table.rows.length; i++){
var row = table.rows[i];
for (var j = 0;row.cells.length; j++){
alert("added to array: "+row.cells[j].innerHTML);
array.push(row.cells[j].innerHTML);
}
}
}
I am getting "<input name="amount" type="text">" in the alert. I have tried using row.cells[j].firstChild.innerHTML, receiving undefined.
What am I doing wrong? how could I get what the user writes in the textboxes?
PS: I'm using Firefox to test. Maybe a browser issue?
You can use:
alert("added to array: " + row.cells[j].getElementsByTagName('INPUT')[0].value);
jsFiddle Example: http://jsfiddle.net/4TjYH/
EDIT: By the way, the code you posted may have been stripped down for simplicity, but if it's your actual code you can really simplify it:
function send(tableID) {
var array = new Array(),
inputs = document.getElementById(tableID).getElementsByTagName('INPUT');
for (var i = 0; i < inputs.length; i++){
alert("added to array: " + inputs[i].value);
array.push(inputs[i].value);
}
}
In the second loop is an error:
for (var j = 0; j < row.cells.length; j++){
"j <" was missing. the same problem was in the answer of Gavin: here the edit fiddle: http://jsfiddle.net/h693g/2/
Well, if you just want what the user has typed in the textboxes, you can assign ids to each textbox and use getElementById():
<input type="text" name="amount" id="amount">
<input type="text" name="text" id="text">
var amount = document.getElementById("amount");
var text = document.getElementById("text");
Then just push those two values on your array:
array.push(amount.value);
array.push(text.value);
You can put this logic in a loop, looping through an array of element ids or something if you didn't want to write similar code over and over.
i want to iterate through the table rows and get the id and name of each checkbox checked in each tr in the first td and save it in a new Object() called values ex: values.id, values.name
Thanks
<table>
<tr>
<td>
<input id="1" type="checkbox" name="name1" checked="checked">
</td>
<td>
Some input control 1
</td>
</tr>
<tr>
<td>
<input id="2" type="checkbox" name="name2">
</td>
<td>
Some input control 2
</td>
</tr>
</table>
Working example
aRecord is an array of objects with each object containing both the name and ID of each checked checkbox found in the table.
$(document).ready(function() {
var aRecord = [];
$('#your_table input:checkbox:checked').each(function() {
var oChkBox = {};
oChkBox.name = $(this).attr('name');
oChkBox.id = $(this).attr('id');
aRecord.push(oChkBox);
});
var i = aRecord.length;
while (i--) {
alert("Name: "+ aRecord[i].name + " ID: "+ aRecord[i].id);
}
});
http://jsfiddle.net/tracyfu/r6RMV/
var values = {};
$('tr input:checked').each(function(i) {
values[i] = [];
values[i].push($(this).attr('id'));
values[i].push($(this).attr('name'));
});
Will produce:
values = { [1, 'name1'] }
I'm leaving this solution as-is, since you specifically said you wanted to store the values in an object named values, but without knowing what you're going to do with the data, I would store the values in an array instead...