How can I adapt this code to make the rows which have been created by the function selectable. I will then use this in as a part of a form to manipulate the data in the specified row.
function staffData() {
if (firstTimeS) {
firstTimeS = false;
// Select the Table
var tbl = document.getElementById('staffInnerTable');
var th = document.getElementById('tableHead_S');
var headerText = ["ID", "Staff Name", "Role"];
// Set number of rows
var rows = 10;
// Set number of columns
var columns = headerText.length;
// create table header
for (var h = 0; h < columns; h++) {
var td = document.createElement("td");
td.innerText = headerText[h];
th.appendChild(td);
}
// create table data
for (var r = 0; r < rows; r++) {
var cellText = ["UNDEFINED", "UNDEFINED", "UNDEFINED"];
// generate ID
x = getRandomNumber(1000, 1);
cellText[0] = x;
// generate Status
x = generateName();
cellText[1] = x;
// generate Role
x = getRole();
cellText[2] = x;
var tr = document.getElementById("s_row" + r);
for (var c = 0; c < columns; c++)
{
var td = document.createElement("td");
td.innerText = cellText[c];
tr.appendChild(td);
}
}
}
}
EDIT - HTML. Tr already defined in html. Would it be possible to somehow put an onclick on the table rows?
<table style="width: 100%; color:white;" id="staffInnerTable">
<tr id="tableHead_S">
</tr>
<tr id="s_row0"></tr>
<tr id="s_row1"></tr>
<tr id="s_row2"></tr>
<tr id="s_row3"></tr>
<tr id="s_row4"></tr>
<tr id="s_row5"></tr>
<tr id="s_row6"></tr>
<tr id="s_row7"></tr>
<tr id="s_row8"></tr>
<tr id="s_row9"></tr>
</table>
If you do this:
var tr = document.getElementById("s_row" + r);
tr.onclick = function(event) {
alert('Clicked: ' + event.target.parentNode.id)
}
...you'll see that a click is detected that tells you which row was clicked on. Hopefully that's enough to get you started on whatever you wanted to do.
Related
This block of code is to create 3 arrays with the values pulled from the user's input in a popup menu in the HTML file, but the values here are needed to fill in the table below.
var arrM = new Array; var arrT = new Array; var arrA = new Array;
arrM[0] = mod0.mod.value; arrT[0] = mod0.target.value; arrA[0] = mod0.actual.value;
arrM[1] = mod1.mod.value; arrT[1] = mod1.target.value; arrA[1] = mod1.actual.value;
arrM[2] = mod2.mod.value; arrT[2] = mod2.target.value; arrA[2] = mod2.actual.value;
arrM[3] = mod3.mod.value; arrT[3] = mod3.target.value; arrA[3] = mod3.actual.value;
arrM[4] = mod4.mod.value; arrT[4] = mod4.target.value; arrA[4] = mod4.actual.value;
arrM[5] = mod5.mod.value; arrT[5] = mod5.target.value; arrA[5] = mod5.actual.value;
arrM[6] = mod6.mod.value; arrT[6] = mod6.target.value; arrA[6] = mod6.actual.value;
arrM[7] = mod7.mod.value; arrT[7] = mod7.target.value; arrA[7] = mod7.actual.value;
arrM[8] = mod8.mod.value; arrT[8] = mod8.target.value; arrA[8] = mod8.actual.value;
arrM[9] = mod9.mod.value; arrT[9] = mod9.target.value; arrA[9] = mod9.actual.value;
the code in between the block above and the block below(not shown here) is just to compute the average values and does not interact with the block below
the code below is to create a table with the same number of rows as the number of rows the user filled in the popup menu.
var tableGenerator = document.getElementById("tableGenerator");
tbl = document.createElement('table');
tbl.style.width = '500px';
tbl.style.height = '100px';
tbl.style.border = '1px solid black';
tbl.style.margin = '50px';
tbl.style.float = 'left';
if (j < 6) {
j = 6;
}
for (var a = 0; a < j+1; a++) {
var tr = tbl.insertRow();
for (var b = 0; b < 3; b++) {
if (a == j && b == 3) {
break;
} else {
var td = tr.insertCell();
td.appendChild(document.createTextNode(""));
td.style.border = '1px solid black';
if (a == 0 && b == 0) {
var newtext = document.createTextNode(Text);
var celltext = "Year " + year.value + " Semester " + semester.value;
td.appendChild(document.createTextNode(celltext));
td.setAttribute('colSpan', '3'); break;
}
//this else block below here obviously doesn't work, but this idea is there and I want something that
//works like the pseudo code below
else {
for (a = 1; a < j; a++) {
tbl[a][0] = arrM[a];
tbl[a][1] = arrT[a];
tbl[a][2] = arrA[a];
}
}
}
}
}tableGenerator.appendChild(tbl);
I am very unfamiliar with HTML/JS/CSS, is it possible for us to access cell values of a table as if it is an array? or is there any better way to do this?
In JavaScript you'll need to either create text nodes and assign the content of that node, or assign the content to the textContent, innerText or innerHTML properties to give the table cells their values.
td.textContent = 'Hello'; // This is the preferred property for text.
The help you achieve this it would be wise to structure your data in a way that you can loop over, because you're basically doing the same thing in a specific order. For example:
var data = [
arrM,
arrT,
arrA
];
This will put your arrays in another array. Now you can loop over the data array and create a table row for each array, and a table cell for each item in the nested array.
for (var i = 0; i < data.length; i++) {
// ... create table row.
for (var j = 0; j < data[i].length; j++) {
// ... create table cell and assign textContent property.
}
}
Examine the example below. It's a runnable version of the thing I've explained above. I hope it helps you out.
function createTable(headers, values) {
var table = document.createElement('table');
// Build <thead>
var tableHeader = table.createTHead();
// Create <tr> inside <thead>
var tableHeaderRow = tableHeader.insertRow();
for (var i = 0; i < headers.length; i++) {
// Create <th>
var tableHeaderCell = document.createElement('th');
// Set text of <th> to value in array.
tableHeaderCell.textContent = headers[i];
// Add <th> to <tr> inside <thead>
tableHeaderRow.appendChild(tableHeaderCell);
}
// Build <tbody>
var tableBody = table.createTBody();
for (var j = 0; j < values.length; j++) {
// Create <tr> inside <tbody>
var tableBodyRow = tableBody.insertRow();
for (var k = 0; k < values[j].length; k++) {
// Create <td> inside <tr>
var tableBodyCell = tableBodyRow.insertCell();
// Set text of <td> to value in array.
tableBodyCell.textContent = values[j][k];
}
}
// Add <table> to the <body>
document.body.appendChild(table);
}
var titles = [
'One',
'Two',
'Three'
];
var characters = [
['Batman', 'Robin', 'Batgirl'],
['Joker', 'Two-Face', 'Poison Ivy'],
['James Gordon', 'Alfred Pennyworth', 'Clayface']
];
createTable(titles, characters);
How can I adapt this code so that when the row is selected the color changes but also resets anything else that has been clicked back to the original color. Obviously right now it changes the rows colour every click and all past selected rows colours stay the same.
var tr = document.getElementById("r_row" + r);
for (var c = 0; c < columns; c++) {
var td = document.createElement("td");
td.innerText = cellText[c];
tr.appendChild(td);
//Makes the rows selectable
tr.onclick = function(event) {
selectedItem = this;
selectedItem.style.background = "#828891";
}
}
An alternative is to add a class, i.e selected and check for a selected TR using a collection of the selectable TRs.
var trs = Array.from(document.querySelectorAll('[id^="r_row"]'));
trs.forEach(function(elem) {
elem.addEventListener('click', function() {
trs.forEach(function(tr) {
if (tr !== elem) tr.classList.remove('selected');
});
this.classList.add('selected');
});
});
function addTRs(ids) {
var columns = 3;
ids.forEach(function(r) {
var tr = document.getElementById("r_row" + r);
for (var c = 0; c < columns; c++) {
var td = document.createElement("td");
td.innerText = `This is a test - ${r}`;
tr.appendChild(td);
}
});
}
addTRs([1, 2]);
.selected {
background-color: #828891;
}
tr {
cursor: pointer
}
<table>
<tbody>
<tr id='r_row1'></tr>
<tr id='r_row2'></tr>
<tr>
<td colSpan='3'>Not selectable!</td>
</tr>
</tbody>
</table>
I have a <th> header row with a stated class, and one fixed row with a stated class. Both are contenteditable. I'm adding new rows and new columns. I want to calculate the AverageValue in the final cell. I have tried the code on a fixed number of rows and it works, but when I try it this way it is only taking in the number of columns, not the DATA inserted. It is also not recognizing the row DATA. I'm clearly missing a function?!
I'm at the stage where I need an extra pair of eyes.
JavaScript:
func = function() {
var table = document.getElementById("mytable");
var rows = table.rows;
for (var j = 1; j < rows.length; j++) {
var total = 0;
var cells = rows[j].cells;
for (var i = 2; i < (cells.length - 1); i++) {
var a = document.getElementById("mytable").rows[j].cells[i].innerHTML;
a = parseInt(a);
if (!isNaN(a)) {
total = total + a;
}
}
total = total / (cells.length - 3);
total = Math.round(total);
if (total < 40) {
document.getElementById("mytable").rows[j].cells[cells.length - 1].style.backgroundColor = "red";
document.getElementById("mytable").rows[j].cells[cells.length - 1].style.color = "white";
}
document.getElementById("mytable").rows[j].cells[cells.length - 1].innerHTML = total + "%";
}
}
addRow = function() {
var table = document.getElementById('mytable'); // table reference
var row = table.insertRow(table.rows.length); // append table row
// insert table cells to the new row
for (i = 0; i < table.rows[0].cells.length; i++) {
createCell(row.insertCell(i), "-");
}
}
createCell = function(cell, text, style) {
var div = document.createElement('div');
txt = document.createTextNode(text);
div.appendChild(txt); // append text node to the DIV
div.setAttribute("class", style); // set DIV class attribute
div.setAttribute("className", style);
div.setAttribute("contenteditable", true);
div.setAttribute('placeholder', '' - '');
cell.appendChild(div); // append DIV to the table cell
}
createCellCol = function(cell, text, style) {
var div = document.createElement('div');
txt = document.createTextNode(text);
div.appendChild(txt); // append text node to the DIV
div.setAttribute("class", style); // set DIV class attribute
div.setAttribute("className", style);
div.setAttribute("contenteditable", true);
div.setAttribute("placeholder", "-");
cell.appendChild(div); // append DIV to the table cell
}
addColumn = function() {
var table = document.getElementById("mytable"); // table reference
var rowNums = table.rows.length;
for (i = 0; i < rowNums; i++) {
if (i == 0) {
createCell(table.rows[i].insertCell(table.rows[i].cells.length - 1), "-");
} else {
createCellCol(table.rows[i].insertCell(table.rows[i].cells.length - 1), "-");
}
}
}
HTML:
<table class="tg" id="mytable">
<tr>
<th class="tg-s6z2" contenteditable="true">Student Name</th>
<th class="tg-s6z2" contenteditable="true">Student ID</th>
<th class="tg-s6z2" contenteditable="true">Assignment 1</th>
<th class="tg-s6z2" contenteditable="true">Final Grade</th>
</tr>
<tr>
<td class="tg-031e" contenteditable="true">Student1</td>
<td class="tg-031e" contenteditable="true">StudentNo</td>
<td class="tg-0ord" contenteditable="true"></td>
<td class="tg-0ord" contenteditable="true"></td>
</tr>
</table>
<button id="btnFinalGrade" class="btn btn-action" onClick="func();">Final Grade</button>
<button id="btnaddRow" class="btn btn-action" onclick="addRow();">AddRow</button>
<button id="btnaddColumn" class="btn btn-action" onclick="addColumn();">AddColumn</button>
You were adding a div to td element which was throwing error while executing this line document.getElementById("mytable").rows[j].cells[i].innerHTML
which returns a div element not the text you entered!
No need to add a div, Here is the updated code,
func = function () {
var table = document.getElementById("mytable");
var rows = table.rows;
for (var j = 1; j < rows.length; j++) {
var total = 0;
var cells = rows[j].cells;
for (var i = 2; i < (cells.length - 1); i++) {
var a = document.getElementById("mytable").rows[j].cells[i].innerHTML;
a = parseInt(a);
if (!isNaN(a)) {
total = total + a;
}
}
total = total / (cells.length - 3);
total = Math.round(total);
if (total < 40) {
document.getElementById("mytable").rows[j].cells[cells.length - 1].style.backgroundColor = "red";
document.getElementById("mytable").rows[j].cells[cells.length - 1].style.color = "white";
}
document.getElementById("mytable").rows[j].cells[cells.length - 1].innerHTML = total + "%";
}
}
addRow = function () {
var table = document.getElementById('mytable'); // table reference
var row = table.insertRow(table.rows.length); // append table row
// insert table cells to the new row
for (i = 0; i < table.rows[0].cells.length; i++) {
createCell(row.insertCell(i), "-","tg-031e");
}
}
createCell = function (cell, text, style) {
var div = document.createElement('td');
txt = document.createTextNode(text);
cell.appendChild(txt); // append text node to the DIV
cell.setAttribute("class", style); // set DIV class attribute
cell.setAttribute("className", style);
cell.setAttribute("contenteditable", true);
cell.setAttribute('placeholder', '' - '');
//cell.appendChild(div); // append DIV to the table cell
}
createCellCol = function (cell, text, style) {
var div = document.createElement('td');
txt = document.createTextNode(text);
cell.appendChild(txt); // append text node to the DIV
cell.setAttribute("class", style); // set DIV class attribute
cell.setAttribute("className", style);
cell.setAttribute("contenteditable", true);
cell.setAttribute("placeholder", "-");
//cell.appendChild(div); // append DIV to the table cell
}
addColumn = function () {
var table = document.getElementById("mytable"); // table reference
var rowNums = table.rows.length;
for (i = 0; i < rowNums; i++) {
if (i == 0) {
createCell(table.rows[i].insertCell(table.rows[i].cells.length - 1), "-","tg-031e");
} else {
createCellCol(table.rows[i].insertCell(table.rows[i].cells.length - 1), "-","tg-s6z2");
}
}
}
I have page with table.
In tbody I show data via angularjs. In thead I have same row as in tbody, but its empty, and when I filled input field and click somewhere (focus lost), one row adds to my table (thead). And I need to make some flag on filled row, as like - rowAdded = true, because without that I clicking on input of one row and rows adds. And one more problem is that rows adds to the end of table.
it's all works on this script:
var tbody = $('.table-timesheet thead');
tbody.on('blur', ':text', function () {
var tr = $(this).closest('tr'),
notEmpty = $(':text', tr).filter(function () {
return $.trim($(this).val()) != '';
}).length;
if (notEmpty) {
$('.note-input').css('width', '88%').css('float', 'left');
$('.timesheet-delete-button').css('display', 'block');
//tr.clone(true).appendTo(tbody).find(':text').val('');
insRow();
}
});
function deleteRow(row) {
var i = row.parentNode.parentNode.rowIndex;
document.getElementById('table-body').deleteRow(i);
}
function insRow() {
var table = document.getElementById('table-body');
var newRow = table.rows[1].cloneNode(true);
var len = table.rows.length;
newRow.cells[0].innerHTML = len;
var inp1 = newRow.cells[1].getElementsByTagName('input')[0];
inp1.id += len;
inp1.value = '';
var inp2 = newRow.cells[2].getElementsByTagName('input')[0];
inp2.id += len;
inp2.value = '';
table.appendChild(newRow);
}
There is my example in plunker:
http://plnkr.co/edit/rcnwv0Ru8Hmy7Jrf9b1C?p=preview
Is this what you are looking for
function insRow(ind){
var table = document.getElementById('table-body');
var newRow = table.rows[1].cloneNode(true);
var len = table.rows.length;
newRow.cells[0].innerHTML = ind!==undefined ? ind : len;
if(ind!==undefined)
$(table).find('tr:eq('+ind+')').before(newRow);
else table.appendChild(newRow);
}
insRow(2);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="table-body">
<tbody>
<tr><td>1</td></tr>
<tr><td>2</td></tr>
<tr><td>3</td></tr>
</tbody>
</table>
I have the following HTML structure:
<table id="j_idt28:innerContent" class="innerContent">
<tbody>
<tr>
<tr>
<tr>
<tr>
.......
<tr>
<tr>
</tbody>
</table>
The tags are being populated with a parsed XML response.
I usually have 20 or so tr tags.
I want that after the 4th, 8th, 12, etc tag to create a and insert the 4 tags into it.
Here is my jquery so far:
var i = 1;
var j = 2;
var margin = 0;
var max = $('.innerContent tr').length;
for(i = 1; i<=max; i++)
{
var child1 = i - 3;
var child2 = i - 2;
var child3 = i - 1;
var hotel1 = $('.innerContent tr:nth-child('+child1+')');
var hotel2 = $('.innerContent tr:nth-child('+child2+')');
var hotel3 = $('.innerContent tr:nth-child('+child3+')');
var hotel4 = $('.innerContent tr:nth-child('+i+')');
if(i%4 == 0)
{
$('.innerContent tbody').prepend('<div class="line_wrapper"></div>');
$('.line_wrapper').append(hotel1,hotel2,hotel3,hotel4);
}
}
for(j =2; j<=max ;j++)
{
var hotel = $('.innerContent tr:nth-child('+j+')');
margin = margin + 280;
hotel.css('margin-left',margin+'px');
//$('.line_wrapper').append(hotel);
}
This just does not quite work as I would have expected. I want to add the divs in order for me to use bootstrap fluid layout.
You can do it using each:
$('#mytable tr').each(function (i) {
i%4?$(this).prev('div').append(this):$(this).wrap('<div/>');
});