Javascript Datatable Time Sum - javascript

I'm trying to do something with JavaScript DataTable but I'm stuck somewhere .
There are 2 DataTable on the same page .
I am sending data from the first DataTable second DataTable . I can write in the footer section that collects in the second DataTable int .
I collect information on hours in a second column in the DataTable I want to write a footer . I could not do it.
How do you think I should proceed . Existing employees script below.
Thank you to everyone.
<script type="text/javascript" language="javascript">
$(document).ready(function() {
var t = $('#FlowList').DataTable({
rowReorder: true,
"footerCallback": function ( row, data, start, end, display ) {
var api = this.api(), data;
// Remove the formatting to get integer data for summation
var intVal = function ( i ) {
return typeof i === 'string' ?
i.replace(/[\$,]/g, '')*1 :
typeof i === 'number' ?
i : 0;
};
// Tüm sayfaların toplamı
total = api
.column( 3 )
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
}, 0 );
// Gösterilen sayfanın toplamı
pageTotal = api
.column( 3, { page: 'current'} )
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
}, 0 );
// Footer Güncelleme
$( api.column( 3 ).footer() ).html(
/* '$'+pageTotal +' ( $'+ total +' Toplam)' */
'Toplam ' + total
);
}
});
var counter = 1;
var table = $('#NewsListTable').DataTable();
$('#NewsListTable tbody').on('dblclick', 'tr', function(){
var data = table.row( this ).data();
//alert(data[3]);
t.row.add( [
counter +'', //Sıra numarasını her seferinde 1 arttırıyoruz.
data[1],
data[2],
data[3],
data[4],
data[5],
data[6],
data[7],
data[8]
]
).draw( false );
counter++;
});
});
</script>

Related

jQuery DataTable rows conditional formatting, grand total by column

I have two tasks to do in DataTables:
To display green row if 'amount' field value is less than 500 and red if amount is more than 5000
To display sum by 'amount' column at the bottom
I am getting output if I call each function individually, but if I tried to call them together, I get no result.
var table=$('table.display').DataTable(
{"fnRowCallback": function( nRow, aData, iDisplayIndex,
iDisplayIndexFull )
{
if (aData[5]<500){
$('td', nRow).css('background-color', 'Orange');}
else if (aData[5]>5000){$('td', nRow).css('background-color', '#9EF395');}}
"footerCallback": function ( row, data, start, end, display ) {
var api = this.api(), data;
var intVal = function ( i ) {
return typeof i === 'string' ?
i.replace(/[\$,]/g, '')*1 :
typeof i === 'number' ?
i : 0;};
total = api
.column(2)
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
}, 0 );
pageTotal = api
.column( 2, { page: 'current'} )
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
}, 0 );
$( api.column( 2 ).footer() ).html(''+pageTotal +' ( '+
total +' total)');}});} );
Here you go:
//source data
var myData = [
{item: 'apple', amount: 250},
{item: 'pear', amount: 570},
{item: 'pinaple', amount: 6700},
{item: 'banana', amount: 140}
];
//data table initialization
var dataTable = $('#mytable').DataTable({
sDom: 't',
data: myData,
columns: [
{data: 'item', title: 'item'},
{data: 'amount', title: 'amount'}
]
});
//append sum
$('#mytable').append(`<tfoot>${Array(dataTable.columns().count()).fill('<th></th>').join('')}</tfoot>`);
var sum = dataTable.column(1).data().reduce((acc, entry) => acc+=entry);
$('#mytable tfoot th').eq(1).text(sum);
//conditional formatting
dataTable.rows().every(function(){
let color = this.data().amount > 5000 ? 'red' : this.data().amount < 500 ? 'green' : 'unset';
$(this.node()).css('background-color', color);
});
<!doctype html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<table id="mytable"></table>
</body>
</html>
Do this example :
const Table = $('#foo').DataTable({
. . . . . .,
. . . . . .,
drawCallback: function(){
Table.columns(5, {
page: 'current'
}).every(function() {
var sum = this
.data()
.reduce(function(a, b) {
var x = parseFloat(a) || 0;
var y = parseFloat(b) || 0;
return x + y;
}, 0);
console.log(sum);
$(this.footer()).html(sum);
});
}
});
in this case, the column was column number 5

