tablesorter to sort columns which has <br> within them - ruby-on-rails

I have a table which has one of the column's as datetime: eg: 1/11/2011 12:34 PM
Unfortunately, the width of the column does not allow me to display datetime in full length in one line, hence I am displaying the contents in two lines, like
1/11/2011
12:34 PM
But tablesorter will not work if the column contents have a <br> in them. Any idea how I can achieve sorting via tablesorter for this issue? I am having tablesorter revision 2.0.5b. I cannot upgrade to newer version because it might break existing features of the rails app.
tablesorter is the jquery plugin

You'll probably need a custom parser to remove the carriage return; honestly, I don't think a <br> needs to be added if the text is allowed to wrap, and you set a width for that column.
Anyway, try this code (demo)
$(function () {
$.tablesorter.addParser({
// set a unique id
id: 'date',
is: function (s, table, cell) {
// return false so this parser is not auto detected
return false;
},
format: function (s, table, cell, cellIndex) {
// replace extra spacing/carriage returns
var str = s.replace(/\s+/g," "),
date = new Date( str );
return date instanceof Date && isFinite(date) ? date.getTime() : s;
},
// set type, either numeric or text
type: 'numeric'
});
$('table').tablesorter({
theme: 'blue',
headers: {
7: { sorter: 'date' }
}
});
});

Related

custom sort order in tablesorter - jquery

