TableSorter multi-filter - tablesorter

I have a tablesorter table that contains a 'Category' column. My searches reveal many different ways to filter on various types of columns but they all boil down to a single filter criteria.
What I have is a section on the page that lists all the categories with checkboxes, the idea is to allow the user to select which categories they want to look at (there are 10 different categories) and have these selected categories be applied to filter the rows in the tablesorter.
I could always brute force this with a post back to my controller and return a model with a filtered set of rows, but if there is a sensible way to accomplish this on the client side I would greatly appreciate anyones input on where to begin tackling a problem like this.

This is my first crack at it. So assume I have a bunch of checkboxes representing the categories to filter on. The class 'tablesorter' is what I called the table containing the data. I added an id attribute to the cell which has the category in it. I did it this way because I do not want the id to be visible on screen. At the end I refresh the zebra striping after hiding/unhiding rows. If there is a better way to do this, I'm all ears (I am a total newb to javascript/jquery/tablesorter).
function FilterCompanies() {
$(':checkbox:not(:checked)').each(function () {
var unselectedCategoryId = $(this).attr('id').substring(3);
$('.tablesorter > tbody > tr > td[id]').each(function() {
if ($(this).attr('id') == unselectedCategoryId) {
$($(this).parent()).addClass('hidden');
}
});
});
$(':checkbox:checked').each(function () {
var unselectedCategoryId = $(this).attr('id').substring(3);
$('.tablesorter > tbody > tr > td[id]').each(function () {
if ($(this).attr('id') == unselectedCategoryId) {
$($(this).parent()).removeClass('hidden');
}
});
});
$(".tablesorter").trigger("applyWidgets")
}
Here's what it looks like:

Related

How to set different select items in Vaadin Grid Pro's editComponent based on row item

I have Grid Pro displaying Products. A single column is configured as an EditColumn of type 'select' (dropdown/combobox). I'm trying to set the items for this component based on the Product of that row. Is this possible using the 'select' editColumn?
I tried to achieve what I want using the grid's 'addCellEditStartedListener' event, but I can't seems to access the editComponent from CellEditStartedEvent..
thx!
Yes, the this is missing feature in CellEditStartedEvent. As an alternative you can use custom editor in your edit column, as then you have reference to the field you are using, see example
// Use custom editor
EmailField emailField = new EmailField();
emailField.setWidth("100%");
emailField.addThemeName("grid-pro-editor");
grid.addEditColumn(Person::getEmail)
.custom(emailField, (item, newValue) -> {
item.setEmail(newValue);
}).setHeader("E-mail ");
// Use edit started listener to set the field conditionally enabled
grid.addCellEditStartedListener(event -> {
if (!event.getItem().isSubscriber()) {
emailField.setReadOnly(true);
} else {
emailField.setReadOnly(false);
}
});
Full code here: https://cookbook.vaadin.com/grid-pro-conditional-edit

angular ui-grid selecting all under grouping