Add Columns And Separate By Category

I have a datatable that is using standard features (pagination, sorting, searching, date range, etc.), but I also need to have a portion at the bottom of the table that displays the total salary of each office. The output would (ideally) look something like this if you searched for, say, "engineer":
London: $295,500
San Francisco: $409,350
Singapore: $234,500
Tokyo: $139,575
Edinburgh: $103,600
New York: $125,250
Total Hours: $1,307,775.00
I have tried a handful of different approaches, but frankly my script knowledge is lacking and I am out of my depth. Can anyone point me in the right direction on how to solve this issue?
Here is my script:
"footerCallback": function (row, start, end, display) {
var api = this.api(),
data;
// Remove the formatting to get integer data for summation
var intVal = function (i) {
return typeof i === 'string' ?
i.replace(/[\$,]/g, '') * 1 :
typeof i === 'number' ?
i : 0;
};
// ************NOT WORKING************ \\
// Total by category
// First Attempt
if (api.column(5,
{
search: 'applied'
})
.data()
.length) {
var byCategory = api
.rows()
.data()
.reduce(function (a, c) {
a[c[7]] = a[c[7]] || 0;
a[c[7]] += intVal(c[5]);
return a;
},
{});
}
else {
byCategory = 0;
}
console.clear();
console.dir('by category', byCategory);
/*
// Second Attempt
if (api.column(5, {
search: 'applied'
}).data().length) {
var byCategory = api
.rows(5, {
search: 'applied'
})
.data()
.reduce(function (category, hours) {
category[hours[7]] = category[hours[7]] || 0;
category[hours[7]] += intVal(hours[5]);
return category;
}, {});
}
else {
byCategory = 0;
}
console.clear();
console.dir('by category', byCategory); */
// ************NOT WORKING************ \\
// Third Attempt
/*var byCategory = api
.rows()
.data()
.reduce(function (a, c) {
a[c[7]] = a[c[7]] || 0;
a[c[7]] += intVal(c[5]);
for (var key in byCategory) {
if (byCategory.hasOwnProperty(key)) {
console.log(key + " -> " + byCategory[key]);
}
}
}, {}); */
// Total over all pages
total = api
.column(5)
.data()
.reduce(function (a, b) {
return intVal(a) + intVal(b);
}, 0);
// Total over all filtered pages
if (api.column(5, {
search: 'applied'
}).data().length) {
pageTotal = api
.column(5, {
search: 'applied'
})
.data()
.reduce(function (a, b) {
return intVal(a) + intVal(b);
});
} else {
pageTotal = 0;
}
// Update footer
$(api.column(5).footer()).html(
pageTotal.toFixed(2) + ' hours ( ' + total.toFixed(2) + ' total hours)' + '<br>' + Object.entries(byCategory) + ' hours'
//pageTotal.toFixed(2) + ' hours ( ' + total.toFixed(2) + ' total hours)' + '<br>' + Object.keys(byCategory).map(key => { console.log(key, byCategory[key]) }) + ' hours'
//pageTotal.toFixed(2) + ' hours ( ' + total.toFixed(2) + ' total hours)' + '<br>' + Object.keys(byCategory).forEach(key => { console.log(key, byCategory[key]) }) + ' hours'
);
}
Here is a link to my jsfiddle: https://jsfiddle.net/l337method/hfyo90w7/
You Can do sum of salary by office using below code sample as said over here, which you can modify according to your need.
Replace 1 by column number you want to compare data with.
total = api.cells( function ( index, data, node ) {
return api.row( index ).data()[1] === 'textA' ?
true : false;
}, 0 )
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
} );
To be more specific : you can do something like this, you can use this function to sum up values. see #davidkonrad for exactly what you want with filter.
$("#example").on('search.dt', function() {
alert(table.column( 0, {page:'current'} ).data().sum() );
});
You should really consider using the small sum() plug-in. In your case, all what you need next is something like
drawCallback: function() {
var sum = this.api().column( 5, { search:'applied', page: 'all' }).data().sum();
$( this.api().column(5).footer() ).text(
'$'+Number(sum.toFixed(1)).toLocaleString()
);
}
You can translate this into "get the sum of all column(5) values from all pages, but only those which is not filtered out". drawCallback will be triggered each and every time you search, filter etc.
Here is a forked version of your fiddle -> https://jsfiddle.net/7cjL35dr/
The code was a little bit confusing so I tried to cleanup before I added the sum() plugin and the drawCallback.

