jQuery Table sorter Sorting of Float distance - javascript

I am using tablesorter to sort the table content. My table is as below.
<table class="results" border="1">
<thead>
<tr>
<th class="header">No</th>
<th class="header">Distance</th>
<th class="header">Diagnostic Fee</th>
<th class="header">Regular Price </th>
<th class="header">Company Price</th>
<th class=""> </th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td class="distance"><a>16.50 kms.</a></td>
<td class="brand"><a>Credited</a></td>
<td><a>$5</a></td>
<td><a>$5<small>after 5% cash back</small></a></td>
</tr>
<tr>
<td>2</td>
<td class="distance"><a>6.30 kms.</a></td>
<td class="brand"><a>Credited</a></td>
<td><a>$8</a></td>
<td><a>$8<small>after 5% cash back</small></a></td>
</tr>
<tr>
<td>3</td>
<td class="distance"><a>10.25 kms.</a></td>
<td class="brand"><a>Credited</a></td>
<td><a>$2</a></td>
<td><a>$2<small>after 5% cash back</small></a></td>
</tr>
</tbody>
</table>​
I want to sort the table using distance and price.
I am facing difficulty is solving table with distance, because distance is displayed in alphanumeric like "12 kms". So, The table is not getting sorted.
Can anyone advise how to parse the content by taking only digits?
here is the jsfiddle demo

Tablesorter provides a way of defining additional parsers for cells in which it can't obtain data correctly. You need to define 2 parsers for the 2 columns you're interested in.
So you might have:
$.tablesorter.addParser({
id: 'distance',
is: function(s) {
return false;
},
format: function(text, table, cell) {
return parseFloat(text.replace('kms.', ''));
},
type: 'numeric'
});
for distance, and:
$.tablesorter.addParser({
id: 'price',
is: function(s) {
return false;
},
format: function(text, table, cell) {
return parseFloat(text.replace('$', ''));
},
type: 'numeric'
});
for price. You then tell tablesorter which columns to use the parses on, so:
$("table").tablesorter({
debug:false,
sortList: [[0, 0], [2, 0]],
headers: {
1: {
sorter: 'distance'
},
3: {
sorter: 'price'
}
}
});​

Tablesorte has an option 'textExtraction', so you can define a function to go through the text before sorting. Example:
$("table").tablesorter({
debug:false,
sortList: [[0, 0], [2, 0]],
textExtraction: function(node) {
var $node = $(node)
var text = $node.text();
if ($node.hasClass('distance')) {
text = text.replace('kms', '');
};
return text;
}
});
Updated fiddle

Related

Bootstrap Table: sort by date field

I am using this Bootstrap table plugin. But sorting by date is not working properly.
Here is the code:
<table class=" table-striped" id="table" data-toggle="table"
data-search="true"
data-filter-control="true"
data-click-to-select="true"
data-escape="false">
<thead>
<tr>
<th data-field="expiry_date" data-sortable="true" scope="col"><?= 'expiry date' ?></th>
</tr>
</thead>
Date is in this format: d/m/y (17/7/14)
How I can fix it in order to sort dates properly?
You must use a custom sorter with "data-sorter" attribute like data-sorter="datesSorter"
Then to fit your needs :
function datesSorter(a, b) {
if (new Date(a) < new Date(b)) return 1;
if (new Date(a) > new Date(b)) return -1;
return 0;
}
Put at the begining of <td> content the date translate to number like this
<span style="display:none">{{strtotime($date)}}</span>
I use a function with a short syntax, with the 'data-sorter' option:
<table
id="table"
data-toggle="table"
data-height="460"
data-url="json/data1.json">
<thead>
<tr>
<th data-field="id">ID</th>
<th data-field="name">Item Name</th>
<th data-field="date" data-sortable="true" data-sorter="dateSorter">Item Date</th>
</tr>
</thead>
</table>
<script>
function dateSorter(a, b){
return(new Date(a).getTime() - new Date(b).getTime());
}
</script>
You must use a custom sorter with "data-sorter" attribute like data-sorter="datesSorter".
Then to fit your needs:
function datesSorter(a, b) {
return Date.parse(a) - Date.parse(b);
}
I got it working like this....
I added a new column (numerical) and set it to hidden. You could do that easily by converting that date to a number.
$('#mainTable').bootstrapTable({
sortStable: true,
pagination: true,
pageSize: 100,
toolbar:"#toolbar",
search: true,
searchOnEnterKey: false,
sortOrder: "desc",sortOrder: "desc",
// here we determine the column that will sort the table
sortName: "rel0",
columns: [
{
// this is the hidden numeric column that works as sorter
field: 'rel0',
title: 'rel0',
visible:false,
},
{
// this is the visible column
field: 'rel',
title: 'Date / hour',
},
],
data: objetoData
});

