How to access to the second row of a Datatables footer - javascript

I would like to add a second <tr> to the footer of my datatable in order to display the grand total (after doing some sums).
All the calculations are already working, I just want to inject the value of rowSum when j >= 12 in the 2nd row of the footer.
Concept of the desired result (cropped image):
This is what I've tried:
✓ Adding a second <tr> to the datatable (working)
✗ Inject the value of rowSum to the last column of the second row of the footer (I guess I am doing something wrong here)
And this is the part of the code that I think is wrong:
$('#example > tfoot > tr').each(function(index, tr) {
var rowSum = 0;
for (let j = 0; j < 12; j++) {
if (j >= 2) {
var tdCellValue = numberFromString(tr.cells[j].innerText);
rowSum = rowSum + tdCellValue;
}
if (j >= 11) {
tr.cells[12].innerText = rowSum;
tr[1].cells[12].innerText = rowSum;
}
}
});
Here I tried to access to the second row of the footer: tr[1].cells[12].innerText = rowSum; and I think this is where I made the mistake.
DEMO JS BIN
Does anyone know how can I access the second row of the datatable footer and inject the value properly?

Just replace your JS code with the following. Here is Demo of the working file.
<script>
$(document).ready(function() {
var DT1 = $('#example').DataTable({
columnDefs: [{
orderable: false,
className: 'select-checkbox',
targets: 0,
}],
select: {
style: 'os',
selector: 'td:first-child'
},
order: [
[1, 'asc']
],
"language": {
"info": "Showing _START_ to _END_ of _TOTAL_ Projects",
"infoEmpty": "Showing 0 to 0 of 0 Projects",
"infoFiltered": "(filtered from _MAX_ total Projects)"
},
"pagingType": "numbers",
dom: 'rtip',
initComplete: function(settings, json) {
// calculate the sum when table is first created:
doSum();
}
});
$('#example').on('draw.dt', function() {
// re-calculate the sum whenever the table is re-displayed:
doSum();
});
$(".selectAll").on("click", function(e) {
if ($(this).is(":checked")) {
DT1.rows().select();
} else {
DT1.rows().deselect();
}
});
// This provides the sum of all records:
function doSum() {
// get the DataTables API object:
var table = $('#example').DataTable();
// set up the initial (unsummed) data array for the footer row:
var totals = ['', 'Total:', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
// iterate all rows - use table.rows( {search: 'applied'} ).data()
// if you want to sum only filtered (visible) rows:
totals = table.rows().data()
// sum the amounts:
.reduce(function(sum, record) {
for (let i = 2; i <= 12; i++) {
sum[i] = sum[i] + numberFromString(record[i]);
}
return sum;
}, totals);
// place the sum in the relevant footer cell:
for (let i = 1; i <= 12; i++) {
var column = table.column(i);
$(column.footer()).html(formatNumber(totals[i]));
}
$('#example > tbody > tr').each(function(index, tr) {
var rowSum=0;
for(let j=0; j<12; j++)
{
if(j>=2){
var tdCellValue= numberFromString(tr.cells[j].innerText);
rowSum=rowSum+tdCellValue;
}
if(j >=11){
tr.cells[12].innerText=rowSum;
}
}
});
var grandTotal=0;
$('#example > tfoot > tr').each(function(index, tr) {
if(index<1){
grandTotal=0;
var rowSum = 0;
for (let j = 0; j < 12; j++) {
if (j >= 2) {
var tdCellValue = numberFromString(tr.cells[j].innerText);
rowSum = rowSum + tdCellValue;
}
if (j >= 11) {
tr.cells[12].innerText = rowSum;
grandTotal=rowSum;
}
}
}else{
tr.cells[11].innerText = "Grand Total";
tr.cells[12].innerText = grandTotal;
}
});
}
function numberFromString(s) {
return typeof s === 'string' ?
s.replace(/[\$,]/g, '') * 1 :
typeof s === 'number' ?
s : 0;
}
function formatNumber(n) {
return n.toLocaleString(); // or whatever you prefer here
}
});
</script>

If you want to calculator value of last column, you need get sum of all cells in this row ( not 2 rows with $('#example > tfoot > tr').each -> in html , you have 2 tr )
$('#example > tfoot > tr').each(function(index, tr) {
if (index == 0) {
var rowSum = 0;
for (let j = 0; j < totalCol; j++) {
if (j >= 2 && j < 12) {
var tdCellValue = numberFromString(tr.cells[j].innerText);
rowSum = rowSum + tdCellValue;
}
if (j >= 12) {
tr.cells[12].innerText = rowSum;
// tr[1].cells[12].innerText = rowSum;
}
}
}
});

Related

Creating a Word Find grid

I am attempting to create a grid that contains one letter in each box (like a Word Find puzzle).
I have successfully created a grid that shows w/ the determined number of cols/rows, but when I attempt to put one letter in each box, I get the following ten times in each box instead of a single letter:
[object
Object]
Here is the JavaScript:
$(function() {
var letters = [
'rzeabppssgcddrvddydtjrkei', // 1
'cezcqubhniittonieqerbiuvm', // 2
'jqcjnasionsncvbsrwtabddsu', // 3
'olselesitneagittrjanreinv', // 4
'nqnaisdenmeibvurellsnrioc', // 5
'ydnlevrnyeaidrwifkufmsuis', // 6
'dcccjeeaogsemudbeemefaptn', // 7
'evonsqpdepislsnudnurwjbpo', // 8
'grytiunnafsexattmtclaimoi', // 9
'pnqrhocbiieeinoitacilppat', // 10
];
var letter = [];
function splitRows(arr, arr2) {
for (let i=0; i < arr.length; i++) {
arr[i].split();
for (let j=0; j < arr.length; j++) {
arr2[j] = arr[i][j];
}
}
}
splitRows(letters, letter);
function* gen(arr) {
for(i=0; i < arr.length; i++) {
yield arr[i];
}
}
function generateGrid(rows, cols, arr) {
var grid = "<table>";
for(row = 1; row <= rows; row++) {
grid += "<tr>";
for(col = 1; col <= cols; col++) {
grid += "<td>";
for(let i=0; i < arr.length; i++) {
grid += gen(arr).next(); // not sure if the .next() generator works yet
}
grid += "</td>"; // 'letters' needs to input the next letter in letters each time it is called
}
grid += "</tr>";
}
return grid;
}
$("#tableContainer").append(generateGrid(26, 22, letter));
});
The first function is intended to take rows and split them into singular letters (eventually taking rows as an input, but for testing purposes I have them in an array)
The second function is a generator to insert into the generateGrid() function that is used to generate the next letter in the sequence each time a box is created.
You should convert your string data to a matrix first then you can run the matrix through a table.
The following jQuery plugin clears the table and replaces it with rows and columns based on the data.
Note: I also added in tag name validation, in the case where the element the plugin was being invoked upon was not a <table> element.
var DEBUG_EXPERIMENTAL = false;
initializePlugins(); // Forward Declaration of jQuery plugins
let rawStringData = `
rzeabppssgcddrvddydtjrkei
cezcqubhniittonieqerbiuvm
jqcjnasionsncvbsrwtabddsu
olselesitneagittrjanreinv
nqnaisdenmeibvurellsnrioc
ydnlevrnyeaidrwifkufmsuis
dcccjeeaogsemudbeemefaptn
evonsqpdepislsnudnurwjbpo
grytiunnafsexattmtclaimoi
pnqrhocbiieeinoitacilppat
`;
$('.word-search').buildWordSearch(rawStringData, 'letter');
$('.letter').enableHighliting('highlight');
function initializePlugins() {
(($) => {
$.stringToMatrix = function(str) {
return str.trim().split('\n').map(row => row.trim().split(''));
};
$.fn.buildWordSearch = function(stringData, cellClass) {
this.throwErrorIfNotType('TABLE');
return this.append($('<tbody>')
.append($.stringToMatrix(stringData).map(row => {
return $('<tr>').append(row.map(col => {
return $('<td>').addClass(cellClass).text(col);
}));
})));
};
$.fn.throwErrorIfNotType = function(expectedTagName) {
let actualTagName = this.prop('tagName');
if (actualTagName !== expectedTagName) {
throw Error(`Element '${actualTagName}' is not a '${expectedTagName}'!`);
}
};
$.fn.getCell = function(x, y) {
return this.find(`tr:nth-child(${y + 1}) td:nth-child(${x + 1})`);
};
$.fn.enableHighliting = function(cls) {
return this.each(() => {
this.on({
mouseover: function() {
let $table = $(this).closest('table');
let $row = $(this).closest('tr');
let rowIndex = $row.index();
let colIndex = $(this).index();
let rowCount = $table.find('tbody tr').length;
let colCount = $row.find('td').length;
// Hightlights diagonals.
if (DEBUG_EXPERIMENTAL) {
let limit = rowCount;
let xNeg = colIndex - 1;
let xPos = colIndex + 1;
let yNeg = rowIndex - 1;
let yPos = rowIndex + 1;
while (limit > 0) {
if (xNeg > -1 && yNeg > -1) {
$table.getCell(xNeg, yNeg).addClass(cls);
}
if (xPos < colCount && yNeg > -1) {
$table.getCell(xPos, yNeg).addClass(cls);
}
if (xNeg > -1 && yPos < rowCount) {
$table.getCell(xNeg, yPos).addClass(cls);
}
if (xPos < colCount && yPos < rowCount) {
$table.getCell(xPos, yPos).addClass(cls);
}
xNeg--;
xPos++;
yNeg--;
yPos++;
limit--;
}
}
$row.addClass(cls);
$table.find(`td:nth-child(${colIndex + 1})`).addClass(cls);
},
mouseout: function() {
let $table = $(this).closest('table');
let $row = $(this).closest('tr');
let rowIndex = $row.index();
let colIndex = $(this).index();
let rowCount = $table.find('tbody tr').length;
let colCount = $row.find('td').length;
// Un-hightlights diagonals.
if (DEBUG_EXPERIMENTAL) {
let limit = rowCount;
let xNeg = colIndex - 1;
let xPos = colIndex + 1;
let yNeg = rowIndex - 1;
let yPos = rowIndex + 1;
while (limit > 0) {
if (xNeg > -1 && yNeg > -1) {
$table.getCell(xNeg, yNeg).removeClass(cls);
}
if (xPos < colCount && yNeg > -1) {
$table.getCell(xPos, yNeg).removeClass(cls);
}
if (xNeg > -1 && yPos < rowCount) {
$table.getCell(xNeg, yPos).removeClass(cls);
}
if (xPos < colCount && yPos < rowCount) {
$table.getCell(xPos, yPos).removeClass(cls);
}
xNeg--;
xPos++;
yNeg--;
yPos++;
limit--;
}
}
$row.removeClass(cls);
$table.find(`td:nth-child(${colIndex + 1})`).removeClass(cls);
}
});
});
};
})(jQuery);
}
.word-search {
border: 2px solid #000;
border-collapse: collapse;
}
.word-search td {
width: 1.25em;
height: 1.25em;
line-height: 1.25em;
text-align: center;
}
.highlight {
background: #FFD;
}
.letter.highlight:hover {
background: #FF0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="word-search"></table>

Unable to print table grid using jQuery

I am unable to print a grid. This is what I am trying to do:
Take the grid size as an input from the user.
Dynamically create the grid based on the input.
Below is a part of the code.
$(document).ready(function() {
$("#grid-input").click(function() {
$(".drawing-area").empty();
var rows = $("#row").val();
var cols = $("#col").val();
if (rows > 0 && cols > 0) {
for (var i = 1; i <= rows; i++) {
var rowClassName = 'row' + i;
$('<tr></tr>').addClass(rowClassName).appendTo('.drawing-area'); //Adding dynamic class names whenever a new table row is created
for (var j = 1; j <= cols; j++) {
var colClassName = 'col' + j;
$('<td width="20px" height="20px" style="border: 1px solid #000"></td>').addClass(colClassName).appendTo('.rowClassName');
}
}
} else {
alert("You haven't provided the grid size!");
}
});
});
});
<table class="drawing-area">
</table>
There is an error in your code, Last brackets are not required.
Append dom at the end of your code,
Try following code
$(document).ready(function() {
$("#grid-input").click(function() {
$(".drawing-area").empty();
var rows = $("#row").val();
var cols = $("#col").val();
if (rows > 0 && cols > 0) {
for (var i = 1; i <= rows; i++) {
var rowClassName = 'row' + i;
var tr = $('<tr>').addClass(rowClassName);
tr.appendTo('.drawing-area'); //Adding dynamic class names whenever a new table row is created
for (var j = 1; j <= cols; j++) {
var colClassName = 'col' + j;
$('<td width="20px" height="20px" style="border: 1px solid #000">').addClass(colClassName).appendTo(tr);
}
}
} else {
alert("You haven't provided the grid size!");
}
});
});
You can try to save the dynamic table row to a variable $tr first and then add the dynamic table column to that $tr variable like:
$("#grid-input").click(function() {
$(".drawing-area").empty();
var rows = $("#row").val();
var cols = $("#col").val();
if (rows > 0 && cols > 0) {
for (var i = 1; i <= rows; i++) {
var rowClassName = 'row' + i;
// Saving dynamic table row variable
var $tr = $('<tr/>').addClass(rowClassName).appendTo('.drawing-area');
for (var j = 1; j <= cols; j++) {
var colClassName = 'col' + j;
$('<td>'+ (i * j) +'</td>').addClass(colClassName)
// Append the new td to this $tr
.appendTo($tr);
}
}
} else {
alert("You haven't provided the grid size!");
}
});
.drawing-area{font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;border-collapse:collapse;width:100%}
.drawing-area td,.drawing-area th{border:1px solid #ddd;padding:8px}
.drawing-area tr:nth-child(even){background-color:#f2f2f2}
.drawing-area tr:hover{background-color:#ddd}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Row: <input type="number" id="row"><br/>
Col: <input type="number" id="col"><br/>
<button id="grid-input">Save</button><br/><br/>
<table class="drawing-area">
</table>

how to dynamically add multiple checkboxes to an html table?

I want to dynamically add checkboxes to multiple rows in an html table, without having to add input type ="checkbox" for each . Is this possible?
The code snippet for making the table and a function 'check()' to add check boxes is given below...but it does not work. please help.
// Builds the HTML Table out of myList json data.
function buildHtmlTable(myList) {
var columns = addAllColumnHeaders(myList);
for (var i = 0; i < myList.length; i++) {
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = myList[i][columns[colIndex]];
if (cellValue == null) {
cellValue = "";
}
row$.append($('<td/>').html(cellValue));
}
$("#excelDataTable").append(row$);
}
}
// Adds a header row to the table and returns the set of columns.
function addAllColumnHeaders(myList) {
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0; i < myList.length; i++) {
var rowHash = myList[i];
for (var key in rowHash) {
if ($.inArray(key, columnSet) == -1) {
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
//check();
}
// check();
}
//check();
}
$("#excelDataTable").append(headerTr$);
return columnSet;
check();
}
function check() {
for (var i = 0; i < myList.length; i++) {
$('<input />', {
type: 'checkbox',
id: 'id' + i,
})
.appendTo("#excelDataTable");
}
}
You can add the checkboxes after the table is created.
Below, you can see the updated code. Your table creation works perfect. But you were trying to append the checkboxes to the table itself, not td elements.
In $(document).ready function below, you can see that I create the table first and after that call check() function. It basicly creates a new checkbox for each row, wraps it in a td and put that into the row.
I also added a change event method for the first checkbox to control all the others.
// Builds the HTML Table out of myList json data.
function buildHtmlTable(myList) {
var columns = addAllColumnHeaders(myList);
for (var i = 0; i < myList.length; i++) {
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = myList[i][columns[colIndex]];
if (cellValue == null) {
cellValue = "";
}
row$.append($('<td/>').html(cellValue));
}
$("#excelDataTable").append(row$);
}
}
// Adds a header row to the table and returns the set of columns.
function addAllColumnHeaders(myList) {
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0; i < myList.length; i++) {
var rowHash = myList[i];
for (var key in rowHash) {
if ($.inArray(key, columnSet) == -1) {
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
//check();
}
// check();
}
//check();
}
$("#excelDataTable").append(headerTr$);
return columnSet;
//check();
}
function check() {
// foreach row in the table
// we create a new checkbox
// and wrap it with a td element
// then put that td at the beginning of the row
var $rows = $('#excelDataTable tr');
for (var i = 0; i < $rows.length; i++) {
var $checkbox = $('<input />', {
type: 'checkbox',
id: 'id' + i,
});
$checkbox.wrap('<td></td>').parent().prependTo($rows[i]);
}
// First checkbox changes all the others
$('#id0').change(function(){
var isChecked = $(this).is(':checked');
$('#excelDataTable input[type=checkbox]').prop('checked', isChecked);
})
}
$(document).ready(function() {
var myList = [{
"ASN": "AS9498 BHARTI Airtel Ltd.",
"COUNTRY": "IN",
"IP": "182.72.211.158\n"
}, {
"ASN": "AS9874 StarHub Broadband",
"COUNTRY": "SG",
"IP": "183.90.37.224"
}, {
"ASN": "AS45143 SINGTEL MOBILE INTERNET SERVICE PROVIDER Singapore",
"COUNTRY": "SG",
"IP": "14.100.132.200"
}, {
"ASN": "AS45143 SINGTEL MOBILE INTERNET SERVICE PROVIDER Singapore",
"COUNTRY": "SG",
"IP": "14.100.134.235"
}]
buildHtmlTable(myList);
check();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="excelDataTable"></table>

Fire onkeyup in generated table with contenteditable

I've got a small problem in my javascript which i am stuck on for a while now.
What i did is :
Create an empty table.
Generate the tr/td tags and values inside the table(from JSON-object).
for (var i = 0 ; i < myList.length ; i++) {
var row$ = $('<tr/>');
for (var colIndex = 0 ; colIndex < columns.length ; colIndex++) {
var cellValue = myList[i][columns[colIndex]];
if(colIndex == columns.indexOf("type"))
{
var box$ = $('<td/>');
if(cellValue == "Organisation")
box$.addClass( "uk-badge uk-badge-danger" );
else
box$.addClass( "uk-badge uk-badge-primary" );
box$.html(cellValue);
row$.append(box$);
}
else
{
var box$ = $('<td/>');
box$.html(cellValue);
box$.attr('contenteditable','true');
box$.attr('onkeyup','updateJSON('+colIndex+','+i+')');
row$.append(box$);
}
}
$(selector).append(row$);
}
table looks fine:
td contenteditable="true" onkeyup="updateJSON(3,0)">Timmy/td>
The problem occurs when the table is generated and i edit a field. the 'onkeyup' does not 'fire' while it should. Replacing the 'onkeyup' with an 'onclick' works just fine. I have no clue why this does not work, can anybody help?
var myList = [
{
"id": 1,
"name": "arnold"
},
{
"id": 2,
"name": "hans"
},
{
"id": 3,
"name": "jack"
},
{
"id": 4,
"name": "Peter"
}];
function loadDoc3() {
$("#RelationDataTable tr").remove();
buildHtmlTable('#RelationDataTable');
}
// Builds the HTML Table out of myList.
function buildHtmlTable(selector) {
var columns = addAllColumnHeaders(myList, selector);
for (var i = 0 ; i < myList.length ; i++) {
var row$ = $('<tr/>');
for (var colIndex = 0 ; colIndex < columns.length ; colIndex++) {
var cellValue = myList[i][columns[colIndex]];
if(colIndex == columns.indexOf("type"))
{
var box$ = $('<td/>');
if(cellValue == "Organisation")
box$.addClass( "uk-badge uk-badge-danger" );
else
box$.addClass( "uk-badge uk-badge-primary" );
box$.html(cellValue);
row$.append(box$);
}
else
{
var box$ = $('<td/>');
box$.html(cellValue);
box$.attr('contenteditable','true');
box$.attr('onkeyup','updateJSON('+colIndex+','+i+')');
//box$.click(function() {
// alert( "Handler for .keyup() called." );
//});
row$.append(box$);
}
}
$(selector).append(row$);
}
}
var currentcolumns = [];
// Adds a header row to the table and returns the set of columns.
// Need to do union of keys from all records as some records may not contain
// all records
function addAllColumnHeaders(myList) {
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0 ; i < myList.length ; i++) {
var rowHash = myList[i];
for (var key in rowHash) {
if ($.inArray(key, columnSet) == -1 && key != "id") {
columnSet.push(key);
headerTr$.append($('<th/>').html(key));
}
}
}
$("#RelationDataTable").append(headerTr$);
currentcolumns = columnSet;
return columnSet;
}
function updateJSON(xx,y)
{
var cellValue = myList[y][currentcolumns[xx]];
alert(document.getElementById("RelationDataTable").rows[y+1].cells[xx].firstChild.nodeValue);
myList[y][currentcolumns[xx]] = document.getElementById("RelationDataTable").rows[y+1].cells[xx].firstChild.nodeValue;
x = 2;
}
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<input id="searchname" type="text" name="InsertSearchname" onkeyup="loadDoc3()"><h2>Search Contact</h2>
<table id="RelationDataTable">
<thead>
</thead>
<tbody>
</tbody>
</table>
</body>
contenteditable="true" should be set for your <td> elements, not on the <table>.
Otherwise the td will not trigger an event.
So add box$.attr('contenteditable','true'); in your loop.

Alternating Table Rows With Javascript issue

I have the following script working to add odd and even classes to alternating table rows which works fine.
function alternate(){
if(document.getElementsByTagName){
var table = document.getElementsByTagName("table");
var rows = document.getElementsByTagName("tr");
for(i = 0; i < rows.length; i++){
//manipulate rows
if(i % 2 == 0){
rows[i].className = "even";
}else{
rows[i].className = "odd";
}
}
}
}
However a problem arises when there is more than one table on a page. I need the counter to reset for each table on the page so the first row of each table always has the same class (i.e. odd). Currently the second table on the page will just carry on counting rows odd-even so it will start on a different class if the first table has an odd number of rows.
Can anyone help me change this code to achieve this?
Here you go:
function alternate() {
var i, j, tables, rows;
tables = document.getElementsByTagName( 'table' );
for ( i = 0; i < tables.length; i += 1 ) {
rows = tables[i].rows;
for ( j = 0; j < rows.length; j += 1 ) {
rows[j].className = j % 2 ? 'even' : 'odd';
}
}
}
Live demo: http://jsfiddle.net/simevidas/w6rvd/
Alternative solution:
(Substituting the for iteration statements with forEach invocations makes the code more terse. Doesn't work in IE8 though :/.)
function alternate() {
var tables = document.getElementsByTagName( 'table' );
[].forEach.call( tables, function ( table ) {
[].forEach.call( table.rows, function ( row, i ) {
row.className = i % 2 ? 'even' : 'odd';
});
});
}
Live demo: http://jsfiddle.net/simevidas/w6rvd/1/
You have to add a for for each table:
function alternate(){
if(document.getElementsByTagName){
var table = document.getElementsByTagName("table");
// each table
for(a = 0; a < table.length; a++){
var rows = table[a].getElementsByTagName("tr");
for(i = 0; i < rows.length; i++){
//manipulate rows
if(i % 2 == 0){
rows[i].className = "even";
}else{
rows[i].className = "odd";
}
}
}
}
}
do this work, based on each table
function alternate(){
if(document.getElementsByTagName){
var table = document.getElementsByTagName("table");
var rows = document.getElementsByTagName("tr");
for(var a = 0; a < table.length; a++){
{
for(var i = 0; i < table[a].rows.length; i++){
//manipulate rows
if(i % 2 == 0){
table[a].rows[i].className = "even";
}else{
table[a].rows[i].className = "odd";
}
}
}
} }
}

Categories

Resources