jQuery tablesorter plugin secondary "hidden" sorting - jquery-plugins

I'm using the jQuery tablesorter plugin and I have a column that contains name of month and year like this
April, 1975
January, 2001
I would like to sort this column as if it were a date column. As I understand it, it is possible to sort the column with some other 'hidden' value, but I just can't seem to find the documentation for that feature. Any help out there?
Update
This fork http://mottie.github.com/tablesorter/docs/index.html of the tablesorter had just what I needed; the ability to store the value to sort by in an attribute, worked really great.

Just using the textExtraction function. Set data-sort-value on your TDs. Defaults to normal text if it's not present.
$(".sort-table").tablesorter({
textExtraction: function(node) {
var attr = $(node).attr('data-sort-value');
if (typeof attr !== 'undefined' && attr !== false) {
return attr;
}
return $(node).text();
}
});

I have a fork of tablesorter that allows you to write a parser that can extract data attributes from the table cell as well as assign specific textExtraction for each column.
$(function(){
$.tablesorter.addParser({
// set a unique id
id: 'myParser',
is: function(s) {
// return false so this parser is not auto detected
return false;
},
format: function(s, table, cell, cellIndex) {
// get data attributes from $(cell).attr('data-something');
// check specific column using cellIndex
return $(cell).attr('data-something');
},
// set type, either numeric or text
type: 'text'
});
$('table').tablesorter({
headers : {
0 : { sorter: 'myParser' }
}
});
});

This is now a STANDARD FEATURE of tablesorter, though it's undocumented for some reason. If you open the file https://github.com/christianbach/tablesorter/blob/master/jquery.tablesorter.js and look at the line # 307 you'll see it supports the "data-sort-value" attribute.
Usage:
<td data-sort-value="42">Answer to the question</td>