Transpose dynamic table from rows to columns and vice versa

config.previewData = [
{
Cartridges:27989,
Total Accounts:294,
Metrices:"MVC",
Toner Cartridges:5928,
INK Cartridges:22061
},
{
Cartridges:56511,
Total Accounts:376,
Metrices:"SMB",
Toner Cartridges:15253,
INK Cartridges:41258
},
{
Cartridges:84,500,
Total Accounts:670,
Metrices:"Grand Total",
Toner Cartridges:21,181,
INK Cartridges:63,319
},
]
and my html code like this
<table class="table table-striped">
<thead>
<tr role="row">
<th data-ng-repeat="(key, val) in config.previewData[0]">
{{ key}}
</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="row in config.previewData">
<td data-ng-repeat="column in row">
{{column}}
</td>
</tr>
</tbody>
</table>
this code will print perfect like below image
now i want to transpose this table into rows to columns and columns to rows.
Is this possible with dynamic table because my object is dynamic not fixed.
Help me if anyone knows how to do this.
After transpose table looks like this
Using the same assumptions your example codes does (i.e. config.previewData always contains at least one object, and all objects have the same properties...)
<table class="table table-striped">
<tbody>
<tr data-ng-repeat="(key, val) in config.previewData[0]">
<th>
{{ key }}
</th>
<td data-ng-repeat="row in config.previewData">
{{ row[key] }}
</td>
</tr>
</tbody>
</table>
Using reduce, you can have something like this to transpose your data, which can then be used to iterate over using ng-repeat very easily!
Example snippet (in Pure JS for simplification):
var previewData = [{
"Cartridges": 27989,
"Total Accounts": 294,
"Metrices": "MVC",
"Toner Cartridges": 5928,
"INK Cartridges": 22061
},
{
"Cartridges": 56511,
"Total Accounts": 376,
"Metrices": "SMB",
"Toner Cartridges": 15253,
"INK Cartridges": 41258
},
{
"Cartridges": 84500,
"Total Accounts": 670,
"Metrices": "Grand Total",
"Toner Cartridges": 21181,
"INK Cartridges": 63319
}
]
var transpose = previewData.reduce(function(arr, obj) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
arr[key] = arr[key] || []
arr[key].push(obj[key])
}
}
return arr
}, {})
console.log(transpose)
this is the only (dirty) way i could think out
<tr>
<td data-ng-repeat="row in previewData">{{row['Metrices']}}</td>
</tr>
<tr>
<td data-ng-repeat="row in previewData">{{row['Total Accounts']}}</td>
</tr>
<tr>
<td data-ng-repeat="row in previewData">{{row['Toner Cartridges']}}</td>
</tr>
...... and so on
other options: Transposing JSON
If you have a 2-D array which can be logged into console by the function
tab = [[2,3,4],[-4,6,0],[1,0,9]]
console.table(tab)
You can log the transpose of it by using the following function:
function transpose_table(tab) {
let columns = tab.length;
let rows = tab[0].length;
let trans = [];
for (i=0; i<rows; i++) {
trans.push([]);
}
for (i=0; i<columns; i++) {
for (j=0; j<rows; j++) {
trans[j][i] = tab[i][j];
}
}
return trans;
}
Now run:
console.table(transpose_table(tab))

