Dynamically sorted table sort lost on update - javascript

I am creating a table dynamically using JQuery as the number of rows in the table depends on the amount of Agents configured to a server I am pulling data from.
The statistics in the table need to be "real-time" so I am recreating the table every second with fresh statistics. I am using the JQuery TableSorter plugin - http://tablesorter.com/docs/
to allow me to make the table sortable as is one of my requirements, However every time the table is recreated this renders the sort useless. Can anyone think of a solution?
This is my code to create the table.
function addToTable() {
var agentData = getAgentStats();
var ids = getAgentIds();
var names = getAgentNames();
// Add new Row to to table
for(var i =0;i<agentData.length;i++){
$('#StatsContainer').append('<tr><td>'+ids[i]+'</td><td>'+names[i]+'</td><td>'+agentData[i].statistics[13]+'</td><td>'+agentData[i].statistics[3]+'</td>\n\
<td>'+agentData[i].statistics[4]+'</td><td>'+agentData[i].statistics[6]+'</td><td>'+agentData[i].statistics[12]+'</td><td>'+agentData[i].statistics[14]+'</td><tr>');
}
// Let table sorter know that table contents has changed
$("table").trigger("update");
}
Thank you in advance.

Without seeing more of your code to gain context:
Tablesorter supports the ability to send it controls about how you want to sort the table.
$("#trigger-link").click(function() {
// set sorting column and direction, this will sort on the first and third column the column index starts at zero
var sorting = [[0,0],[2,0]];
// sort on the first column
$("table").trigger("sorton",[sorting]);
// return false to stop default link action
return false;
});
You could intercept clicks on headers to take note of the sort order, and then call on tablesorter as demonstrated above.
Once you are intercepting how the table should be sorted you can apply that sort after every time you rebuild the table.

Related

How do you filter Tabulator data on a class