DataTables combine FooterCallback and select filtering

Good evening.
I had some problems combining two DataTables functions (see title).
This (FooterCallback) to display the sum of a column with numeric values:
$(document).ready(function() {
$('#pr_table').DataTable( {
"footerCallback": function ( row, data, start, end, display ) {
var api = this.api(), data;
// Remove the formatting to get integer data for summation
var intVal = function ( i ) {
return typeof i === 'string' ?
i.replace(/[\$,]/g, '')*1 :
typeof i === 'number' ?
i : 0;
};
// Total over all pages
total = api
.column( 4 )
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
}, 0 );
// Total over this page
pageTotal = api
.column( 4, { page: 'current'} )
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
}, 0 );
// Update footer
$( api.column( 4 ).footer() ).html(
'cub.m'+pageTotal +' ( cub.m'+ total +' total)'
);
}
} );
} );
With this (select filtering):
$(document).ready(function() {
$('#pr_table').DataTable( {
"initComplete": function () {
var api = this.api();
api.columns().indexes().flatten().each( function ( i ) {
var column = api.column( i );
var select = $('<select><option value=""></option></select>')
.appendTo( $(column.header()).empty() )
.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search( val ? '^'+val+'$' : '', true, false )
.draw();
} );
column.data().unique().sort().each( function ( d, j ) {
select.append( '<option value="'+d+'">'+d+'</option>' )
} );
} );
}
} );
} );
If I use only one of the functions in my script, everything is working just fine. But trying to combine them results in DataTables failing to initialize at all (just raw html table shows up).
I am relatively unfamiliar with javascript this advanced, so it would help me if someone would give me an example of the script with a little explanation how to use multiple functions in one initialization.

How to remove columns in JQuery Datatables?

I want to remove the columns which have total = 0.
So I've tried in different ways.
First, I assigned ID to all columns, for example; every <td> is of column will have their ID eg: First columns <td ID = 'col_1'> , second column all <td ID = 'col_2'> etc. And then in when footer callback I've tried to remove if this column total is ZERO then this $("col_"+i).remove(); this code removed table headers only so I've tried again with $("col_"+i).empty() but again it's just empty. <th> only
Then I've tried to hide the columns by creating dynamic but I don't get any values.
"footerCallback": function ( row, data, start, end, display )
{
var api = this.api(), data;
var intVal = function ( i ) { return typeof i === 'string' ? i.replace(/[\$,]/g, '')*1 : typeof i === 'number' ? i : 0;};
var col_gonna_invis = '[';
for(i=1;i<length_of_coloumns;i++)
{
total_salary = api.column( i ).data().reduce( function (a, b) {return intVal(a) + intVal(b);},0 );
$('#total_cont_'+i).html(total_salary);
if(total_salary == 0)
{
col_gonna_invis += '{"targets": [ '+i+' ], "visible": false, "searchable": false },';
}
}
col_gonna_invis += ']';alert(col_gonna_invis);
},
"aoColumnDefs": col_gonna_invis;
Please someone help me fix this issue or please someone tell me how to hide or remove columns which footer total is 0.
Thank you in advance.
I will suggest you use the visible() API method along with the sum() plugin :
Enhance the API with a column().sum() method :
jQuery.fn.dataTable.Api.register( 'sum()', function ( ) {
return this.flatten().reduce( function ( a, b ) {
if ( typeof a === 'string' ) {
a = a.replace(/[^\d.-]/g, '') * 1;
}
if ( typeof b === 'string' ) {
b = b.replace(/[^\d.-]/g, '') * 1;
}
return a + b;
}, 0 );
} );
now, in initComplete() you can very easy hide columns which have a total or sum() of 0 :
var table = $('#example').dataTable({
//...
initComplete : function() {
var api = this.api(),
colCount = api.row(0).data().length;
for (var i=0; i<colCount; i++) {
if (api.column(i).data().sum() == 0) {
api.column(i).visible(false);
}
}
}
});
demo -> http://jsfiddle.net/qer7e5os/

