How to merge 2 arrays of DOM elements - javascript

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/

Related

Building Arrays dynamically for inserting into SQL

I have a table with inputs in the cells. These inputs need to be inserted into SQL in a single insert. I am having trouble with just trying to build the arrays. I can push the value that is inputted into an array no problem. Its when I push another input, the first array is overwritten. I need the array to resume or a new one to be created so the contents of the first array are stored and the values for the second array of data are stored all in one array.
I want the user to click a save button which takes all that data and inserts it into sql. There may be only 1 array of data or 3 arrays or 10 arrays. So I guess the question becomes; How do I create an array and push values inside a global array then create another array and push values in the global array without clearing the first array's values?
I haven't gotten to the AJAX request yet, just trying to build the array in preparation.
Any help is most appreciated.
HTML
<tr class="rows" id="row3" >
<td class="celltimes4a"id="row3Project"></td>
<td class="celltimes4c"id="row3Name">General</td>
<td class="celltimes4"id="row3Sun" ><input id="num3Sun" class="alignRight" type="text" name="hours" value="" onchange="tott(this)"></input></td>
<td class="celltimes4"id="row3Mon" ><input id="num3Mon" class="alignRight" type="text" name="hours" value="" onchange="tott(this)"></input></td>
<td class="celltimes4"id="row3Tue" ><input id="num3Tue" class="alignRight" type="text" name="hours" value="" onchange="tott(this)"></input></td>
<td class="celltimes4"id="row3Wed" ><input id="num3Wed" class="alignRight" type="text" name="hours" value="" onchange="tott(this)"></input></td>
<td class="celltimes4"id="row3Thu" ><input id="num3Thu" class="alignRight" type="text" name="hours" value="" onchange="tott(this)"></input></td>
<td class="celltimes4"id="row3Fri" ><input id="num3Fri" class="alignRight" type="text" name="hours" value="" onchange="tott(this)"></input></td>
<td class="celltimes4"id="row3Sat" ><input id="num3Sat" class="alignRight" type="text" name="hours" value="" onchange="tott(this)"></input></td>
<td class="celltimes4b"id="total3"></td>
</tr>
JavaScript
var temp = {};
var SqlArr = [];
function tott(element) {
var totwLeg = element.id;
var splitNumero = totwLeg.split(/([A-Za-z]+)([0-9]+)/);
var getNumero = splitNumero[2];
var getDay = splitNumero[3];
var EmpId = document.getElementById('num1').value;
var WeekEnding = document.getElementById('theDate').value;
var DateOccur = document.getElementById('row1' + getDay).innerHTML;
var JobNum = getNumero - 2;
var Customer = getNumero - 2;
var HourValue = document.getElementById('num' + getNumero + getDay).value;
var cnt = 0;
Empdata = 'EmpData' + cnt + '';
temp = {
EmpId, WeekEnding, DateOccur, JobNum, Customer, HourValue
};
SqlArr.push({
Empdata: temp
});
}
Results
temp=EmpId="2", WeekEnding="09-19-2015",DateOccur="09-14-2015",JobNum=6,Customer=6,HourValue="2"
Desired Results
temp={EmpId="2", WeekEnding="09-19-2015",DateOccur="09-14-2015",JobNum=6,Customer=6,HourValue="2"},{EmpId="2", WeekEnding="09-19-2015",DateOccur="09-16-2015",JobNum=6,Customer=6,HourValue="4"},{EmpId="2", WeekEnding="09-19-2015",DateOccur="09-16-2015",JobNum=6,Customer=6,HourValue="5"}
Not sure this is all that's wrong but first take var SqlArr = []; out of your function tott(). Every time you call the function you create a new empty array. So when you call SqlArr.push() your always pushing the first item on the array.
OK it looks like it's working to me. Check out this fiddle: http://jsfiddle.net/r1L9oj80/1/
However you might look at your 'DateOccur' variable. it contains your entire input element.
Your temp object is invalid, try it like this...
temp = {
'EmpId': EmpId, 'WeekEnding': WeekEnding, 'DateOccur': DateOccur, 'JobNum': JobNum, 'Customer': Customer, 'HourValue': HourValue
};
plus the array SqlArr should be defined outside the function as mentioned in another answer...

Get the values from an array

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.

How do I loop through children objects in javascript?

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);
}

