Selection count in extjs works too slow - performance

I use standart Ext.grid.Panel in extJs.
I need to select up to 500 rows in grid, and I want to know how many rows I have selected. I do it in such way:
multiSelect: true,
listeners:
{
'select':
function( combo, record)
{
mainNS.app.pagingTB.items.get('selected-sited').update(' count of selected rows: ' +
mainNS.app.mainGrid.getSelectionModel().getCount())
}
},
But it works too slow, how can I optimize this operation?

The select event will fire for every record during a multiple selection. So if n rows are being selected at once, that means you're updating the content and, most importantly, triggering a layout n times.
You have 2 options:
Listen to the selectionchange event, which will fire only once for a batch of selections.
Add buffer: 1 as an option to the select event, so it will buffer the event from firing until the last selection has occurred.
No. 1 is the preferred solution.

Related

jqGrid custom recordtext and using loadComplete to get records count

I am trying to change the recordtext of a display grid to a custom format. I am using a treeview as the selector that refreshes the display grid. I need to find the total records for the grid and I am able to get this value using the getGridParam records method when I click on the treeview node and load the display grid.
However, after I get this value and try to create the custom recordtext, the record count is the previous value, not the current records count. I know that the gridComplete happens before the loadComplete, but even placing the get in the gridComplete and the set int he loadComplete, it still doesn't work, even with a reloadGrid trigger. If I click on the treeview node twice, I get the correct value.
I am thinking it is a timing issue as to when the new value is ready to set the recordtext. Any help would be great, thanks in advance.
I recommend you to try updatepager method, which updates the information on the pager. Alternatively you can do for example the following:
loadComplete: function () {
var p = $(this).jqGrid("getGridParam");
p.records = 123;
p.recordtext = "My View {0} - {1} of <i>{2}<i>";
this.updatepager();
}
to see the viewrecords

Using JQgrid beforesearch and aftersearch for a loading dialog

I'm using jqgrid with a lot of data and, as the filter is taking too long, I'd like to show a dialog before the search and close it after the search.
The thing that's happening to me, is that when I run the filter in debug mode I see the methods that open and close the dialog get called before the search and after the search, but when I run the filter without interruptions I can't see the dialog, my filter waits 10 seconds or more to refresh the table but the dialog isn't shown.
is it a syncronous problem? or why isn't my dialog showing up?
Here's my code:
jQuery("#mytable").jqGrid('filterToolbar',{
searchOnEnter : false,
stringResult : true,
defaultSearch:'cn',
beforeSearch: openDialogLoading,
afterSearch: closeDialogLoading
}
);
function openDialogLoading(){
$( "#DialogLoading" ).dialog({
resizable: false,
autoOpen: false,
height: 110,
width: 50,
title: 'Loading...',
modal: true,
bgiframe: true
});
$( "#DialogLoading" ).dialog('open');
}
function closeDialogLoading(){
if ($( "#DialogLoading" ).dialog('isOpen')) {
$( "#DialogLoading" ).dialog('close');
}
}
Thanks
It's really important to know the details of the grid (options which you use). It's important to use local paging to have good performance with large number of rows. I created some demos for you which you can try and the the time of loading/sorting/filtering:
the demo1 uses 13 columns, 400 rows and the page size 20.
the demo2 uses 13 columns, 400 rows and the page size 400 (no local paging).
the demo3 uses 13 columns, 4000 rows and the page size 20.
the demo4 uses 13 columns, 40000 rows and the page size 20.
the demo5 uses 13 columns, 1000 rows and the page size 1000 (no local paging).
You can see that the performance of the grid depends very havy from the page size. You can play more with differnet values of columns, rows and the page size using the JSFiddle demo http://jsfiddle.net/OlegKi/1rmmyeLh/ where I used
rowNum: 20
UPDATED: The demo http://jsfiddle.net/1rmmyeLh/7/ which you posted later in the comment some important problems. Modifing the code so that it do displays the "Loading" gif with anymation is realtively easy, see http://jsfiddle.net/OlegKi/1rmmyeLh/8/.
I included the call of closeDialogLoading(); inside of loadComplete and modified beforeSearch so that it returns true instead of false, which prevent reloading of grid by jqGrid. Additionally I trigger reloadGrid inside of setTimeout manually:
.jqGrid("filterToolbar", {
beforeSearch: function () {
var $self = $(this);
openDialogLoading();
setTimeout(function () {
$self.jqGrid("setGridParam", { search: true })
.trigger("reloadGrid", [{ page: 1 }]);
}, 0);
startTime = new Date();
measureTime = true;
return true; // SKIP filtering
}
})
Such modification of the code solves the issue with displaying of the "Loading" div. On the other side I stay on my opinion, that the main problem which you have is in ingoring the usage of local paging of data (rowNum option).
I want to stress that it's better, in my opinion, to make the application quickly as to display some "Loading" massage and to hold the application slow. You use in the demo rowNum: 4000 with 4000 rows of data. On the other side I can see on my display about 35 rows of data only. If I just change rowNum from 4000 to 30 I see the peformance improvement in about 20 times!!! Now you should set clear your priorities. One can speak long about the difficulty for very stupid user to undesrtand the meaning of pager buttons, but in my opinion the difference in performance in 20 times makes any discussions unneeded. Practically every user have used already applications with pagers. So I strictly recommend you to use local data paging. You will be able to work in the style with much more large dataset (see the demo with 40000 rows and the page size 20, which responsibility is more as 3 times better in IE11 as the responsibility of the demo with 400 rows and no paging).

