How to use sorttable.js to Sort a Column of Checkboxes - sorttable.js

I have a column of checkboxes that represent selected "favorites" in a large table. I'm attempting to use sorttable.js to sort the table so the rows that are checked can be brought to the top of the table. I'm not having any luck. I've tried the "sorttable.innerSortFunction.apply" snippet from the docs but it caused an error: sorttable.js:211 Uncaught TypeError: node.getAttribute is not a function. Any suggestions?

I happen to use sorttable.js albeit without checkboxes (CBs).
I guess it would involve:
The CB's .onclick event that would update its .checked (true/false) status to the parent TD cell's sorttable_customkey value as true or false.
I.e. (assuming CB INPUT is directly under TD):
CBobj.onclick = function() { this.parentNode.sorttable_customkey = this.checked }
or, more standardized:
CBobj.onclick = function() { this.parentNode.setAttribute("sorttable_customkey", this.checked) }
(You would obviously load the default TD sorttable_customkey=true/false values in accordance with your checkboxes from the server, but you can loop them on the client side with JS)

Related

JQuery Datatables SearchPane Filter Value

I am using the SearchPanes extension to Datatables, I am trying to capture the value of the item in the SearchPane they chose, it appears that since SearchPanes uses filter() instead of search() that value is not available. Am I wrong?
You can access the selections as follows:
1) Add stateSave: true to the DataTable initialization definition. See this example.
This will cause all selections to be saved in the browser's local storage.
2) Use the following logic to access the browser's local storage:
var myStorage = window.localStorage;
var searchPanes = JSON.parse(myStorage.getItem('yourStorageIndexGoesHere'));
//console.log(searchPanes); // the full JSON - large!
//console.log(searchPanes['searchPanes']['panes']); // one object per search pane
searchPanes['searchPanes']['panes'].forEach(function(pane) {
console.log('ID = ' + pane.id + ' - selected: ' + pane.selected);
});
In my case, I used the search panes shown in this demo.
Here is a screenshot with some selections:
Here is what the sample code writes to the browser console for the above selections:
The "ID" data value is a zero-based column index. So, column 3 (index 2) is the Office column, and column 6 (index 5) is the Salary column.
The related "selected" data are arrays, containing one or more value. You can iterate the arrays to get each separate value.
You will need to replace yourStorageIndexGoesHere with the actual name of your storage entry. The easiest (manual) way to find this is to perform a filter using SearchPanes, and then open your browser tools (usually F12). Then (assuming FireFox in my case) navigate to Storage > Local Storage > and select the relevant key text.
Points to Note:
a) This assumes you are OK with activating the "local storage" feature. It means that the browser will remember the last applied filter, and re-apply it when a user returns to the DataTable browser page. If users do not want that feature, then my solution will not be suitable for you.
b) I can't advise you on where you need to place the JavaScript I provided, because I don't know what you want to do with this information. But, for example, you might want to use it after every draw() event - in which case, see here.
Jsut want to add, how the search pattern or the preselected searchPanes filters can be erased on demand - is stateSave is been enabled.
.on( 'stateLoadParams.dt', function (e, settings, data) {
//get the last search pattern, if this setting is enabled
//if not, erase last search
if (!cnf_lastSearch) {
//erase search input field
data.search.search = '';
data.start = 0;
//console.log(data)
} else {
}
//search through search panes array and erase content
if (!cnf_searchPanes) {
$.each((data['searchPanes']['panes']), function( i, val ) {
val.selected = '';
});
}
})

jQuery DataTable filtering - so confusing

I am new to the jQuery dataTables plugin found on https://datatables.net/
I am trying to implement a custom filter for the table:
Basically, when I click a button, a custom filtering function will test the value of column #1 (numeric value) for all rows, and if the value in the column < 50 for a row, the row stays, otherwise the row is hidden.
The concept should be very simple, but I can't seem to find the right way to use the API:
column.filter() returns an array of column value
column.search() can only accept text data (not function)
What's the API that can achieve the effect?
Is there anything like the following?
var api = $('#table').DataTable();
api.column(1).data().somefilterfunction(function (val, ind) {
return parseFloat(val) < 50;
}).draw();
Have you seen this article in the documentation -> https://datatables.net/examples/plug-ins/range_filtering.html ??
You can create a custom filtering function on-the-fly, triggered by a button :
<button id="filter">filter < 50</button>
script :
$("#filter").click(function() {
$.fn.dataTable.ext.search.push(
function( settings, data, dataIndex ) {
return parseFloat(data[0])<50
? true
: false
}
);
table.draw();
$.fn.dataTable.ext.search.pop();
});
demo -> http://jsfiddle.net/dpwgqs2o/
Notice that the filter is created inside the click handler itself, and removed again as soon the table is drawn. This makes the filter temporary, i.e when the user click on a column header, the filter is cleared. If you want a permanent filter, make the filter global and do not remove it.

DataTables - createdRow in conjunction with dynamic column hide/unhide