How to get the value from the before selected radio?

In my case I have lines of radioboxes, every radio has a value. This value must be calculated and the result must be placed in a DIV.
My Problem is, I can't find a way to subtract the value of the choosen radion before.
let me show you a sample markup:
<table>
<tr>
<td><input name="tools" value="20" type="radio"></td>
<td><input name="tools" value="300" type="radio"></td>
<td><input name="tools" value="1000" type="radio"></td>
</tr>
<tr>
<td><input name="addons" value="5" type="radio"></td>
<td><input name="addons" value="10" type="radio"></td>
</tr>
</table>
<div id="result"></div>
JavaScript :
var radioClick = $('input[type="radio"]');
radioClick.on('change', function(evt){
// function sub or add the price...
// here is a shortcut of the add calc version...
var price = $(this).val(),
showPrice = $('#result').text(),
endresult = parseFloat(showPrice) + parseFloat(price),
$('#result').text(endResult);
});
With checkboxes it works fine, but in case of radioboyes I don't have a click-event to identify this on I must subtract.
in the first line we see the radios name=tools. here I take at first this one with value 20.
after that the value 20 will be shown in the#result, fine. But when I take now another radio name=tools the new value will add to the 20. and that is my problem. I don't know how to find the before selected radio button to get this value and subtract it.
Try using this:
html code:
<table>
<tr>
<td><input name="tools" class="test1" value="20" type="radio"></td>
<td><input name="tools" class="test1" value="300" type="radio"></td>
<td><input name="tools" class="test1" value="1000" type="radio"></td>
</tr>
<tr>
<td><input name="addons" class="test" value="5" type="radio"></td>
<td><input name="addons" class ="test" value="10" type="radio"></td>
</tr>
javascript:
<script>
var testPrice = 0;
var test1Price = 0;
var endprice = 0;
var price ='';
$('.test').click(function(){
price = $(this).val();
testPrice = price;
endPrice = parseFloat(testPrice) + parseFloat(test1Price),
$('#result').text(endPrice);
});
$('.test1').click(function(){
var price = $(this).val();
test1Price = price;
endPrice = parseFloat(testPrice) + parseFloat(test1Price),
$('#result').text(endPrice);
});
</script>
try it's demo on http://jsfiddle.net/rxrzX/
You don't need to substract. You can just find 2 value of 2 diff radio button : tools and addons. Then just add them and write in the div
You can get radio button value by :
$('input[name=radioName]:checked').val();
I think try this :
var radioClick = $('input[type="radio"]');
radioClick.on('change', function(evt){
// function sub or add the price...
// here is a shortcut of the add calc version...
var toolsprice = $('input[name=tools]:checked').val(),
var addonsprice = $('input[name=addons]:checked').val(),
endresult = parseFloat(toolsPrice) + parseFloat(addonsprice),
$('#result').text(endResult);
});
You could use an object literal that tracks the value, using a closure:
radioClick.on('change', (function()
{
var valTracker = {},
resultDiv = $('#result');//easier on the DOM
return function(evt)
{
valTracker[this.name] = valTracker[this.name] || 0;//get old value
var endResult = parseFloat(resultDiv.text()) + parseFloat($(this).val()) - valTracker[this.name];//subtract old value, too
valTracker[this.name] = parseFloat($(this).val());//set current value
resultDiv.text(endResult);
}
}()));
The valTracker object literal tracks the current radio value (the name of the element is used as property). I've also kept a reference to the $('#result') div in the closure. That way, you don't have to query the DOM every time the callback function is called.
Try using the code below: JSFIDDLE
var radio_groups = []
$(":radio").each(function(){
if (radio_groups.indexOf(this.name) == -1){
radio_groups.push(this.name);
}
});
$('input:radio').change(function(evt){
var resultPrice = 0;
$.each(radio_groups, function(){
curPrice = $(':radio[name="' + this + '"]:checked').val();
if (!(curPrice)){
curPrice = 0;
}
resultPrice = parseInt(resultPrice) + parseInt(curPrice);
});
$('#result').text(resultPrice);
});
This will work, even if you add more radio button groups. If you want this functionality only for specific groups, define the names in the array radio_groups instead of getting them from the document.

jQuery foreach checkbox checked in tr > first td

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...

Categories

Resources