Sort DataTable by week and day - javascript

I use jQuery datatables to build up the table that shows project progress in the following format:
Project |Stage |Start |Finish
____________________________________
project 1 |stage 1 |W1D1 |W2D2
project 1 |stage 2 |W2D3 |W4D5
...
Project milestones are measured in the form 'W_D_' (Week, Day).
The problem is when I start sorting by column Start or Finish it doesn't work properly.
My code so far:
HTML:
<table id="projectStatus">
<thead>
<tr>
<th>Project</th><th>Stage</th><th>Start</th><th>Finish</th>
</tr>
</thead>
<tbody>
<tr>
<td>project 1</td><td>stage 1</td><td>W1D1</td><td>W2D2</td>
</tr>
<tr>
<td>project 1</td><td>stage 2</td><td>W2D3</td><td>W11D5</td>
</tr>
<tr>
<td>project 1</td><td>stage 3</td><td>W11D6</td><td>W5D6</td>
</tr>
</tbody>
</table>
JS:
$('#projectStatus').DataTable({
orderable: true,
processing: true,
defaultContent: '',
pageLength: 10
});
How do I fix that sorting issue? Thank you.

Since your data has numeric nature, I'm afraid, you can't benefit from data-order/data-sort attributes of corresponding table cells which will sort your rows alphabetically.
The way out (without loading extra plug-in) is to set up your own custom data type (say 'weekday') and corresponding sorting method for that:
//init DataTable
$('#projectStatus').DataTable({
//set data type 'weekday' for columns 2, 3
columnDefs: [{
targets: [2,3],
type: 'weekday'
}]
});
//turn 'week+day' string into number of days
const weekDay2Num = str => ([week, day] = str.match(/W(\d+)D(\d+)/).slice(1), week*7+day);
//specify sorting method for type 'weekday'
Object.assign($.fn.DataTable.ext.oSort, {
'weekday-asc': (a,b) => weekDay2Num(a)-weekDay2Num(b),
'weekday-desc': (a,b) => weekDay2Num(b)-weekDay2Num(a)
});
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" 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">
<table id="projectStatus">
<thead>
<tr>
<th>Project</th><th>Stage</th><th>Start</th><th>Finish</th>
</tr>
</thead>
<tbody>
<tr>
<td>project 1</td><td>stage 1</td><td>W1D1</td><td>W2D2</td>
</tr>
<tr>
<td>project 1</td><td>stage 2</td><td>W2D3</td><td>W11D5</td>
</tr>
<tr>
<td>project 1</td><td>stage 3</td><td>W11D6</td><td>W5D6</td>
</tr>
</tbody>
</table>

You should provide the wrong results.
What I see is that you have string values, which are not treated as numbers. E.g., W11D5 is shown before W2D3.
Try to use the data-order attribute, concatenating week and day:
<td>project 1</td>
<td>stage 2</td>
<td data-order="23">W2D3</td>
<td data-order="115">W11D5</td>
If it still doesn't work, zero-pad it:
<td>project 1</td>
<td>stage 2</td>
<td data-order="023">W2D3</td>
<td data-order="115">W11D5</td>

You can add the data-order attribute to the cells. DataTables will use this value to order your rows instead of the text inside. You can concatenate the Week and Day in this attribute.
<table id="projectStatus">
<thead>
<tr>
<th>Project</th><th>Stage</th><th>Start</th><th>Finish</th>
</tr>
</thead>
<tbody>
<tr>
<td>project 1</td><td>stage 1</td><td data-order="11">W1D1</td><td data-order="22">W2D2</td>
</tr>
<tr>
<td>project 1</td><td>stage 2</td><td data-order="23">W2D3</td><td data-order="115">W11D5</td>
</tr>
<tr>
<td>project 1</td><td>stage 3</td><td data-order="116">W11D6</td><td data-order="56">W5D6</td>
</tr>
</tbody>
</table>

Related

Js Jquery td auto numbering with custom locale language