I implemented a dynamic column visibility to hide/show columns, e.g. DT.columns(5).visible(true) and DT.columns(5).visible(false) to show/hide column 5. I also have a callback for createdRow which let's say makes a html button out of the text in column 5.
Currently in createdRow I check this.api().columns(5).visible() and if true then I proceed to do $('td:eq(5)',row).html('<button>'+data[5]+'</button>') cell content, and if false then I return because otherwise I'd overwrite the current 5th <td> which is not the intended one. But then when I unhide column 5, it comes up as text since I did not run the previous code.
I'd like to be able to run the code and cache the html of the cell in column 5 so that when it's unhidden, it comes up with the intended <button>. What's the best way to do that? The column-visibility event?
Note that I know I can use the render: function (...) {} option for the column, but I do not want to use that because it affects the raw data of the table and affects filtering and searching - I want the raw data to remain unaffected, which is why I was using the createdRow or rawCallback callbacks.
Assume column 5 has visibile: false in the DataTable initialization object which looks like this:
var DT = $('#dt').DataTable({
...
createdRow: function (row, data) {
if (this.api().column(5).visible()) {
$('<button>' + data[5] + </button>')
.appendTo($('td:eq(5)',row).text(''));
}
);
Cheers
Look into using columnDefs and the 'render' function instead...
var DT = $('#dt').DataTable({
...
"columnDefs":[
{
'targets':[0],
'visible':false,
'render':function(data, type, row, meta){
...
}
]
});
https://datatables.net/reference/option/columns.render
https://datatables.net/reference/option/columns.data

Getting id from row clicked on a dgrid List

I just started using dgrid, and going through the dTunes sample, I'm unable to find the id associated with each row in the list. This is pretty remedial on my part, but how would I also get the id I sent from the datasource?
define([
'require',
'dgrid/List',
'dgrid/OnDemandGrid',
'dgrid/Selection',
'dgrid/Keyboard',
'dgrid/extensions/ColumnHider',
'dojo/_base/declare',
'dojo/_base/array',
'dojo/Stateful',
'dojo/when',
'dstore/RequestMemory',
'put-selector/put',
'dojo/domReady!'
], function (require, List, Grid, Selection,
Keyboard, Hider, declare, arrayUtil, Stateful,
when, RequestMemory, put) {
var cstsNode = put(listNode, 'div#cstsCars');
...
var cstsList = new TunesList({}, cstsNode);
var dataCSTS = new RequestMemory({ target: require.toUrl('./dataCSTS.json') });
...
dataCSTS.fetch().then(function (cars) {
cstsCars = arrayUtil.map(cars, pickField('Description'));
cstsCars.unshift('All (' + cstsCars.length + ' CSTS Cars' + (cstsCars.length !== 1 ? 's' : '') + ')');
cstsList.renderArray(cstsCars);
});
...
cstsList.on('dgrid-select', function (event) {
var row = event.rows[0];
console.log(row.id); // shows row number. How do I get the real id or other fields?
console.log(row.data); // shows row text that is displayed ("sample text 1")
console.log(row.data.id); // undefined
});
Here is a snippet of sample data like I'm supplying:
[{"id":"221","Description":"sample text 1"},
{"id":"222","Description":"sample text 2"},
{"id":"223","Description":"sample text 3"}]
I'd like to see the id. Instead, row.id returns 1,2 and 3, ie the row numbers (or id dgrid created?).
You haven't really shown a complete example, but given that you're using a store anyway, you'd have a much easier time if you let dgrid manage querying the store for you. If you use dgrid/OnDemandList (or dgrid/List plus dgrid/extensions/Pagination), you can pass your dataCSTS store to the collection property, it will render it all for you, and it will properly pick up your IDs (since Memory, and RequestMemory by extension, default to using id as their identity property).
The most appropriate place to do what you're currently doing prior to renderArray would probably be in the renderRow method if you're just using List, not Grid. (The default in List just returns a div with a text node containing whatever is passed to it; you'll be passing an object, so you'd want to dig out whatever property you actually want to display, first.)
If you want a header row, consider setting showHeader: true and implementing renderHeader. (This is false in List by default, but Grid sets it to true and implements it.)
You might want to check out the Grids and Stores tutorial.
I think the problem might be that I was modeling my code based on the dTunes sample code, which has 3 lists that behave a little differently than a regular grid.
For now, I'm using the cachingStore that is available in the lists. So the way I get the id:
cstsList.on('dgrid-select', function (event) {
var row = event.rows[0];
var id = storeCSTS.cachingStore.data[row.id - 1].id; // -1 because a header was added
console.log(id);
});
I'm not sure whether this will work if I ever try to do sorting.

extjs 4.1 how to reset the itemselector

I am using extjs 4.1.1a for developing some application.
I had a form consisting of two combo-boxes and an item-selector.
Based on the value selected in first combo-box , the itemselector will load its data from database. This is working fine.
My problem is, if i reselect the first combo-box the new data will be displayed in itemselector along with previous data displayed in itemseletor .That is previous data displayed in itemselector will remain there itself.
for example: name "test1" consists of ids 801,2088,5000. on selecting test1 in firstcombobox itemselector must show output as below.
and if "test2" consists of ids 6090,5040. on selecting test2 in firstcombobox itemselector must show output as below.
problem is. for first time if i select "test1" from firstcombobox , output will come as expected. if i reselect "test2" from firstcombobox , output will come as below.
as you can see, previous data displayed (marked in red rectagle) remains there itself with new data displayed (marked with green rectangle).
I want for every reselection of first combobox, previously displayed data in itemselector to be erased before printing new data on itemselector.
How can I reset the itemselector for every reselection of first combobox?
You should remove all items from the store of the itemselector by the removeAll command. After that you should load the store of the itemselector.
itemselector.store.removeAll();
itemselector.store.load();
Any solutions above solve my problem.
i found solution from Sencha Forum.
https://www.sencha.com/forum/showthread.php?142276-closed-Ext-JS-4.0.2a-itemselector-not-reloading-the-store
in the itemselector.js file, change the line marked below.
populateFromStore: function(store) {
var fromStore = this.fromField.store;
// Flag set when the fromStore has been loaded
this.fromStorePopulated = true;
// THIS LINE BELOW MUST BE CHANGED!!!!!!!!!!!!
fromStore.loadData(store.getRange()); //fromStore.add(store.getRange());
// setValue waits for the from Store to be loaded
fromStore.fireEvent('load', fromStore);
},
You need to insert...
this.reset();
at the head of the function that is inserting the data.
As an example...
Ext.override( Ext.ux.ItemSelector, {
setValue: function(val) {
this.reset();
if (!val) return;
val = val instanceof Array ? val : val.split(this.delimiter);
var rec, i, id;
for (i = 0; i < val.length; i++) {
var vf = this.fromMultiselect.valueField;
id = val[i];
idx = this.toMultiselect.view.store.findBy(function(record){
return record.data[vf] == id;
});
if (idx != -1) continue;
idx = this.fromMultiselect.view.store.findBy(function(record){
return record.data[vf] == id;
});
rec = this.fromMultiselect.view.store.getAt(idx);
if (rec) {
this.toMultiselect.view.store.add(rec);
this.fromMultiselect.view.store.remove(rec);
}
}
}
});
are u got it?
when u select that combobox frist stoe of item selector is null after store load with ur pass the para meters
for example
store.load(null),
store.proxey.url='jso.php?id='+combobox.getrawvalue(),
store.load();
like that so when ur select a value in ur combobox that time ur used a listeners to ur combobox in that listners ur used above code , select ur some value in combobox that time frist store is get null after ur pass some values to json.php then store load with responce so that time old data is remove and new data load in that store
if u post ur code i will give correct code
I ran into the same issue with ExtJS 4.2.1. I got it to work by calling reload() on the data store and then setValue() with an empty string on the item selector in the data store's reload() callback.
Ext.create("Ext.form.field.ComboBox", {
// Other properties removed for brevity
listeners: {
change: function(field, newValue, oldValue, eOpts) {
Ext.getStore("ExampleStore").reload({
callback: function() {
Ext.getCmp("ExampleItemSelector").setValue("");
}
});
}
}
});
Ext.create("Ext.data.Store", {
storeId: "ExampleStore",
// Other properties removed for brevity
});
Ext.create("Ext.form.FormPanel", {
// Other properties removed for brevity
items:[{
xtype: "itemselector",
id: "ExampleItemSelector",
// Other properties removed for brevity
}]
});
For any folks that are curious, I'm fairly convinced there's a bug in the item selector's populateFromStore() function. When the function is called, it blindly adds all of the values from the bound store (store) to the internal store (fromStore). I suspect there should be a call to fromStore.removeAll() prior to the call to fromStore.add(). Here's the relevant code from ItemSelector.js.
populateFromStore: function(store) {
var fromStore = this.fromField.store;
// Flag set when the fromStore has been loaded
this.fromStorePopulated = true;
fromStore.add(store.getRange());
// setValue waits for the from Store to be loaded
fromStore.fireEvent('load', fromStore);
},
EDIT 12/18/2013
If you've configured any callback events on the item selector (e.g. change), you may want to disable the events temporarily when you call setValue(""). For example:
var selector = Ext.getCmp("ExampleItemSelector");
selector.suspendEvents();
selector.setValue("");
selector.resumeEvents();
I had the same problem and finally I decided to modify the extjs source code, not considering it a big issue as extjs itself its saying in the start of the file
Note that this control will most likely remain as an example, and not as a core Ext form
control. However, the API will be changing in a future release and so should not yet be
treated as a final, stable API at this time.
Based on that, as jstricker guessed (and sadly I didn't read and took me a while to arrive to the same conclusion), adding fromStore.removeAll() before fromStore.add() solves the problem.
Outside of the problem (but I think it can be interesting as well), additionally, I also added listConfig: me.listConfig in the MultiSelect configuration (inside createList), that way it's possible to format each item additional options (such as images, etc.) setting in the 'itemselector' the option listConfig as it's explained in the (irrealistic) documentation.
Need to reset the store used in ItemSelector that can be done by setting Empty object like below. Also need to call clearValue() method of ItemSelector component.
store.setData({});
ItemSelectorComponent.clearValue();