XPages: how to count paginated view panel rows

I have a view panel in xpages and a computed field to show the row-count. I have 2 problems:
1st: how can i count only the rows of the current page of the pager?it seems that viewPanel.getRowCount() gets all rows from the beginning until the current page, so if i have 30 entries per page and i am in page 2, it shows 60 instead of 30.
2nd: even if i achieve the above, the pager only refreshes the view and i can't refresh the computed field or another panel. Can i put the computed field inside the view panel or make it somehow to be refreshed in each page change? i would prefer not to do it with full page refresh if possible...
Given the computed field refresh issue, even if you managed to get a count of rows (eg on a page-scope SSJS variable), it woudln't update the computed field.
It might be easier to to count to rows in the HTML table using clientside javascript ?
something like ..
page onload event :
get the HTML table
get the table rows property (array of rows in the table)
number or rows = that value (1st row = TH (header) row if there is one = row 0)
use javsscript to plug that value into a known DIV
You could also hijack the partial refresh issued from the pager and check for the ID that has been refreshed. If the ID match your view panel's ID, you could do another partial update in order to update another panel.
Example code for hijacking the partial refresh:
var sysHijackPartialRefresh = function(){
XSP._inheritedPartialRefresh = XSP._partialRefresh;
XSP._partialRefresh = function( method, form, refreshId,options) {
if (options){
if (!options.onComplete) {
options.onStart = function(){
};
options.onComplete = function(){
if (refreshId == "<client id of view panel>") {
// issue another partial refresh
XSP.partialRefreshGet(<client id of the other panel>);
}
};
}
}
this._inheritedPartialRefresh(method, form, refreshId, options); }
}
XSP.addOnLoad(sysHijackPartialRefresh);
See http://xpageswiki.com/web/youatnotes/wiki-xpages.nsf/dx/Work_with_events_and_partial_or_full_refresh for more information about partial updates.
The pager should have a "refreshID" property in which you can put the client ID (!) of the panel you want to refresh. Use getClientId() to compute the client ID of the panel.
For the row count: use the XPages debug toolbar (from openNTF) to check for a property of the view panel or the pager which gives you the current page number. If you got that, you can simply compute by using viewPanel.getRowCount() - (page number * number of rows per page).

slickgrid select rows while filter is on forgets previous selections