Is there any way to auto numbering table data with local or custom language. I'm a Bengali, I know how to auto numbering table each row 1st data using css and js. But I don’t know how to use custom number, e.g. Bangla or Arabic.
Look at my code:
<table border="1">
<tr>
<td>blue</td>
</tr>
<tr>
<td>red</td>
</tr>
<tr>
<td>black</td>
</tr>
</table>
I want something like that;
১. Apple
২. Banana
৩. Orange
৪. Strawberry
How can I get that using Javascript / jquery.. Without adding any third party plugin.
You need to use toLocaleString() method or Intl.NumberFormat() constructor with the locale language as a parameter.
For example.
For Arabic numbers num.toLocaleString('ar-EG').
For Bangla numbers num.toLocaleString('bn-BD')
const table = document.querySelector('table');
[...table.rows].forEach((row, index) => {
row.cells[0].textContent = (index + 1).toLocaleString('bn-BD')
})
<table border="1">
<tr>
<td></td>
<td>blue</td>
</tr>
<tr>
<td></td>
<td>red</td>
</tr>
<tr>
<td></td>
<td>black</td>
</tr>
A CSS only solution would be using the CSS counter(..) function and pass the counter-style parameter (list-style-type) for 'bengali'.
E.g. td::before { content: counter(some-counter, bengali) }
Reference: MDN: counter() and MDN: list-style-type
table {
counter-reset: row 0;
}
tr {
counter-increment: row;
}
td::before {
content: counter(row, bengali) '. ';
}
<table border="1">
<tr>
<td>blue</td>
</tr>
<tr>
<td>red</td>
</tr>
<tr>
<td>black</td>
</tr>
</table>

Can anyone help me convert a table such as this example into a dynamic one in Javascript by using the for loop?

Can anyone help me learn how to convert an HTML table into a dynamic Javascript table using the for loop? This is an example I found in my book and wanted to see how I could go about doing this.
Heading There is sections of the table that need to have the rows combined and he columns combined. I have been struggling with this for some time. Any help would be appreciated. I did not include the CSS portion of the code only the table.
<html>
<body>
<table class="table">
<tr>
<th colspan= "3" class= "MH">Conversion Tables</th>
</tr>
<tr>
<th rowspan="3" class="heading1">Meters to
<br />Feet</th>
<td>1 meter</td>
<td>3.28 feet</td>
</tr>
<tr class="difrow">
<td>50 meters</td>
<td>164.04 feet</td>
</tr>
<tr>
<td>100 meters</td>
<td>328.08 feet</td>
</tr>
<tr class="difrow">
<th rowspan="3" class="heading1">Kilometers to
<br />Miles</th>
<td>1 kilometer</td>
<td>0.62 miles</td>
</tr>
<tr>
<td>50 kilometers</td>
<td>31.07 miles</td>
</tr>
<tr class="difrow">
<td>100 kilometers</td>
<td>62.14 miles</td>
</tr>
</table>
</body>
</html>
you can add id attribute to table tag then call a javascript method on page load:
<table class="table" id="tableId">
function createRows(){
var items = "<tr><td></td></tr>...";
document.getElementById("tableId").innerHTML = items;
}
in javascript method you can use for to generate table rows.

jQuery load template inside a loop

