I have a scenario where there is a table of 4 rows, in the 4th row is a textbox. When an "onchange" event of the textbox is triggered, I want to extract the data in the cells of the same specific row into another table. and ofcourse my table is consisted of more than one row.
<div class="ProductsTable">
<table class="tablestyle">
<tr>
<th>Item</th>
<th>Price</th>
<th>Preview</th>
<th class="auto-style4">Quantity</th>
<th class="auto-style15">Selected Items</th>
</tr>
<tr id="row1">
<td class="auto-style1" id="item_name">Sofa</td>
<td class="auto-style2" id="item_price">$280.00</td>
<td class="auto-style3">
<img class="itemimage" src="images\sofa1.jpg" />
</td>
<td class="auto-style4">
<input class="quantitybox" id="item_quantity" type="text" onchange="get_quantity();" />
</td>
<td rowspan="10">
<table class="InvoiceTable" id="invoice">
<tr>
<th class="auto-style7">Item</th>
<th class="auto-style2">Price</th>
<th class="auto-style4">Quantity</th>
</tr>
</table>
</td>
</tr>
</table>
</div>
And my javascript is:
function get_quantity() {
var table = document.getElementById("invoice");
var row = table.insertRow(1);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var cell3 = row.insertCell(2)
cell1.innerHTML = document.getElementById("item_name").innerHTML;
cell2.innerHTML = document.getElementById("item_price").innerHTML;
cell3.innerHTML = document.getElementById("item_quantity").value;
}
How can I create a loop to check through all my table when an "onchange" event is triggered. As I actually have 10 rows in my table.
Preferably without using jquery.
If I understand you correctly you are looking for a function to copy the content of the changed row, that is the data in each column, into the invoice table.
I expect the rows to be created dynamicaly with some sort of iteration. When iterating I expect a unique number is availabe why this can be used as a general selector.
Here is a function to do this:
function get_quantity(rowNumber) {
var table = document.getElementById("invoice" + rowNumber);
var row = table.insertRow(1);
var columns = document.getElementById("row" + rowNumber).childNodes;
var dataColumnIndex = 0;
for (var i = 0; i < columns.length; i++) {
if (columns[i].className == "data") {
var cell = row.insertCell(dataColumnIndex);
cell.innerHTML = columns[i].innerHTML;
dataColumnIndex++;
}
}
var inputQuantity = document.getElementById("item_quantity" + rowNumber).value
row.insertCell(dataColumnIndex).innerHTML = inputQuantity;
}
You select what columns to copy by marking the them with class data.
I gets the invoice table by expecting it to have the id invoice + number. Fx. invoice1. Same goes with each row and the input field.
Here is a plunker with a full example.
Edit
There should only be a single invoice table where all products are added to.
By selecting the same table for row insertion in the function this is fixed.
This updated plunker has the change
Related
I am working on a project using HTML5, CSS3, Javascript and Bootstrap.
The current page I'm having issues with has an HTML Table that requires four main functionalities: add new row, move row up, move row down, delete row.
To be more specific, I need it to be able to:
Provide the user the option to add an IP range to a new row at the bottom of the table.
Provide the new IP Range with an order number that follows the previously defined order. (Example: if there are 10 IP Ranges listed, the new IP Range should have an order number of 11)
Provide user buttons in each row to move an IP Range up or down in order.
Provide the user the option to delete an IP Range.
Right now I can add IP Ranges to a new row at the bottom of the table. I can move rows up and down. I can also delete a row.
Currently my code requires me to select the row I plan to move before I move it, which is a feature I would like to remove.
What I need help with:
1. How can I remove the need to SELECT the row before doing these functionalities? Example: if the user presses the UP arrow in row 2, just move the IP Range from row 2 to row 1?
2. How can I automatically reorder the rows based on if a row is deleted? Example: if there exists an IP Range in the table, it should start with a value Order=1. Any subsequent IP Range rows 'n' should have a value of 1+n. If there are three IP Ranges in the table and the second IP Range is deleted, how can I ensure that the order will not be (1, 3) and instead (1, 2)?
Note: the information in the table in the example provided is static but I will be filling dynamically from database. I will not know beforehand how many IP Ranges there are.
code:
function SomeDeleteRowFunction() {
// event.target will be the input element.
var td = event.target.parentNode;
var tr = td.parentNode; // the row to be removed
tr.parentNode.removeChild(tr);
}
//This function adds a user-input IP Range to the end of table body
function addEndIPRanges() {
//Accessing table body
var table = document.getElementById("myTableBody");
//Insert row at end of table body (-1 appends)
var row = table.insertRow(-1);
//Insert 3 new cells into new row
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var rowCount = table.rows.length;
cell1.innerHTML = rowCount;
cell2.innerHTML = document.getElementById('addIPRange').value;
}
"use strict";
const tbody = document.querySelector("#table tbody");
let selected = null;
tbody.addEventListener("click", function(e) {
let row = e.target.closest("tr");
if (row === selected) {
row.classList.toggle("selected")
selected = null;
} else {
if (selected) {
selected.classList.toggle("selected");
}
selected = row;
row.classList.toggle("selected");
}
});
function upNdown(direction) {
let up, down;
if (selected) {
up = direction == "up" ? selected : selected.nextElementSibling;
down = direction == "up" ? selected.previousElementSibling : selected;
if (up && down) {
tbody.insertBefore(up, down); // put up before down
var temp = up.firstElementChild.textContent; // swap first cells' text content
up.firstElementChild.textContent = down.firstElementChild.textContent;
down.firstElementChild.textContent = temp;
}
}
}
tr {
cursor: pointer
}
.selected {
background-color: red;
color: #fff;
font-weight: bold
}
<figure class="text-center mb-3">
<h1 class="display-5">IP Range Management</h1>
</figure>
<hr>
<input type='text' id='addIPRange' />
<button style="text-align: center;" onclick="addEndIPRanges()">Add IP Range</button>
<hr>
<h4 class="iprangetableheader" style="text-align: center;">IP Ranges</h4>
<table id="table" style="margin: auto; width: 75%;">
<thead>
<tr style="text-align: center;">
<th scope="col">Order</th>
<th scope="col">IP Range</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody id="myTableBody">
<tr>
<td>1</td>
<td>255.255.255.255</td>
<td><button onclick="upNdown('up');">↑</button>
<button onclick="upNdown('down');">↓</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
<tr>
<td>2</td>
<td>234.132.1.642</td>
<td><button onclick="upNdown('up');">↑</button>
<button onclick="upNdown('down');">↓</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
<tr>
<td>3</td>
<td>24.32.2.25</td>
<td><button onclick="upNdown('up');">↑</button>
<button onclick="upNdown('down');">↓</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
</tbody>
</table>
<hr>
Link to JS Fiddle: What I've got so far
It might look weird but it works:
You can send the clicked button as a parameter to the function and derive the row which it belongs to. That row is your required element.
const tbody = document.querySelector("#table tbody");
function upNdown(direction,button) {
// Here button parameter is getting the button which is clicked
// Its parent element is a td whose parent element is a tr which is to be moved and voila
let selected = button.parentElement.parentElement;
let up, down;
if (selected) {
up = direction == "up" ? selected : selected.nextElementSibling;
down = direction == "up" ? selected.previousElementSibling : selected;
if (up && down) {
tbody.insertBefore(up, down); // put up before down
var temp = up.firstElementChild.textContent; // swap first cells' text content
up.firstElementChild.textContent = down.firstElementChild.textContent;
down.firstElementChild.textContent = temp;
}
}
}
<table id="table" style="margin: auto; width: 75%;">
<thead>
<tr style="text-align: center;">
<th scope="col">Order</th>
<th scope="col">IP Range</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody id="myTableBody">
<tr>
<td>1</td>
<td>255.255.255.255</td>
<td><button onclick="upNdown('up',this);">↑</button>
<button onclick="upNdown('down',this);">↓</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
<tr>
<td>2</td>
<td>234.132.1.642</td>
<td><button onclick="upNdown('up',this);">↑</button>
<button onclick="upNdown('down',this);">↓</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
<tr>
<td>3</td>
<td>24.32.2.25</td>
<td><button onclick="upNdown('up',this);">↑</button>
<button onclick="upNdown('down',this);">↓</button>
<input type="button" value="Delete Row" onclick="SomeDeleteRowFunction()">
</td>
</tr>
</tbody>
</table>
This is how you can maintain the index:
Add a class ip-row or whatever you want to all the tr elements which hold the ip.
Remember to give that class to only the elements which hold the ip otherwise it will index all the rows.
Take that class and insert the following code in the delete function and put it after you have removed the element like this-
function SomeDeleteRowFunction() {
// event.target will be the input element.
var td = event.target.parentNode;
var tr = td.parentNode; // the row to be removed
tr.parentNode.removeChild(tr);
// Select all trs
let trs = Array.from(tbody.querySelectorAll('.ip-row'))
// Start index
let index = 1;
trs.forEach((tr) => {
// For all trs give a value to its first td which holds the index
tr.querySelectorAll('td')[0].innerHTML = index;
// increment the index
index++
})
}
I have a table with td's that if double clicked, become input fields. Now, I want to jump from an input to another.
I already made this to change my td to an input:
var id = $(this).closest("tr").find("cell_id").text();
var html = $(this).text();
var input = $('<input id="txt_id" type="text"/>');
input.val(html);
$(this).html(input);
And this to jump from one to other:
$("#mainTable").on("keydown","td.mainCellQuantity",function(e) {
var keyCode = e.keyCode || e.which;
if(keyCode==9||keyCode==13){
e.preventDefault();
var cellIndex = $(this).index();
$(this).closest('tr').next().children().eq(cellIndex).dblclick();
}
});
The above codes are working but the input's are not focused. I want them to be focused after tab press.
var rows = parseInt(document.getElementById("my_table").getElementsByTagName("tbody")[0].rows.length);
var table = document.getElementById("mainTable").getElementsByTagName("tbody")[0];
var row = table.insertRow(rows);
var cell1 = row.insertCell(0);
cell1.innerHTML = editable_cell_being_transformed_to_input;
I want this cell1 to be focused since upon double clicked, it only change the td to input but not focusing:
An alternative: Instead of replacing td with input you can set contenteditable attribute to true for each td. This allows editing the td content. Also pressig Tab key moves focus to next td by default.
Example:
<table>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
<tr>
<td contenteditable="true">data 1</td>
<td contenteditable="true">data 2</td>
<td contenteditable="true">data 3</td>
</tr>
</table>
I have a small question: I want to get a one table value row by row my selected cell value. I use for loop for select each row.For loop is correct but I cannot see anything in alert.
My table is
<div style="overflow-x:auto;">
<table id="abctable" class="display nowrap" cellspacing="0" border="0">
<thead>
<th width="15%">Registered Agents</th>
</thead>
<c:forEach items="${Agentsdetail}" var="Agent">
<tr>
<td><input type="text" id="a" value="${Agent.vatNumber}"></td>
</tr>
</c:forEach>
</table>
</div>
I want to select this table cell value of each row to alert. I use this jQuery code:
<script>
$(document).ready(function () {
var table = document.getElementById("abctable");
var rowCount = table.rows.length;
for (i = 1; i <= rowCount; i++) {
alert($('#userstable tr:eq(1) td:eq(0)').val());
}
});
</script>
The row count is successful and when run a program, it returns nothing in the alert. Please help me
As MartinWebb said, the table id is "usertable" not "abctable"
But also the value you are looking for is on the input, not the table cell (td), so your selector is incomplete.
$(document).ready(function() {
var table = document.getElementById("userstable");
var rowCount = table.rows.length;
for (i = 1; i <= rowCount; i++) {
alert($('#userstable tr:eq(1) td:eq(0) input').val());
}
});
I need to edit values in a table where the rows/cells are generated dynamically so I they have no html id. I am currently doing this by going to tr:nth-child, but this only works if the value I set for rowID corresponds to that position in the table. Ex: If I remove the 3rd item from the table, the item with rowID=4 is now the 3rd child of the tr, and the following code will edit the wrong cells.
// I get the rowID like this:
rowID = $(this).data("row-id");
// This is what I'm doing now to edit the table:
$('#or-table tr:nth-child(' + rowID + ') td:nth-child(3)').html($('#aff-selector').val());
$('#or-table tr:nth-child(' + rowID + ') td:nth-child(4)').html($('#editor-code').val());
$('#or-table tr:nth-child(' + rowID + ') td:nth-child(5)').html($('#editor-lat').val());
$('#or-table tr:nth-child(' + rowID + ') td:nth-child(6)').html($('#editor-long').val());
<!-- This is the table: -->
<table id="or-table" class="table table-condensed table-hover table-striped bootgrid-table">
<thead>
<tr>
<th data-column-id="id" data-identifier="true" data-type="numeric">ID</th>
<th data-column-id="aff" align="center">Affiliation</th>
<th data-column-id="code">Symbol Code</th>
<th data-column-id="lat">Latitude</th>
<th data-column-id="long">Longitude</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">Commands</th>
</tr>
</thead>
<tbody></tbody>
</table>
You could dynamically assign the row ids using a for loop and then redo that calculation every time you remove a row.
function foo () {
var rowCount = $('#or-table tbody tr').length;
for (i=1;i <= rowCount; i++) {
$('#or-table tbody tr:nth-child("'+i+'")').data('row', i);
}
}
You could run this function on $(document).ready and again after the removal of any row.
Use the HTMLTableElement interface. BTW, why would you need to remove a <td>? Wouldn't be easier just to remove the data inside the <td>?
Get a reference to the <table>
-var or = document.getElementById('or-table');
Then use the .rows property.
-or.rows[0] // first row of table
Next, use the .cells property.
-or.rows[0].cells[2] // first row, 3rd cell
Finally, edit the value of cell with innerHTML or textContent.
-or.rows[0].cells[2].innerHTML='test' // set first row, 3rd cell content to "test"
The following Snippet demonstrates the use of the HTMLTableElement interface:
SNIPPET
var or = document.getElementById('or-table');
function seekCell(row, cell) {
var data = document.getElementById('data').value;
var row = parseInt(row, 10);
var cell = parseInt(cell, 10);
var rows = or.rows.length; // max number of rows
var cells = rows * 6; //max number of cells
(row > rows) ? row = rows: row = row - 1;
(cell > cells) ? cell = cells: cell = cell - 1;
var tgt = or.rows[row].cells[cell];
tgt.innerHTML = data;
}
[type='number'] {
width: 30px;
}
<!-- This is the table: -->
<table id="or-table" class="table table-condensed table-hover table-striped bootgrid-table">
<thead>
<tr>
<th data-column-id="id" data-identifier="true" data-type="numeric">ID</th>
<th data-column-id="aff" align="center">Affiliation</th>
<th data-column-id="code">Symbol Code</th>
<th data-column-id="lat">Latitude</th>
<th data-column-id="long">Longitude</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">Commands</th>
</tr>
</thead>
<tbody>
<tr>
<td>01</td>
<td>NONE</td>
<td>🗡</td>
<td>20</td>
<td>30</td>
<td>KILL</td>
</tr>
<tr>
<td>02</td>
<td>NONE</td>
<td>🖉</td>
<td>30</td>
<td>30</td>
<td>EDIT</td>
</tr>
</tbody>
</table>
<form id='f1' name='f1' onsubmit='seekCell(row.value, cell.value)'>
<fieldset>
<legend>Row & Cell</legend>
<label>Row:
<input id='row' name='row' type='number' min='1' max='99'>
</label>
<label> <small>Note: The first row is the <thead></small>
</label>
<br/>
<label>Cell:
<input id='cell' name='cell' type='number' min='1' max='6'>
</label>
<label><small> Note: The number will be adjusted for 0-Index enumeration. (i.e. input -1)</small>
</label>
<br/>
<label>Data:
<input id='data'>
</label>
<input type='submit'>
</fieldset>
</form>
I am running into a very small issue which has taken more than two hours.
What I want is to insert a row in an HTML table and then sort it in ascending order. I've looked at this answer and thought that I can get this simple task working, but in vein.
Here is my little form and table:
Name: <input type="text" name="name" id="name"><br>
Status: <input type="text" name="status" id="status">><br>
<button onclick="myFunction(document.getElementsByName('name')[0].value,document.getElementsByName('status')[0].value)">Click</button><br><br>
<table id="myTable">
<thead>
<tr>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Doe, John</td>
<td>Approved</td>
</tr>
<tr>
<td>aaa, John</td>
<td>Approved</td>
</tr>
</tbody>
</table>
My inline JavaScript function looks like this:
function myFunction(name, status) {
var table = document.getElementById('myTable').getElementsByTagName('tbody')[0];
var row = table.insertRow(0);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.innerHTML = name;
cell2.innerHTML = status;
// The following code should sort the table.
var tbody = $('#mytable').find('tbody');
tbody.find('tr').sort(function (a, b) {
return $('td:first', a).text().localeCompare($('td:first', b).text());
}).appendTo(tbody);
}
Please note that adding a row to the table works fine, it just adds it to the top.
There are no console errors. The code which (apparently) should sort the table does not do anything. I've the subset of my HTML here on Fiddle, and yes that works fine.
I know about jQuery tablesorter plugin but do not need to use it.
This selector:
$('#mytable')
...is incorrect. Your table's ID is myTable, and IDs are case-sensitive. Here's a working version of your code with that fix.