Using tablesorter.js to sort table columns.
I have one column with images, so I used textExtraction to get image alt value to do sorting.
Now I want to use textExtraction to sort other columns with commas and currency symbols.
Independently, both will work but I am not able to get both of them working.
Tablesorter has an example that I am not able to adapt.
textExtraction: {
0: function(node, table, cellIndex){ return $(node).find("strong").text(); },
1: function(node, table, cellIndex){ return $(node).find("div").text(); },
2: function(node, table, cellIndex){ return $(node).find("span").text(); },
3: function(node, table, cellIndex){ return $(node).find("em").text(); },
4: function(node, table, cellIndex){ return $(node).find("a").text(); },
'.date' : function(node, table, cellIndex){ return $(node).find("u").text(); }
}
I modified my code as follows:
$(document).ready(function($){
$("#cardSort").tablesorter(
{
initWidgets: true,
textExtraction: {
0: function(s){
if($(s).find('img').length == 0) return $(s).text();
return $(s).find('img').attr('alt');
},
1: function(s){
return $(s).text().replace(/[,$£€]/g,'');
}
}
}
);
}
);
This appears to be same as the tablesorter example eg it is using the numbered function method. But in this format neither work.
Any ideas on how to have both textExtraction functions?
Edit to add: this is TableSorter Version 2.0.5b
It sounds like you might still be using the original version of tablesorter (v2.0.5)... setting the textExtraction as an object doesn't work on that version, you'll need to use my fork of tablesorter.
Update: If you must use v2.0.5, then try the following:
textExtraction: function(node) {
var $cell = $(node),
text = $cell.text();
switch(node.cellIndex) {
case 0:
return $cell.find('img').length ? $cell.find('img').attr('alt') : text;
case 1:
return text.replace(/[,$£€]/g,'');
default:
return text;
}
}
Note: This method won't work as expected when there are colspans within the tbody.
Related
I have an ag-grid in angular project. I have set the column def as:
this.columnDef.push(
headerName: col,
field: col,
valueFormatter: setMyValue,
filter: 'agNumberColumnFilter',
filterParams: { valueFormatter: setMyValue }
)
function setMyValue (params) {
return params.value.toFixed(2); // OPTION #1 WORKS
//let temp = params.value * 100;
//return temp.toFixed(2); // OPTION #2 DOES NOT WORKS
}
OPTION #1: this logic works in the ag-grid and i am able to correcly filter using equal, great then etc.
OPTION #2: this logic does not work, when i enter any number in filter, it returns empty rows.
What I have tried:
I have tried to bind the function to component:
valueFormatter: setMyValue.bind(this)
and I also tried to force the return value to number as :
return parsInt(temp.toFixed(2));
I am using the datatables plugin for jQuery however I am having issues with the render function:
I have a string that contains some html elements in a column, I do not want the html elements to render in the table so I use the function $.fn.dataTable.render.text()
I also only want this data to be a preview as the string can be incredibly long therefore I am using an ellipsis function $.fn.dataTable.render.ellipsis(40)
The ellipsis function is defined here:
// https://datatables.net/manual/data/renderers#Text-helper
$.fn.dataTable.render.ellipsis = function (cutoff) {
return function (data, type, row) {
if (type === 'display') {
var str = data.toString(); // cast numbers
return str.length < cutoff ?
str :
str.substr(0, cutoff - 1) + '…';
}
// Search, order and type can use the original data
return data;
};
};
Would it be possible to combine these functions in any way?
The closest solution to my problem is this found on the datatables forum.
This is exactly what I want to do however it does not work as d = renderArray[r](d, type, row, meta); is not a function.
Thanks in advance.
Edit:
The mRender function is passed the data for the whole row. So, you can access any property you want to access render multiple function using datatables
{
mData: "bar",
mRender: function(data, type, val) {
switch (type) {
case 'display':
return '' + data.bar + '';
break;
// optionally, add case statements for 'sort', 'filter', and 'type'
default:
return data.bar;
break;
}
}
}
i'm trying to implement a function on Datatables that has to look up the table data, do a regex and then, if it returns true, then, when i click on the header to sort data, it will sort it by the last 5 digits, ignoring the letters that comes up in the beginning of the string.
i have the following code
$.fn.dataTable.ext.oSort['custom'] = function (settings, col) {
return this.api().column(col, {order: 'index'}).nodes().map(function (td, i) {
var string= $(td).html();
return $.trim(string.substr(string.length - 4));
});
}
$.fn.dataTable.ext.type.detect.push(
function (value) {
var test = (/PT\d/).test(value);
return test ? 'custom' : null;
}
);
this is for a custom data that has lots of trash in the beggining, like country code and stuff, but the data order is only by the last 5 digits.
i've been searching all over i'm having a hard time to understand and debug. Debuguing the detect works, if 1 put an alert, it gives-me true when it hits the colum with the values i want, but the custom sorting doesn't work, can anybody help?
hope i'm clear about it
thanks
actualy i solved it myself.
the problem was that DataTables needs to make the entire column return true, so, if the regex fails in any value in the same column it fails.
$.fn.dataTable.ext.type.detect.unshift(
function (d) {
var pt = (/^PT\d/).test(d);
var es= (/^ES\d/).test(d);
var en= (/^EN\d/).test(d);
if (pt || es|| en) {
return 'custom'
} else {
return false;
}
}
);
$.fn.dataTable.ext.type.order['custom-pre'] = function (string) {
return $.trim(string.substr(string.length - 4));
};
so this is my last code used and it works just fine.
i'm posting it so anybody with the same problem can have a clue to solve some future problem :)
I am looking for a means of doing an OR filter against multiple columns in jQuery TableSorter much like DataTable Multiple column OR filter. I upgraded to 2.21.5.
I have a fiddle example. I have tried to do filter_functions:
filter_functions: {
'.filter-OR': function (e, n, f, i, $r, c) {
/*
manually check the row for all columns
with a class of filter-OR
*/
}
}
but applying a function to any classes overrides the filter-availOnly option.
Not sure how to move forward with this.
The way of using filter_functions is a bit different from the way you were using it in your example.
You have to provide the columns to which the filter function will be applied as well as a key representing the value of the select that will trigger the function.
You do that in the form of an object whose keys are the columns and the value of those keys is another object whose keys are the values of the select and the values of those keys the function that will be triggered.
For instance:
filter_functions: {
1: {// Column one...
"Yes" : function() {},//... will trigger the anonymous function when "Yes" is selected.
"No" : function() {}//... will trigger the anonymous function when "No" is selected.
}
}
If you want an OR you could do something like:
function (e, n, f, i, $r, c) {
return $r.find("td")// For all the tds of this row
.not(":first")// Avoid checking the first one (usually the ID)
.filter(function (_, el) {// filter all tds which value differs from "Yes"
return $(el).text() === "Yes";
})
.length > 0;// If length is bigger than one it means we have at least one "Yes", therefore we tell tablesorter not to filter this row.
};
Same applies to "No" except we change the value that we'll be checking.
Wrapping everything up and making it a bit tidier we have:
var checker = function (value) {
return function (e, n, f, i, $r, c) {
return $r.find("td")
.not(":first")
.filter(function (_, el) {
return $(el).text() === value;
})
.length > 0;
};
}, objChecker = function () {
return {
"Yes": checker("Yes"),
"No": checker("No")
};
};
$('table').tablesorter({
// Here goes your code to set up the table sorter ...
filter_functions: {
1: objChecker(),
2: objChecker(),
3: objChecker()
}
}
});
You can check it out in this fiddle
Hope it helps.
If I am understanding the request, maybe try something like this (demo):
$(function () {
var $table = $('table'),
// get 'filter-OR' column indexes
orColumns = $('.filter-OR').map(function (i) {
return this.cellIndex;
}).get(),
filterfxn = function (e, n, f, i, $r, c) {
var col, v,
showRow = false,
content = [];
$r.children().filter(function (indx) {
if (orColumns.indexOf(indx) > -1) {
v = (c.$filters.eq(indx).find('.tablesorter-filter').val() || '').toLowerCase();
showRow = showRow || $(this).text().toLowerCase() === v;
}
});
return showRow;
};
$table.tablesorter({
theme: 'green',
widgets: ['uitheme', 'zebra', 'columns', 'filter'],
sortReset: true,
sortRestart: true,
widthFixed: true,
widgetOptions: {
filter_functions: {
'.filter-OR': {
'Yes': filterfxn,
'No' : filterfxn
}
}
}
});
});
I am using jqgrid in 'multiselect' mode and without pagination. When the user selects individual records by using mouse click, is there any way that I can bring those selected records to the top of the grid?
Thanks in advance for your help.
After small discussion with you in comments I could reformulate your question so: "how one can implement sorting by multiselect column?"
The question find is very interesting so I invested some time and could suggest a solution in case of jqGrid which hold local data (datatype which is not 'xml' or 'json' or which has 'loadonce: true' option).
First of all the working demo which demonstrate my suggestion you can find here:
The implementation consist from two parts:
Making selection as part of local data. As the bonus of the selection will be hold during paging of local data. This feature is interesting independent on the sorting by multiselect column.
The implementation of sorting by multiselect column.
To implement of holding selection I suggest to extend local data parameter, which hold local data with the new boolean property cb (exactly the same name like the name of the multiselect column). Below you find the implementation:
multiselect: true,
onSelectRow: function (id) {
var p = this.p, item = p.data[p._index[id]];
if (typeof (item.cb) === "undefined") {
item.cb = true;
} else {
item.cb = !item.cb;
}
},
loadComplete: function () {
var p = this.p, data = p.data, item, $this = $(this), index = p._index, rowid;
for (rowid in index) {
if (index.hasOwnProperty(rowid)) {
item = data[index[rowid]];
if (typeof (item.cb) === "boolean" && item.cb) {
$this.jqGrid('setSelection', rowid, false);
}
}
}
}
To make 'cb' column (multiselect column) sortable I suggest to do following:
var $grid = $("#list");
// ... create the grid
$("#cb_" + $grid[0].id).hide();
$("#jqgh_" + $grid[0].id + "_cb").addClass("ui-jqgrid-sortable");
cbColModel = $grid.jqGrid('getColProp', 'cb');
cbColModel.sortable = true;
cbColModel.sorttype = function (value, item) {
return typeof (item.cb) === "boolean" && item.cb ? 1 : 0;
};
UPDATED: The demo contain a little improved code based on the same idea.
If you have the IDs of the row(s) you can do a special sort on server side by using following command for e.g. MySQL:
Select a,b,c
FROM t
ORDER BY FIND_IN_SET(yourColumnName, "5,10,44,29") DESC
or
ORDER BY FIELD(yourColumnName, "5") DESC