https://jsfiddle.net/4byyuqtc/1/
I'm looking to have the ui-grid select all "children" under a grouping when the grouping line is selected. In this case Kit Kat(1), Mr. Goodbar(1), Krackel(2) and ultimately selecting the actual records (the non bold lines). One would expect that when selecting a parent in a grouping all it's children would get selected as well.
Currently when selecting the 1 grouping above the actual records in the data (the non bold lines) it does select those actual records with the following code:
$scope.gridApi.selection.on.rowSelectionChanged($scope, function (rowChanged) {
console.log(rowChanged.treeLevel);
if (typeof (rowChanged.treeLevel) !== 'undefined' && rowChanged.treeLevel > -1) {
// this is a group header
children = $scope.gridApi.treeBase.getRowChildren(rowChanged);
console.log(children);
children.forEach(function (child) {
if (rowChanged.isSelected) {
$scope.gridApi.selection.selectRow(child.entity);
} else {
$scope.gridApi.selection.unSelectRow(child.entity);
}
});
}
});
I'm not experienced enough with ui-grid at this point to figure out how to cycle through children of the selected line and select all of them.
[EDIT]
With Paul's code below it doesn't select the groupings but it's closer. This screenshot is me selecting the first 337 record. Notice it selects that record and all the lowest child records (which is good because ultimately those are the ones that matter) but visually the grouped records (MFG and Item Desc group) aren't selected and need to be as the user won't ever open the lowest data records so they need to see the groups selected.
I checked the documentation and I don't think there's any exposed API Method. You could recursively select/deselect rows as a solution. Please try out the example below.
$scope.gridApi.selection.on.rowSelectionChanged($scope, function (rowChanged) {
console.log(rowChanged.treeLevel);
if (typeof(rowChanged.treeLevel) !== 'undefined' && rowChanged.treeLevel > -1) {
var children = $scope.gridApi.treeBase.getRowChildren(rowChanged);
selectChildren(children, rowChanged.isSelected);
}
});
function selectChildren(gridRows, selected) {
if (gridRows && gridRows.length > 0) {
gridRows.forEach(function (child) {
if (selected) {
$scope.gridApi.selection.selectRow(child.entity);
} else {
$scope.gridApi.selection.unSelectRow(child.entity);
}
var children = $scope.gridApi.treeBase.getRowChildren(child);
selectChildren(children, selected); //recursively select/de-select children
});
}
}
Here's a working Plunkr: http://plnkr.co/edit/XsoEUncuigj9Cad1vP5E?p=preview
Handling automatic deselection is a bit more tricky though as it seems the api doesn't handle that really well.
UPDATE
So I checked the jsFiddle you shared and managed to get it working with a slight tweak.
I modified the selectionHandler to the following:
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
$scope.gridApi.selection.on.rowSelectionChanged($scope, function(rowChanged) {
if (rowChanged.treeNode.parentRow) { //Added this parent row selection
rowChanged.treeNode.parentRow.setSelected(rowChanged.isSelected);
}
console.log(rowChanged.treeLevel);
if (typeof(rowChanged.treeLevel) !== 'undefined' && rowChanged.treeLevel > -1) {
var children = $scope.gridApi.treeBase.getRowChildren(rowChanged);
selectChildren(children, rowChanged.isSelected);
}
});
Please see this fork of your code: https://jsfiddle.net/1eg5v77w/
The downside with this is that if you select a low level entry (one without children) it will still select its parent. If you really really want this to work as well, you'll have to access the DOM and make some ugly checks.
$scope.gridApi.selection.on.rowSelectionChanged($scope, function(rowChanged, $event) {
var wasHeaderRowClicked = true;
try { //This can be written more beautifully if you used jQuery. But I would still be against it as it relies on the class of the ui-grid never changing when you update your ui-grid version.
wasHeaderRowClicked = $event
.srcElement
.parentElement
.parentElement
.parentElement
.previousElementSibling
.firstChild
.firstChild
.firstChild
.getAttribute('class') === 'ui-grid-icon-minus-squared';
} catch(err) { console.log('Couldnt determine if header row was clicked'); }
if (rowChanged.treeNode.parentRow && wasHeaderRowClicked) {
rowChanged.treeNode.parentRow.setSelected(rowChanged.isSelected);
}
console.log(rowChanged.treeLevel);
if (typeof(rowChanged.treeLevel) !== 'undefined' && rowChanged.treeLevel > -1) {
var children = $scope.gridApi.treeBase.getRowChildren(rowChanged);
selectChildren(children, rowChanged.isSelected);
}
});
Here is the fiddle: https://jsfiddle.net/Lf8p7Luk/1/
I'd also like to add, thanks to this post, that according to the UI-Grid documentation: Group header rows cannot be edited, and if using the selection feature, cannot be selected. They can, however, be exported.
So it is intentional that it's so difficult to get this to work because it's not the intended design. My recommendation would be to alter your logic to either use Tree Levels or get around the selection logic because even though my fork is currently selecting everything, you will most likely run into other issues down the road. For example: I couldn't get automatic deselection to work in the grid when you click on another group header.
If you still have the issue take a look with this..
https://github.com/angular-ui/ui-grid/issues/3911

Webix Pager scroll to particular row