It's a bit of a hack (OK, it's a total hack), but if you set the parser for the column to 'text', and pre-fix your pretty output with the string you really want to sort on within a hidden span it will sort correctly.
You can set the parser on a column with the headers option, e.g. to set the parser on the first and second columns to 'text' you would set the following:
headers: {0: {sorter: 'text'}, : {sorter: 'text'}
To do this trick with dates, you can use the ISO8601 date format which sorts lexically. JS's Date objects can generate ISO8601 date strings via the toISOString() function.
Given the CSS:
span.hidden{
display:none;
}
A sample cell in the table would look like this:
<td><span class="hidden">2015-04-18T23:48:33</span>19 April 2015</td>
Not the prettiest code in the world, but it does work.

I am using
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.29.0/js/jquery.tablesorter.min.js"></script>
Working with data-text
<td data-text="42">Answer to the question</td>
Not Working with data-sort-value
<td data-sort-value="42">Answer to the question</td>

You need to write your own parser. Your parser might end up looking something like:
var months = {'January':1,'February':2, ...};
$.tablesorter.addParser({
id: 'myDate',
is: function(s) { return false; },
format: function(s) {
var x = s.split(', ');
return x[1]+'-'+months[x[2]];
},
type: 'numeric'
});
Not tested, but general idea.

Related

Change column header Treelist KendoUI

I want to be able to change my column header dynamically triggered by year picker onChange, but I can't find the proper style to handle it.
I've tried to modify with a check on the inspect element, but it also didn't work.
And my code:
$("#monthpicker").kendoDatePicker({
start: "year",
depth: "year",
format: "yyyy",
dateInput: true,
change: function() {
var year = kendo.toString($("#monthpicker").data("kendoDatePicker").value(), 'yyyy');
$("#treelist").data("kendoTreeList").dataSource.read({start: year});
$(".k-grid-header th.k-header:first-child").text(year);
}
});
And it should be like this:
(just change on the column header above Month column)
is there anyone experienced with this? Thanks.
Your query .k-grid-header th.k-header:first-child is selecting the wrong headers.
I propose using a headerTemplate with a placeholder, for instance:
headerTemplate: function(x) {
return '<span class="year-goes-here"></span>'
}
And then set the year via:
$("#treelist").find(".year-goes-here").text(2018)
Working example: https://dojo.telerik.com/uXuwIDeK

Custom template in kendo-ui grid column with inconsistent data type

I need to use kendo-ui grid for data editing. Problem is that every possible item in returned response is string, but which contains other types of value (eg Value = "true" or Value = "32%" or Value = "[0:standard, 1:advanced]").
So I need to set up template on grid to correspond different data type within string.
So for true/false i have to have checkbox, for 32% it should provide text box but with percent validation, for array response it needs to be a drop down.
I managed to set up drop down and text box options using editor, but I cannot make checkbox to handle properly in any way. Checkbox is displayed as expected, but whatever I try it won't bind data to the grid after grid is saved. (it is always not checked, regardless of value)
Here is code snippet of column "value" and what I used for template (item.type === "3" is boolean).
field: 'value',
title: 'value',
headerAttributes: {
'class': 'table-header-cell'
},
template: function (item) {
if (item.type === "3") {
var boolValue = (/true/i).test(item.value);
item.value = boolValue;
return '<input id="' + item.name+ '" type="checkbox" #= value ? \'checked="checked"\' : "" # class="chkbx" />';
} else {
return ''; //this will follow for other types
}
},
Thanks in advance.
When the template definition is a function, you don't need to use the # markers to differentiate between markup and javascript like you do when you are defining a kendo template using kendo's template language or a string directly.
This is because inside the function it is always javascript and the # markers are only directives in the kendo templating language.
So, simplify your template to just:
template: function (item) {
return '<input class="chkbx" id="' + item.name + '" type="checkbox"' + (item.value ? 'checked="checked"' : '') + '/>';
}
I've left out the other datatype handling for simplicity.
Then, you need to add code to push the checkbox changes into the grid's datasource when they occur:
$("#grid").on("click", ".chkbx", function () {
var $checkBox = $(this),
checked = $checkBox.is(":checked"),
dataItem = grid.dataItem($checkBox.closest("tr"));
dataItem.set("value", checked);
});
This is a technique that I am currently using in production code.
Dojo example
It may also be possible to use the kendo MVVM bindings in your template for a more elegant solution instead of the explicit click handler, but I'd have to experiment more with that to figure it out.

JqGrid - Freeze columns

I read all the posts regarding freezing column. But still I am unable solve my problem.
When I called setFrozenColumns my column has frozen but along with another column header is added to the grid. So the column headers one more than the columns. How to resolve this. Here is my over view of code.
makeJqueryGridInstance(grid, gridSettings);
window.prepareSortableColumns(grid);
makefrozenColumns(grid);
function makeFrozenColumn( grid )
{
var colmodel = grid.jqGrid('getGridParam', 'colModel');
if (colmodel[0].name === 'cb')
{
grid.jqGrid('setColProp', colmodel[0].name, { frozen: true });
grid.jqGrid('setFrozenColumns');
fixPositionsOfFrozenDivs.call(grid[0]);
}
}
function prepareSortableColumns(grid)
{
var gridSettings = grid.data('settings');
var gridId = gridSettings.gridId;
var columnHeaders = $("#" + "gview_" + gridId.replace("#", "")).find(".ui-jqgrid-htable > thead > tr > th");
var colModel = grid[0].p.colModel;
$.each(columnHeaders, function (index, columnHeader)
{
if (colModel[index].sortable == false)
{
$(columnHeader).find("div").removeClass("ui-jqgrid-sortable");
}
});
}
For the first time, it is working fine and the column has frozen.
But second time when the call made to prepareSortableColumns(grid), the columnHeader having one more than colModel (I debugged through devTools). So I am getting error for that particular columnHeader sortable is undefined.
Can anybody help me with this. Thanks in advance.
The code of prepareSortableColumns seems be wrong. Its not oriented on dives added in case of usage of frozen columns (see the answer for more details and use Developer Tools to examine the structure of the grids). You can try to use grid[0].grid.headers array instead of selecting columnHeaders in the way like you do this.
Additionally it's in general wrong to remove ui-jqgrid-sortable class. The meaning of the class will be frequently misunderstood because of the name. Non-sortable columns have to have the class too. What you need to do instead is to set CSS style cursor: default on the headers. See the old answer for the corresponding code example.

YUI datatable conditional dropdown editor

I'm currently editing an application which uses YUI 2.5. I haven't used it before and could use some help.
I want to be able to add a dropdown editor for a particular column's rows using datatable, but I only want it to appear if specific values appear in another column in the corresponding row.
Is it possible to add some kind of If statement in the column definitions? Would I have to use a custom formatter?
eg.
var eventColumnDefs = [
{key:"event_id", sortable:false},
{key:"event_name", sortable:true},
{key:"extended", sortable:true, formatter: function (o) {
if (event_name=type1||event_name=type4||event_name=type5) {
editor:"dropdown", editorOptions:{dropdownOptions:eventData.extendedList}
}
}
}];
I know this code wouldn't work, by the way, I would just appreciate a bit of guidance.
You are close. In the column definition you add the information about the dropdown editor as if you always wanted it to show up. Now, going to the code sample here: http://developer.yahoo.com/yui/datatable/#cellediting
See the last line that attaches onEventShowCellEditor to whatever event you want to make the editor pop up? That is where you put the conditional. Instead of just asking to show the cell editor under any circumstance, you put some code there, like:
myDataTable.subscribe("cellClickEvent", function (ev) {
if ( ** whatever ** ) {
this.myDataTable.onEventShowCellEditor.apply(this, arguments);
}
});
I haven't been doing YUI2 for quite some time now so I don't remember the details on the arguments received by the event listener. I believe that you might also use showCellEditor() instead of onEventShowCellEditor, the later only massages the arguments as received from the event listener and ends up calling showCellEditor so you might as well skip it.
Found a hacky solution as follows
In Column Definitions:
var eventColumnDefs = [
{key:"player_name", sortable:true, editor:"dropdown", editorOptions:{dropdownOptions:currenteam}}
];
Then later on in initialiseTables:
eventDataTable.subscribe("cellClickEvent", function(ev) {
var target, column, field;
target = ev.target;
column = this.getColumn(target);
if (column.key === "player_name") {
field= this.getRecord(target).getData("team_id");
}
if (hometeamlistID == field) {
currenteam=hometeamlist;
} else if (awayteamlistID == field) {
currenteam=awayteamlist;
}
eventDataTable._oColumnSet._aDefinitions[8].editorOptions.dropdownOptions = currenteam;
});
hometeamlist, awayteamlist, hometeamlistID and awayteamlistID are pulled from an XML string. I haven't included that code above, but some of it is included in my question here:
YUI 2.5. Populating a dropdown from XML

jqGrid Custom Formatter Set Cell wont work with options.rowId

Ive been through all the posts, finally got setCell to work with hardcoded values, but not using the options.rowId.
function StatusFormatter(cellvalue, options, rowObject) {
if (cellvalue == 'C'){
jQuery("#list").setCell(options.rowId , 'SOORDLINE', '', { color: 'red' });
jQuery("#list").setCell("[2.000]", 'SOORDLINE', '', { color: 'red' });
jQuery("#list").setCell('[2.000]', 'SOREQDATE', '', { color: 'red' });
jQuery("#list").setCell(options.rowId, 'SOPRICE', '', { color: 'red' });
}
return cellvalue;
};
The FIRST and LAST lines dont work, but the 2 with the hardcoded rowId DO work. I inspected what comes back in the option.rowId and they are the same as the hardcoded values, (just different depending on the row of course. What am I missing? Please help. I dont see any difference between the lines, or values.
EDITED-
I tried the answer, and it seems to be what I need. I tried the following
{ name: 'SOORDLINE', index: 'SOORDLINE', width: 25, search: false ,celattr: function () { return ' style="color: red"'; }
},
To aleast make them all red before I dove into the logic, and it didnt do anything for me.
Sorry, but you use custom formatter in absolute wrong way. The goal of the custom formatter to to provide HTML fragment to fill the content of the cells in the corresponding column. So the StatusFormatter will be called before the row with the id equal to options.rowId will be created. Moreover for performance purpose one use typically gridview: true. in the case the whole content of the grid (the whole body of the grid) will be constructed first as string and only after that will be placed in the grid body in one operation. It improve the performance because after placing of any element web browser have to recalculate position of all other elements on the page.
If you want to set text color on the SOORDLINE cell you should cellattr instead:
celattr: function () { return ' style="color: red"'; }
The celattr can be used also in the form celattr: function (rowId, cellValue, rawObject) {...} and you can test the property of rawObject which represent of the values for any column and return the cell style based on the cell value.
Alternatively you can enumerate the rows inside of loadComplete and set the style on <tr> element instead of setting the same styles for every row. See the answer as an example.

Resources