DataTables footerCallback and contenteditable

I have a DataTable that sums over each column using footerCallback. This works perfectly given the data in each column, but I also want to add the ability to change each cell's value that is being summed. I've tried adding "contenteditable" to those cells, but making a change does not affect the sum in the footer.
Here is a simple jsfiddle showing the behavior I'm experiencing: https://jsfiddle.net/rantoun/552y9j90/6/
HTML:
<table id="table1">
<thead>
<tr>
<th>Fruit</th>
<th># Eaten</th>
<th># Remaining</th>
</tr>
</thead>
<tfoot>
<tr>
<th align="right">Count</th>
<th align="left"></th>
<th align="left"></th>
</tr>
</tfoot>
<tbody>
<tr>
<td>Apples</td>
<td contenteditable>3</td>
<td contenteditable>8</td>
</tr>
<tr>
<td>Oranges</td>
<td contenteditable>6</td>
<td contenteditable>5</td>
</tr>
<tr>
<td>Bananas</td>
<td contenteditable>2</td>
<td contenteditable>9</td>
</tr>
</tbody>
</table>
jQuery:
$("#table1").DataTable({
"paging": false,
"searching": false,
"info": false,
"footerCallback": function ( row, data, start, end, display ) {
var columns = [1, 2];
var api = this.api();
_.each(columns, function(idx) {
var total = api
.column(idx)
.data()
.reduce(function (a, b) {
return parseInt(a) + parseInt(b);
}, 0)
$('tr:eq(0) th:eq('+idx+')', api.table().footer()).html(total);
})
}
});
I have also found the DataTables editor (https://editor.datatables.net/examples/inline-editing/simple), which would be perfect for this situation - but it is not open source. Any ideas on how to mimic this inline editing functionality is welcome. I would like to avoid doing this with modals. Any help is appreciated!
Here is an answer that allows you to edit in place with contenteditable.
Note that this requires the dataTables KeyTable plugin
Working Fiddle here
/* Note - requires datatable.keys plugin */
var table = $("#table1").DataTable({
"keys": true,
"paging": false,
"searching": false,
"info": false,
"footerCallback": function ( row, data, start, end, display ) {
var columns = [1, 2];
var api = this.api();
_.each(columns, function(idx) {
var total = api
.column(idx)
.data()
.reduce(function (a, b) {
return parseInt(a) + parseInt(b);
}, 0)
$('tr:eq(0) th:eq('+idx+')', api.table().footer()).html(total);
})
}
});
// keys introduces the key-blur event where we can detect moving off a cell
table
.on( 'key-blur', function ( e, datatable, cell ) {
// The magic part - using the cell object, get the HTML node value,
// put it into the dt cell cache and redraw the table to invoke the
// footer function.
cell.data( $(cell.node()).html() ).draw()
} );
Note - I can foresee that you may get non-numeric data entered. You will have to police that in the key-blur event where you can test the dom node value and act accordingly.

Only show table data on todays date

Ok so I have a table with information. Inside of this table are the columns namer and date (DD-MM-YYYY).
I need to restrict the table to only showing rows in my table that have a date that is equal to the current date. So if there are 10 rows and only 5 of them have today's date in the date column, only those 5 should show.
So I wondered if anyone knew of any code that would show only the rows on todays date, and change date automatically everyday.
Current HTML
<table class="tablesorter">
<thead>
<tr>
<th>Name</th>
<th>Release Date</th>
</tr>
</thead>
<tbody>
<tr>
<td>Peter Parker</td>
<td>11/07/2015</td>
</tr>
<tr>
<td>John Hood</td>
<td>12/07/2015</td>
</tr>
<tr>
<td>Clark Kent</td>
<td>12/07/2015</td>
</tr>
<tr>
<td>Bruce Almighty</td>
<td>13/07/2015</td>
</tr>
<tr>
<td>Bruce Evans</td>
<td>14/07/2015</td>
</tr>
</tbody>
</table>
Current Javascript
$(document).ready(function () {
$("table").tablesorter({
headers: {
0: {
sorter: false
},
1: {
sorter: false
},
2: {
sorter: false
}
}
});
});
I'd suggest doing this before they appear in the HTML, but here is how to do it with jQuery.
$("document").ready(function () {
var t = new Date();
$("tr td:nth-child(2)").each(function () {
var text = $(this).text().match(/(\d+)/g);
var d = new Date(text[2], text[1] - 1, text[0]);
if (d.toDateString() == t.toDateString()) {
var d = new Date(text[2], text[1] - 1, text[0]);
$(this).closest('tr').addClass('hidden');
};
});
});
Today's dat eis defined. The function will cycle through the second TD in each TR, define a date from the text inside (using regex-match to separate the date components), compare that to today's date, and if they are the same it will add the hidden class to the whole row.
JSFiddle
Hope that helps.
EDIT: Forgive me, I didn't read the question properly! It seems you want to hide those that don't have today's date. In that case change the == in the if block to !=. This will do the opposite. JSFiddle 2

Data Tables and Nested tables

I am having real trouble understanding what is happening with Data Tables. I create a DataTable as follows
var dTable = $('#sessionReport').dataTable({
"bInfo" : false,
"bFilter" : false,
"aaData" : data,
"bDestroy" : true,
"fnFooterCallback" : function(nRow, aaData, iStart, iEnd, aiDisplay){
var totalAttendees = 0;
var totalTime = 0;
var avgSatisfaction = 0;
for(var i=0; i<aaData.length; i++){
avgSatisfaction = avgSatisfaction + ((aaData[i][7]*1)+3*1)/aaData.length; // range is from -2 to + 2; have added 3 to each result to make range of positive numbers only
totalAttendees = totalAttendees + aaData[i][5]*1;
startTime = new Date(aaData[i][0]);
endTime = new Date(aaData[i][1]);
totalTime = totalTime + (endTime - startTime)/10000;
}
//alert(secondsToString(totalTime));
//$('#tfAttendees').innerHTML = parseInt(totalAttendees);
var nCells = nRow.getElementsByTagName('th');
nCells[5].innerHTML = parseInt(totalAttendees);
nCells[7].innerHTML = parseFloat(avgSatisfaction.toFixed(2));
}
});
return dTable;
My data is formatted like this:
[ 0: "2012-10-24 09:43:03"
1: "2012-10-24 09:49:47"
2: "5002028"
3: "Eamonn"
4: "Dannys Memories"
5: "7"
6: ""
7: "0" ],
[O:....],
But I run into problems when I want to add a column with an icon to each row like in this solution
http://datatables.net/blog/Drill-down_rows
I have tried using aoColumns and aoColumnsdef. But not really sure how. My problem is that table html is being built by the data. So if there are only 7 items in the data array there will only be 7 columns in my Html Table. How can I add an eighth column. I want the beginning on each row to have a clickable icon.
And my html looks like this...
<table id="sessionReport" class="table table-striped fTable">
<thead>
<tr>
<td>Start Session</td>
<td>End Session</td>
<td>Session Id</td>
<td>Facilitator</td>
<td>Group Name</td>
<td>No. Attendees</td>
<td>Assistant</td>
<td>Satisfaction</td>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<th id="tfStartSession">
Total Hours
</th>
<th id="tfEndSession">
</th>
<th id="tfSessionId">
</th>
<th id="tfFacilitator">
</th>
<th id="tfGroupName">
TOTAL ATTENDEES :
</th>
<th id="tfAttendees">
</th>
<th id="tfAssistant">
AVG SATISFACTION :
</th>
<th id="tfSatisfaction">
</th>
</tr>
</tfoot>
</table>
Any ideas. I'm a bit stumped by DataTables documentation and they don't seem to provide any usage examples of either aoColumns or aoColumnsDef.
Many thanks

Categories