I do use tablesorter (https://mottie.github.io/tablesorter/docs/index.html)
To sort my HTML tables.
I have one sorting I cannot find howtoo. ie.
(4)
(dns)
1
2
3
5
dns
is to be sorted as:
1
2
3
(4)
5
(dns)
dns
in short: the () are to be ignored and numeric sort, numeric first then alphabetical.
I have seen how to replace characters, (doesn't work as "empty" as some rank too)
The parsers I have seen thusfar require me to create per header and known value to be replaced.
ie:
$.tablesorter.addParser({
id: 'nummeriek',
is: function(s) {
return false;
},
format: function(s) {
// format your data for normalization
return s.toLowerCase().replace('dns',999).replace('(dns)',999).replace('(4)',4);
},
type: 'numeric'
});
$('.tablesorter').tablesorter({
headers: {
6: {
sorter:'nummeriek'
}
}
});
If I have to do this for every possible table content I end up creating hundreds of replace() statements. as I have scores from 1 to 100 Thus (1) to (100) is possible too...
There must be an easier way. Any help is much appreciated.
The default digit parser "assumes" that numbers wrapped in parentheses are negative; this is a common method of indicating a negative number in accounting (ref).
To get around this, you will need to slightly modify the parser (demo)
$(function() {
$.tablesorter.addParser({
id: 'nummeriek',
is: function(s) {
return false;
},
format: function(str) {
// format your data for normalization
var s = str.replace(/[()]/g, ""),
n = parseFloat(s);
return !isNaN(n) && isFinite(n) ? n : s;
},
type: 'numeric'
});
$('.tablesorter').tablesorter({
headers: {
0: {
sorter: 'nummeriek'
}
}
});
});
Note: this parser always returns a non-numeric string without parentheses, e.g. "(dns)" will become "dns". I kept it this way so the "(dns)" entries will sort as if they are "dns".

Using tablesorter custom parser only for filtering

I have a table with checkbox column for which filter is used so I can get only selected rows.
I've added custom parser for that column to use checkboxes' "checked" prop values for filtering.
The thing is that parser is added to column using 'sorter' property in 'headers' option for tablesorter initializer, so that when I click on some checkbox and trigger 'update' event, sorting is applied to checkbox column and selected rows are moved to the bottom of the table.
Is there a way to add parser to column so that it's used only for filtering, not for sorting?
UPD: I think I should clarify what I'm trying to do.
I have a custom parser for checkboxes that looks like the following:
var myCustomParser = {
id: 'myCustomParser',
is: function() { return false; },
format: function(cellText, table, cellNode, cellIndex) {
return $(cellNode).find('.checkbox-to-find').prop('checked') ? '1' : '0';
},
parsed: true,
type: 'text'
};
Then I add it to tablesorter and use in initializer:
$.tablesorter.addParser(myCustomParser);
//...
$table.tablesorter({
// ...
headers: {
0: {sorter: 'myCustomParser'}
},
//...
);
This enables filtering but sorting is also applied. I have a checkbox for selecting all rows in header cell for that column and when I click it sorting is applied and checkboxes are sorted.
This is what I use for now to disable sorting:
$table.tablesorter({
//...
textSorter: {
0: function() { return 0; }
},
headers: {
0: {sorter: 'myCustomParser'}
},
//...
);
Stub sorter practically disables sorting while leaving filter enabled. But this seems wrong. According to docs I can't use parser option for setting parser name. filter option also seems to be only for false and parsed values. I'd like to be able to do something like this:
$table.tablesorter({
// ...
headers: {
0: {parser: 'myCustomParser'}
},
//...
);
If this would enable parsing (and make filtering use these parsed values) while keeping sorting disabled, that would be great.
P.S. I've found out there's a parser for checkboxes in repo, but the question remains: how do I specify parser so that sorting is not enabled.
I am guessing that you are using my fork of tablesorter. If that is the case, setting the column to not sort does not stop the parser from processing the information in that column. Here is some information you may have missed in the documentation.
Column features (sort, filter or parsing) can be disabled using any of the methods within the associated section (they all do the same thing), in order of priority:
Disable sort (ref)
Parsing of column content still occurs
jQuery data data-sorter="false".
Metadata class="{ sorter: false }". This requires the metadata plugin.
Headers option headers : { 0 : { sorter: false } }.
Header (<th>) class name class="sorter-false".
Disable filter (ref)
jQuery data data-filter="false".
Metadata class="{ filter: false }". This requires the metadata plugin.
Headers option headers : { 0 : { filter: false } }.
Header (<th>) class name class="filter-false".
If using the "all" column external filter, the disabled column will be included in the query. You can exclude the disabled column by setting a range in the column attribute of the external filter (ref)
<input class="search" type="search" data-column="0-2,4,6-7">
Disable parsing (ref)
When parsing is disabled, both sorting and filtering are automatically disabled, and the column data stored within the cache is set to an empty string.
jQuery data data-parser="false".
Metadata class="{ parser: false }". This requires the metadata plugin.
Headers option headers : { 0 : { parser: false } }.
Header (<th>) class name class="parser-false".
Update: In your case, I would disable sorting (using any sorter methods above), then use a custom textExtraction function that targets the column containing checkboxes:
textExtraction : {
0 : function(node, table, cellIndex) {
return $(node).find('.checkbox-to-find').prop('checked') ? '1' : '0';
}
}

How do you set the tablesorter default filter type

I have a tablesorter table with titles in the cells. I'd like to be able to search on multiple, non-contiguous words in the title. The fuzzy match (~) does the job. How do I get this to be the default matcher? I don't want my users to have learn/remember it.
I tried a custom filter like this
....
widgetOptions: {
filter_external: '.search', // input box that user input goes into
filter_columnFilters: false,
filter_functions : {
1: function (e, n, f, i, $r) {
return this.filter.types.fuzzy( e, '~' + n, f, i, $r);
}
}
}
.....
but that didn't work. Ideas?
I just added a new filter widget option filter_defaultFilter in the working branch of the GitHub repository
To use it, include the column class name or index and a filter mask with the filter selector (~ in your case) and a query tag ({query} or {q}).
$(function () {
$('table').tablesorter({
theme: 'blue',
widgets: ['zebra', 'filter'],
widgetOptions: {
filter_defaultFilter: {
// set default fuzzy match on first column
0 : '~{q}'
}
}
});
});
Here is a demo applying a default exact match to filter selects for issue #704.
The documentation is available now in the working branch. The main documentation won't be updated until this weekend.

Convert Select2 input to tokens

Does the Select2 jQuery plug-in have a built-in function for converting strings to tokens?
I want to be able to call this tokenizing function when the user pastes strings into a Select2 field so that the pasted input becomes tokens.
I think I have solved the question myself with the following code:
// force tokenizing of Select2 auto-complete fields after pasting
$('body').on('paste', '.select2-input', function() {
// append a delimiter and trigger an update
$(this).val(this.value + ',').trigger('input');
});
This assumes that commas are set as delimiters in the plug-in's "tokenSeparators" initialization setting.
For 4.0.1 version:
$('#my-select').data('select2').dataAdapter.$search.val("tag1,tag2,").trigger("input");
This will add two tags: tag1 and tag2 (note trailing ,).
Important: you should add data: [] into select2 init parameters.
Use an input type text, and assign the select2 to it. Like
<input type="text" id="makeTokens" />
and then in javascript
$("#makeTokens").select2({
placeholder: "Paste data",
tags: ["red", "green", "blue"],
tokenSeparators: [",", " "]
});
in the tags, you can assign any values that you want it to display as select options and use the tokenSeperators to seperate the text on commas or spaces etc.
Note: The resultant input value will be comma seperated tokens.
For some reason Donald's solution didn't work for me (maybe newer versions of select2 behaves differently). This is what worked for me:
$('body').on('paste', '.select2-input', function (e) {
var pasteData = (e.originalEvent || e).clipboardData.getData('text/plain') || '';
$(this).val(pasteData + ',');
e.preventDefault();
});
Since at the point the event was triggered the value of .select2-input was an empty string, I extractacted the pasted string from the event object. Apparently the default select2 for copying action was still triggering after this, so I had to add e.preventDefault(); to stop it from running and messing up the input.
just run this jQuery which takes the separatoes from options.tokenSeparators directly, and applies for all select2 instances in the page automatically:
$(document).on('paste', 'span.select2', function (e) {
e.preventDefault();
var select = $(e.target).closest('.select2').prev();
var clipboard = (e.originalEvent || e).clipboardData.getData('text/plain');
var createOption = function (value, selected) {
selected = typeof selected !== 'undefined' ? selected : true;
return $("<option></option>")
.attr("value", value)
.attr("selected", selected)
.text(value)[0]
};
$.each(
clipboard.split(new RegExp(select.data('select2').options.options.tokenSeparators.map(function (a) {
return (a).replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}).join('|'))),
function (key, value) {
if (value && (!select.val() || (select.val() && select.val().indexOf('' + value) == -1))) {
select.append(createOption(value));
}
});
select.trigger('change');
});

extjs4 grid - changing column editor per row basis

ExtJS4 grid anticipates appropriate editor (cellEditor or rowEditor) per column.
If a column's header field is dateField - date selector will be applied on every row in that column.
What I need is an editor with different field editors per row, not per column.
The Extjs3 solution is provided here - unfortunately doesn't fit in Extjs4 case.
(please check that link to see explanatory images, cause I can't post images yet)
There's also a single column solution called property grid, but again - it supports only one column and is very deviated from the standard Ext.grid component
I have tried manually changing grid editor by customizing column.field and reloading grid.editingPlugin.editor, but always get a blank rowEditor panel with no fields.
//by default rowEditor applies textField to all cells - I'm trying to force custom numberFiled on apropriate row
var numberField=Ext.form.field.Number();
grid.columns[0].field=numberField;
//destroy current rowEditor's instance
delete grid.editingPlugin.editor;
//now, upon doubleClick on apropriate cell it should reinitialize itself (initEditor()) - and it does, but is an empty panel
what am I missing here? once I delete editingPlugin.editor everything should start from the beginning like during the first time rowEditor is called, but it looses all the fields
Solution for Ext4:
I was looking for a solution for this and this guy said the property grid has this behavior.
I have adapted it to work in a clean way for me
on initComponent I declared:
this.editors = {
'date' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Date', {selectOnFocus: true})}),
'string' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Text', {selectOnFocus: true})}),
'number' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Number', {selectOnFocus: true})}),
'int' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Number', {selectOnFocus: true})}),
'boolean' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.ComboBox', {
editable: false,
store: [[ true, 'Sim' ], [false, 'Não' ]]
})})
};
I used these functions to help me (copied):
this.renderCell = function(val, meta, rec) {
var result = val;
if (Ext.isDate(val)) {
result = me.renderDate(val);
} else if (Ext.isBoolean(val)) {
result = me.renderBool(val);
}
return Ext.util.Format.htmlEncode(result);
};
this.getCellEditor = function(record, column) {
return this.editors[record.get('type')];
};
And finally, associate these functions to the column:
{text: "Valor", name : 'colunaValor', width: 75, sortable: true, dataIndex: 'valor', width:200,
renderer: Ext.Function.bind(this.renderCell, this),
getEditor: Ext.Function.bind(this.getCellEditor, this)
}

Resources