I have a json file with some data and I am using a Js loop to load a jQuery template to iterate through and load a table made of 4 rows based on the data, so far I only get the last row. https://github.com/codepb/jquery-template
<script type="text/html" id="tableContent">
<tr>
<th>Key</th>
<th>Product</th>
<th>Bookings</th>
<th>%</th>
<th>Transactions</th>
</tr>
<tr>
<td data-content="">sth</td>
<td data-content="Product"></td>
<td data-content="Bookings"></td>
<td data-content="Percentage"></td>
<td data-content="Transactions"></td>
</tr>
</script>
function builTable(){
var table = "",
colors = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6'];
for(i = 0; i< source.Products.length; i++){
$("table").loadTemplate($("#tableContent"),
{
Product: source.Products[i].Product,
Bookings: source.Products[i].Bookings,
Percentage: source.Products[i].Percentage,
Transaction: source.Products[i].Transaction
} );
$(document).ready(function(){
builTable();
});
<table border="1" cellpadding="2">
</table>
Is there something wrong inside the loop?
http://jsfiddle.net/9JV7t/1/
I think you just need to add an array because it loads the whole content just once and then overrides it again. But therefore you need to only include the data rows in the template and add the headings to the table (DEMO):
<script type="text/html" id="tableContent">
<tr>
<td data-content="">sth</td>
<td data-content="Product"></td>
<td data-content="Bookings"></td>
<td data-content="Percentage"></td>
<td data-content="Transactions"></td>
</tr>
</script>
Your table:
<table>
<thead>
<tr>
<th>Key</th>
<th>Product</th>
<th>Bookings</th>
<th>%</th>
<th>Transactions</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
And the js:
function builTable(){
$("tbody").loadTemplate($("#tableContent"), source.Products);
}

JQuery Tablesorter - Filter by clicking link

I'm using #Mottie's excellent fork of Tablesorter and would like to be able to filter table column(s) with external links.
It isn't strictly necessary, but I'd like to make multiple clicks toggle the filter on and off. Alternatively, I could always add an All Records link that resets the column(s).
I don't need to combine filters in a single column. In other words, the data wouldn't be both January and October.
I found a table sort with external link demo, but that one sorts, not filters, and it doesn't toggle.
I also found a table filter with buttons demo which is pretty close. However, as I mentioned, I'd really like links instead, would like to have the links toggle if possible, and don't need the filters to combine.
Thanks in advance.
This was actually a lot easier than I thought. Here's a working demo that came directly from Mottie's demo code above. I replaced the buttons with links, renamed the associated class so it made more sense and replaced the class on the JavaScript function to match the one on the links.
Fair warning: I don't claim to know everything, so my modifications could have very silly errors.
$('.link-filter').click(function() {
var filters = $('table').find('input.tablesorter-filter'),
col = $(this).data('filter-column'),
txt = $(this).data('filter-text');
// filters.val('');
filters.eq(col).val(txt).trigger('search', false);
});
The filters in the various columns combine, but I only need a single column filter at the moment, so that's not really an issue for me.
Country:<br>
All Countries |
Netherlands |
Belgium |
Germany
<br /><br />
<table id="festivaloverzichttable" class="tablesorter">
<thead>
<tr>
<th width="17%" data-placeholder="Search...">Event</th>
<th width="18%" data-placeholder="Search...">Date</th>
<th width="9%" data-placeholder="Search...">Duration</th>
<th width="12%" data-placeholder="Search...">Place</th>
<th width="10%" data-placeholder="Search...">Country</th>
<th data-placeholder="Zoek...">Genre(s)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Event 1</td>
<td data-date="06-02">TBA</td>
<td>2</td>
<td>Oisterwijk</td>
<td>Netherlands</td>
<td>Hardstyle</td>
</tr>
<tr>
<td>Event 2</td>
<td data-date="10-11">11 October t/m 13 October</td>
<td>3</td>
<td>Volkel</td>
<td>Netherlands</td>
<td>Pop, Rock, Urban, Electronic</td>
</tr>
<tr>
<td>Event 3</td>
<td data-date="06-02">TBA</td>
<td>1</td>
<td>Amsterdam</td>
<td>Netherlands</td>
<td>Electronic</td>
</tr>
<tr>
<td>Event 4</td>
<td data-date="09-01">TBA</td>
<td>1</td>
<td>Utrecht</td>
<td>Netherlands</td>
<td>Electronic, Urban</td>
</tr>
<tr>
<td>Event 5</td>
<td data-date="07-06">6 July - 7 July</td>
<td>2</td>
<td>Beek en Donk</td>
<td>Netherlands</td>
<td>Electronic, Hardstyle</td>
</tr>
...
</tbody>
</table>​
Javascript
$("#festivaloverzichttable").tablesorter({
sortList: [[0, 0]],
widgets: ['zebra', 'filter', 'saveSort'],
widgetOptions: {
filter_reset: 'button.reset'
}
});
$('.link-filter').click(function() {
var filters = $('table').find('input.tablesorter-filter'),
col = $(this).data('filter-column'),
txt = $(this).data('filter-text');
// filters.val('');
filters.eq(col).val(txt).trigger('search', false);
});

Calculate cell value based on formula and values in other cells

I have a table in a HTML file, and I want to calculate one cell's value based on other cells' values and a cell value as a formula. Take a look at this picture:
In my table, I have 1900 ratios and three factors in three columns. How I can calculate the result column values based on their respective formula column value?
Note: I use only *, /, +, and - in my formulas. Also, the table has an ID (ratiotable), but the <tr> and <td> don't have any ID or class names assigned to them.
If you know another webpage that did something like this, please let me see this.
Thank you very much.
Edit: The HTML code is like this. Note, I snipped a number of the rows. The actual number of rows is 1900:
<table>
<thead>
<tr>
<th>Ratio Name</th>
<th>Factor1</th>
<th>Factor2</th>
<th>Factor3</th>
<th>Formula</th>
<th>Result</th>
</tr>
</thead>
<tbody>
<tr>
<td>Name1</td>
<td>22</td>
<td>11</td>
<td></td>
<td>Factor1/Factor2</td>
<td></td>
</tr>
<tr>
<td>Name2</td>
<td>22</td>
<td>33</td>
<td>11</td>
<td>Factor1/Factor2*Factor3</td>
<td></td>
</tr>
<tr>
<td>Name1</td>
<td>12</td>
<td></td>
<td>4</td>
<td>(Factor1+Factor2)/Factor3</td>
<td></td>
</tr>
</tbody>
This was a really interesting challenge. I've put together a little JSFiddle here that does what you describe. It essentially replaces the string parts of the formula with their value counterparts, then evals the result. Hopefully this helps!
My Markup
<table>
<thead>
<tr>
<th>Ratio Name</th>
<th>Factor1</th>
<th>Factor2</th>
<th>Factor3</th>
<th>Formula</th>
<th>Result</th>
</tr>
</thead>
<tbody>
<tr>
<td>Name1</td>
<td>22</td>
<td>11</td>
<td></td>
<td>Factor1/Factor2</td>
<td></td>
</tr>
<tr>
<td>Name2</td>
<td>22</td>
<td>33</td>
<td>11</td>
<td>Factor1/Factor2*Factor3</td>
<td></td>
</tr>
<tr>
<td>Name1</td>
<td>12</td>
<td></td>
<td>4</td>
<td>(Factor1+Factor2)/Factor3</td>
<td></td>
</tr>
</tbody>
</table>
​
My JavaScript
$(function() {
$('tbody tr').each(function() {
var $this = $(this),
f1 = $this.find('td').eq(1).text() || 0,
f2 = $this.find('td').eq(2).text() || 0,
f3 = $this.find('td').eq(3).text() || 0,
formula = $this.find('td').eq(4).text(),
resultTd = $this.find('td').last();
formula = formula.replace('Factor1',f1)
.replace('Factor2',f2)
.replace('Factor3',f3);
resultTd.text(eval(formula));
});
});​
loop through all rows and use javascript eval() function
function cellValue(x,y){
return $('#ratiotable').find('tr:eq('+(y+1)+')>td:eq('+(x+1)+')').text();
}
function setCellValue(x,y,s){
$('#ratiotable').find('tr:eq('+(y+1)+')>td:eq('+(x+1)+')').text(s);
}
$(function(){
$.each($('#ratiotable tr'),function(i,tr){
var Factor1 = parseInt(cellValue(0,i));
var Factor2 = parseInt(cellValue(1,i));
var Factor3 = parseInt(cellValue(2,i));
var Formula = $.trim(cellValue(3,i));
var Result = eval(Formula);
setCellValue(4,i,Result);
});
});
like this

Categories