The datatable has a select method, which selects a given row.
The pager also has a select method, which scrolls to a given page.
However, I cannot find a way to tell the pager to scroll to a page which contains a given row.
Namely, I want to select a row in the datatable, but also show it if the view is on a different page.
There's no specific method that can both select and show the needed row at a time, but the combination of the following methods will do the job well:
datatable.select(35); //selects row
datatable.showItem(35); //scrolls or pages to make the row visible
See at this example in the Snippets
webix.ui({
rows:
[
{ view:"button", type:"iconButton",icon:"fa fa-bolt",label:"Go 52", width:100,on:
{
'onItemClick': function()
{
$$("dTable").select(52);
$$("dTable").showItem(52);
}
}
},
{
view:"datatable",name:"dTable",id:"dTable",select:true,
columns:[
{ id:"rank", header:"", css:"rank", width:50},
{ id:"title", header:"Film title",width:200},
{ id:"year", header:"Released" , width:80},
{ id:"votes", header:"Votes", width:100}
],
autowidth:true,
data: big_film_set
},
]
});
big_film_set it is a variable with a JSON.
var big_film_set = [{"id":1,"title":"The Shawshank Redemption","year":"1994","votes":"678.79","rating":"9.2","rank":"1"} /*...*/ ];

JQGrid ContextMenu - Dynamic Menus

I have a page, which is used for building queries and running them against different entities (Kind of a query builder/generic search).
The results are displayed in JQGrid, so effectively the same grid will be used for rendering results from different entities.
This results grid has to support context menus, which will differ for each entity. So I need a way to change the context menu as per the entity. Each entity may have different number of menu items in context menu and each item may respond in a different manner (sometimes an alert, sometimes an action spawning in a different tab).
Rendering different menus (through li) is not an issue but attaching the methods to the li is proving to be a challenge. Any pointers will be highly appreciated.
I am using jquery.contextmenu-ui.js .
Following is from a sample that I picked from their (JQGrid) site
function initGrid() {
$("#EntityGrid").contextMenu('cMenu'
,{
bindings: { /* I would like to avoid this and pass all the actions to one method*/
'edit': function (t) {
editRow();
},
'add': function (t) {
addRow();
},
'del': function (t) {
delRow();
}
},
onContextMenu: function (event, menu) {
var rowId = $(event.target).parent("tr").attr("id")
var grid = $("#EntityGrid");
grid.setSelection(rowId);
return true;
}
}
);
}
Thanks,
Avinash
You can use onShowMenu callback of contextMenu instead of static binding using bindings. In the same way the menuId used as the first parameter of contextMenu could be the id of dynamically created div with empty <ul>. The onShowMenu has the form
onShowMenu: function (e, $menu) {
// here one can clear `<ul>` child of $menu
// and append it with "<li>" items
return $menu;
}
In the answer you will find an example of the code which build menu dynamically.

jquery UI problem sending string extracted from ui.item object

I have 2 sortable, connected lists with pics: Album and Favorites.
When I drag and item from Album -> Favorites I want to check if it's already in the Favorites list.
If it is, do NOT accept it (maybe disable sorting or something?)
If it is not, clone the item back to the original index in Albums (connected sortable lists do only move items, so this mimics copying)
I have a function that checks if the pics are in the Favorites list:
function isInFavorites(url) {
return $(".favorites li img[src*='" + url + "']").length > 0;
}
This function works like expected...
However when I extract the scr attr with ui.item and pass the argument to this function I always get a true boolean??
var itemSrc = ui.item.find("img").attr("src");
if (isInFavorites(itemSrc)) { alert('item allready in favorites, do not accept'); }
else { alert('OK, now clone back to album'); }
I have been banging my head way to long on this and would appreciate some help!
A JS Fiddle can be found here: http://jsfiddle.net/tunafish/CTps3/
Cheers!
Not sure if this is the best way to process the logic but the order the events are firing is the source of your problem
function isInFavorites(url) {
return $(".favorites li img[src*='" + url + "']").length > 0;
}
This event runs AFTER the item has been moved. if it is a duplicate you will have length 2, but you will always have length 1 because you just moved the item into the lower list.
quick fix is to test for $(".favorites li img[src*='" + url + "']").length > 1

Resources