Problem sort numbers (currency )with thousands, millions and billions - javascript

I have a problem to sort a table in ascending and descending order. Need your help!!! I have numbers from 0,0000000052€ till 31.939€. Here is my tablesort.js, how can i solve this problem any ideas. My target is to sort the table in ascending and descending order when i click the headers. For all help i am very grateful.
$(document).ready(function () {
$('th').each(function (col) {
$(this).hover(
function () {
$(this).addClass('focus');
},
function () {
$(this).removeClass('focus');
}
);
$(this).click(function () {
if ($(this).is('.asc')) {
$(this).removeClass('asc');
$(this).addClass('desc selected');
sortOrder = -1;
} else {
$(this).addClass('asc selected');
$(this).removeClass('desc');
sortOrder = 1;
}
$(this).siblings().removeClass('asc selected');
$(this).siblings().removeClass('desc selected');
var arrData = $('table').find('tbody >tr:has(td)').get();
arrData.sort((a, b) => {
var val1 = $(a).children('td').eq(col).text().toUpperCase();
parseFloat(val1);
var val2 = $(b).children('td').eq(col).text().toUpperCase();
parseFloat(val2);
if ($.isNumeric(val1) && $.isNumeric(val2))
return sortOrder == 1 ? val1 - val2 : val2 - val1;
else return val1 < val2 ? -sortOrder : val1 > val2 ? sortOrder : 0;
});
$.each(arrData, function (index, row) {
$('tbody').append(row);
});
});
});
});
//Example ejs File
<% layout('layouts/boilerplate') -%>
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--4-col">
<table
id="myTable"
class="mdl-data-table table table-sortable mdl-js-data-table mdl-data-table mdl-shadow"
>
<thead>
<tr>
<th class="mdl-data-table__header-cell--sorted">Kurs</th>
</tr>
</thead>
<tbody id="coinTable">
<tr>
<td class="current_price">0,0000234</td>
</tr>
<tr>
<td class="current_price">9,99</td>
</tr>
<tr>
<td class="current_price">31780,86</td>
</tr>
<script src="javascripts/tablesort.js"></script>
</tbody>
</table>
</div>
</div>``