I have a large list where I've implemented filtering. I'd like to user to be able to select some rows, filter the list, select a few more, change the filter, select more, and have all of the selections remain.
I am following this example:
http://mleibman.github.com/SlickGrid/examples/example4-model.html
Follow these steps to see my problem:
Click on the 0 row
Shift-click on the 10 row. Rows 0 through 10 are selected now.
Move the slider up to about 90%, so only a few of the rows 0 - 10 show. (For me, 2, 6, and 8 still show and are still selected.)
Ctrl-click on an un-selected row (for me, row 29)
Slide the filter back down to zero.
Now this issue is seen. For me, only rows 2, 6, 8, and 29 are selected. I would prefer that 0 through 10 and 29 remain selected. Is there an option to get this behavior? If not, can someone recommend an approach that might work?
This problem has been solved on Github.
First, add a variable to store id.
var selectedIds=[];
Second, modifiy syncGridSelection
DataView.syncGridSelection(grid, true, true, function(syncIds) { selectedIds = syncIds;});
The trick is to:
Save some indication for every selected row
As you build the filtered data, note which lines are selected in an array
Call "setSelectedRows" after "setGridData"
Here is code that does it.
// filter grid without harming selection
// grid: a SlickGrid Object
// filter: a function that receieves a "data row" and returns true if it meets the filter
function filterGrid(grid,filter) {
var oldline;
var olddata=grid.getData();
var oldselection=grid.getSelectedRows()
var newline=0;
var newdata=[];
var newselection=[];
for (oldline=0; oldline<olddata.length ; oldline++ ) {
if (filter(olddata[oldline]) {
newdata.push(olddata[oldline]);
if (oldselection.indexOf(oldline)>-1) { // note on condition: ECMA5 - in IE8 you will need to loop
newselection.push(newline);
newline++;
}
}
}
grid.setData(newdata);
grid.setSelectedRows(newselection);
grid.updateRowCount();
grid.render();
}
Note that this code DOES NOT preserve selected rows which do not pass the filter.

Hide expand/collapse symbol or deactivate spec. rows in jqGrid subgrid

I have a grid with a subgrid: Only the first row of the Main grid need to have a subgrid.
The solutions I found by Google and http://www.trirand.com/....i:subgrid&s[]=hidecol
doesn't work.
Is there a quick and dirty (hard coded) solution?
Hiding the 'subgrid' column with jQuery("#grid_id").hideCol('subgrid'); remove full column which can be used to expand or collapse the subgrid, so you can not use the way in your case.
I suggest you to clear contain of the 'subgrid' column and unbind the 'click' event for the cells inside of loadComplete event handle:
loadComplete: function() {
$("td.sgcollapsed:not(:first)","#list").unbind('click').html('');
}
you will have the following results:
(You can see the corresponding example live here). It's important to understand, that the loadComplete event will be called on any page, so on the second page you will have subrgid also only on the first row.
If you need to implement more complex logic in choosing of the rows which need have subgrids you can use following code
loadComplete: function() {
var grid = $("#list");
var subGridCells = $("td.sgcollapsed",grid[0]);
$.each(subGridCells,function(i,value){
if (i!==0) {
$(value).unbind('click').html('');
}
});
}
The code above do the same as the statement $("td.sgcollapsed:not(:first)","#list").unbind('click').html(''), but you can easy modify the last version of the code to implement more complex behavior.
UPDATED: If you need detractive subgrid only for some row identified by the rowid you can use
$("#"+rowid+" td.sgcollapsed",grid[0]).unbind('click').html('');
(see live here) inside of the loadComplete. If you need deactivate subgrid for all rows which id is not equal to rowid you can make something like following
$('td.sgcollapsed:not("#'+rowid+' td.sgcollapsed")',grid[0]).unbind('click').html('');
(see live here)
UPDATED: free jqGrid now have new feature described in the answer: hasSubgrid callback which can be specified in subGridOptions. It allows to inform jqGrid which rows should don't have subgrids.

Resources