I am trying to get the values of multiple inputs on a page. The ids of the inputs are generated dynamically.
<input id="updates_662224305" class="text quantity" type="text" value="1" name="updates[662224305]" size="4">
I am running a loop for the table and cells in which the inputs are contained. I was getting the innerHTML of the cells the inputs are located in, and then slicing the section where their ids are:
var racetamarray = [],
racetamtotal = 0,
table = document.getElementById('cart-table'),
cells = table.getElementsByTagName('td');
for (var i=0,len=cells.length; i<len; i++){
if(cells[i].innerHTML.indexOf("ncombo-racetam") != -1) {
i+=3;
var racetaminput = cells[i].innerHTML;
var racetaminputcontain = racetaminput.slice(43,60);
var racetamelem = document.getElementById(racetaminputid);
racetamarray.push(parseInt(racetamelem.value));
}
}
This worked in firefox, as I was able to extract their ids and put them in the variable racetamelem. However when I tried it in chrome it does not work, the slice occurs at a different section of the string and does not capture their ids. Is there a better way to slice this or of converting the inputs from a string to a DOM element?
HTML of one of the rows in the table:
<tr class="item sampler-pramiracetam-capsules">
<td>
<span class="ncombo-racetam"></span>
<a href="/products/sampler-pramiracetam-capsules">
<img src="//cdn.shopify.com/s/files/1/0173/1766/products/PramiracetamCaps_grande_thumb.jpg?v=1396441752" alt="Sampler, Pramiracetam Capsules" />
</a>
</td>
<td>
Sampler, Pramiracetam Capsules - 30 Capsules</td>
<td>$8.90</td>
<td><input class="text quantity" type="text" size="4" id="updates_658967781" name="updates[658967781]" value="1" class="replace" /></td>
<td>$8.90</td>
<td><a class="btn remove-from-cart" href="/cart/change?id=658967781&quantity=0">Remove</a></td>
</tr>
This walks through the table rows and checks for any elements in the first cell with the class name, and if found then push the input value (from the fourth cell) to the array.
Demo: http://jsfiddle.net/SEaE4/
var racetamarray = [];
var table = document.getElementById('cart-table');
var row;
for(var i=0; i<table.rows.length; i++){
row = table.rows[i];
if(row.cells.length > 3){
if(row.cells[0].querySelectorAll('.ncombo-racetam').length) {
racetamarray.push(row.cells[3].getElementsByTagName('input')[0].value);
}
}
}
console.log(racetamarray);
Side note: if you need to support IE7 or older then you will need to replace the querySelectorAll() call with more code to check each element for the class.
Related
I have a list of items, generated by PHP that is quite long. I don't want to show this list in a dropdown menu. Instead, I'm using jquery to have users type in a textbox, then filtering from that list based on user input:
Example HTML:
<table id = "table">
<tr>
<td>Select an animal:</td>
<td><input type="text" id = "animal" name="animal" placeholder="Choose an animal...">
<td id="animals">
<span class="animal_list">
<p onclick="insertme('horse')">Horse</p>
</span>
<span class="animal_list">
<p onclick="insertme('goat')">Goat</p>
</span>
<span class="animal_list">
<p onclick="insertme('sheep')">Sheep</p>
</span>
<span class="animal_list">
<p onclick="insertme('cow')">Cow</p>
</span>
</div>
</tr>
</table>
And the CSS to hide the list:
#animals .animal_list {
display: none;
}
JQuery filter:
$(document).ready(function(){
$('#animal').keyup(function() {
var search = this.value.split(';');
$('.animal_list').each(function(index, element) {
var text = $(element).text().toLowerCase();
var show = search.filter(function(e) {
return e != '' && text.indexOf(e.toLowerCase()) >= 0;
}).length > 0;
$(element).toggle(show);
});
});
});
And here's some JavaScript that allows users to click on the option to input it in the textbox:
function insertme(label){
document.getElementById('animal').value = label;
//when selected, hide all of variable 1 list
var list = document.getElementsByClassName("animal_list");
for (var i = 0; i < list.length; i++) {
list[i].style.display = "none";
};
}
This works great as is. However, for my application, the users need to be able to duplicate rows dynamically. My idea was to copy the html from the div (the "animals" div) and repeat it for every row:
function add_row(ID) {
var table = document.getElementById(ID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
// insert a row label
// insert a row label
var col1 = row.insertCell(0);
col1.innerHTML = "Select an animal:"
// second column...
// insert a search box
var col2 = row.insertCell(1);
var element = document.createElement("input");
element.type = "text";
element.name = "animal";
col2.appendChild(element);
// get the existing elements
var existing_list = document.getElementById("animals");
// create new object (so I can delete the first)
var list_copy = existing_list
// delete old list so it's not duplicating jquery effect across all rows
existing_list.remove();
//append list to new row
col2.appendChild(list_copy);
}
However, this doesn't seem to work. The second row doesn't filter based on the list anymore. According to my development console, the div does indeed get deleted from the first row, then inserted in the second row, but the list of items is not displaying based on user input. In other words, the JQuery filtering stops working at the second row.
Any ideas how to fix this? I'm happy to abandon my approach if there's a better way (i.e., better than copying a div to a new row and deleting the div associated with the original row).
(P.S. sorry for slovenly mixing JavaScript with JQuery. I'm a bit of a noob with both).
Putting it all together:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
function add_row(ID) {
var table = document.getElementById(ID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
// insert a row label
var col1 = row.insertCell(0);
col1.innerHTML = "Select an animal:"
// second column...
// insert a search box
var col2 = row.insertCell(1);
var element = document.createElement("input");
element.type = "text";
element.name = "animal";
col2.appendChild(element);
// get the existing elements
var existing_list = document.getElementById("animals");
// create new object (so I can delete the first)
var list_copy = existing_list
// delete old list so it's not duplicating jquery effect across all rows
existing_list.remove();
//append list to new row
col2.appendChild(list_copy);
}
function insertme(label){
document.getElementById('animal').value = label;
//when selected, hide all of variable 1 list
var list = document.getElementsByClassName("animal_list");
for (var i = 0; i < list.length; i++) {
list[i].style.display = "none";
};
}
$(document).ready(function(){
$('#animal').keyup(function() {
var search = this.value.split(';');
$('.animal_list').each(function(index, element) {
var text = $(element).text().toLowerCase();
var show = search.filter(function(e) {
return e != '' && text.indexOf(e.toLowerCase()) >= 0;
}).length > 0;
$(element).toggle(show);
});
});
});
</script>
<style type="text/css">
#animals .animal_list {
display: none;
}
</style>
</head>
<body>
<table id = "table">
<tr>
<td>Select an animal:</td>
<td><input type="text" id = "animal" name="animal" placeholder="Choose an animal...">
<td id="animals">
<span class="animal_list">
<p onclick="insertme('horse')">Horse</p>
</span>
<span class="animal_list">
<p onclick="insertme('goat')">Goat</p>
</span>
<span class="animal_list">
<p onclick="insertme('sheep')">Sheep</p>
</span>
<span class="animal_list">
<p onclick="insertme('cow')">Cow</p>
</span>
</div>
</tr>
</table>
<input type="button" onclick="add_row('table')" value = "Add Row">
</body>
</html>
The HTML for each row was incorrect.
Unclosed tags and hanging end tags. I've adjusted it so that the cells are consistent.
id must be unique, so I've changed it to be class="animals", which may be helpful in the future for DOM selection.
changed CSS style #animals -> .animals
It's important that each row is encapsulated, self-contained, and consistent so that DOM traversal can be done reliably. This allows for code related to each DOM node to be self-contained, so you can treat them like components. It will also help with CSS styling.
With this organization, all you have to do is cloneNode(true) the row to add a new one, and for the events traverse within the row to select the DOM nodes you need to target.
I've used Event Delegation to attach a single event to the table that targets every input[name="animals"] node inside it. So all new rows get targeted correctly.
Since all the DOM traversal and event handlers are self-contained for each row, the same event handler can be reused for all nodes.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
function add_row(ID) {
var table = document.getElementById(ID);
var rowCount = table.rows.length;
// (full) clone the last row and append to table
table.appendChild(table.rows[rowCount - 1].cloneNode(true))
}
function insertme(el, label) {
var row = $(el).closest('tr')
row.find('input[name="animal"]')[0].value = label;
//when selected, hide all of variable 1 list
var list = row[0].getElementsByClassName("animal_list");
for (var i = 0; i < list.length; i++) {
list[i].style.display = "none";
};
}
$(document).ready(function() {
// event delegation on table for all inputs with name "animal"
$('#table').on('keyup', 'input[name="animal"]', function(event) {
var search = this.value.split(';');
// traverse DOM to find containing row, then search for animal list nodes
$(this).closest('tr').find('.animal_list').each(function(index, element) {
var text = $(element).text().toLowerCase();
var show = search.filter(function(e) {
return e != '' && text.indexOf(e.toLowerCase()) >= 0;
}).length > 0;
$(element).toggle(show);
});
});
});
</script>
<style type="text/css">
.animals .animal_list {
display: none;
}
</style>
</head>
<body>
<table id="table">
<tr>
<td>Select an animal:</td>
<td><input type="text" name="animal" placeholder="Choose an animal..."></td>
<td class="animals">
<span class="animal_list">
<p onclick="insertme(this,'horse')">Horse</p>
</span>
<span class="animal_list">
<p onclick="insertme(this,'goat')">Goat</p>
</span>
<span class="animal_list">
<p onclick="insertme(this,'sheep')">Sheep</p>
</span>
<span class="animal_list">
<p onclick="insertme(this,'cow')">Cow</p>
</span>
</td>
</tr>
</table>
<input type="button" onclick="add_row('table')" value="Add Row">
</body>
</html>
I need to retrieve date from the generic input field. The number of how many date (input field) user can create in form is unknown by me, so I count them by rowCount.
I'm not enable to extract the value of field (Syntax error maybe).
N.B when I lunch my code I get: Cannot set property '0' of undefined
html code:
<div>
<table id='dynamic_field_edit'>
<tbody>
<tr>
<td>Date</td>
<td><input type="text" placeholder="Enter date" /></td>
</tr>
<tr>
<td>Date:</td>
<td><input type="text" placeholder="Enter date" /></td>
</tr>
</tbody>
</table>
</div>
JS code :
var arrayDate = [];
var rowCount = document.getElementById('dynamic_field_edit').rows.length;
console.log(rowCount);
var allInputs = document.querySelectorAll('input');
for (let i = 0; i < allInputs.length; i++) {
arrayDate.push(allInputs[i].value);
}
console.log(arrayDate);
Edit:
After all suggested change it works, but it retrieve all values from input in document.
You just need to initialize your array:
var arrayDate = [];
EDIT:
Seems to work in this sample, can you compare to your code?
https://jsfiddle.net/emeLdecm/1/
(I added a button to fire off your JS, just to demonstrate)
Y you use jQuery syntax in plain javascript?
Select your table via:
table = document.getElementById('dynamic_field_edit');
and that iterate:
for (var i = 0, row; row = table.rows[i]; i++) {
// do your stuff
};
I find a way to achieve what I wanted to do by doing this.
#proggrock solution is also good for retrieving all input values in the document.
var arrayDate = [];
var rowCount = document.getElementById('dynamic_field_edit').rows.length;
console.log(rowCount);
$("#dynamic_field_edit").find('input:text')
.each(function() {
arrayDate.push($(this).val());
});
console.log(arrayDate);
Here is the following table code and I want to store all TD values into an Array.
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
For this I have written this following code:
function checkForm() {
var table = document.getElementsByClassName("item-row");
var arr = new Array();
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
arr.push(row.cells[j].val);
}
}
}
But this gives me no output...I am new to javascript so may be am missing something in big time.
Your code is almost right, the thing is that rows property work for tables not for trs so you have to take a table instead of the tr directly.
The other thing is that getElementsByClassName returns an array of your elements so you have to use [index] to get your element.
The last thing is that to get the value for the cell you can't use val, so use firstChild to get the child and value to get the value as in the code, or better as #pawel suggest directly cell.textarea :)
Try with this code:
function checkForm() {
var table = document.getElementsByClassName("yourTable")[0];
var arr = new Array();
for (var i = 0, row; row = table.rows[i]; i++) {
for (var j = 0, col; col = row.cells[j]; j++) {
arr.push(row.cells[j].firstChild.value);
}
}
console.log(arr);
}
<table class="yourTable">
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
<tr class="item-row">
<td class="item-name"><textarea>Item</textarea></td>
<td class="description"><textarea>Item</textarea></td>
<td><textarea class="cost">$0.00</textarea></td>
<td><textarea class="qty">0</textarea></td>
<td><span class="price">$0.00</span></td>
</tr>
</table>
<input type="button" onclick="checkForm();" value="check form"/>
Hope this helps,
What you have is a good first effort for being new to JavaScript, but, yes, there are quite a few items that need updating. :)
Here is what you would need to do what you are trying to do:
function checkForm() {
var rows = document.getElementsByClassName("item-row");
var arr = new Array();
for (i = 0; i < rows.length; i++) {
var cols = rows[i].getElementsByTagName("td");
for (j = 0; j < cols.length; j++) {
arr.push(cols[j].textContent);
}
}
}
You need to cycle through each row . . . the easiest way to do this by going from i = 0 to i < rows.length in your for loop.
Once you have a row, you need to gather all of the columns in the row, by finding all of the <td> elements (var cols = rows[i].getElementsByTagName("td"););
Then, you loop through each of those, just like you did with the rows (j = 0 to j < cols.length
Finally, to get the text contained in each td, you use the textContent property . . . values (i.e., the value property) are used only for <input> elements
There were a couple of syntax errors in there, too (you used , instead of ;, when building your for loop and you used val instead of value, when attempting to get the td content), but that was all that I saw.
Edit: I'm also assuming that you just did not paste your <table> tags in when you added your HTML, but, if you didn't your <tr> tags must be inside a <table.
Edit 2: My solution also skips the looking at the tags inside the <td> elements, since they are not standard (4 contain <textarea> inputs and the 5th a <span>). If you want to go down one more level of detail, you could use .value on the textareas and (again) .textContent on the <span>. By using .textContent one level up, you are ignoring all HTML tags insid the <td> tags and returning only the text.
This is my first attempt in Javascript, so may be this is fairly easy question.
I need to access row element of a table, each row contains checkbox and two other column. If checkbox is checked, i need to get the id of checkbox.
I made following attempt but element_table.rows returns undefined, therefore i could not proceed. I debugged using Inspect element tool of eclipse and found element_table contains the rows.
Please suggest where I am making a mistake.
Javascript code:
function myfunction3(){
var element_table = document.getElementsByName('collection');
var element_tableRows = element_table.rows;
var selectedTr = new Array();
var data = "";
for(var i =0 ; element_tableRows.length;i++)
{
var checkerbox = element_tableRows[i].getElementsByName('checkmark');
if(checkerbox.checked){
selectedTr[selectedTr.length] = element_tableRows[i].getAttribute("name");
data = data + element_tableRows[i].getAttribute("name");
}
}
var element_paragraph = document.getElementsByName('description');
element_paragraph.innerHTML = data;
}
html code:
<table name="collection" border="1px">
<tr name="1">
<td><input type="checkbox" name="checkmark"></td>
<td>Tum hi ho</td>
<td>Arjit singh</td>
</tr>
<tr name="2">
<td><input type="checkbox" name="checkmark"></td>
<td>Manjha</td>
<td>Somesh</td>
</tr>
<tr name="3">
<td><input type="checkbox" name="checkmark"></td>
<td>Ranjhana</td>
<td>A.R Rehman</td>
</tr>
</table>
<input type="button" value="Check" onclick="myfunction3()">
here's a working version
function myfunction3(){
var element_table = document.getElementsByName('collection');
var element_tableRows = element_table[0].rows;
var selectedTr = new Array();
var data = "";
for(var i =0 ; i < element_tableRows.length;i++)
{
var checkerbox = element_tableRows[i].cells[0].firstChild;
if(checkerbox.checked){
//selectedTr[selectedTr.length] = element_tableRows[i].getAttribute("name"); //not sure what you want with this
data = data + element_tableRows[i].getAttribute("name");
}
}
var element_paragraph = document.getElementsByName('description');
element_paragraph.innerHTML = data;
alert(data);
}
http://jsfiddle.net/eZmwy/
jsfiddle for your example, your problem is mainly at when you getElementsByName you need to specify the index, also not that not all getElement methods are available in the table
i would also suggest you learn jQuery, this makes life easier, also not sure why you want to display the data as 1,2,3 the name on the tr... seems pretty strange to me
Actually this line
var element_table = document.getElementsByName('collection');
will return collection of elements. If you are sure that you have exactly one table with the specified name, try this approach:
var element_table = document.getElementsByName('collection')[0];
actually if you are using jQuery (very recommanded )
you can do something like
var idsArray = [];
$("[name=collection] tr td [type=checkbox]:checked").parent().each(function() {
idsArray .push($(this).attr('name'))
});
this answer related only to jQuery use (which is same as javascript only more compiled.)
This is a function that, when passed a table as an argument, applies a different style color to alternating rows to improve readability. i.e. first row is dark grey, second row is light grow, third row is dark grey etc.
As mentioned, it gets passed the whole table as an argument. None of the rows have ids. Starting at this line var aTBODY = oTable.getElementsByTagName("tbody");, I understand what is happening. Namely, it gets the table body and then all the rows within it and stripes them alternately.
1) But what is happening exactly in the first five lines of the program? The comments don't explain it clearly for me.
2) does looping over a table length (i.e idArray.length) create an array of rows? what is happening with var id = idArray[indx]; ?
3) When it says, in the comments, get the table that corresponds to this id, using the code var oTable = document.getElementById(id) why is this a necessary step? what is happening?
thank you if you can explain
function createStripedTable(idArray) {
// for each table ID that we're given, stripe all the rows.
for (var indx = 0; indx < idArray.length; indx++) {
var id = idArray[indx];
// get the table that corresponds to this ID
var oTable = document.getElementById(id);
if (oTable == null)
return;
// get its table body, which contains all the TR tags
var aTBODY = oTable.getElementsByTagName("tbody");
// set the CSS class for each one of the TR tags
for (var i = 0; i < aTBODY.length; i++) {
// get an array of all the TR tags in the TBODY
var aTR = aTBODY[i].getElementsByTagName("tr");
for (var j = 0; j < aTR.length; j++) {
// the % operator divides the given number by another
// and returns the remainder. This is how we alternate the
// rows.
aTR[j].className = (j % 2 == 1) ? "stripe1" : "stripe2";
}
}
}
}
Here's the code that's calling it.
function() {createStripedTable(new Array("MSFTQuotes"))
Here's an excerpt of the one and only one table that is passed.
<body>
<table id="MSFTQuotes">
<thead>
<tr>
<th colspan="7" align="center">
<span class="TableTitle">Stock Activity for Aug 5, 2008 - Nov 5, 2008 </span>
</th>
</tr>
<tr>
<th align="center" width="14%">
<div align="right" class="style5">
Date</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
Open</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
High</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
Low</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
Close</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
Volume</div>
</th>
<th align="center" width="14%">
<div align="right" class="style5">
Adj Close</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td align="right">
5-Nov-08
</td>
<td align="right">
29.21
</td>
<td align="right">
29.36
</td>
<td align="right">
29.03
</td>
<td align="right">
29.31
</td>
<td align="right">
95,337,696
</td>
<td align="right">
29.31
</td>
The function accepts an array of id values corresponding to table elements. It loops through those IDs and does its striping work on all of the tbody elements within the tables.
Somewhat more annotated (see TJC:s):
function createStripedTable(idArray) {
// for each table ID that we're given, stripe all the rows.
// TJC: Loop through all of the IDs in the given array
for (var indx = 0; indx < idArray.length; indx++) {
// TJC: Get the ID value for index `indx` in the array
var id = idArray[indx];
// get the table that corresponds to this ID
var oTable = document.getElementById(id);
if (oTable == null) // TJC: Invalid ID, ignore it
return;
// get its table body, which contains all the TR tags
// TJC: Get the `tbody`s under the table. One table
// can have multiple `tbody` elements.
var aTBODY = oTable.getElementsByTagName("tbody");
// set the CSS class for each one of the TR tags
for (var i = 0; i < aTBODY.length; i++) {
// get an array of all the TR tags in the TBODY
// TJC: It's actually a NodeList, but you can largely
// treat it as an array
var aTR = aTBODY[i].getElementsByTagName("tr");
for (var j = 0; j < aTR.length; j++) {
// the % operator divides the given number by another
// and returns the remainder. This is how we alternate the
// rows.
aTR[j].className = (j % 2 == 1) ? "stripe1" : "stripe2";
}
}
}
}
The good news is that IE9 finally supports the nth-child pseudo-class, so someday you'll be able to stop doing this with code.
idArray is an array of all IDS for more than one table. This function will change the alternate rows for each of the tables whose id is in idArray.
The outer loop is iterating through ids. The first five lines inside the loop are assuming they are ids of tables, and fetching the contents of the table element corresponding to each ID.
The next five lines in the loop then fetch the table body contents and change the css class of alternate rows.
Add these lines before the first for loop in the code
var tabarray=new Array();
tabarray.push(thetableidYoupassed);
idArray=tabArray
'thetableidYoupassed' is the actual argument with which you called the function 'createStripedTable'
Keep the rest of the code as it is...This should work fine...
Your method accepts an array of table IDs. So all the tables need to have IDs.
function createStripedTable(idArray) { //idArray is an array of table IDs
Then it loops through them and gets the ID one by one
for (var indx = 0; indx < idArray.length; indx++) {
var id = idArray[indx]; //this is the ID of a table
Then it checks whether the table actually exists in the DOM or not
var oTable = document.getElementById(id); //IF the table with a matching ID is not found, you get NULL
if (oTable == null)
return; //no table that matches the ID? return
Ideally, that line should be continue or something similar. Because in this instance. If you pass your method an array like ['table1', 'table2', 'faketable', 'table3'], your method won't strip table3 because it never gets there in the array (because of the return)