I'm wondering if it's possible to set a filter to filter rows against a class rather than actual table data (so for instance only show rows where a particular class is present)? If so would this have to be a custom filter or can I use the standard filter operators?
FYI I'm using Tabulator v3.5. Any examples would be much appreciated :-)
Thanks for the reply Oli.
I've implemented mutators to define a few new properties as per your suggestion but I've got another problem of how to remove a filter for a particular property without using clearFilter which as I understand it clears ALL active filters? I've tried removeFilter but this doesn't seem to work.
For example (when checkbox is ticked):
if (chk) {
$("#allocations-table").tabulator("setFilter", "Allocated", "=", "is-allocated");
} else {
$("#allocations-table").tabulator("removeFilter", "Allocated", "=", "is-allocated");
}
Trying to filter a row based on class would be a bit of an anti-pattern when it comes to using Tabulator because you would have to use a formatter to apply the class in the first place, at which point you might as well set a property on the row and then filter things the normal way.
The correct approach would be to create a hidden column that uses a mutator to define a new property on the row, lets call it class, then you use a row formatter to apply this to the row, and then you can filter it as normal.
So lets start by creating our mutator, im going to add some arbitrary logic in this to set a class based on the value of another column (lets say age):
var classMutator = function(value, data){
if(data.age >= 18){
return "is-adult";
}else{
return "is-child";
}
}
Then we want to add that to a column definition, for a hidden column that uses this mutator:
{field:"class", mutator:classMutator, visible:false},
Then we will need a row formatter to apply that class to the row:
rowFormatter:function (row){
row.getElement().classList.add(row.getData().class);
}
So all together we have a table constructor that looks like this:
var table = new Tabulator("#example-table", {
columns:[
{field:"class", mutator:classMutator, visible:false},
//... other table columns go here
],
rowFormatter:function (row){
row.getElement().classList.add(row.getData().class);
}
}
Then to filter you can simply using the setFilter function:
table.setFilter("class", "=", "is-child");
As a side note, i would strongly recommend upgrading to the latest version of Tabulator, v3.5 is almost 2 years old at this point, and there have been significant improvements since then. If you are worried about jQuery compatibility, all of the latest versions come with a [jQuery Wrapper](http://tabulator.info/docs/4.7/jquery] to make migration easier

how to get the searched data in datatable but not show it

I want to check if the data is already exist in datatable in certain column but I don't know how to do it.
Heres what I tried
var issueData = $('#table').DataTable().column(2).search($('input[name=search]').val()).rows({search: 'applied'}).data().toArray();
if(issueData == '')
{
var data = [];
data.push(rowData[0]);
data.push(rowData[3]);
data.push(rowData[2]);
data.push(rowData[4]);
data.push(rowData[6]);
$('#table').DataTable().row.add(data).draw(false);
}
the problem on this is I if the issueData is empty it will just overwrite the existing data and have filter on the bottom of the datatable
here's what the filter
Showing 1 to 1 of 1 entries (filtered from 3 total entries)
I don't want to filter it I just want to check if the data is existing already on a certain column then add the data if its not existing if it exist then do nothing.
search() as you say will search the actual table. To filter it without changing the user's view of the table, use filter(). See docs here: https://datatables.net/reference/api/filter()

jQuery on page load sorting will not sort with leading currency symbol

In my previous question I was trying to sort a table on page load without any client side table sorting toggle switches just so the table would be sorted for a user as they arrive on the page.
The question was answered and I got a pretty good response and thought i'd solved the issue so I went to sleep, so as I tried to use the code on my website today I realized the sorting technique is not working but works perfectly in jsfiddle https://jsfiddle.net/ghzch66e/12/.
So I then realized the table wont sort on my website because on the webpage the data contains a leading (£) symbol https://jsfiddle.net/ghzch66e/13/.
How can I make the table sort even with a leading (£) symbol.
jQuery(document).ready(function(e) {
var dataRows = [];
//Create an array of all rows with its value (this assumes that the amount is always a number. You should add error checking!! Also assumes that all rows are data rows, and that there are no header rows. Adjust selector appropriately.
$('#internalActivities > tbody > tr').each(function(i,j) {
dataRows.push({'amount': parseFloat($(this).find('.amount').text()), 'row': $(this)});
})
//Sort the data smallest to largest
dataRows.sort(function(a, b) {
return a.amount - b.amount;
});
//Remove existing table rows. This assumes that everything should be deleted, adjust selector if needed :).
$('#internalActivities').empty();
//Add rows back to table in the correct order.
dataRows.forEach(function(ele) {
$('#internalActivities').append(ele.row);
})
});
replace the "£" with "" when pushing it to the array
$('#internalActivities > tbody > tr').each(function(i,j) {
dataRows.push({'amount': parseFloat($(this).find('.amount').text().replace(/£/,"")), 'row': $(this)});
})

How to change order of rows in table based on list of rows id?

I have table with id test_table
<table id="test_table"> </table>
and or has different id.
I have ordered list of rows' id like
["name","value","description"]
what is different from rendered table on screen ( user can on fly set new order, that is how I fill list of rows' id).
How to set new order in that table based on ordered list ?
(Explanation:
I have two lists one aside other, user can drag and drop rows in first table and I need to have same order in second, ids in second table have same id like in first +prefix "preview".
This is how I drag/drop in first table. )
$("#cleanVert").tableDnD({
onDragClass: "myDragClass",
onDrop: function(table, row) {
var rows = table.tBodies[0].rows;
var debugStr = "New Order: ";
var outStr = "";
for (var i=0; i<rows.length; i++) {
debugStr += rows[i].id+" ";
outStr += rows[i].id;
if(i<(rows.length-1)){
outStr+=","
}
}
$("#debugArea").html(debugStr);
},
onDragStart: function(table, row) {
$("#debugArea").html("Started dragging row "+row.id);
}
});
I think you are after a client side table sorting, there's quite a few available online, it depends what javascript library you are familiar with. I have chosen to use a jQuery plugin called tablesorter and I am assuming based on your tags that it might be a good option for you too.
The downside to it is that it is client-side only, so If a user doesn't have Javascript enabled, they will not be able to sort the table, I'd say that is not a major problem, the average user always have Javascript enabled.
The other option is to build a server-side sorting, this can be as easy as adding
ORDER BY "$selectedField" "$order"
in your database query. It will also ensures that it works without Javascript.
Nowadays many of the popular web development frameworks provide that sort of feature, if you haven't discovered it yet, I encourage you to take a look at some options for your programming language.
If you are wanting to do everything in jQuery, which it looks like you are trying to do, then I would look into jQuery Sortable but if you want it to be like a link/button that sorts each field by say Ascending or Descending order, or by like usernames etc, and keep it server-side then what I would suggest is have the button/link reload itself with a sub-query in the url that would say something like ?order_by=asc or ?order_by=username&dir=asc then run a check for it on the page, passing that variable/sub-query ($_GET['order_by']) to a function. In the function, do a query that looks similar to this:
$order_by = "ORDER BY " . $_GET['order_by'] . $_GET['dir'];
$query = "SELECT *
FROM table
$order_by";
You could then use this same query for the main page load (that hasn't been sorted) without difficulty using the variable, then when the query is re-run with a loaded $order_by then the list will be ordered by parameter.

Most Efficient way of Filtering an Html Table?

I have an ajax function which call a servlet to get list of products from various webservices, the number of products can go up to 100,000. I need to show this list in a html table.
I am trying to provide users an interface to filter this list based on several criteria. Currently I am using a simple jQuery plugin to achieve this, but I found it to hog memory and time.
The Javascript that I use basically uses regex to search and filter rows matching the filtering criteria.
I was thinking of an alternate solution wherein I filter the JSON array returned by my servlet and bind the html table to it. Is there a way to achieve this, if there is, then is it more efficient than the regex approach.
Going through up to 100,000 items and checking if they meet your criteria is going to take a while, especially if the criteria might be complex (must be CONDO with 2 OR 3 bedrooms NOT in zip code 12345 and FIREPLACE but not JACUZZI).
Perhaps your servlet could cache the data for the 100,000 items and it could do the filtering, based on criteria posted by the user's browser. It could return, say, "items 1-50 of 12,456 selected from 100,000" and let the user page forward to the next 50 or so, and even select how many items to get back (25, 50, all).
If they select "all" before narrowing down the number very far, then a halfway observant user will expect it to take a while to load.
In other words, don't even TRY to manage the 100,000 items in the browser, let the server do it.
User enters filter and hits
search.
Ajax call to database, database has indexes on appropriate
columns and the database does the filtering.
Database returns result
Show result in table. (Probably want it to be paged to
only show 100-1000 rows at a time
because 100,000 rows in a table can
really slow down your browser.
Edit: Since you don't have a database, the best you're going to be able to do is run the regex over the JSON dataset and add results that match to the table. You'll want to save the JSON dataset in a variable in case they change the search. (I'm assuming that right now you're adding everything to the table and then using the jquery table plugin to filter it)
I'm assuming that by filtering you mean only displaying a subset of the data; and not sorting.
As you are populating the data into the table add classes to each row for everything in that row you want to filter by. e.g.:
<tr class="filter1 filter2 filter3">....
<tr class="filter1 filter3">....
<tr class="filter2">....
<tr class="filter3">....
Then when you want to apply a filter you can do something like:
$('TR:not(.filter1)').hide();
I agree with Berry that 100000 rows in the browser is bit of a stretch, but if there's anything that comes close to handling something of that magnitude then it's jOrder. http://github.com/danstocker/jorder
Create a jOrder table based on your JSON, and add the most necessary indexes. I mean the ones that you must at all cost filter by.
E.g. you have a "Name" field with people's names.
var table = jOrder(json)
.index('name', ['Name'], { sorted: true, ordered: true });
Then, for instance, this is how you select the records where the Name field starts with "John":
var filtered = table.where([{ Name: 'John' }], { mode: jOrder.startof, renumber: true });
Later, if you need paging in your table, just feed the table builder a filtered.slice(...).
If you're getting back xml, you could just use jQuery selection
$('.class', context) where context is your xml response.
From this selection, you could just write the xml to the page and use CSS to style it. That's where I'd start at first, at least. I'm doing something similar in one of my applications, but my dataset is smaller.
I don't know what you mean by "bind"? You can parse JSON and then use for loop (or $.each()) to populate ether straight HTML or by using grid plugin's insert/add

Categories

Resources