I have been stuck on an issue where I am trying to use Javascript to add and remove a row from a table.
I got the add part working, the delete somewhat. The delete fails if you delete the first row or a row in the middle (live code can be seen here
I uploaded its code on PasteBin
<script type="text/javascript">
var itemNumber = 0
var currentRow = 0;
var selectedRow = 0;
function theIndex(theRow){
selectedRow = theRow;
}
document.getElementById("addItem").addEventListener("click", function(){
if (document.getElementById('whatToDo').value != ""){
currentRow++;
var table = document.getElementById('myList');
var row = table.insertRow(currentRow);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var cell3 = row.insertCell(2);
var cell4 = row.insertCell(3);
itemNumber++;
// alert(currentRow);
// cell1.innerHTML = itemNumber;
cell2.innerHTML = document.getElementById('whatToDo').value;
cell3.innerHTML = document.getElementById('whenToDo').value;
cell4.innerHTML = document.getElementById('whereToDo').value;
row.addEventListener('click', theIndex.bind(null, currentRow));
document.getElementById('whatToDo').value = "";
document.getElementById('whenToDo').value = "";
document.getElementById('whereToDo').value = "";
}
});
document.getElementById("removeItem").addEventListener("click", function(){
// var theRow = document.getElementById('whatToMark').value;
var theRow = selectedRow;
alert("index: " +theRow + " elements: " + currentRow);
if (theRow > 0){
document.getElementById("myList").deleteRow(theRow);
document.getElementById('whatToMark').value = "";
currentRow--;
itemNumber--;
}
selectedRow = 0;
});
document.getElementById("markAsDone").addEventListener("click", function(){
// var theRow = document.getElementById('whatToMark').value;
var theRow = selectedRow;
alert("index: " +theRow + " elements: " + currentRow);
var table = document.getElementById('myList');
if (theRow != 0){
table.rows[theRow].style.setProperty("text-decoration", "line-through");
document.getElementById('whatToMark').value = "";
}
selectedRow = 0;
});
</script>
I am learning Javascript and wanted to do more than the exercise that was being given by adding new features to it.
Your approach to mark the current selected row has some issues:
row.addEventListener('click', theIndex.bind(null, currentRow));
Instead of using a global variable I suggest to use a row attribute (or class). Hence, change that line to:
row.addEventListener('click', function(e) {
document.querySelectorAll('tr[selected]').forEach(function(item) {
item.removeAttr('selected');
})
row.setAttribute('selected', true);
});
Add the attribute selected for the current row and remove the same attribute for other rows.
In this way, when you need to get the current selected row you can simply:
var rSelected = document.querySelector('tr[selected]');
var theRow = (rSelected == null) ? 0 : rSelected.rowIndex;
var itemNumber = 0
var currentRow = 0;
var selectedRow = 0;
function theIndex(theRow) {
selectedRow = theRow;
}
document.getElementById("addItem").addEventListener("click", function () {
if (document.getElementById('whatToDo').value != "") {
currentRow++;
var table = document.getElementById('myList');
var row = table.insertRow(currentRow);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var cell3 = row.insertCell(2);
var cell4 = row.insertCell(3);
itemNumber++;
// alert(currentRow);
// cell1.innerHTML = itemNumber;
cell2.innerHTML = document.getElementById('whatToDo').value;
cell3.innerHTML = document.getElementById('whenToDo').value;
cell4.innerHTML = document.getElementById('whereToDo').value;
//row.addEventListener('click', theIndex.bind(null, currentRow));
row.addEventListener('click', function(e) {
document.querySelectorAll('tr[selected]').forEach(function(item) {
item.removeAttr('selected');
})
row.setAttribute('selected', true);
});
document.getElementById('whatToDo').value = "";
document.getElementById('whenToDo').value = "";
document.getElementById('whereToDo').value = "";
}
});
document.getElementById("removeItem").addEventListener("click", function () {
// var theRow = document.getElementById('whatToMark').value;
var rSelected = document.querySelector('tr[selected]');
var theRow = (rSelected == null) ? 0 : rSelected.rowIndex;
if (theRow > 0) {
document.getElementById("myList").deleteRow(theRow);
//document.getElementById('whatToMark').value = "";
currentRow--;
itemNumber--;
}
selectedRow = 0;
});
document.getElementById("markAsDone").addEventListener("click", function () {
// var theRow = document.getElementById('whatToMark').value;
var theRow = selectedRow;
alert("index: " + theRow + " elements: " + currentRow);
var table = document.getElementById('myList');
if (theRow != 0) {
table.rows[theRow].style.setProperty("text-decoration", "line-through");
document.getElementById('whatToMark').value = "";
}
selectedRow = 0;
});
<div class="container">
<div class="row">
<div class="col-lg-4 col-sm-6">
<table class="table table-hover">
<tr>
<td colspan="3">
<h1>To Do List Example</h1>
</td>
</tr>
<tr>
<th><label>Item</label></th>
<th><label>Date</label></th>
<th><label>Location</label></th>
</tr>
<tr>
<td>
<input type="text" id="whatToDo" value="">
</td>
<td>
<input type="date" id="whenToDo" value="">
</td>
<td>
<input type="text" id="whereToDo" value="">
</td>
</tr>
<tr>
<td>
<button id="addItem" class="btn btn-default btn-primary active">
<i class="fas fa-plus"></i> Add This Item
</button>
</td>
<td>
<button id="markAsDone" class="btn btn-default ">
<i class="fas fa-check"></i> Mark As Done
</button>
</td>
<td>
<button id="removeItem" class="btn btn-default">
<i class="fas fa-trash-alt"></i> Remove Item
</button>
</td>
</tr>
</table>
</div>
</div>
<div class="row">
<div class="col-lg-4 col-sm-6">
<table class="table table-hover" id="myList">
<tr>
<th><label></label></th>
<th><label>Event</label></th>
<th><label>Date</label></th>
<th><label>Location</label></th>
</tr>
</table>
</div>
</div>
</div>
This line is throwing a null value error:
document.getElementById('whatToMark').value = "";
Neither in your JS, nor in your HTML, do you ever set an element to the ID of whatToMark.
Related
I have Vue component with a table with users data:
<table class="worker-table" id="worker-table">
<tr>
<th><b>Phone number</b></th>
<th><b>Debet card</b></th>
<th><b>Money</b></th>
<th><b>Work hours</b></th>
<th><b>Responsible</b></th>
<th><b>Delete</b></th>
</tr>
<tr>
<tr v-for="worker in workers">
<td >
<div v-if="worker.parent == 1">
<strong v-on:click="toggleChildWorkers(worker)" class="pointer">
{{worker.phone}}(+{{child_workers[worker.id].length}})
</strong>
</div>
<div v-else>
{{worker.phone}}
</div>
</td>
<td>{{worker.debit_card}}</td>
<td>{{worker.money}}</td>
<td>{{worker.work_hours}}</td>
<td>{{worker.responsible_for_money}}</td>
<td>
<a href="#"
v-bind:disabled="(application.state > CLOSED_ST)? true: false"
class="btn btn-xs btn-danger"
v-on:click="deleteEntry(worker.id)"
>
Delete
</a>
</td>
</tr>
</table>
The button in the last <td> successfully deletes worker from the table.
Function toggleChildWorkers insert new rows with child workers and delete (hide, actually) them like this:
toggleChildWorkers(parentWorker)
{
var table = document.getElementById("worker-table");
var childWorkers = this.child_workers[parentWorker.id];
var childWorkersCount = childWorkers.length;
var parentWorkersIndexes = this.openAccordionsIndexes;
var dI = 0;
var userWantsCloseThisAccordion = false;
var indexOfClosingAcc = -1;
console.log(parentWorker);
for (var j = 0; j < parentWorkersIndexes.length; j++)
{
if (parentWorkersIndexes[j] < parentWorker.index)
{
dI += this.openAccordionsStrCount[j];
}
else if (parentWorkersIndexes[j] == parentWorker.index)
{
userWantsCloseThisAccordion = true;
indexOfClosingAcc = j;
}
}
if (userWantsCloseThisAccordion)
{
for (var i = 0; i < this.openAccordionsStrCount[indexOfClosingAcc]; i++)
{
table.deleteRow(parentWorker.index + 3 + dI);
}
this.openAccordionsIndexes.splice(indexOfClosingAcc, 1);
this.openAccordionsStrCount.splice(indexOfClosingAcc, 1);
return;
}
this.openAccordionsIndexes.push(parentWorker.index);
this.openAccordionsStrCount.push(childWorkersCount);
for (var i = 0; i < childWorkersCount; i++)
{
var row = table.insertRow(parentWorker.index + 3 + dI + i);
var cell1 = row.insertCell(0);
cell1.style.cssText = this.styleOfOpenAccStrings;
var cell2 = row.insertCell(1);
cell2.style.cssText = this.styleOfOpenAccStrings;
var cell3 = row.insertCell(2);
cell3.style.cssText = this.styleOfOpenAccStrings;
var cell4 = row.insertCell(3);
cell4.style.cssText = this.styleOfOpenAccStrings;
var cell5 = row.insertCell(4);
cell5.style.cssText = this.styleOfOpenAccStrings;
var cell6 = row.insertCell(5);
cell6.style.cssText = this.styleOfOpenAccStrings;
cell1.innerHTML = (childWorkers[i].phone === undefined) ?
'' : childWorkers[i].phone;
cell2.innerHTML = (childWorkers[i].debit_card === undefined) ?
'' : childWorkers[i].debit_card;
cell3.innerHTML = (childWorkers[i].money === undefined) ?
'' : childWorkers[i].money;
cell4.innerHTML = (childWorkers[i].work_hours === undefined) ?
'' : childWorkers[i].work_hours;
cell5.innerHTML = childWorkers[i].responsible_for_money;
cell6.innerHTML = "<a href=\"#\"\n" +
" v-bind:disabled=\"(application.state > CLOSED_ST)? true: false\"\n" +
" class=\"btn btn-xs btn-danger\"\n" +
" v-on:click=\"deleteEntry(props.row.index)\"\n" +
" >";
row.className = "openAccordionRow";
}
},
As you can see, I'm trying to embed buttons in the new cells of inserted rows (blue ones). But they are not displayed as it was intended and don't work at all.
How can I embed button with Vue code into new cell of inserted row?
I found a simple solution here. But I did't understand it at the beginning and use it without closure and it did't work as I expected. Then I found topic about Javascript infamous loop issue
and used the closure magic:
for (var i = 0; i < childWorkersCount; i++)
{
/* ...
...
...
*/
var btn = document.createElement('input');
btn.type = "button";
btn.className = "btn btn-xs btn-danger";
btn.value = "Delete " + childWorkers[i].phone;
var app = this;
var parentId = parentWorker.id;
btn.onclick = function (worker) {
return function () {
app.deleteEntryById(worker.id, parentId);
};
}(childWorkers[i]);
}
HTML part... a To do list with 4 properties: the property "description" its not to be shown on the table. But when you dbclick on first cell(title), it should return all the 4 properties.
<body>
<h1 id="h1">ToDo Lijst</h1>
<label for="item">Titel</label><br>
<input type="text" id = "Item"><br><br>
<!--<p style="color:red; font-size:18px;" id="FoutInput"></p>-->
<label for = "aantal">Omschrijving</label><br>
<input class="desc" type="text" id="description"><br><br>
<label for="person">Toegewezen Person</label><br>
<input type="text" id = "person"><br><br>
<label for="deadline">Deadline</label><br>
<input type="text" id="deadline">
<button type = "button" onclick="Toevoegen()"><span>+</span></button>
<button type="button" onclick="Edit()" >Aanpassen</button>
<button style="background-color: crimson" onclick="Verwijderen()"><i class="fa fa-trash-o"></i></button>
<p style="color:red; font-size:15px;" id="FoutInput"></p>
<table id="table">
<tr>
<th>Titel</th>
<th>Toegewezen Person</th>
<th>Deadline</th>
</tr>
</table>
//javascript part
var rIndex,
table = document.getElementById("table");
function Toevoegen()
{
var newrow = table.insertRow(table.length),
cell1 = newrow.insertCell(0),
cell2=newrow.insertCell(1),
cell3=newrow.insertCell(2),
Titel = document.getElementById("Item").value,
person = document.getElementById("person").value,
deadline = document.getElementById("deadline").value;
//var description = document.getElementById("description").value;
if(Titel != "" && person != "" && deadline != "")
{
cell1.innerHTML = Titel;
cell2.innerHTML = person;
cell3.innerHTML = deadline;
document.getElementById("Item").value = ""; document.getElementById("person").value = "";
document.getElementById("deadline").value = "";
document.getElementById("description").value = "";
console.log(description);
var text1 = "Toegevoegd!";
document.getElementById("FoutInput").innerHTML = text1;
}
else{
cell1 = newrow.deleteCell(0);
cell2 = newrow.deleteCell(0,1);
var text = "Veld(en) mag(mogen) niet leeg blijven!";
document.getElementById("FoutInput").innerHTML = text;
}
selectedRowtoinput();
selectedCell();
}
function selectedCell(){
for(var i = 1;i<table.rows.length; i++){
table.rows[i].cells[0].ondblclick = function(){
var titel = document.getElementById("Item").value;
var person = document.getElementById("person").value;
var deadline = document.getElementById("deadline").value;
var description =
document.getElementById("description").value;
console.log(description);
alert("overzicht:" + "\n" + titel+ "\n" + person+ "\n" + deadline + "\n" + "omschrijving: " + description);
}
}
}
function selectedRowtoinput()
{
for(var i =1; i< table.rows.length; i++)
{
table.rows[i].onclick = function()
{
rIndex = this.rowIndex;
document.getElementById("Item").value =this.cells[0].innerHTML;
document.getElementById("person").value =this.cells[1].innerHTML;
document.getElementById("deadline").value =this.cells[2].innerHTML;
}
}
}
selectedRowtoinput();
I cant get data from:
var description =
document.getElementById("description").value;
console.log(description);
I just get an empty line. I get the info from the other 3 except this one...
Ok, I've updated your code and alter it with logic, that you DO create cell for description, but make in hidden, so it is not visible, but still holds the data, check example
var rIndex,
table = document.getElementById("table");
function Toevoegen()
{
var newrow = table.insertRow(table.length),
cell1 = newrow.insertCell(0),
cell2=newrow.insertCell(1),
cell3=newrow.insertCell(2),
cell4=newrow.insertCell(3),
Titel = document.getElementById("Item").value,
person = document.getElementById("person").value,
deadline = document.getElementById("deadline").value,
description = document.getElementById("description").value;
// Make hidden cell for description
cell4.className += " hidden";
if(Titel != "" && person != "" && deadline != "")
{
cell1.innerHTML = Titel;
cell2.innerHTML = person;
cell3.innerHTML = deadline;
// Put data in hidden cell
cell4.innerHTML = description;
document.getElementById("Item").value = "";
document.getElementById("person").value = "";
document.getElementById("deadline").value = "";
document.getElementById("description").value = "";
var text1 = "Toegevoegd!";
document.getElementById("FoutInput").innerHTML = text1;
}
else{
cell1 = newrow.deleteCell(0);
cell2 = newrow.deleteCell(0,1);
var text = "Veld(en) mag(mogen) niet leeg blijven!";
document.getElementById("FoutInput").innerHTML = text;
}
selectedRowtoinput();
selectedCell();
}
function selectedCell(){
for(var i = 1;i<table.rows.length; i++){
table.rows[i].cells[0].ondblclick = function(){
var titel = document.getElementById("Item").value;
var person = document.getElementById("person").value;
var deadline = document.getElementById("deadline").value;
var description = document.getElementById("description").value;
alert("overzicht:" + "\n" + titel+ "\n" + person+ "\n" + deadline + "\n" + "omschrijving: " + description);
}
}
}
function selectedRowtoinput()
{
for(var i =1; i< table.rows.length; i++)
{
table.rows[i].onclick = function()
{
rIndex = this.rowIndex;
document.getElementById("Item").value = this.cells[0].innerHTML;
document.getElementById("person").value = this.cells[1].innerHTML;
document.getElementById("deadline").value = this.cells[2].innerHTML;
document.getElementById("description").value = this.cells[3].innerHTML;
}
}
}
selectedRowtoinput();
.hidden {
display: none;
}
<body>
<h1 id="h1">ToDo Lijst</h1>
<label for="item">Titel</label><br>
<input type="text" id = "Item"><br><br>
<!--<p style="color:red; font-size:18px;" id="FoutInput"></p>-->
<label for = "aantal">Omschrijving</label><br>
<input class="desc" type="text" id="description"><br><br>
<label for="person">Toegewezen Person</label><br>
<input type="text" id = "person"><br><br>
<label for="deadline">Deadline</label><br>
<input type="text" id="deadline">
<button type = "button" onclick="Toevoegen()"><span>+</span></button>
<button type="button" onclick="Edit()" >Aanpassen</button>
<button style="background-color: crimson" onclick="Verwijderen()"><i class="fa fa-trash-o"></i></button>
<p style="color:red; font-size:15px;" id="FoutInput"></p>
<table id="table">
<tr>
<th>Titel</th>
<th>Toegewezen Person</th>
<th>Deadline</th>
</tr>
</table>
So I have pieced together a script I want to use to create invoices. It adds "Invoice Items" as a table row which includes checkbox, Quantity, Item, Unit Cost, and Price.
You can then check item, or use check-all option (Upper Left) to remove rows. As well as that it auto calculates row totals as well as a Sub Total for the whole "Invoice". As long as you remain linear, add items as will without removing them (unless removing all of them) it adds up fine. The issue I am having is if you remove any items in the middle it wont calculate total anymore.
Here is a jsfiddle too.
This is my first post and any help is greatly appreciated- Thanks in advance!!
<INPUT type="button" value="Add Invoice Item" onclick="addRow('dataTable')" />
<INPUT type="button" value="Delete Item(s)" onclick="deleteRow('dataTable')" />
<form action="" method="post" enctype="multipart/form-data">
<TABLE id="dataTable" width="350px" border="1" style="border-collapse:collapse;">
<TR>
<TH>
<INPUT type="checkbox" name="select-all" id="select-all" onclick="toggle(this);">
</TH>
<TH>Quanity</TH>
<TH>Item</TH>
<TH>Unit Cost</TH>
<TH formula="cost*qty" summary="sum">Price</TH>
</TR>
<TR>
<TD>
<INPUT type="checkbox" name="chk[]">
</TD>
<TD>
<INPUT type="text" id="qty1" name="qty[]" onchange="totalIt()"> </TD>
<TD>
<INPUT type="text" id="item1" name="item[]"> </TD>
<TD>
<INPUT type="text" id="cost1" name="cost[]" onchange="totalIt()"> </TD>
<TD>
<INPUT type="text" id="price1" name="price[]" readonly="readonly" value="0.00"> </TD>
</TR>
</TABLE>
</form>
Sub Total: <input type="text" readonly="readonly" id="total"><br><input type="submit" value="Create Invoice">
<!-------JAVASCRIPT--------->
<script>
function calc(idx) {
var price = parseFloat(document.getElementById("cost" + idx).value) *
parseFloat(document.getElementById("qty" + idx).value);
//alert(idx+":"+price);
document.getElementById("price" + idx).value = isNaN(price) ? "0.00" : price.toFixed(2);
//document.getElementById("total") = totalIt;
}
function totalIt() {
var qtys = document.getElementsByName("qty[]");
var total = 0;
for (var i = 1; i <= qtys.length; i++) {
calc(i);
var price = parseFloat(document.getElementById("price" + i).value);
total += isNaN(price) ? 0 : price;
}
document.getElementById("total").value = isNaN(total) ? "0.00" : total.toFixed(2);
}
window.onload = function() {
document.getElementsByName("qty[]")[0].onkeyup = function() {
calc(1)
};
document.getElementsByName("cost[]")[0].onkeyup = function() {
calc(1)
};
}
var rowCount = 0;
function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var cell1 = row.insertCell(0);
var element1 = document.createElement("input");
element1.type = "checkbox";
element1.name = "chk[]";
cell1.appendChild(element1);
var cell3 = row.insertCell(1);
var element3 = document.createElement("input");
element3.type = "text";
element3.name = "qty[]";
element3.id = "qty" + rowCount;
element3.onkeyup = totalIt;
cell3.appendChild(element3);
var cell4 = row.insertCell(2);
var element4 = document.createElement("input");
element4.type = "text";
element4.name = "item[]";
element4.id = "item" + rowCount;
cell4.appendChild(element4);
var cell5 = row.insertCell(3);
var element5 = document.createElement("input");
element5.type = "text";
element5.name = "cost[]";
element5.id = "cost" + rowCount;
element5.onkeyup = totalIt;
cell5.appendChild(element5);
var cell6 = row.insertCell(4);
var element6 = document.createElement("input");
element6.type = "text";
element6.name = "price[]";
element6.id = "price" + rowCount;
element6.value = "0.00";
$(element6).attr("readonly", "true");
cell6.appendChild(element6);
}
function deleteRow(tableID) {
try {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
document.getElementById("select-all").checked = false;
for (var i = 1; i < rowCount; i++) {
var row = table.rows[i];
var chkbox = row.cells[0].childNodes[0];
if (null != chkbox && true == chkbox.checked) {
table.deleteRow(i);
rowCount--;
i--;
}
}
} catch (e) {
alert(e);
}
}
</script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script>
<script>
$("input").blur(function() {
if ($(this).attr("data-selected-all")) {
//Remove atribute to allow select all again on focus
$(this).removeAttr("data-selected-all");
}
});
$("input").click(function() {
if (!$(this).attr("data-selected-all")) {
try {
$(this).selectionStart = 0;
$(this).selectionEnd = $(this).value.length + 1;
//add atribute allowing normal selecting post focus
$(this).attr("data-selected-all", true);
} catch (err) {
$(this).select();
//add atribute allowing normal selecting post focus
$(this).attr("data-selected-all", true);
}
}
});
function toggle(source) {
var checkboxes = document.querySelectorAll('input[type="checkbox"]');
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i] != source)
checkboxes[i].checked = source.checked;
}
}
</script>
The error occurs after a row in the middle is deleted due to the current code being bound to the indices that are used in html (e.g. ids like "cost1", "price1" etc).
When totalIt function is invoked, it tries to access rows that have been already deleted. To have this issue fixed, you can abstract from particular indices by using more broad selectors. Here is a drop in replacement totalIt function that does not depend on indices:
function totalIt() {
var costs = document.getElementsByName("cost[]");
var quantities = document.getElementsByName("qty[]");
var prices = document.getElementsByName("price[]");
var total = Array.prototype.reduce.call(costs, function(total, cost, index) {
var price = parseFloat(cost.value) * parseFloat(quantities[index].value);
prices[index].value = isNaN(price) ? "0.00" : price.toFixed(2);
return isNaN(price) ? total : total + price;
}, 0)
document.getElementById("total").value = isNaN(total) ? "0.00" : total.toFixed(2);
}
Also, should you want to recompute the total on row delete - call totalIt in the delete handler (deleteRow). Note that you will likely need to wrap it in setTimeout so that re-computation will occur in the next event loop iteration, after the record is actually removed from DOM
Need to Dynamically Add/Remove rows in HTML table using JavaScript getting a type error.
Type Error: cannot read property 'childNodes' of undefined?
Catches this exception in run time during deleteRow function execution.
On pressing Add Row, a dynamic row will be created and added in the table. And on selecting the checkbox and pressing Delete Row, the row will be removed.
Following is the source.
<html>
<head>
<script>
var b = new Array();
var entryListCounter = 0;
var counter = 0;
function insertEntry(f) {
var test = 0;
//local array collects input values
var a = new Array();
a[0] = f.ticker.value;
a[1] = f.cusip.value;
a[2] = f.quantity.value;
//store local array in entry list array
b[entryListCounter] = a;
entryListCounter++;
if (a[0] == "" && a[1] == "" || a[2] == "") {
console.log("val not filled");
}
else if(a[0].length > 0 && a[1].length > 0){
console.log("only fill one");
}
else {
var table = document.getElementById("manualEntryInputTable");
var row = table.insertRow(table.rows.length);
var cell1 = row.insertCell(0);
var t1 = document.createElement("input");
t1.id = "t" + counter;
cell1.appendChild(t1);
var cell2 = row.insertCell(1);
var t2 = document.createElement("input");
t2.id = "c" + counter;
cell2.appendChild(t2);
var cell3 = row.insertCell(2);
var t3 = document.createElement("input");
t3.id = "q" + counter;
t3.style = "text-align:right";
cell3.appendChild(t3);
var cell4 = row.insertCell(3);
var t4 = document.createElement("input");
t4.type = "checkbox";
t4.name = "chkbox";
cell4.appendChild(t4);
f.quantity.value = "";
f.cusip.value = "";
f.ticker.value = "";
}
}
function deleteRow(e) {
try {
var table = document.getElementById("manualEntryInputTable");
var rowCount = table.rows.length;
for(var i=0; i<rowCount; i++) {
var row = table.rows[i];
var chkbox = row.cells[3].childNodes[0];
if(null != chkbox && true == chkbox.checked) {
if(rowCount <= 1) {
alert("Cannot delete all the rows.");
break;
}
table.deleteRow(i);
rowCount--;
i--;
}
}
}catch(e) {
alert(e);
}
}
</script>
</head>
<body>
<form>
<table id="manualEntryInputTable">
<tr>
<td><b>T</b></td>
<td><b>C</b></td>
<td><b>Q</b></td>
</tr>
<tr>
<td class="label"><input size="" type="text" name="ticker"
value="" ></td>
<td class="label"><input size="" type="text" name="cusip"
value=""></td>
<td class="label"><input size="" type="text" name="quantity"
style="text-align: right;" value="">
</td>
<td><input type="button" onClick="insertEntry(this.form)" value="Add"/>
</td>
<td><input type="button" onClick="deleteRow(this.form)" value="Delete"/>
</td>
</tr>
</table>
</form>
</body>
</html>
By looking at the conditional checking for null, I would rewrite it like this:
var chkbox = row.cells[3].childNodes.length ? row.cells[3].childNodes[0] : null;
That should avoid the error being thrown, but might not get the row deleted if the cell with index 3 doesn't exist. Consider checking the value of the right cell index row.cells[YOUR_CELL_INDEX_HERE].childNodes[0]
I am not entirely sure what you are trying to do, but the reason for exception is that you are trying to access the element which doesn't exists.
This line is giving the error row.cells[3].childNodes[0] since you do not have row.cell[3] property. The row.Cells has length 3 but since the index starts from 0, you can refer to the last element using row.cells[2] You get undefined and hence row.cells[3].childNodes[0] method doesn't work.
change it to row.cells[2].childNodes[0]
<html>
<head>
<script>
var b = new Array();
var entryListCounter = 0;
var counter = 0;
function insertEntry(f) {
var test = 0;
//local array collects input values
var a = new Array();
a[0] = f.ticker.value;
a[1] = f.cusip.value;
a[2] = f.quantity.value;
//store local array in entry list array
b[entryListCounter] = a;
entryListCounter++;
if (a[0] == "" && a[1] == "" || a[2] == "") {
console.log("val not filled");
}
else if(a[0].length > 0 && a[1].length > 0){
console.log("only fill one");
}
else {
var table = document.getElementById("manualEntryInputTable");
var row = table.insertRow(table.rows.length);
var cell1 = row.insertCell(0);
var t1 = document.createElement("input");
t1.id = "t" + counter;
cell1.appendChild(t1);
var cell2 = row.insertCell(1);
var t2 = document.createElement("input");
t2.id = "c" + counter;
cell2.appendChild(t2);
var cell3 = row.insertCell(2);
var t3 = document.createElement("input");
t3.id = "q" + counter;
t3.style = "text-align:right";
cell3.appendChild(t3);
var cell4 = row.insertCell(3);
var t4 = document.createElement("input");
t4.type = "checkbox";
t4.name = "chkbox";
cell4.appendChild(t4);
f.quantity.value = "";
f.cusip.value = "";
f.ticker.value = "";
}
}
function deleteRow(e) {
try {
var table = document.getElementById("manualEntryInputTable");
var rowCount = table.rows.length;
for(var i=0; i<rowCount; i++) {
var row = table.rows[i];
var chkbox = row.cells[2].childNodes[0];
if(null != chkbox && true == chkbox.checked) {
if(rowCount <= 1) {
alert("Cannot delete all the rows.");
break;
}
table.deleteRow(i);
rowCount--;
i--;
}
}
}catch(e) {
alert(e);
}
}
</script>
</head>
<body>
<form>
<table id="manualEntryInputTable">
<tr>
<td><b>T</b></td>
<td><b>C</b></td>
<td><b>Q</b></td>
</tr>
<tr>
<td class="label"><input size="" type="text" name="ticker"
value="" ></td>
<td class="label"><input size="" type="text" name="cusip"
value=""></td>
<td class="label"><input size="" type="text" name="quantity"
style="text-align: right;" value="">
</td>
<td><input type="button" onClick="insertEntry(this.form)" value="Add"/>
</td>
<td><input type="button" onClick="deleteRow(this.form)" value="Delete"/>
</td>
</tr>
</table>
</form>
</body>
</html>
I used normal addRow function and removeRow function to dynamically add and remove the row in a table.
function addRow()
{
var ptable = document.getElementById('ptableQuestion');
var lastElement = ptable.rows.length;
var index = lastElement;
var row = ptable.insertRow(lastElement);
var cellLeft = row.insertCell(0);
var textNode = document.createTextNode(index);
cellLeft.appendChild(textNode);
var cellText = row.insertCell(1);
var element = document.createElement('textarea');
element.name = 'question' + index;
element.id = 'question' + index;
element.rows="2";
element.cols="60"
var cellText1 = row.insertCell(2);
var element1 = document.createElement('input');
element1.type = 'checkbox';
element1.name = 'cb';
element1.id = 'cb';
cellText.appendChild(element);
cellText1.appendChild(element1);
document.getElementById("psize").value=index;
}
function checkCheckboxes() {
var e = document.getElementsByName("cb");
var message = 'Are you sure you want to delete?';
var row_list = {length: 0};
for (var i = 0; i < e.length; i++) {
var c_box = e[i];
if (c_box.checked == true) {
row_list.length++;
row_list[i] = {};
row_list[i].row = c_box.parentNode.parentNode;
row_list[i].tb = row_list[i].row.parentNode;
}
}
if (row_list.length > 0 && window.confirm(message)) {
for (i in row_list) {
if (i == 'length') {
continue;
}
var r = row_list[i];
r.tb.removeChild(r.row);
}
} else if (row_list.length == 0) {
alert('You must select an email address to delete');
}
}
<form action="show.jsp" method="post" onsubmit="return validate();">
<input type="hidden" name="psize" id="psize">
<table style="border:1px solid #000000;" bgcolor="#efefef"
id="ptablePerson" align="center">
<tr>
<th colspan="3">Add New Person</th>
</tr>
<tr>
<td>1</td>
<td><input type="text" name="person1" id="person1" size="30" />
<input type="button" value="Add" onclick="addRow();" /></td>
<td><input type="checkbox" id="cb" name="cb"/></td>
</tr>
</table>
<table align="center">
<tr>
<td><input type="button" value="Remove" onclick="checkCheckboxes();" />
<input type="Submit" value="Submit" /></td>
</tr>
</table>
</form>
</BODY>
</HTML>
My problem is when the table got 5 row, if i click checkbox to delete row 3 the index become 1 2 4 5. Is there any method can rearrange it to 1 2 3 4
This looks like simple delete element from the list. You have to get all the rows of the table, and shift all rows one step backword after delete operation is completed.
There is a small code i which i has created a spn in every td.So that I will replace the value in the iterartion. It will work if u deleted 3(1,2,3,4,5) then the content of span will be 1,2,3,4 .Jquery i am using here
var rowCount = $('#ptableQuestion tr').length;
if (rowCount != 0) {
i = 0;
$('#ptableQuestion tr').each(function(i) {
$(this).find("td .spn").html(i);
});
}
});
Hope it will work for you.