Ok thanks for help. I found a way that works for me. Sure it is not the best way but it works fine and fast. I optimized my tablesort, here my solution.
var val1 = $(a)
.children('td')
.eq(col)
.text()
.toUpperCase()
.replace(/[.]/g, '')
.replace(/[_]/g, '0.0')
.replace(/[,]/g, '.');
var val3 = parseFloat(val1);```

Related

HTML Table Filtering/Selection

I have an HTML table that has some static data and some from MySQL. It is currently filtering properly, what I need help is adding the "yes" and "no" selections to the selection list. These are just test values, they are being read from MySQL. I am unable to figure out what values to insert here to add values from MySQL to the selection list. Any assistance will be appreciated! Thank you
.append($table.find('tbody tr')
<!DOCTYPE html>
<html lang="en">
<link rel="stylesheet" href="/stylesheets/style.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<head>
<meta charset="utf-8">
<title>Filter</title>
</head>
<script>
$.ajax({
url: 'http://localhost:7003/getTable',
type: "get",
dataType: "json",
success: function(data) {
drawTable(data);
}
});
function drawTable(data) {
for (var i = 0; i < data.length; i++) {
drawRow(data[i]);
}
}
</script>
</body>
</html>
<table id="myTable" class="table table-striped">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th class="dropdown-header">Age</th>
<th>Email</th>
<th class="dropdown-header">Gender</th>
<th class="dropdown-header">Term</th>
<th class="dropdown-header">Enrolled</th>
</tr>
</thead>
<tbody>
<script>
function drawRow(rowData) {
var row = $("<tr />")
$("#myTable").append(row);
row.append($('<td>' + rowData.County + '</td>'));
row.append($('<td>' + rowData.County + '</td>'));
row.append($('<td>').attr('data-field-name', 'age').text(rowData.County));
row.append($('<td>' + rowData.County + '</td>'));
row.append($('<td data-field-name="gender">' + rowData.County + '</td>'));
row.append($('<td data-field-name="term">' + rowData.County + '</td>'));
row.append($('<td data-field-name="enrolled">' + rowData.County + '</td>'));
}
</script>
<tr>
<td>John</td>
<td>Smith</td>
<td data-field-name="age">15</td>
<td>123</td>
<td data-field-name="gender">Male</td>
<td data-field-name="term">Summer2017</td>
<td data-field-name="enrolled">Fall2018</td>
</tr>
<tr>
<td>Jane</td>
<td>Doe</td>
<td data-field-name="age">16</td>
<td>456</td>
<td data-field-name="gender">Female</td>
<td data-field-name="term">Fall2018</td>
<td data-field-name="enrolled">Fall2019</td>
</tr>
<tr>
<td>Bobby</td>
<td>Adams</td>
<td data-field-name="age">15</td>
<td>789</td>
<td data-field-name="gender">Male</td>
<td data-field-name="term">Spring2019</td>
<td data-field-name="enrolled">Fall2018</td>
</tr>
<tr>
<td>Sarah</td>
<td>Lee</td>
<td data-field-name="age">15</td>
<td>456</td>
<td data-field-name="gender">Female</td>
<td data-field-name="term">Fall2018</td>
<td data-field-name="enrolled">Fall2018</td>
</tr>
</tbody>
</table>
<script>
(function($) {
$.fn.tableFilterHeaders = function(filterFn) {
this.each((index, header) => {
let $header = $(header),
$table = $header.closest('table'),
text = $header.text(),
colIndex = $header.closest('th').index(),
fieldName = $header.attr('data-field-name') || text.toLowerCase(),
$select = $('<select>')
.data('fieldName', fieldName)
.append($('<option>').text(text).val('').prop('disabled', true))
.append($('<option>').text('All').val('all'))
.append($table.find('tbody tr')
.toArray()
.map(tr => {
return $(tr).find(`td:eq(${colIndex})`).text();
})
.filter(text => text.trim().length > 0)
.sort()
.filter((v, i, a) => a.indexOf(v) === i)
.map(text => {
return $('<option>').text(text).val(text);
}));
$header.empty().append($select.val('').on('change', filterFn));
});
};
$.fn.initRowClasses = function(oddCls, evenCls) {
this.find('tbody tr').each(function(i) {
$(this).toggleClass(oddCls, i % 2 == 0).toggleClass(evenCls, i % 2 == 1);
});
};
$.fn.updateRowClasses = function(oddCls, evenCls) {
this.find('tbody tr:visible:even').addClass(oddCls).removeClass(evenCls);
this.find('tbody tr:visible:odd').addClass(evenCls).removeClass(oddCls);
};
})(jQuery);
$('#myTable').initRowClasses('odd', 'even');
$('.dropdown-header').tableFilterHeaders(filterText);
function filterText(e) {
let $filter = $(e.target),
$table = $filter.closest('table'),
$filters = $table.find('.dropdown-header select'),
filterObj = $filters.toArray().reduce((obj, filter) => {
let $filter = $(filter);
return Object.assign(obj, { [$filter.data('fieldName')] : $filter.val() });
}, {});
if ($filter.val() === 'all') {
$filter.val('')
}
$table.find('tbody tr').each(function() {
$(this).toggle($(this).find('td').toArray().every(td => {
let $td = $(td), fieldName = $td.attr('data-field-name');
if (fieldName != null) {
return filterObj[fieldName] === null ||
filterObj[fieldName] === '' ||
filterObj[fieldName] === 'all' ||
filterObj[fieldName] === $td.text();
}
return true;
}));
});
$table.updateRowClasses('odd', 'even');
}
</script>
Not showing yes and no options.
Your filtering logic and odd/even row coloring logic is called BEFORE the data returns from your ajax even though it appears AFTER on the page/code. This is how async methods work.
You need to call the header and coloring logic inside the drawTable() function after, of course, you are done drawing the table... like this:
function drawTable(data) {
for (var i = 0; i < data.length; i++) {
drawRow(data[i]);
}
$('#myTable').initRowClasses('odd', 'even');
$('.dropdown-header').tableFilterHeaders(filterText);
}
Make sure to remove the foloowing 2 lines of code:
$('#myTable').initRowClasses('odd', 'even');
$('.dropdown-header').tableFilterHeaders(filterText);
from your code, wherever elsewhere they appear. Leaving them will not break anything, it will just run multiple times unnecessary.

Jquery sort table td not sorting currency properly

Hi I am new to jquery and HTML I am trying to sort my table by currency but its not sorting properly if its currency but if its alphabetical sorting its working anyone can help me or guide me I will realy appreciate thank you in advance.My currency format has thousand separator and decimal. whenever the th is clicked the row will be sort
function sortTable(f, n) {
var rows = $('#mytable tbody tr').get();
rows.sort(function(a, b) {
var A = getVal(a);
var B = getVal(b);
if (A < B) {
return -1 * f;
}
if (A > B) {
return 1 * f;
}
return 0;
});
function getVal(elm) {
var v = $(elm).children('td').eq(n).text().toUpperCase();
if ($.isNumeric(v)) {
v = parseInt(v, 10);
}
return v;
}
$.each(rows, function(index, row) {
$('#mytable').children('tbody').append(row);
});
}
var f_sl = 1;
var f_nm = 1;
$("#sl").click(function() {
f_sl *= -1;
var n = $(this).prevAll().length;
sortTable(f_sl, n);
});
$("#nm").click(function() {
f_nm *= -1;
var n = $(this).prevAll().length;
sortTable(f_nm, n);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="mytable">
<thead>
<tr>
<th id="sl">VAL</th>
<th id="nm">name</th>
</tr>
</thead>
<tbody>
<tr>
<td>RM 1,000.00</td>
<td>AINA (W)</td>
</tr>
<tr>
<td>RM 20,000.00</td>
<td>HEYZA</td>
</tr>
<tr>
<td>RM 5,000.15</td>
<td>ANA</td>
</tr>
<tr>
<td>RM 5,000.16</td>
<td>ZED</td>
</tr>
</tbody>
</table>
You can use localeCompare, along with it's numeric option
Instead of:
if (A < B) {
return -1 * f;
}
if (A > B) {
return 1 * f;
}
return 0;
You would use:
if (f === 1) {
return A.localeCompare(B, 'en', {numeric: true});
} else {
return B.localeCompare(A, 'en', {numeric: true});
}
Also, localeCompare can handle the numerical values as Strings, so you don't need to parseInt() in your getVal function - The only additional change for handling Numbers is to use a Regex to remove all the , seperaters from your numbers while sorting; it won't have any affect after sorting, or on words
function sortTable(f, n) {
var rows = $('#mytable tbody tr').get();
rows.sort(function(a, b) {
var A = getVal(a).replace(/(\d),(?=\d)/g, '$1');
var B = getVal(b).replace(/(\d),(?=\d)/g, '$1');
if (f === 1) {
return A.localeCompare(B, 'en-UK', {
numeric: true
});
} else {
return B.localeCompare(A, 'en-UK', {
numeric: true
});
}
});
function getVal(elm) {
return $(elm).children('td').eq(n).text().toUpperCase();
}
$.each(rows, function(index, row) {
$('#mytable').children('tbody').append(row);
});
}
var f_sl = 1;
var f_nm = 1;
$("#sl").click(function() {
f_sl *= -1;
var n = $(this).prevAll().length;
sortTable(f_sl, n);
});
$("#nm").click(function() {
f_nm *= -1;
var n = $(this).prevAll().length;
sortTable(f_nm, n);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="mytable">
<thead>
<tr>
<th id="sl">VAL</th>
<th id="nm">name</th>
</tr>
</thead>
<tbody>
<tr>
<td>RM 6,533.00</td>
<td>AINA (W)</td>
</tr>
<tr>
<td>RM 20.00</td>
<td>HEYZA</td>
</tr>
<tr>
<td>RM 1,174.00</td>
<td>ANA</td>
</tr>
<tr>
<td>RM 50.16</td>
<td>ZED</td>
</tr>
</tbody>
</table>

sorting html table with jquery

I have a table in html, I have set for each td an id that I will need to sort the table with a Jquery code.
Sorting works with the FireFox browser, but with Chrome it does not work ... do you know how to help me?
$(function() {
$(".table-user-th").click(function() {
var o = $(this).hasClass('asc') ? 'desc' : 'asc';
$('.table-user-th').removeClass('asc').removeClass('desc');
$(this).addClass(o);
var colIndex = $(this).prevAll().length;
var tbod = $(this).closest("table").find("tbody");
var rows = tbod.find("tr");
rows.sort(function(a, b) {
var A = $(a).find("td").eq(colIndex).attr('id');;
var B = $(b).find("td").eq(colIndex).attr('id');;
if (!isNaN(A)) A = Number(A);
if (!isNaN(B)) B = Number(B);
return o == 'asc' ? A > B : B > A;
});
$.each(rows, function(index, ele) {
tbod.append(ele);
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1">
<thead>
<tr>
<th class="table-user-th">Firstname</th>
<th class="table-user-th">Lastname</th>
</tr>
</thead>
<tbody>
<tr>
<td id="Mark">Mark</td>
<td id="Red">Red</td>
</tr>
<tr>
<td id="Nick">Nick</td>
<td id="Sid">Sid</td>
</tr>
<tr>
<td id="Alex">Alex</td>
<td id="Nirv">Nirv</td>
</tr>
</tbody>
</table>
It seems like there is no purpose of using ids here.
Actually the problem was in you sort function. It should return not just true/false but the numeric difference between two values. As usual it is return -1/0/1
So here I wrote comparator func that does just that. And depending on sort type I just multiply it on -1 or 1.
I've also refactored a little bit your code not to use classes or ids. Using jquery you can use data method that stores data on element by key/value.
$(function() {
function cmp(a,b) {return a < b ? 1 : a > b ? -1 : 0}
$(".sortable-table").on('click', 'th', function() {
var th = $(this);
var colIndex = th.data('column');
if(typeof colIndex === 'undefined') {
return;
}
var sortType = th.data('sort') === 'asc' ? 'desc' : 'asc';
th.data('sort', sortType);
var table = $(this).closest("table");
table.find('thead th').removeClass('asc desc');
th.addClass(sortType);
var tbody = table.find("tbody");
var rows = tbody.find("tr");
rows.sort(function(a, b) {
var A = $(a).find("td").eq(colIndex).text();
var B = $(b).find("td").eq(colIndex).text();
return cmp(A,B) * (sortType === 'asc' ? -1 : 1);
});
$.each(rows, function(index, ele) {
tbody.append(ele);
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1" class="sortable-table">
<thead>
<tr>
<th data-column="0">Firstname</th>
<th data-column="1">Lastname</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mark</td>
<td>Red</td>
</tr>
<tr>
<td>Nick</td>
<td>Sid</td>
</tr>
<tr>
<td>Alex</td>
<td>Nirv</td>
</tr>
</tbody>
</table>
Update
Added
var table = $(this).closest("table");
table.find('thead th').removeClass('asc desc');
th.addClass(sortType);

Sorting table rows rooted from custom attribute and text in td

Stuck, I need to sort a table based off a custom attribute in the table row for each level then based off the text in the td itself. So for all levels go through and sort a higher level
So I have:
<table>
<tbody>
<tr data-level="1" data-parent="0"><td>3</td></tr>
<tr data-level="1" data-parent="0"><td>1</td></tr>
<tr data-level="2" data-parent="1"><td>1b</td></tr>
<tr data-level="2" data-parent="1"><td>1c</td></tr>
<tr data-level="2" data-parent="1"><td>1a</td></tr>
<tr data-level="1" data-parent="0"><td>2</td></tr>
</tbody>
</table>
my expectation would look like this:
<table>
<tbody>
<tr data-level="1" data-parent="0"><td>1</td></tr>
<tr data-level="2" data-parent="1"><td>1a</td></tr>
<tr data-level="2" data-parent="1"><td>1b</td></tr>
<tr data-level="2" data-parent="1"><td>1c</td></tr>
<tr data-level="1" data-parent="0"><td>2</td></tr>
<tr data-level="1" data-parent="0"><td>3</td></tr>
</tbody>
</table>
I have tried this:
function sortMultilevel(level){
var $sort = this;
var $table = $('table');
var $rows = $('tbody > tr[data-level="'+level+'"]',$table);
$rows.sort(function(a, b){
var keyA = $('td',a).text();
var keyB = $('td',b).text();
if($($sort).hasClass('asc')){
return (keyA > keyB) ? 1 : 0;
} else {
return (keyA < keyB) ? 0 : 1;
}
});
$.each($rows, function(index, row){
$table.append(row);
});
}
function doMultilevelSort(){
if($("tr").length > 0){
$("tr").not(".sorted").each(function(){
$(this).addClass("sorted");
var level = $(this).attr("data-level");
sortMultilevel(level);
console.log("sorting: " + level);
});
}
}
doMultilevelSort(); // call the function
I may be way over thinking this. If I am I am your student and I am all ears. Appreciate the look.
DEMO
$('#sort').click(function (e) {
var $table = $('#sort_me');
var $rows = $('tbody > tr', $table);
$rows.sort(function (a, b) {
var keyA = $('td', a).text();
var keyB = $('td', b).text();
return (keyA > keyB) ? 1 : 0;
});
$.each($rows, function (index, row) {
$table.append(row);
});
e.preventDefault();
});

sorting table using template

I have knockout binding on table with columns. I was trying to achieve table sorting for each column.
The view looks like:
<table id="notes" class="notes_table">
<tr class="head">
<th data-bind='click: function() { SortItems("CreatedDate")}'>
<span>Date</span>
</th>
<th data-bind='click: function() { SortItems("Type")}'>
<span>Type</span>
</th>
<th data-bind='click: function() { SortItems("Category")}'>
<span>Category</span>
</th>
<th data-bind='click: function() {SortItems("AddedBy")}'>
<span>Added by</span>
</th>
</tr>
<tbody data-bind="template: { name: 'StudentNote', foreach: notes }"></tbody>
</table>
<script type="text/html" id="StudentNote">
<tr class="even">
<td><span data-bind="text: CreatedDate"></span></td>
<td><span data-bind="text: Type"></span></td>
<td><span data-bind="text: Category"></span></td>
<td><span data-bind="text: AddedBy"></span></td>
</tr>
</script>
and the javascript is like:
function notesViewModel() {
var _this = {};
_this.colName = "CreatedDate";
_this.sortOrder = "desc";
_this.notes = ko.observableArray();
_this.SortItems = function (ColumnName) {
var newNotes = _this.notes();
if (_this.sortOrder === "desc") {
this.notes(newNotes.sort(notesViewModel._getSortFunction = function (a, b) {
_this.sortOrder = "asc";
return a[ColumnName] < b[ColumnName] ? -1 : 1;
}));
} else {
this.notes(newNotes.sort(notesViewModel._getSortFunction = function (a, b) {
_this.sortOrder = "desc";
return a[ColumnName] > b[ColumnName] ? -1 : 1;
}));
}
};
ko.applyBindings(_this, $("body").get(0));
return _this;
Even though it does sorting, it just switches between ascending and descending sort on each of the column, but not recognises which column it is sorting.. How to do sorting by each column..
Try this:
function notesViewModel() {
var _this = {};
_this.colName = "CreatedDate";
_this.sortOrder = 1;
_this.notes = ko.observableArray();
_this.SortItems = function (ColumnName) {
if(ColumnName == _this.colName)
_this.sortOrder = _this.sortOrder * -1;
else
_this.colName = ColumnName;
_this.notes.sort(function (a, b) {
return (a[ColumnName] < b[ColumnName] ? -1 : 1) * _this.sortOrder;
});
};
ko.applyBindings(_this, $("body").get(0));
return _this;
}

Categories