columnfilterwidget in Datatables Filter sort issue

I am using DataTables 1.10 with Columnfilterwidget,
Problem i am facing is
I have values like
0,1.44,10,100,100.00,20,20.13
Right now Columnfilterwidget is sorting these values alphabetically
0
1.44
10
100
100.00
20
20.13
But i want them to be filtered numerically
0
1.44
10
20
20.13
100
100.00
Like this,
This is what i have tried so far
In Columnfilterwidget.js file
ColumnFilterWidget.prototype.fnDraw = function() {
var widget = this;
var oDistinctOptions = {};
var aDistinctOptions = [];
var aData;
if ( widget.asFilters.length === 0 ) {
// Find distinct column values
aData = widget.oDataTable.fnGetColumnData( widget.iColumn );
$.each( aData, function( i, sValue ) {
var asValues = widget.sSeparator ? sValue.split( new RegExp( widget.sSeparator ) ) : [ sValue ];
$.each( asValues, function( j, sOption ) {
if ( !oDistinctOptions.hasOwnProperty( sOption ) ) {
oDistinctOptions[sOption] = true;
aDistinctOptions.push( sOption );
}
} );
} );
// Build the menu
widget.$Select.empty().append( $( '<option></option>' ).attr( 'value', '' ).text( widget.oColumn.sTitle ) );
// aDistinctOptions.sort();
aDistinctOptions.sort(function(a,b){return a - b});
$.each( aDistinctOptions, function( i, sOption ) {
var sText;
if(sOption==='')
sText = $( '<div> (Blank )</div>' ).text();
else
sText = $( '<div>' + sOption + '</div>' ).text();
widget.$Select.append( $( '<option></option>' ).attr( 'value', sOption ).text( sText ) );
} );
if ( aDistinctOptions.length > 1 ) {
// Enable the menu
widget.$Select.attr( 'disabled', false );
} else {
// One option is not a useful menu, disable it
widget.$Select.attr( 'disabled', true );
}
}
};
I changed sort function to numeric, but how can i identify the coming value is numeric, also i checked sValue values are string, so is there any way i can define Columns i want to numeric.
Also tried setting options oColumnFilterWidgets still it didn't worked.
oColumnFilterWidgets: {
"aiExclude": [ 0, 1, 10 ],
"aoColumnDefs": [
// { "bSort": false, "sSeparator": " / ", "aiTargets": [ 5 ] },
{ "fnSort": function( a, b ) { return a-b; }, "aiTargets": [6] },
{"sType": "numeric", "aiTargets":[6]}
]
},
What am i doing wrong here?
Thanks to cyberhobo who fixed this issue.
[https://github.com/cyberhobo/ColumnFilterWidgets/commit/01efef439c557154bad3d61aa00d47285b6d21d6#diff-72250e81389e20ff2fa22ff884fcb6aaR309][1]
Just made the changes he highlighted inside plugin and
"oColumnFilterWidgets": {
"aoColumnDefs": [
{ "bSort": false, "sSeparator": " / ", "aiTargets": [ 2 ] },
{ "fnSort": function( a, b ) { return a-b; }, "aiTargets": [ 3 ] }
]
}
Hope this helps.

Categories

Resources