PDA

View Full Version : Ext.ux.LiveGrid



Pages : [1] 2 3 4

ThorstenSuckow
10 Nov 2007, 11:26 AM
Edit 16.07.2014

Version 0.8.3 (GPL)
16-April-2014

Changelog:

V0.8.3
- enhancement: added method "wasLastRequestSuccessful()" which tells whether the most recent request was successful or not


Version 0.8.2 (GPL)
13-April-2014

Changelog:

V0.8.2
- enhancement: provided enhanced functionality to try to rebuffer a grid if
any buffer request fails; added fallbacks for grid view's properties in
case loading/buffer operation was not successfull, so functionality doesn't
break
- enhancement: made sure livegrid's store contents get removed before the load
operation is triggered
- fixed: fixed an issue where the grid view would try to render its body,
although no data is available
- fixed: fixed an issue where the scroll position of the grid would be applied
from the browser's internal cache, but it shouldn't
- fixed: fixed an issue where the starting parameter for an erroneous loaded
state of a grid would not be calculated properly
- enhancement: added "reloadFromState()" method as a convenient way to reload a
grid from a given state
- enhancement: updated copyright information; enhanced toolbar to give more
information about the state of load-/buffer-operations


Version 0.8.1 (GPL)
12-April-2014

Changelog:

V0.8.1
- fixed: fixed an issue where in rare cases "-1" would be sent to the attached data storage as the "start" parameter for the requested range


Version 0.8 (GPL)
14-November-2013

Changelog:

V0.8
- enhancement: livegrid is now staful, thus able to restore selections and scroll position upon load


Version 0.7.1 (GPL)
09-December-2012

Changelog:

V0.7.1
- fixed: fixed an issue where references to selected records would get lost after reloading or sorting the store


Version 0.7 (GPL)
07-December-2012

Changelog:

V0.7
- fixed: fixed an issue where inserting data would not work properly if the sorting is in ascending order and the very last record of the whole dataset represented is viewed
- enhancement: added support for store's "paramNames" configuration options
- enhancement: added event "insertindexfound" to store to notify interested components of the insert index of a record the store will use. Attached listener can change this value before the store uses it for updating it's internal data set


Version 0.6.1 (GPL)
28-October-2012

Changelog:

V0.6.1
- fixed: (Store.js) fixed an issue where sortData() would not
be working with ExtJS 3.4


Version 0.6 (GPL)
27-October-2012

Changelog:

V0.6
- enhancement: (GridView.js) brought full 3.4 support by fixing an issue where drag zones would not be properly instantiated. Removed renderUi() override. Added optional argument to reset() in case reset reloads the data, sicne changes with 3.4 in store's load() method would not carry references for options.params around. It is recommended to not rely on setting the params in the beforeload listener as thiese params would not persist.


Version 0.5.1RC1, 0.4.2RC1 (GPL)
09-February-2011

Changelog:

V0.5.1RC1, V0.4.2RC1
- fixed: (GridView.js) fixed an issue where selections not currently in the buffer would get accidently removed once the grid gets reset
- enhancement: added CheckboxSelectionModel.js to be able to use a checkboxselection with Ext.ux.Livegrid


Version 0.5 (GPL)
06-February-2011

Changelog:

V0.5
- enhancement: (GridView.js) added compatibility for use with Ext 3.3

Changelog:

V0.4.1
- fixed: (Store.js) fixed an issue where the "selectionsProxy" would call a
method that was marked deprecated since Ext 3.0
- enhancement: (GridView.js) splitted "liveScrolleInset" into 3 divs which
fixes issues when a large number of data should be shown in the grid; this
prevents incapabilities of browsers which define max heights for HTML Elements

Edit 11.07.2009

Version 0.3.1 (GPL)
11-July-2009

Changelog:

V0.3.1
11-July 2009
- fixed: (GridView.js) load mask would steal focus from scrollbar in some broswers
- fixed: (GridView.js) (suspendLoadEvent) would not be properly reset after buffering,
which would not remove the loadMask
- enhancement: removed "loadMaskConfig" property and instead delegated loadmask
configuration to loadMask cfg property; simplified "showLoadMask" method
- enhancement: allowed for re-rendering the rows if the store is pre-buffering
- enhancement: "load" event from the store would still fire even if the store
would only buffer; added "suspendLoadEvent" to the list of options so the store does suspend
its events once a buffer finished (see http://www.extjs.com/forum/showthread.php?p=324046#post324046)




Version 0.3RC2 (GPL)
07-December-2008

Edit 07.12.2008

Version 0.3RC2 (GPL)
07-December-2008

Changelog:

- fixed: (GridView.js) "renderUI()" would not set "this.dragZone" properly if
drag & drop is enabled for the GridView's grid
- fixed: (make.bat, make.sh) naming issues for debug-build resolved; enhanced
check if argument was submitted

Edit 23.11.2008

Version 0.3RC1 (GPL)
23-November-2008

Changelog:

- enhancement: added build tools for creating minified deployable versions of
Ext.ux.Livegrid-scripts
- enhancement: (GridView.js) the rowIndex argument of the column's renderer will
now pass the value of the index of the row as available in the view, i.e. as defined
in the row's rowIndex property, which adds support for Ext.grid.RowNumberer
- fixed: (GridView.js) fixed a bug where "getPredictedBufferIndex()" would not
compute the next rowIndex for a request properly, leading to an endless loop
- enhancement: (GridView.js, RowSelectionModel.js) removed override of "onRefresh()"
to keep selections after a refresh or sort occured, if, and only if those records are
returned by the response; removed custom call to selection model's "clearSelections()"
in the GridView's "reset()" method
- enhancement: intercepted "autoLoad" property of Ext.ux.grid.livegrid.Store to make
sure the store gets only loaded if the view has been rendered, if the store's autoLoad
property was set to "true"


Edit 01.11.2008

Version 0.3a4 (GPL)
01-November-2008

Changelog:

- fixed: (EditorGridPanel.js) call to "startEditing()" would throw error if the
requested index in the view is not currently representing a record; overrode
method for checking if record to edit is available
- enhancement: (GridView.js) adjusted behavior of "ensureVisible()" to scroll a
requested cell horizontally into view


Version 0.3a3 (GPL)
01-November-2008

Changelog:

- fixed: (Toolbar.js) when passing the grid as config parameter, the immediate
call to "bind" would throw an error since the views's "ds" property is not available
yet


Version 0.3a2 (GPL)
01-November-2008

Changelog:

- enhancement: (Toolbar.js) config object allows now to specify either the grid
or the view the toolbar is bound to
- fixed: (Store.js) "getAt()" would return "-1" if the data at the passed index
could not be found in some cases; changed to return type "undefined"
- fixed: (GridView.js) overrode method "getCell()" to return "null" if the row
for the specified index could not be found
- fixed: firing of event "cursormove" would happen before "replaceLiveRows()"
has taken care of re-assigning the rowIndex to the rows in the view which could
lead to errors; adjusted method and made sure that "replaceLiveRows()" is called
first
- enhancement: (EditorGridPanel.js, GridPanel.js) added basic support for using
cell editors for the Livegrid (EditorGridPanel-support)
- enhancement: (ext-ux-livegrid.css, DragZone.js) minor code cleanups, changed
css class "x-dd-drop-waiting" to "ext-ux-livegrid-drop-waiting"
- enhancement: (GridView.js) added method "getRow()", removed overriden method
"onCellSelect()", "onCellDeselect()", "onRowOver()", "onRowOut()" and changed
arguments for call of methods that operate on Html-elements in the view to pass
the model index as specified in the elements "rowIndex"-property, which will get
translated internally to the html-element's index in the view, for broadening
compatibility to other plugins/exension, such as the EditorGridPanel
- enhancement: (GridView.js) changed behavior of "processRows()" to paint the selections
if the third argument does not equal to "false"
- enhancement: (RowSelectionModel.js) added method "deselectRecord()" to deselect a record
that is already selected in the model
- enhancement: (GridView.js) added method "isRecordRendered()" to check whether the passed
record is currently within the visible rect of the grid's view
- enhancement: removed programmatically invoking scroll in IE when the grid is rendered,
since this was fixed due to the css changes in a previously version
- fixed: (RowSelectionModel.js) method "isSelected()" would lose it's original argument
while processing it, which could lead to erroneous behavior

Edit 29.09.2008:

Changelog:

- fixed: (GridView.js) missing call to "isBuffering = true" in "updateLiveRows()"
made the component to ignore a previously set queue and request new data immediately

Version 0.3a1 (GPL)
29-September-2008

- enhancement: added Ext 2.2 compatibility, refactored code, changed ui to match
Ext style
- License changed from LGPL to GPL
- enhancement: changed namespace to "Ext.ux.grid.livegrid":


+---------------------------------------+----------------------------------------+
| old name | new name |
+---------------------------------------+----------------------------------------+
| Ext.ux.grid.BufferedGridView | Ext.ux.grid.livegrid.GridView |
|--------------------------------------------------------------------------------|
| Ext.ux.BufferedGridToolbar | Ext.ux.grid.livegrid.Toolbar |
|--------------------------------------------------------------------------------|
| Ext.ux.grid.BufferedGridDragZone | Ext.ux.grid.livegrid.DragZone |
|--------------------------------------------------------------------------------|
| Ext.ux.data.BufferedJsonReader | Ext.ux.grid.livegrid.JsonReader |
|--------------------------------------------------------------------------------|
| Ext.ux.grid.BufferedRowSelectionModel | Ext.ux.grid.livegrid.RowSelectionModel |
|--------------------------------------------------------------------------------|
| Ext.ux.grid.BufferedStore | Ext.ux.grid.livegrid.Store |
+---------------------------------------+----------------------------------------+
+---------------------------------------+----------------------------------------+

- fixed: rows would not be striped properly when grid panel's "stripeRows" property
is set to true
- fixed: rendering bug of the vertical scrollbar in IE7 did not trigger the scroll
event to small; set min height to two times of horizontalScrollOffset property
- fixed: vertical scrollbar would disappear in FF3 if the size of the viewport gets
to small; set min height to two times of horizontalScrollOffset property
- fixed: view would not always calculate the grid's size leading to errors when it
should decide whether the horizontal scrollbar is shown
- enhancement: added "bulkRemove()" method and "bulkremove" event to store, added
"bulkremove"-listener to BufferedGridView
- fixed: (RowSelectionModel.js) added a property for mapping already
selected records to their view index, so that the position of records, which are
no longer in the store, can still be referenced. Added support for removing and
shifting selections if a record was removed that is not part of the store, but
still could be referenced using the map
- fixed: (Store.js) when removing records which are not buffered by the
store, and which are behind the range of the currently buffered record set, the
"remove" method now adjusts the values of the "bufferRange"-property minus the
number of records removed, to reflect the changes in the underlying data model
- fixed: (GridView.js) when removing rows which are not part of the data
model, the "rowIndex" and "lastRowIndex" properties are now both updated, and the
remaining rows in the view processed by "processRows()"
- fixed: (GridView.js) "forceRepaint" argument for the "updateLiveRows"
method is now passed using the "options"-object of the Ajax.request, which will
then be passed to the "replaceLiveRows()".method called by the "liveBufferUpdate()".
- fixed: (GridView.js) last revision had a typo left that caused the rows
not to be updated when the "insertRows()" method would be called with the
"isUpdate"-argument set to true
- enhancement: (GridView.js) changed "onRemove()" method to not support
"isUpdate" argument, since the current implementation of GridView would
never call "onRemove" for simply updating a row in the view
- fixed: bufferRange will now get reset if all records in the store are removed


Edit 11.09.2008:

Version 0.2
11-September-2008


Edit 02.09.2008:
Changelog:

Version 0.2rc5
31-August-2008


fixed: (BufferedGridView.js) typo left in "insertRows()" would prevent the
view to reassign the proper rowIndex when argument "isUpdate" was set to true
fixed: (BufferedGridView.js) wrong parameter passed to "buffer" and
"beforebuffer" event caused listeners to assume wrong number of visible rows



Edit 30.08.2008:
Changelog:

Version 0.2rc4
30-August-2008


fixed: (BufferedStore.js) store would not allow for adding records without throwing errors when the store was initialized with no records; changed bufferRange to be initialized with [0,0] instead of [0, bufferSize] and incremented bufferRange-count according to the records coming in, until bufferRange[1] equals to bufferSize
fixed: (BufferedGridView.js, BufferedRowSelectionModel.js) store "add" event would neccessarily trigger the selectionmodel's onAdd-listener before the onAdd-listener of the GridView, resulting in false rendering of selected records; changed the selection model to listen to the "rowsinserted" event of the view and extended this event to pass the length of added record as the fourth parameter to all it's listeners
fixed: (BufferedGridView.js) collapsed panel would hide added records of the grid when the grid is expanded again and would lose scroll-position; added listener for "expand"-event of the view's gridpanel to recalculate visible rows, the buffer inset and reset the scrollbar's position to the proper value
enhancement: (BufferedGridView.js) improved calculation of rows that would cause spill when new records get added in "insertRows()"
fixed: (BufferedGridView.js) when adding new rows, selected rows which change their position in the view would lose their css-style for indicating that they are selected and pass it to unselected rows; updated "processRows()" to remove css-styles on rows which are currently not selected
fixed: (BufferedGridView.js) "onAdd()" would not always insert records depending on the position they got added in the store; updated and improved code based on "rows get added before first visible row", "rows get added after the last visible row", "rows get added somewhere in between the first and last visible row"





Edit 30.08.2008:
Changelog:

Version 0.2rc3
30-August-2008


BufferedGridView: fixed - last row would not always be rendered proper if the end of records is reached and the panel would be resized so that more records are displayable; improved calculating the height of the buffer inset in both performance and functionality; component now working with Safari 3.1 under windows XP




Edit 29.08.2008:
Changelog:

Version 0.2rc2
29-August-2008


BufferedGridView.js: re-rendering rows would not work proper if a resize of the panel during buffering happened; "adjustVisibleRows()" skips recalculating the "rowIndex" property now if the livegrid is currently buffering. "replaceLiveRows()" would not always calculate the exact range of rows to render; adjusted conditions to check for valid ranges



Edit 29.08.2008:
Changelog:

Version 0.2rc1
29-August-2008



BufferedRowSelectionModel: "selectRow()" would allow selecting indexes greater than
the "totalLength"-property of the store; added condition to check whether the index is
out of bounds (closes google issue 5)

BufferedGridView.js: fixed a bug that would not recalculate the scrollbar's
height if the number of possible rows to display in the view would exceed the
total number of records in the store

BufferedStore.js: buffer range would not store the number of the total length
of the records when last possible range is reached, but instead the number of the
start-parameter with the "limit"-parameter, which lead to errors when a last
possible record to render is requested that cannot be found in the store

BufferedGridView.js: last row in the grid is now clipped instead of removed if
it is not fully displayable




Edit 25.08.2008:
Changelog:


Version 0.1.2
25-August-2008

BufferedGridView: wrong calculation of "start"-parameter for the buffer-request
caused infinite loop. Adjusted calculation of return value in "getPredictedBufferIndex()"
to always return correct value for "start"-parameter if the "nearLimit" property is greater
than or equals to half of store's "bufferSize" property (fixes google issue 4)

Version 0.1.1
25-August-2008

BufferedGridView: grid would not be repainted correctly if a column was moved:
method "onColumnMove()" with appropriate implementation added (fixes google issue 9);
"onRemove()" would not work properly if the end of the data was reached in the visible
rect and rows from within that rect are removed. Adjusted "lastRowIndex" to be equal to
"rowIndex", and skipped implicit "processRows()" call in "replaceLiveRows()" via passing
a new third argument "processRows", which will only call "processRows()" if the argument
was not set to false; removed call to "selections.add()" in "processRows()" since selections
are already in the "bufferedSelections" property of the selection model, and previously
selected records are still part of the "selections"-property of the selection model.

BufferedGridView: Added functionality for listening to erroneous responses from
buffer-requests. Event "bufferfailure" will now be fired if the store indicated that
the proxy's response was erroneous; added "options" parameter to be passed to
"buffer"-event

BufferedGridToolbar: Toolbar is now listening to "bufferfailure"-event and resets
the reload-button to "enabled" if necessary.




Edit 30.05.2008:
Changelog:


fixed: wrong calculation in BufferedGridView.onLiveScroll (based on lastScrollPosition and actual scrollPosition) caused the view sometimes to not re-render some rows
fixed: provided bug fix for "ensureVisible: returned x-coordinate does not take the x-position of the gridpanel into account" (see http://extjs.com/forum/showthread.php?p=175331#post175331)
enhancement: added cfg option "scrollDelay" in BufferedGridView for buffering calls to onLiveScroll when scroll-event gets fired (thanks to Rich Waters)


Edit 28.05.2008:
Ext.ux.LiveGrid is now hosted at google-code: http://code.google.com/p/ext-ux-livegrid/

Changelog:

fixed: wrong calculation of last displayable row after removing a row caused selection-model to get out of synch with the store's data
enhancement: BufferedStore: removed custom applySort() implementation due to changes in findInsertIndex
enhancement: BufferedStore: changed findInsertIndex to use parent implementation first, then check return value and adjust the index if needed
enhancement: BufferedStore/BufferedGridView: moved bufferRange-member to BufferedStore
enhancement: BufferedStore: optimized insert() method in BufferedStore
fixed: when adding a record to the store on the fly, the ensureVisible-method would not work always corect afterwards
fixed: when adding records, a previously made selection would block selecting the newly added record
enhancement: allowed to add records at position "0" in grid (existing records get shifted down)
fixed: skipped request for updateLiveRows in Ext.ux.grid.BufferedGridView.adjustVisibleRows when number of total records in store is less than the number of visible rows
fixed: request for buffering data in Ext.ux.grid.BufferedGridView.updateLiveRows() did not apply the property "lastOptions.params" to the params sent with the buffer-request


Edit 18.03.2008:
Changelog:

works with 2.0.2 now

Edit 03.12.2007:
Changelog:

works with 2.0 stable now

Edit 01.12.2007:
Changelog:

updated project homepage
changed version to 0.5 BETA
Updated documentation of Ext.ux.grid.BufferedGridStore and Ext.ux.BufferedGridToolbar
Fixed a bug in Ext.ux.grid.BufferedRowSelectionModel to allow shifting selections when Ext.ux.grid.BufferedGridStore fires the add-event with an index equal to Number.MIN_VALUE
Fixed lagging repaint of scrollbar inset
Fixed missing scrollbars in Opera 9.24 and IE 6.0 (thanks to andrei, xpressive, Jacob)


Updated project homepage
Edit 28.11.2007: Added zip file containing demo database
Edit 27.11.2007: Added source from data_proxy.php

Project home: http://www.ext-livegrid.com


Please feel free to leave your comments, suggestions and bug reports in this thread.

Regards
Thorsten

jheid
10 Nov 2007, 11:46 AM
Great news! In fact this is one of the missing things in Ext I like in Dojo.
As far as I could see the demo works in IE 7, great work!

cpantel
10 Nov 2007, 12:26 PM
Very nice work! This gives a much better user experience than paging. I hope to see this become an official part of Ext.

wm003
10 Nov 2007, 12:39 PM
WOW! Thats very good work! Works like a charm (if you call it 0.1, what else are you going to implement to get this to 1.0 finally, since it already looks quite finished ?)

Thank you very much for sharing! :)

mdissel
10 Nov 2007, 1:22 PM
Thanks for sharing!!

Troy Wolf
10 Nov 2007, 1:37 PM
Initial impresson = WOW!

I especially like how the rows indicator at the bottom right updates smoothly as you drag the scrollbar.

ThorstenSuckow
10 Nov 2007, 2:02 PM
Initial impresson = WOW!

I especially like how the rows indicator at the bottom right updates smoothly as you drag the scrollbar.

Thanks Troy. The toolbar is listening to the cursormove event of the BufferedGridView and updates the info-text accordingly. The Ext.PagingToolbar inspired me here ;)


(if you call it 0.1, what else are you going to implement to get this to 1.0 finally, since it already looks quite finished ?)

Oh, there's still room for improvement. I'll adjust the predictive fetch algorithm and haven't spend too much time on testing adding and removing rows... But I might jump from 0.1 to 0.9, then ;)

DragonFist
10 Nov 2007, 3:46 PM
Looks real good. I know exactly where I can use it. ;)

KimH
11 Nov 2007, 3:37 AM
Looks great!

However....
- Doesn't work in IE6 (the column headers aren't visible, and no data).
- In Firefox it seems that the call to data-proxy.php returns JSON data or error (see below).

Suggestions:
- Could you make sure that data-proxy.php only returns the first 13 rows of data (or the number of rows that is visible in the grid)?
- If I only scroll one row down it should return the next 13 rows of data (as I'm probably going to advance one row more.... and more....).
- It looks like it is retrieving data even though it should have it cached? If I go from the top to the bottom and back then I get the reloading mask. Could you configure it to keep data in the browser OR reload every time?

Questions:
Which license is this released under? The same as ExtJS?

Animal
11 Nov 2007, 7:08 AM
Very impressive. I like the way it calculates the number of rows fully visible, and asjusts the View height so that it shows an exact number of rows.

galdaka
11 Nov 2007, 7:24 AM
Not work in IE6!!

Thanks for your time!!

ThorstenSuckow
11 Nov 2007, 8:28 AM
Thanks @all for your feedback so far...



However....
- Doesn't work in IE6 (the column headers aren't visible, and no data).
- In Firefox it seems that the call to data-proxy.php returns JSON data or error (see below).


I haven't tested this on IE6. Is the grid component even supposed to work with IE6? Can you send me a screenshot or an error description of the Firefox problem?




Suggestions:
- Could you make sure that data-proxy.php only returns the first 13 rows of data (or the number of rows that is visible in the grid)?


Well, you can adjust the buffer size to only return this specific number of records. However, this means that the store will request new data every time the user scrolls one row up/down AND you have to make sure that your grid never shows more than 13 rows at once, which will totally fail it is resizable (sitting in a resizable Ext.Window, for example). Why would you want this behavior? Is there any use case?



- If I only scroll one row down it should return the next 13 rows of data (as I'm probably going to advance one row more.... and more....).


As of now, the store holds a specific range of data. If you scroll down to a row that's not within this range, a new request for fresh data is being sent.



- It looks like it is retrieving data even though it should have it cached? If I go from the top to the bottom and back then I get the reloading mask. Could you configure it to keep data in the browser OR reload every time?


You get the reloading mask because when you were scrolling down the component tried to load the data that is associated with the current row index. When scrolling up, the store most likely has the data for the very bottom of the component; but since the row index changed, new data has to be requested. Additionally, the view does indeed pre-buffer data to improve scrolling behavior.
There is no way to predict the scroll behavior of a user. Thus, a reload of data is neccessary everytime the row index changes AND the if this row index is not within the range of currently buffered records.
Sure, you could fill up the store with all the records a user once has scrolled through. But then again, when having a large amount of data, browser performance will decrease dramatically.



Questions:
Which license is this released under? The same as ExtJS?


It's the same as ExtJS: LGPL.

wm003
11 Nov 2007, 9:37 AM
There is no way to predict the scroll behavior of a user. Thus, a reload of data is neccessary everytime the row index changes AND the if this row index is not within the range of currently buffered records.
Sure, you could fill up the store with all the records a user once has scrolled through. But then again, when having a large amount of data, browser performance will decrease dramatically.


Well, you dont really need to rebuild all data, you have already in your store loaded. What about just rendering the visible area as usual, but if reloading needs to be neccessary your code could look up into the store, if the desired data has already been loaded before. This way, you will still do a "loading"-part, but not over XHR, but by "loading" from the already present javascript store. I guess this would increase the data access and thus the rendering of the new lines very much, because you dont need to wait for some XHR response and i also guess this won't make it neccessary to display this "loading" layer and makes the overall usage much more smoother and comfortable.

ThorstenSuckow
11 Nov 2007, 9:59 AM
Really? Well, you dont really need to rebuild all data, you have already in your store loaded. What about just rendering the visible area as usual but if reloading needs to be neccessary your code could look up into the store, if the desired data has already been loaded before. This way, you will still do a "loading"-part, but not over XHR, but by "loading" from the already present javascript store. I guess this would increase the data access and thus the rendering of the new lines very much, because you dont need to wait for some XHR response and i also guess this won't make it neccessary to display this "loading" layer and makes the overall usage much more smoother and comfortable.

The problem here is browser performance. If the user scrolls through the grid and the store gets accumulated with all the loaded records (of a 10.000 records store, for example), the browser will request large chunks of memory. Additionally, looking up records in the store will become real slow.
I see your point in letting the user decide how many records he want to have in the store. However, you can still adjust the bufferSize property to the number of records your underlying data model contains. This will load up all records in the beginning, but shouldn't send out any request for new data while scrolling.

krycek
11 Nov 2007, 10:44 AM
MindPatterns, very good extension, congratulations. But what if I want to keep the paging and also want to use your livegrid?

Ex.: showing records from 20 to 30 means on a paging way that users would be in the second page, right? So users could navigate between the records entering a page number to go to or scrolling down/up the table. So when the user entered page 5 the grid would scroll down and show records 50-60.

Could it be done?

ThorstenSuckow
11 Nov 2007, 10:57 AM
MindPatterns, very good extension, congratulations. But what if I want to keep the paging and also want to use your livegrid?

Ex.: showing records from 20 to 30 means on a paging way that users would be in the second page, right? So users could navigate between the records entering a page number to go to or scrolling down/up the table. So when the user entered page 5 the grid would scroll down and show records 50-60.

Could it be done?

Sure, although calculating the row index associated with the page you want to go to is totally up to you, everything you need is to call the method ensureVisible(rowIndex, colIndex, horScroll) from the BufferedGridView component.
This method will handle changing the scroll position and reloading data, if needed.

wm003
11 Nov 2007, 11:58 AM
The problem here is browser performance. If the user scrolls through the grid and the store gets accumulated with all the loaded records (of a 10.000 records store, for example), the browser will request large chunks of memory. Additionally, looking up records in the store will become real slow.

Maybe you take a look at http://www.treegrid.com/TreeGrid5_0/Html/Example1M.html

Here he manages to display about 1000000 records with only loading data, if it hasnt been loaded earlier. When you scroll down a few pages and then up again ( to the records that were shown earlier) the script is _not_ reloading but immediatly displaying the earlier loaded data. So it seems, there must be some possibility to solve this problem.

Maybe if you hold 2 separate stores. One small for the visible grid which only holds the displayed data and one which holds every loaded data and grows by every XHR request for lookup of already available data? Just a fast suggestion. So the original Ext-Grid routine always has just a few "visible" data, but the local script datastore grows to have the data faster than over xhr.

ThorstenSuckow
11 Nov 2007, 12:22 PM
When you scroll down a few pages and then up again ( to the records that were shown earlier) the script is _not_ reloading but immediatly displaying the earlier loaded data. So it seems, there must be some possibility to solve this problem.


Do not get me wrong, it's totally possible to add the loaded records to the store while they were buffered, so the don't have to be reloaded.
The only problem is the waste of memory - in the given example the memory usage for IE7 raised from 40 MB up to 130 MB.

The default behavior of my component will not support adding those records to the store while buffered, since I have no clue about the memory size of my clients' computers, and I do not want my component to cause a "page file limit reached" message ;)

As for now, simply adjust the bufferSize to the total length of data available in your db table.
I might add a configuration option which keeps once-loaded records in the store. However, this depends on the overall need of this feature and the simplicity of implementing it.

wm003
11 Nov 2007, 12:32 PM
in the given example the memory usage for IE7 raised from 40 MB up to 130 MB.

I do not want my component to cause a "page file limit reached" message ;)


Agreed;)

Maybe some of the Ext Core Developers know some performance trick to prevent memoryincreasing? (independant of the gridview, maybe they had some similar problems while developing other parts of ext) If i understood correctly, its not performance (javascript gets slower), but uncontrollable memory-wasting (i dont see a reason, why IE would increase 90 MB, if the raw data, that should be buffered, will most likely never reach such an amount. So it seems to be a (IE specific?) Problem regardless of the used ext-widget?

Hopefully they had similar problems solved earlier and can help out here..(?)

btw. i'll test your widget on IE6 tomorrow.

keep up the good work,mindpatterns, you are on the right way, i think!;)

ThorstenSuckow
11 Nov 2007, 12:39 PM
Maybe some of the Ext Core Developers know some performance trick to prevent memoryincreasing? (independant of the gridview, maybe they had some similar problems while developing other parts of ext) If i understood correctly, its not performance (javascript gets slower), but uncontrollable memory-wasting (i dont see a reason, why IE would increase 90 MB, if the raw data, that should be buffered, will most likely never reach such an amount. So it seems to be a (IE specific?) Problem regardless of the used ext-widget?


The memory usage is caused by the records (Ext.data.Record) that get pushed into the store. Think about having a record that has 10 different fields, and each field holds a minimum of 50 bytes of data. For each row, that makes 500 bytes, 2 rows would make something around 1kB. Multiply that by the number of records you want to keep in the store at once. I do not know how IE and all the other browsers handle intern storage of data in arrays, but from my experience I'd say that for storing 1 kB of data, the browsers reserve much more memory. The more data to be held in the heap, the more memory your browser will request.



btw. i'll test your widget on IE6 tomorrow.

keep up the good work,mindpatterns, you are on the right way, i think!;)

Thanks, I hope my work is usefull for you guys out there. :)

jheid
11 Nov 2007, 3:21 PM
Some things:

1. Is it possible to use the XML reader instead of the JSON reader?
2. Does it work with an alternative proxy (it couldn't see any limit parameter in my test case)?
3. Does it support the CheckboxSelectionModel?

J

wm003
11 Nov 2007, 11:04 PM
I haven't tested this on IE6. Is the grid component even supposed to work with IE6? Can you send me a screenshot or an error description of the Firefox problem?

As promised, here are the screenshots from IE6. (attached)

When the screen starts the columns are displayed at the bottom, so i cannot really say, if the rows are still rendered (i guess, they are). When you scroll down nothing of the grid-content is displayed anymore, although it stucks sometimes, so it seems the loading-progress (and thus your whole script) is still working.

No Javascript Errors though.

My first guess: Could you please try to delete the doctype, if the page loads in IE6? In many cases ExtJs isnt displaying properly in IE6 (just search the forum), because IE6 cannot handle the doctype correctly. Removing _any_ doctype at all fixed the displaying bug in most cases. (recommended from jack also!)

Tell me, when you removed it and i will do testing again.

andrei.neculau
12 Nov 2007, 1:37 AM
@Thorsten (MindPatterns) - First of all - great job, mate! Nicely coded!

The problem with IE6 and not being able to show the grid properly is related to the crappy box-model. But that we all knew, right? The thing is that the header and the scroller(data) are wider than the parentNode's "available width" (that is the width of the parentNode minus the scrollBar).

The x-grid3-viewport element has overflow hidden, but it gets the width of the parentNode, and thus not excluding the rightside scrollBar.

What you need to do is to put float:left to the x-grid3-viewport.

I know that this fixes the issue, and doesn't break anything on IE6, FF2, nor IE7.

// Handshake

wm003
12 Nov 2007, 1:56 AM
What you need to do is to put float:left to the x-grid3-viewport.
I know that this fixes the issue, and doesn't break anything on IE6, FF2, nor IE7.


So, should this be done in the deploying ext-all.css ? If so, you should give this hint to the core developers to include it into the final 2.0 release.

andrei.neculau
12 Nov 2007, 2:23 AM
@wm003 - before wasting Forum space, I would suggest to think/test yourself. If you test one of the grid examples - say http://extjs.com/deploy/dev/examples/grid/array-grid.html - you will see that the grid renders perfectly in IE6.

What happens here is that Thorsten took away the scrolling from the former scroller (data), and put it outside it, on the viewport. So, NO, this is not something that the whole ExtJS package needs to include. It is just specific to this situation.

ThorstenSuckow
12 Nov 2007, 2:55 AM
What happens here is that Thorsten took away the scrolling from the former scroller (data), and put it outside it, on the viewport. So, NO, this is not something that the whole ExtJS package needs to include. It is just specific to this situation.

Thx Andrei, I'll follow your advise when I have access to the source code later this afternoon.


OT: I think your reaction to wm003's question was a little bit harsh ;)


[QUOTE=jheid;85183]Some things:

1. Is it possible to use the XML reader instead of the JSON reader?
2. Does it work with an alternative proxy (it couldn't see any limit parameter in my test case)?
3. Does it support the CheckboxSelectionModel?

J

rodiniz
12 Nov 2007, 3:15 AM
Very impressive work...As for the problem with IE6 try removing or changing the doctype from your page.

andrei.neculau
12 Nov 2007, 4:08 AM
@rodiniz - Removing or setting doctype to loose/transitional doesn't solve it anything

@thorsten - I was very much aware of that when writing it, but I thought the purpose beats the means.

wm003
12 Nov 2007, 6:52 AM
@wm003 - before wasting Forum space, I would suggest to think/test yourself. If you test one of the grid examples - say http://extjs.com/deploy/dev/examples/grid/array-grid.html - you will see that the grid renders perfectly in IE6.


You are right, basically. Of course, the delivered examples work on IE6. ..if they will not be touched in any way. I had the experience that IE6 did not react as it did in the examples, when i tried the complex layout in a very basic form (see my thread about this here (http://extjs.com/forum/showthread.php?t=15855&)), and after hours of tryouts it was finally solved by removing the doctype. The nearly same routine in the examples worked perfectly on IE6. So it was just a suggestion. And i'm glad you found a CSS setting to get it working:). So MindPatterns just needs to include a css-file with his distribution or override the global setting over JS and the problem is gone.

I hope, i haven't wasted too much forumspace again...;)

andrei.neculau
12 Nov 2007, 7:28 AM
So MindPatterns just needs to include a css-file with his distribution or override the global setting over JS and the problem is gone.

No, not really. MindPatterns needs to deliver this fix in his GridView template, same place where he cancels the formal scroller, and adds the outer scroller. I don't know how good this is, but I suggest adding a class like .x-grid3-live or something to the main .x-grid3

A simple

.x-grid3-viewport{float:left}
would change the CSS all over the place, and you never know what that might break.

You need to find your best shot at this, Thorsten - any hint from Ext Core Developers!?

wanclark
12 Nov 2007, 7:33 AM
very nice! thank you for your share

jheid
12 Nov 2007, 9:19 AM
Hi.

I have a strange problem, see http://www.kreisalarm.de/ext/2/2.html (Firefox 2.0.9)

I used a proxy (HttpProxy) and the XML reader, the BufferedStore (bufferSize: 30) and the BufferedGridView (nearLimit: 10).

As you can see it seems to work when scrolling one amount. But when jumping the same page (same offset and limit) is requested over and over again.

Any idea?

J

ThorstenSuckow
12 Nov 2007, 11:28 AM
[QUOTE=jheid;85515]Hi.

I have a strange problem, see http://www.kreisalarm.de/ext/2/2.html (Firefox 2.0.9)

I used a proxy (HttpProxy) and the XML reader, the BufferedStore (bufferSize: 30) and the BufferedGridView (nearLimit: 10).

As you can see it seems to work when scrolling one amount. But when jumping the same page (same offset and limit) is requested over and over again.

Any idea?

J

jheid
12 Nov 2007, 1:06 PM
Okay, a simpler example with the same problem:



var Netz = Ext.data.Record.create([
{name: 'name', mapping: 'name'}
]);
var myReader = new Ext.data.XmlReader ({
totalRecords: '//objects/@count',
record: '//objects/netz',
}, Netz);
var ds = new Ext.ux.grid.BufferedStore/*Ext.data.Store*/ ({
bufferSize: 30,
proxy: new Ext.data.HttpProxy ({url: '/pflege/get-data-Netz.xml' }),
reader: myReader
});
var cm = new Ext.grid.ColumnModel([
{header: "Name", width: 60, sortable: true}
]);
var bufferedView = new Ext.ux.grid.BufferedGridView ({
nearLimit: 10,
loadMask: {
msg: 'Daten werden nachgeladen...'
}
});
var bufferedGridToolbar = new Ext.ux.BufferedGridToolbar ({
view : bufferedView,
displayInfo : true
});
var bufferedSelectionModel = new Ext.ux.grid.BufferedRowSelectionModel();
var grid = new Ext.grid.EditorGridPanel ({
renderTo: 'editor-grid',
cm: cm,
store: ds,
sm: bufferedSelectionModel,
autoWidth: true,
height: 400,
loadMask: true,
bbar: bufferedGridToolbar,
view: bufferedView
});
ds.load ();

mjlecomte
12 Nov 2007, 4:00 PM
First, very nice work.

I'm a newbie so please forgive me if these are obvious:

When I view it in FF2 there is no scrollbar to the right, is that on purpose or might that be forthcoming feature (I think from an earlier post this is intentional, but I wasn't sure why)? I was thinking maybe something like while you click on the scrollbar and drag up and down it shows the range it would return. (I mention this also because you have 0.1 alpha so maybe are keen to some suggestions)

Similar to the above, might be nice to be able to type in say bottom toolbar field what entry you want to go to and then have it zing you to that range (you might enter row 1354 which may not exist, so it should just get plus/minus the requested row?).

andrei.neculau
12 Nov 2007, 11:58 PM
@mjlecomte - Your request should probably be treated as a plugin to this component.

violinista
13 Nov 2007, 12:01 AM
Thank you, impressive work!

ThorstenSuckow
13 Nov 2007, 1:21 AM
@J

jheid
13 Nov 2007, 1:26 AM
The XML file is quite simple regarding my XML reader. Here's an example:



<?xml version="1.0"?>
<data>
<objects count="50">
<netz><name>1</name></netz>
<netz><name>2</name></netz>
...
<netz><name>50</name></netz>
</data>

ThorstenSuckow
13 Nov 2007, 1:29 AM
The XML file is quite simple regarding my XML reader. Here's an example:



<?xml version="1.0"?>
<data>
<objects count="50">
<netz><name>1</name></netz>
<netz><name>2</name></netz>
...
<netz><name>50</name></netz>
</data>


Thx, I'll have a look at it. The extension was not coded having reading from a flat file in mind (as performance will decrease the larger the file is), but from a conceptual point of view, this should work nonetheless.

jheid
13 Nov 2007, 3:41 AM
Thx, I'll have a look at it. The extension was not coded having reading from a flat file in mind (as performance will decrease the larger the file is), but from a conceptual point of view, this should work nonetheless.

The XML file is generated on demand (with the offset and limit parameter), just like your JSON example.
XML is quite an overhead (IMHO JSON is, too) though.

ThorstenSuckow
13 Nov 2007, 4:11 AM
The XML file is generated on demand (with the offset and limit parameter), just like your JSON example.
XML is quite an overhead (IMHO JSON is, too) though.


Okay, I understand the problem now. Since the XML file represents a range of buffered items which are available once the file has been generated, you have to set the bufferSize-value to the count of items available in the xml file. In your given example, this would be "50".


Regards

Thorsten

jheid
13 Nov 2007, 4:16 AM
Okay, I understand the problem now. Since the XML file represents a range of buffered items which are available once the file has been generated, you have to set the bufferSize-value to the count of items available in the xml file. In your given example, this would be "50".


Regards

Thorsten

I don't really understand... Where's the difference between the JSON (using "start" and "limit") and the XML parts (using "start" and "limit")?
The dynamic XML works with Ext's paging and I thought that your solution is compatible with that...?

ThorstenSuckow
13 Nov 2007, 4:38 AM
I don't really understand... Where's the difference between the JSON (using "start" and "limit") and the XML parts (using "start" and "limit")?
The dynamic XML works with Ext's paging and I thought that your solution is compatible with that...?

I'm at work now and have no access to the sources, so this was just a guess. ;) I wasn't aware of the fact that you can page through a XML file using EXT. However, this means your XML file does not change during the lifetime of a pageable Ext component and sits right there in the directory with it's fixed number of items and waits to be paged.
I'll take care of this, just can't do it right now.

jheid
13 Nov 2007, 4:50 AM
I'm at work now and have no access to the sources

I know this problem ;)


, so this was just a guess. ;) I wasn't aware of the fact that you can page through a XML file using EXT.

As I said it's a dyamically generated XML file with a fixed amount and as much children as defined by "start" and "limit".


However, this means your XML file does not change during the lifetime of a pageable Ext component and sits right there in the directory with it's fixed number of items and waits to be paged.
I'll take care of this, just can't do it right now.

True. The "base" XML file does not change and has for example 50 items (in fact there are 800 so a life-grid is very good for that).
In your example the number is 5000 so I'm confused about any difference between your example and mine.

Perhaps I can give you the example:

/pflege/get-data-Netz.xml?start=10&limit=10 will produce



<?xml version="1.0"?>
<data>
<objects count="50">
<netz><name>10</name></netz>
<netz><name>11</name></netz>
<netz><name>12</name></netz>
<netz><name>13</name></netz>
<netz><name>14</name></netz>
<netz><name>15</name></netz>
<netz><name>16</name></netz>
<netz><name>17</name></netz>
<netz><name>18</name></netz>
<netz><name>19</name></netz>
</objects>
</data>

ThorstenSuckow
13 Nov 2007, 5:06 AM
I know this problem ;)



As I said it's a dyamically generated XML file with a fixed amount and as much children as defined by "start" and "limit".



True. The "base" XML file does not change and has for example 50 items (in fact there are 800 so a life-grid is very good for that).
In your example the number is 5000 so I'm confused about any difference between your example and mine.

Perhaps I can give you the example:

/pflege/get-data-Netz.xml?start=10&limit=10 will produce



<?xml version="1.0"?>
<data>
<objects count="50">
<netz><name>10</name></netz>
<netz><name>11</name></netz>
<netz><name>12</name></netz>
<netz><name>13</name></netz>
<netz><name>14</name></netz>
<netz><name>15</name></netz>
<netz><name>16</name></netz>
<netz><name>17</name></netz>
<netz><name>18</name></netz>
<netz><name>19</name></netz>
</objects>
</data>


In your case, the "count" attribute should then equal to 800. The BufferedGrid needs to know the total number of records in the underlying data repository. Please try this.

jheid
13 Nov 2007, 7:51 AM
In your case, the "count" attribute should then equal to 800. The BufferedGrid needs to know the total number of records in the underlying data repository. Please try this.

Hmpf. Of course the count attribute will be correct. It's just the count of the sample XML file I provided you to show you the problem :((

ThorstenSuckow
13 Nov 2007, 7:58 AM
Hmpf. Of course the count attribute will be correct. It's just the count of the sample XML file I provided you to show you the problem :((

hehe... looks like I have to consult the sources at last...

sfrancolla
13 Nov 2007, 12:00 PM
hehe... looks like I have to consult the sources at last...

Hey MindPatterns. Nice work! I just finished skimming through the thread. Are you keeping an enhancement list for this? I and obviously many others are likely very interested in helping building out this component either by helping you organize ideas and/or contributing coding time. You're the author, so it's up to you, but have you given any thought into creating a project for it somewhere?

Thanks.

andrei.neculau
13 Nov 2007, 12:48 PM
@sfrancolla - I'm just putting out my opinion. The following has nothing to do with Thorsten (MindPatterns). This version is still at 0.1 (alpha). So far there hasn't been an update. Just a sneak preview publishing - "official" publishing of the extension pack has been said to be made next weekend.

As for creating a project for it... ExtJS is a project. An extension or a component pack which is at least 5 very big/useful components could be a project. For an extension pack like this one will never need more than a changelog, live demo, usage information. Contributing with code/ideas is always welcome throughout the ExtJS community forum. You will just need to state your view and optionally post your code - you could as well zip your new code and attach it, or create a live demo somewhere. Creating a project (by that understanding changelog, bug tracker, suggestion posting, help, etc) for this is a bit far-fetched don't you think?

@Thorsten - it was bad that you gave your first name, in the first post to the thread. Now I'm inclined to use your first name, while others know/refer to you as MindPatterns :)

jheid
13 Nov 2007, 1:16 PM
Just written a demo:

http://www.kreisalarm.de/ext/livegrid/

I have had to change the reader a bit and the php file is static (so there aren't any number over 300).

The JSP file is quite simple:



<%@ page contentType="text/xml" %><?xml version="1.0"?><data><objects count="5000"><%

int start = request.getParameter ("start") == null ? 1 : Integer.parseInt (request.getParameter ("start"));
int limit = request.getParameter ("limit") == null ? 300 : Integer.parseInt (request.getParameter ("limit"));

for (int i = start; i < start+limit; i++) {
%><netz><id><%= i %></id><name>Name <%= i %></name></netz><%
}
%></objects></data>


It seems that using a to small buffer is the problem. When using 300/100 it seems to work, 60/20 seems to work but flickering with 30/20. But some flickering is still there...

JeffHowden
13 Nov 2007, 1:23 PM
Perhaps you should buffer the calls to the onLiveScroll function so the data loading doesn't start until a set amount of delay after the user has quit scrolling. This should save some round-trips to the server making it and the browser happier.

ThorstenSuckow
13 Nov 2007, 1:36 PM
Just written a demo:

http://www.kreisalarm.de/ext/livegrid/

I have had to change the reader a bit and the php file is static (so there aren't any number over 300).

The JSP file is quite simple:



<%@ page contentType="text/xml" %><?xml version="1.0"?><data><objects count="5000"><%

int start = request.getParameter ("start") == null ? 1 : Integer.parseInt (request.getParameter ("start"));
int limit = request.getParameter ("limit") == null ? 300 : Integer.parseInt (request.getParameter ("limit"));

for (int i = start; i < start+limit; i++) {
%><netz><id><%= i %></id><name>Name <%= i %></name></netz><%
}
%></objects></data>


It seems to work there. So it seems that I have some problems in my code... Urgs.

J

ThorstenSuckow
13 Nov 2007, 1:42 PM
Perhaps you should buffer the calls to the onLiveScroll function so the data loading doesn't start until a set amount of delay after the user has quit scrolling. This should save some round-trips to the server making it and the browser happier.

The view triggers at last one request for new data during scrolling. If the row index changed while the request is busy, this index is being written into a queue. When the user stops scrolling, the current index in the queue is compared with the latest response fetched from the server. If the current index is within this range, everything is fine and the specific records will be displayed. Otherwise a new request will be made.
IMHO there is no other way to update the buffer according to user behavior.

ThorstenSuckow
13 Nov 2007, 1:51 PM
@andrei & sfrancolla

It all depends on what Jack/the Ext dev team will tell us about the livegrid support that's coming with one of the next releases. Brian stated that they will develope something like this in the near future, though it most likely won't find it's way into the 2.x branch.

I'll sure be glad to help the Ext team on this matter, and I think everyone who is willing to do the same is more than welcome.

So yeah, I'd like to hear something "official" ;)

SeaSharp
13 Nov 2007, 2:22 PM
LiveGrid looks excellent and fills a significant functional gap for my application.

My interest is not in presenting large amounts of data in a grid but instead how to cleanly present a small number of rows expected to be less than a page size on most occasions. With LiveGrid I anticipate I will be able to display a minimal list with no scrollbar, paging bar or status bar.

In the above case with the standard Ext grid the majority of users would see unnecessary clutter for grid paging controls.

brian.moeskau
13 Nov 2007, 3:24 PM
@andrei & sfrancolla

It all depends on what Jack/the Ext dev team will tell us about the livegrid support that's coming with one of the next releases. Brian stated that they will develope something like this in the near future, though it most likely won't find it's way into the 2.x branch.

I'll sure be glad to help the Ext team on this matter, and I think everyone who is willing to do the same is more than welcome.

So yeah, I'd like to hear something "official" ;)

The extension looks really fantastic! I know Jack started looking into this himself, but I'm not sure how far he got. We were looking to add similar functionality in 2.x, just not in 2.0. I'm sure Jack will take a look at your code and provide feedback when he gets a chance. Nice job!

xpressive
21 Nov 2007, 8:33 AM
Hi all,

the suggestion from andrei

.x-grid3-viewport{float:left}
works great for IE6 (and still works for other browsers) ;) see screenshot

http://www.webappz.de/images/lifegrid.jpg

Many thanks for that tip and certainly for this great "life-grid"-code

BR
Stefan

tech-nova
21 Nov 2007, 8:57 AM
It doesn't work on Opera PC 9.24 (only 13 elements are loaded)
But it works like a dream in Safari3/PC :)

Wolfgang
21 Nov 2007, 11:58 AM
@MindPatterns

Great extension :)

Regards

Wolfgang

ThorstenSuckow
21 Nov 2007, 2:47 PM
Hey all, thanks for your kind feedback so far, I really appreciate that :)

I'm currently embedding the Livegrid in a larger application which helps me to adjust behavior at some places and fix not-so-obvious bugs ;)

I did start writing a guide with some best-practices when using the extension, so this is still under construction and I'll version it 1.0 as soon as possible.

Thanks for all your testing!

lvanderree
22 Nov 2007, 3:22 AM
Hi Thorsten, great work!

I wonder if it is hard to support groupedGridViews as well?

I am working on a generator, which generator both the json-data-provider, grids and crud-pages in php/symfony with some people at the Symfony forum (http://www.symfony-project.org/forum/index.php/m/40066/#msg_40066). At the moment the json-data and grids can be generated pretty nicely, crud-pages are in active development.

This extension would be a great addition for my implementation of master-detail views (overviews of items (details) which are grouped in groups (master), where the master object can contain 0, 1 or more items. For example products which are part of a product-group, or products which are part of an order, or as in my live demo (http://fun4me.demon.nl/test/test_dev.php/country_cities) cities which are part of a country. (The live demo is far for finished because the crud-pages (edit) are not finished yet, this is in active development however).

The problem with master-detail is that I do an sql query with left-joins (which is nice, since you only need one query to retrieve both all master and detail objects (next to each other in one row)). The problem however is introduced with paging, since you paging can split up the detail-objects belonging to one master-object over several pages. Your implementation with buffering can prevent this problem.

ThorstenSuckow
23 Nov 2007, 7:16 AM
I wonder if it is hard to support groupedGridViews as well?

I am working on a generator, which generator both the json-data-provider, grids and crud-pages in php/symfony with some people at the Symfony forum (http://www.symfony-project.org/forum/index.php/m/40066/#msg_40066). At the moment the json-data and grids can be generated pretty nicely, crud-pages are in active development.

This extension would be a great addition for my implementation of master-detail views (overviews of items (details) which are grouped in groups (master), where the master object can contain 0, 1 or more items. For example products which are part of a product-group, or products which are part of an order, or as in my live demo (http://fun4me.demon.nl/test/test_dev.php/country_cities) cities which are part of a country. (The live demo is far for finished because the crud-pages (edit) are not finished yet, this is in active development however).

The problem with master-detail is that I do an sql query with left-joins (which is nice, since you only need one query to retrieve both all master and detail objects (next to each other in one row)). The problem however is introduced with paging, since you paging can split up the detail-objects belonging to one master-object over several pages. Your implementation with buffering can prevent this problem.

It's hard to tell which rows to request from the data-proxy when scrolling, since it might not always be clear to which group they belong... so yes, from my current point of view it's almost impossible without major changes to the current version of the BufferedGridView. ~o)

Phenothiasine
25 Nov 2007, 10:15 AM
Hi Thorsten,

At first: really perfect work! Your code now is one of the most significant arguments in our EXT/Dojo choice for our further projects. Thanks for sharing!

And now the question. How do you think, is it possible to adopt your solution for the grid with non-constant row heights? I know you are using rowHeight field which is "computed once the store has been loaded for the first time and used for various calculations during the lifetime of the grid component" (your code comments cite), so it looks not so easy to change code for vary-height rows, but... What do you think about this issue? Do you plan to make such changes in the near future?

One suggestion: I realize that re-calculating row height for each row rendered in order to decide if we can draw the next row can significantly decrease the performance. But I think there can be two configurable modes - one like "constRowHeight : true" (current realization) and another like "constRowHeight : false" with slowest calculation but correct displaying vary-height rows.

Thank you in advance,
Andrey

ThorstenSuckow
27 Nov 2007, 3:55 AM
Hi Thorsten,

At first: really perfect work! Your code now is one of the most significant arguments in our EXT/Dojo choice for our further projects. Thanks for sharing!

And now the question. How do you think, is it possible to adopt your solution for the grid with non-constant row heights? I know you are using rowHeight field which is "computed once the store has been loaded for the first time and used for various calculations during the lifetime of the grid component" (your code comments cite), so it looks not so easy to change code for vary-height rows, but... What do you think about this issue? Do you plan to make such changes in the near future?

One suggestion: I realize that re-calculating row height for each row rendered in order to decide if we can draw the next row can significantly decrease the performance. But I think there can be two configurable modes - one like "constRowHeight : true" (current realization) and another like "constRowHeight : false" with slowest calculation but correct displaying vary-height rows.

Thank you in advance,
Andrey

I do not say it is impossible, BUT... the height of the scrollbar gets calculated using the fixed row height and the number of available data in the underlying data model. If the script doesn't know the row height of each record, it cannot draw the scrollbar correctly, thus, browsing through all of the data and each and every record may become clumsy or even impossible.



Edit:
Updated first post with contents of data-proxy.php

Jacob
28 Nov 2007, 2:03 AM
This component doesn't seem to work on Opera 9.24 (R8816)
Th right ScrollBar doens't appear the and mouse wheel is ignored.

Anyway, this is really amazing !

zacware
30 Nov 2007, 11:02 AM
This is exactly what I've been looking for. I had been reviewing the other available solutions for grids with live scrolling and none of them worked for well. This looks great. Any idea when you'll be releasing the code??? (you should put up a link for donations, this is definitely worth it)

ThorstenSuckow
30 Nov 2007, 3:57 PM
This is exactly what I've been looking for. I had been reviewing the other available solutions for grids with live scrolling and none of them worked for well. This looks great. Any idea when you'll be releasing the code??? (you should put up a link for donations, this is definitely worth it)

Thanks zacware! :) I was currently busy with updating the project's homepage http://www.siteartwork.de/livegrid.
You can download the files now, along with a demo setup and a sql-file to create an example database.

Though I haven't updated the version, I have fixed some minor bugs in the last weeks. ~o)

zacware
30 Nov 2007, 11:35 PM
Great. Thanks for the downloadable code!

Note: I was able to make a PayPal donation via my company credit card but it took a little work because the paypal link on your site comes up in german, and I had to try a few different things before I was able to get to a point where things were in English.

ThorstenSuckow
1 Dec 2007, 9:52 AM
Great. Thanks for the downloadable code!

Note: I was able to make a PayPal donation via my company credit card but it took a little work because the paypal link on your site comes up in german, and I had to try a few different things before I was able to get to a point where things were in English.


The code is updated. Scrollbars now appear in both Opera and IE6! See first post for a list of updates and changes...

galdaka
2 Dec 2007, 3:05 AM
I don

jeremia
2 Dec 2007, 3:46 AM
Great work, MindPatterns,

but: I think your grid should render one more row!

You leave out the last visible row if it does not completely fit in the visible area. Instead white space is shown at the bottom end of the visible area. This wasted space grows with the grid's row height.

As my grid rows are quite high (with images), only very few fit into the visible area of my grids at once - sometimes only one and a half. With your implementation i see only the first row, but I'd like to see half of the second row as well. Instead there's just plain white.

Try out with a grid that has rows a little bit higher than half of the whole grid's height.

thanx nevertheless for this great implementation,
jeremia

ThorstenSuckow
2 Dec 2007, 5:23 AM
This wasted space grows with the grid's row height.


I see your point. I will take a look at it!

zieli1
3 Dec 2007, 1:43 AM
Hi!

Very good work - congratulations :-)

But:

Is it possible to add a dynamic column model to the livegrid (functionality like autogrid for ext2 http://ux.designism.nl/ux/autogrid2/


thanks zieli1

ThorstenSuckow
3 Dec 2007, 2:00 AM
Hi!

Very good work - congratulations :-)

But:

Is it possible to add a dynamic column model to the livegrid (functionality like autogrid for ext2 http://ux.designism.nl/ux/autogrid2/


thanks zieli1

Yes, this is possible. But it's not within the focus of current development ;) Regarding the dynamic column model, you could also simply read out the column config from the server and replace the old one with it. The onMetaChange-events should do the rest then...

Blob
10 Dec 2007, 8:39 AM
Hello everybody!

Thank you for sharing MindPatterns. Your solution is really cool.
I'm moving from pagingGrid to liveGrid right now and everything looks good, but...

I'm developing with Ext for about a month, so can't say I am an expert, but looks like BufferedStore.getAt() doesn't work as expected. If (BufferedGridView.bufferRange[0] != 0) I will get wrong or undefined data when calling BufferedStore.getAt(rowIndex), so I have to do manual subtraction like this BufferedStore.getAt(rowIndex - BufferedGridView.bufferRange[0]). For example RowExpander grid plug-in is dependent on this functionality. Could you please tell me if it is possible to fix the issue, so the subtraction is done inside BufferedStore.getAt() automatically?

WoLpH
12 Dec 2007, 7:06 AM
First I'd like to say thanks for the great addon, I really like it :)

I did find a little bug however, when using an editorgridpanel you get the error that c is not defined at row 1124 in BufferedGridView.js

That's because c doesn't exist but is called cellEl instead, replace row 1121-1132 with this code to fix it:

if(hscroll !== false){
var cleft = parseInt(cellEl.offsetLeft, 10);
var cright = cleft + cellEl.offsetWidth;

var sleft = parseInt(cellEl.scrollLeft, 10);
var sright = sleft + cellEl.clientWidth;
if(cleft < sleft){
cellEl.scrollLeft = cleft;
}else if(cright > sright){
cellEl.scrollLeft = cright-cellEl.clientWidth;
}
}

h0tzenpl0tz
19 Dec 2007, 11:56 AM
hello, congratulations to this extension, very nice codebase!

i just tested out your example and examined the XHRs with firebug,
sometimes the grid fires POST-request with no parameters resulting on server-side in php crying.


<br /><b>Notice</b>: Undefined index: sort in <b>E:\web\dbprakt\_docs\livegrid\example\data-proxy.php</b> on line <b>39</b>
<br /><br /><b>Notice</b>: Undefined index: dir in <b>E:\web\dbprakt\_docs\livegrid\example\data-proxy.php</b> on line <b>39</b>
<br /><br /><b>Notice</b>: Undefined index: start in <b>E:\web\dbprakt\_docs\livegrid\example\data-proxy.php</b> on line <b>40</b>
<br /><br /><b>Notice</b>: Undefined index: limit in <b>E:\web\dbprakt\_docs\livegrid\example\data-proxy.php</b> on line <b>40</b>
<br /><br /><b>Warning</b>: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in <b>E:\web\dbprakt\_docs\livegrid\example\data-proxy.php</b> on line <b>44</b>
<br />{"response":{"value":{"items":[],"total_count":"5000","version":1}}}
as your php-example is just a proof-of-concept and does not check _POST,
i understand the php warnings ....... i just wonder what purpose has the casual no-parameters-fetch?

and another question: BufferedStore-documentation states to send the ranges-parameter, couldnt find this one in the XHR requests?

very well done ext!
kai

andrei.neculau
20 Dec 2007, 3:29 PM
Hey. It's been some time since I visited your thread.
Great job - keep it going - feels good to see that I lend a hand with the scrollbars issue ;)

I subscribe to letting the last not-fully-visible row show up!

WoLpH
22 Dec 2007, 10:40 AM
I found a new bug, when editing a row and scrolling the editor doesn't scroll with the rest. The result is that the next time they start editing the edit box appears at the wrong location.

magunes117
24 Dec 2007, 8:41 AM
Hi all,

Thorsten, great component, thx.

I am using .net/mssql instead of php/mysql, so I modified your example for this purpose, and here is how to make it work:

Server Side: test.ashx



[JsonRpcMethod("liveGrid", Idempotent = true)]
[JsonRpcHelp("LiveGrid Test")]
public Dictionary<string, object> LiveGrid(int start, int limit, string sort, string dir)
{
using (OleDbConnection connection = new OleDbConnection("Provider=SQLOLEDB;Data Source=datasource;Initial Catalog=initcatalog;User Id=user;Password=password;"))
{
connection.Open();
string sql = "SELECT * FROM ORDERS ORDER BY " + sort + " " + dir;
OleDbCommand command = new OleDbCommand(sql, connection);
OleDbDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);

DataTable resultSet = new DataTable();

for (int i = 0; i < reader.FieldCount; i++)
{
resultSet.Columns.Add(reader.GetName(i), reader.GetFieldType(i));
}

DataRow[] dr = new DataRow[300];

for (int i = 0; i < start && reader.Read(); i++);

for (int i = 0; i < limit && reader.Read(); i++)
{
dr[i] = resultSet.NewRow();

for (int j = 0; j < resultSet.Columns.Count; j++)
{
dr[i][j] = reader.GetValue(j);
}
resultSet.Rows.Add(dr[i]);
}

command.Cancel();
reader.Close();
connection.Close();

connection.Open();
string csql = "SELECT COUNT(*) FROM ORDERS";
OleDbCommand ccommand = new OleDbCommand(csql, connection);
OleDbDataReader creader = ccommand.ExecuteReader(CommandBehavior.CloseConnection);
creader.Read();
int total = (int)creader.GetValue(0);

creader.Close();
connection.Close();

Dictionary<string, object> ret = new Dictionary<string, object>();
ret["total"] = total;
ret["version"] = 1;
ret["data"] = resultSet.DefaultView;
return ret;
}
}



Client Side: index.html



...

<script type="text/javascript" src="test.ashx?proxy&v=2"></script>

...

Ext.onReady(function(){

var bufferedReader = new Ext.ux.data.BufferedJsonReader({
root : 'result.data',
versionProperty : 'result.version',
totalProperty : 'result.total',
id : 'id'
}, [ {
name : 'OrderID', sortType : 'int'
},{
name : 'CustomerID', sortType : 'string'
},{
name : 'EmployeeID', sortType : 'int'
},{
name : 'OrderDate', sortType : 'int'
},{
name : 'RequiredDate', sortType : 'int'
},{
name : 'ShippedDate', sortType : 'int'
},{
name : 'ShipVia', sortType : 'int'
},{
name : 'Freight', sortType : 'string'
},{
name : 'ShipName', sortType : 'string'
},{
name : 'ShipAddress', sortType : 'string'
},{
name : 'ShipCity', sortType : 'string'
},{
name : 'ShipRegion', sortType : 'string'
},{
name : 'ShipPostalCode', sortType : 'string'
},{
name : 'ShipCountry', sortType : 'string'
}]);

Ext.JsonRpcProxy = function(jsonRpcProxy, listMethod)
{
var _jsonRpcProxy = null ;
var _listMethod = null;

Ext.JsonRpcProxy.superclass.constructor.call(this);

this.load = function(params, reader, callback, scope, arg) {
_jsonRpcProxy[listMethod] (params.start, params.limit, params.sort, params.dir, this.loadResponse.createDelegate(this, [reader, callback, scope, arg], true )
).call(Ext.JsonRpcProxy.ext_channel1);
}

this.loadResponse = function(response, reader, callback, scope, arg) {
var result;
result = reader.read(response) ;
callback.call(scope||this, result, arg, true) ;
}

this.setRpcProxy = function(jsonRpcProxy, listMethod) {
if (jsonRpcProxy)
_jsonRpcProxy = jsonRpcProxy.rpc || jsonRpcProxy ;
_listMethod = listMethod || "list" ;
}
this.setRpcProxy(jsonRpcProxy, listMethod) ;
} ;

Ext.JsonRpcProxy.ext_channel1 = function(call)
{
if (typeof(call.callback) !== 'function')
throw new Error("The EXT channel does not support synchronous methods.");
call.yuiconn = Ext.Ajax.request (
{
url: call.url ,
params: {"JSON-RPC": Ext.util.JSON.encode(call.request)} ,
success: function(response, options) {
call.callback(response) ;
},
failure: function(response, options) {
call.callback({xhr:response});
}
}
);
return call ;
} ;

Ext.extend(Ext.JsonRpcProxy, Ext.data.DataProxy, {
}) ;

var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
proxy : new Ext.JsonRpcProxy(Test.rpc, "liveGrid"),
sortInfo : {field: 'OrderID', direction: 'ASC'},
reader : bufferedReader
});

var bufferedView = new Ext.ux.grid.BufferedGridView({
nearLimit : 100,
loadMask : {
msg : 'Please wait...'
}});

var bufferedGridToolbar = new Ext.ux.BufferedGridToolbar({
view : bufferedView,
displayInfo : true
});

var bufferedSelectionModel = new Ext.ux.grid.BufferedRowSelectionModel();

var colModel = new Ext.grid.ColumnModel([
{header: "OrderID", align : 'left', width: 160, sortable: true, dataIndex: 'OrderID'},
{header: "CustomerID", align : 'left', width: 160, sortable: true, dataIndex: 'CustomerID'},
{header: "EmployeeID", align : 'left', width: 160, sortable: true, dataIndex: 'EmployeeID'},
{header: "OrderDate", align : 'left', width: 160, sortable: true, dataIndex: 'OrderDate'},
{header: "RequiredDate", align : 'left', width: 160, sortable: true, dataIndex: 'RequiredDate'},
{header: "ShippedDate", align : 'left', width: 160, sortable: true, dataIndex: 'ShippedDate'},
{header: "ShipVia", align : 'left', width: 160, sortable: true, dataIndex: 'ShipVia'},
{header: "Freight", align : 'left', width: 160, sortable: true, dataIndex: 'Freight'},
{header: "ShipName", align : 'left', width: 160, sortable: true, dataIndex: 'ShipName'},
{header: "ShipAddress", align : 'left', width: 160, sortable: true, dataIndex: 'ShipAddress'},
{header: "ShipCity", align : 'left', width: 160, sortable: true, dataIndex: 'ShipCity'},
{header: "ShipRegion", align : 'left', width: 160, sortable: true, dataIndex: 'ShipRegion'},
{header: "ShipPostalCode", align : 'left', width: 160, sortable: true, dataIndex: 'ShipPostalCode'},
{header: "ShipCountry", align : 'left', width: 160, sortable: true, dataIndex: 'ShipCountry'}
]);

var grid = new Ext.grid.GridPanel({
ds : bufferedDataStore,
enableDragDrop : false,
cm : colModel,
sm : bufferedSelectionModel,
loadMask : {
msg : 'Loading...'
},
view : bufferedView,
title : 'Test',
bbar : bufferedGridToolbar
});

var w = new Ext.Window({
title : 'LiveGrid',
maximizable : true,
resizable : true,
layout : 'fit',
items : [grid],
height : 480,
width : 600
});

w.show();

});



Table Structure: orders



CREATE TABLE ORDERS (
"OrderID" "int" IDENTITY (1, 1) NOT NULL ,
"CustomerID" nchar (5) NULL ,
"EmployeeID" "int" NULL ,
"OrderDate" "datetime" NULL ,
"RequiredDate" "datetime" NULL ,
"ShippedDate" "datetime" NULL ,
"ShipVia" "int" NULL ,
"Freight" "money" NULL DEFAULT (0),
"ShipName" nvarchar (40) NULL ,
"ShipAddress" nvarchar (60) NULL ,
"ShipCity" nvarchar (15) NULL ,
"ShipRegion" nvarchar (15) NULL ,
"ShipPostalCode" nvarchar (10) NULL ,
"ShipCountry" nvarchar (15) NULL
)



Since there isn't a replacement for mysql's limit in mssql, I used a different method here. Anyway, it works fine with 500.000 rows. Sorting the columns take a little long, because the 'order by' clause sorts the whole table and if there are millions of rows ordering may become a pain.

I want to thank FritFrut, for the "jayrock tutorial" and for helping me write this code.

Regards.

WoLpH
24 Dec 2007, 3:59 PM
Since there isn't a replacement for mysql's limit in mssql, I used a different method here. Anyway, it works fine with 500.000 rows. Sorting the columns take a little long, because the 'order by' clause sorts the whole table and if there are millions of rows ordering may become a pain.Not a direct replacement, but using TOP works pretty well or this method if you're using SQL 2005: http://select-sql.com/mssql/how-to-make-limit-from-to-in-mssql-2005.html

magunes117
24 Dec 2007, 11:27 PM
Not a direct replacement, but using TOP works pretty well or this method if you're using SQL 2005: http://select-sql.com/mssql/how-to-make-limit-from-to-in-mssql-2005.html

Hi WoLpH,

I know about 'TOP' but you can only use it as top X rows, not like the rows between X and Y. So it is not much useful. And I am using sql2005 as well as sql2000, oracle, etc. But if you have a better solution, I will be happy to use it.

Regards.

WoLpH
25 Dec 2007, 4:52 AM
Yeah, it's not a perfect solution, here are a few others but I still think MS should have gone with the PostgreSQL/MySQL way of doing it: http://databases.aspfaq.com/database/how-do-i-page-through-a-recordset.html

Although Oracle's implementation isn't that bad either, but less transparent imho.

franck34
31 Dec 2007, 5:14 AM
Hi,

Just starting using extJs since 3 days. Seem's very cool, just need to learn. Big thanks for sharing.

Regarding liveGrid, i've just have a little strange thing (both ie and ff). Not sure it's liveGrid because i'm using it into a Desktop app.

Go here: http://innovacode.com/extjs/admin/
Click the Example icon.
On my side, I only have one item in the grid, but you will see that php file sent 2 items. If you resize/reduce/maximize the window, 2 items appear, as expected.

Using Firebug, i can confirm when i see only one item, there is only one div (x-gridX-row), expected 2. Have an idea ?

Thanks in advance.
Best Regards,
Franck

WoLpH
31 Dec 2007, 5:57 AM
It is most likely caused by the animating effect, when animating it sees the height of the grid as 0 when rendering, so it only renders 1 item. Perhaps a proper solution for this would be always rendering atleast x items.

I have detected a little bug of my own by the way, when inserting rows it is only possible to insert rows at index 0 when there are not enough rows to scroll yet. After that inserting at 0 gives an error and only 1 and up is working.

franck34
31 Dec 2007, 7:22 AM
It is most likely caused by the animating effect, when animating it sees the height of the grid as 0 when rendering, so it only renders 1 item. Perhaps a proper solution for this would be always rendering atleast x items.

Not sure about that because FireBug show only one div, expected 2. I can be wrong cause i'm starting with extJs.

franck34
1 Jan 2008, 7:34 AM
Fixed:
this.grid.syncSize();

( just after win.show(); in my desktop app)

meteorbites
3 Jan 2008, 2:25 AM
impressive plugin. ;)

i've seen this kind of implementation before and it's great to have this as a plugin for EXT.

Good job.

fred
4 Jan 2008, 2:58 AM
Hello,
I'm a new user with Ext and discover yesterday this amazing widget.
I try to get value on a rowclick event with no success; hereafter my code :


Ext.onReady(function(){

var bufferedReader = new Ext.ux.data.BufferedJsonReader({
root : 'response.value.items',
versionProperty : 'response.value.version',
totalProperty : 'response.value.total_count',
id : 'id'
}, [ {
name : 'number_field', sortType : 'int'
},{
name : 'string_field', sortType : 'string'
},{
name : 'date_field', sortType : 'int'
}]);

var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
sortInfo : {field: 'number_field', direction: 'ASC'},
url : '../services/data-proxy.php'
});

var bufferedView = new Ext.ux.grid.BufferedGridView({
nearLimit : 100,
loadMask : {
msg : 'Chargement...'
}});

var bufferedGridToolbar = new Ext.ux.BufferedGridToolbar({
view : bufferedView,
displayInfo : true
});

var bufferedSelectionModel = new Ext.ux.grid.BufferedRowSelectionModel();

var colModel = new Ext.grid.ColumnModel([
{header: "Number", align : 'left', width: 160, sortable: true, dataIndex:'number_field'},
{header: "String", align : 'left', width: 160, sortable: true, dataIndex: 'string_field'},
{header: "Date", align : 'right', width: 160, sortable: true, dataIndex: 'date_field'}
]);


var grid = new Ext.grid.GridPanel({
ds : bufferedDataStore,
enableDragDrop : false,
cm : colModel,
sm : bufferedSelectionModel,
loadMask : {msg : 'Chargement...'},
view : bufferedView,
title : 'Fonction2',
bbar : bufferedGridToolbar
});

grid.on("rowclick", function(grid, rowIndex, e) {
rec = ds.data.items[rowIndex].id; // doesn't work !!!
alert(rec);
str = rec.get('Number');
alert(str);
},this);

var viewport = new Ext.Viewport({
maximizable : true,
resizable : true,
layout : 'fit',
items : [grid],
});

});


How get 'Number' value of the selected row ?
Thanks for your help.
Frederic

ThorstenSuckow
8 Jan 2008, 4:28 AM
A late Happy New Year to you all!

Just wanted to let you all know that I was on vacation and that I'm aware about your recent posts.

I'll provide feedback as soon as I am back home at my working place.

Best regards


Thorsten

magunes117
8 Jan 2008, 7:04 AM
Hi Thorsten,

Happy new year. ;)

I am using this component in a .NET environment (as you can see the sample a few posts above). I need to ask sth: When I start dragging the scrollbar, a request is immediately sent to the server, and when I release the scrollbar it sends another request. So I have to wait for the end of both requests to see the data. Now, when I have a lot of data (1 million rows for instance), the first request takes 9 seconds and the second takes 10 seconds.

Is there a way to disable the sending of that first request, so I only wait for the second one. It will be 2 times faster. The request will only be sent when I release the scrollbar?

Thanks and regards.

zergworld
14 Jan 2008, 12:26 PM
Sorry if this question has already been asked and answered, but are there EXT-style API docs available? If so, please link. If not, is there anything you'd suggest to learn the live grid options that are not fully represented in the example demo?

Thanks !

eliasp
16 Jan 2008, 9:12 AM
I probably found another bug:

Scroll down some rows
Click an item
Move the selection upwards using the up key at your keyboard
Firebug shows this error:



Index or size is negative or greater than the allowed amount" code: "1
[Break on this error] return this.getRows()[row];
ext-all-debug.js (line 29577)

Can anybody confirm this? It's not a mission critical bug, but sometimes a little annoying.

Thanks anyway for this really great extension. Exactly what I was looking for!

Regards, Elias P.

zergworld
17 Jan 2008, 9:37 AM
Hi Thorsten.

First off, exellent work. Your implementation of Live Grid is awesome.

I have a few "questions" regarding the inherent differences in the natures of Live Grid and Paging that perhaps others have already considered and are handling in some way.

1. Live Grid is "live", so the act of scrolling fetches new data by re-running the original query and potentially changing the virtual result set (if the backing data has changed), such that data selections might be moved simply by scrolling.

2. A range selection that crosses frames (pages) constitutes a "virtual subset". Scrolling after a range selection can affect the data "within" that set if the backing data is affected.

3. Range selections (virtual selections), don't point to IDs directly, so that range selection needs to be mapped to records on the server side for update purposes. However, the process of correlating the virtual selections to actual IDs on the server is not reliable since that involves re-running the query and mapping row positions... however, the backing data has changed.

All live grids involve virtual sets and therefore have these characteristics and potential mapping issues due the live re-querying that is needed to fetch frames of data.

Now, it's true that a paging solution's virtual set also changes during paging, so any cross-frame action will have the same consequences. However, in the case of a paged view, the user and UI is typically expecting to operate only on data within the current page view - i.e. actions on data are not targeted at the virtual set but only on the actual subset in view.

Facing these matters, I'm trying to determine when and where to use live grid versus paging interfaces. It seems that the answer is not merely a UI decision but is informed by the functional behavior.

My thought at this time is that actionable lists for which group actions (esp those that are targeted at cross frame ranges in the virtual data set) are to be applied, where a group action might be "delete the selected rows from the db", should use a paging interface, and that a live grid is OK for pure views, as in the common case of "search, scroll, click to view detail".

Does this sound right, and have others dealt with these considerations?

Thanks,
Joe Hanink

zergworld
17 Jan 2008, 10:01 AM
In sum,

Live Grid over Live Data (data that might change during use) poses the above challenges. Live Grid over historical data that doesn't change poses none of the above challenges.

If dealing with Live Data, then Live Grid poses difficulties for managing range selections and actions on those selections. ID-based single selections are no problem, of course.

In the case of actionable lists over live data, a paging interface may be preferred, simply to avoid such issues.

Opinions?

Thanks Again,
Joe Hanink

Confused
17 Jan 2008, 3:57 PM
I have ran into an issue using this extension. It's not a normal use of grids. I have one Store that fetches a record set with 7 columns and 2 grids that share that Store. One grid has 2 of the columns from one record, and 2 other columns are in the other grid. The remaining columns are for css formating and UIDs. If I update both grid's view to a new Ext.ux.grid.BufferedGridView, one of the grids doesn't display the rows. If I remove that view, it displays the rows that are in the Store, but looses the understanding of where the cursor is located and no scroll bars.

How can I share the Store between these two grids and still be able to set the view for both grids?

Here's the code for the store:


var bufferedReader = new Ext.ux.data.BufferedJsonReader({
root: 'file',
id: 'nLine',
versionProperty: 'version',
totalProperty: 'total'
}, [
{ name: 'iDiff' },
{ name: 'aType' },
{ name: 'uComment' },
{ name: 'lNumber' },
{ name: 'lContent' },
{ name: 'rNumber' },
{ name: 'rContent' }
]);

this.diff = new Ext.ux.grid.BufferedStore({
bufferSize: 300,
url: 'ajax/diffs.cgi',
reader: bufferedReader
});


Here's the code for the left grid:


items: new Ext.grid.GridPanel({
id: 'leftView',
ds: this.diff,
sm: new Ext.ux.grid.BufferedRowSelectionModel(),
cm: new Ext.grid.ColumnModel([
{ header: 'Line', width: 50, dataIndex: 'lNumber' },
{ header: 'Content', id: 'lc', dataIndex: 'lContent' }
]),
view: new Ext.ux.grid.BufferedGridView({
nearLimit: 100,
loadMask: { msg: 'Please Wait...' }
}),
title: '<span class="tbheader">Original File</span>',
autoExpandColumn: 'lc'
})


Here's the code for the right grid:


items: new Ext.grid.GridPanel({
id: 'rightView',
ds: this.diff,
sm: new Ext.ux.grid.BufferedRowSelectionModel(),
cm: new Ext.grid.ColumnModel([
{ header: 'Line', width: 50, dataIndex: 'rNumber' },
{ header: 'Content', id: 'rc', dataIndex: 'rContent' }
]),
view: new Ext.ux.grid.BufferedGridView({
nearLimit: 100,
loadMask: { msg: 'Please Wait...' }
}),
title: '<span class="tbheader">Changed File</span>',
autoExpandColumn: 'rc'
})


I have attached a screenshot of the grids when both views are set.

vpell
18 Jan 2008, 8:46 AM
LiveGrid is really awesome. The one issue I have is using it with grids that have a large number of columns. For example, one of my grids has 40 columns, all of which are important. This makes vertical scrolling really slow and cluncky. Is it possible to remove columns from the view that are out of scroll range but still display the horizontal scroll bar as if all the columns were there? Then, when the user scrolls horizontally, dynamically add/remove the columns to the view. This would make LiveGrid perform well even with a large number of columns.

Confused
23 Jan 2008, 12:50 PM
I think this was already suggested, but I would like to see the option to either pull the rows from a local Store or pull from a server. I have done a lot of debugging in my application that has two grids side-by-side and found that it's not the Store that's hurting performance, it's the calls to get the style for each row and doing other calculations.

provagino
25 Jan 2008, 12:19 AM
live grid don't work whit Ext 2.0.1

robw
25 Jan 2008, 3:53 AM
Hi,

I'm interested in making the same functionality work on a dataview. Any suggestions on how to achieve this would be most welcome. Is any of this code reusable?

Thanks
Rob

zacware
25 Jan 2008, 9:56 PM
There hasn't been any updates to livegrid in a while, especially in related to the 2.01 release of Ext. Are there any plans to keep this plugin updated?

cs_alpha
29 Jan 2008, 2:32 AM
Or maybe some other expert can provide the nescecary fixes that makes this tool work for the 2.01 version of Ext?

I'm having problems when selecting a row. I get the error "F has no properties" from ext-base.js, even in the provided example.

I really want to use this tool but I also rely on the updates of Ext version 2.01.

look
29 Jan 2008, 3:04 PM
I am with a serious problem in return for the information JSON livegrid my code that the link: http://extjs.com/forum/showthread.php?t=24681&highlight=servlet.

Does someone could help me because I am not understanding the reason is not returning to the values my grid.

thank!

mjhaston
29 Jan 2008, 7:25 PM
I would love to use this with HttpProxy. Would it be possible? Any suggestions on coding that?

mattb
30 Jan 2008, 2:49 PM
Has anyone used Livegrid + the Grid Filter plugin? I'm trying this out and the grid and filters work as expected except when I apply a filter and then scroll the grid -- once the grid makes a request for new rows, it doesn't pass the filter to my server-side function so it ends up pulling new rows from an unfiltered dataset...

Any ideas on how to pass the filters through livegrid and back to the server?

thx

Matt

zergworld
31 Jan 2008, 12:41 AM
in ext-base.js, add the stuff between the comments

var G=E.translatePoints(F);/*Fix For Live Grid - Start*/G.left=(G.left?G.left:0);G.top=(G.top?G.top:0);/*Fix For Live Grid - End*/

zergworld
31 Jan 2008, 12:47 AM
Tried to get these two to work together... but no dice. The are completely incompatible. RowExpander changes a row's height, and live grid expects all the rows to be the same height and performs calculations on the given uniform row height.

Each one works great by itself though!

zergworld
31 Jan 2008, 12:53 AM
Since RowExpander isn't going to work with live grid, I figured that I could toggle single and multi line view with a getRowClass implementation in the viewConfig.

This works great except for one problem... the scrollbar doesn't position itself correctly after toggling and doing a view.refresh().

Also, has anyone noticed that clicking the scroll arrows skips rows sometimes? Using multiline format, the problem with the scroll arrows is the opposite - it can take two clicks to move a row.

It seems that the scroll arrows try to scroll the view one row at a time but that the scrollbar movement isn't mapped precisely.

Will try to figure out both of these.

FYI - I already had to make a mod to live grid to use the multiline format toggle, so a few more won't hurt :)

cs_alpha
31 Jan 2008, 1:24 AM
in ext-base.js, add the stuff between the comments

var G=E.translatePoints(F);/*Fix For Live Grid - Start*/G.left=(G.left?G.left:0);G.top=(G.top?G.top:0);/*Fix For Live Grid - End*/

Thanks for your help. I've tried your fix but it doesn't work for me. I attached the firebug output with the error.

pluesch0r
31 Jan 2008, 1:41 AM
Hi there,

thanks for making this ux!
Unfortunately, when defining an autoExpandColumn, a horizontal scrollbar gets added, no matter what.



autoExpand : function(preventUpdate){
var g = this.grid, cm = this.cm;
if(!this.userResized && g.autoExpandColumn){
var tw = cm.getTotalWidth(false);
var aw = this.grid.getGridEl().getWidth(true)-this.scrollOffset;
if(tw != aw){
var ci = cm.getIndexById(g.autoExpandColumn);
var currentWidth = cm.getColumnWidth(ci);
// fix for horizontal scrollbar display
var cw = Math.min(Math.max(((aw-tw)+currentWidth), g.autoExpandMin), g.autoExpandMax) - 2;
if(cw != currentWidth){
cm.setColumnWidth(ci, cw, true);
if(preventUpdate !== true){
this.updateColumnWidth(ci, cw);
}
}
}
}
},


The above (untested) code fixes this .. just put it into BufferedGridView.js and enjoy ..

Thanks again,
Martin

eliasp
31 Jan 2008, 1:59 AM
Has anyone used Livegrid + the Grid Filter plugin? I'm trying this out and the grid and filters work as expected except when I apply a filter and then scroll the grid -- once the grid makes a request for new rows, it doesn't pass the filter to my server-side function so it ends up pulling new rows from an unfiltered dataset...

Any ideas on how to pass the filters through livegrid and back to the server?

thx

Matt

I'm facing exactly the same problem here. Didn't find a solution yet.
My current code: http://pastebin.ca/884729

Regards, Elias P.

mattb
31 Jan 2008, 3:14 PM
Has anyone used Livegrid + the Grid Filter plugin? I'm trying this out and the grid and filters work as expected except when I apply a filter and then scroll the grid -- once the grid makes a request for new rows, it doesn't pass the filter to my server-side function so it ends up pulling new rows from an unfiltered dataset...

Any ideas on how to pass the filters through livegrid and back to the server?

thx

Matt

I found a solution for this -- I had already created a buildQuery function in the GridFilters definition. Whenever that function is executed to change the filters, I change the URL for the data store to pass the filter to the server:



var url = '/cdt/grid_data';
var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
sortInfo : {field: 'display_name', direction: 'ASC'},
url : url
});

var filters = new Ext.ux.grid.GridFilters({
filters : [
{type: 'string', dataIndex: 'display_name'},
{type: 'string', dataIndex: 'infohash'},
{type: 'boolean', dataIndex: 'enabled'}
],
buildQuery : function(filters) {
var myarray = [];
for(var i = 0; i < filters.length; i++) {
myarray.push({'field' : filters[i].field, 'type' : filters[i]['data'].type, 'value' : filters[i]['data'].value});
};
filterstring = Ext.util.JSON.encode(myarray);
bufferedDataStore.proxy.conn.url = url + "?filters=" + filterstring;
return {'filters' : filterstring};
}
});


thx

m

efattal
4 Feb 2008, 2:53 AM
My solution for combining Livegrid and RowNumberer:
- Define an extension of Ext.grid.RowNumberer:

Ext.ux.grid.RowNumberer = Ext.extend(Ext.grid.RowNumberer, {
renderer : function(v, p, record, rowIndex, colIndex, store){
if(this.rowspan){
p.cellAttr = 'rowspan="'+this.rowspan+'"';
}
return store.getGridView().bufferRange[0]+rowIndex+1;
}
});
- Use this class as a column in the ColumnModel

var colModel = new Ext.grid.ColumnModel([
new Ext.ux.grid.RowNumberer(),
{header: "Ticker", width: 60, sortable: true},
...
]);
- Link both when creating the BufferedStore :


this.view = new Ext.ux.grid.BufferedGridView({
....
});
new Ext.ux.grid.BufferedStore({
....,
getGridView: function(){return this.view}.createDelegate(this)
});

It works.

Does anyone have a better solution ?

Thanks for your answers

redxiii
5 Feb 2008, 11:48 PM
I cannot access to http://www.siteartwork.de/2007/11/10...nt-with-extjs/ (http://www.siteartwork.de/2007/11/10/livegrid-component-with-extjs/) is has a message
" This Domain is currently inaccessible! "

Please post it to me.

thank a lot

mattb
7 Feb 2008, 2:29 PM
Hi all,

Anyone had any luck plugging LiveGrid into an editable grid?

I'm having some success, but I'm having trouble getting record inserts to work without really messing up the grid view...

m

Sultanalifezar
12 Feb 2008, 7:39 AM
Anyone have the latest? I had to get a copy of the code from a chinese website, thx god I can read a little chinese. Anyhow it has alot of bugs\defects and I've fixed alot of them, but I was wondering if there was a more stable version available, and since I can't get to the guys domain says its down. Any help is appreciated. THx.

Sultanalifezar
15 Feb 2008, 6:00 AM
Thanks for your help. I've tried your fix but it doesn't work for me. I attached the firebug output with the error.

Ok I fixed it, what is happening is the scroll is being adjusted and the last row is not painted before other code runs so it doesn't exist and that causes the error.

In BufferedGridView.js in adjustScrollerPos add the marked line of code, it will force an update of the grid and make it all good. Enjoy.


adjustScrollerPos : function(pixels, suspendEvent)
{
var liveScroller = this.liveScroller;

if (suspendEvent === true) {
liveScroller.un('scroll', this.onLiveScroll, this);
}

liveScroller.dom.scrollTop += pixels;
this.onLiveScroll(); //forces grid to update fixed using arrow keys to move up from top or down from bottom.

if (suspendEvent === true) {
liveScroller.dom.scrollTop = liveScroller.dom.scrollTop;
liveScroller.on('scroll', this.onLiveScroll, this);
}

}

Shmoo
19 Feb 2008, 7:13 PM
I found a solution for this -- I had already created a buildQuery function in the GridFilters definition. Whenever that function is executed to change the filters, I change the URL for the data store to pass the filter to the server:



var url = '/cdt/grid_data';
var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
sortInfo : {field: 'display_name', direction: 'ASC'},
url : url
});

var filters = new Ext.ux.grid.GridFilters({
filters : [
{type: 'string', dataIndex: 'display_name'},
{type: 'string', dataIndex: 'infohash'},
{type: 'boolean', dataIndex: 'enabled'}
],
buildQuery : function(filters) {
var myarray = [];
for(var i = 0; i < filters.length; i++) {
myarray.push({'field' : filters[i].field, 'type' : filters[i]['data'].type, 'value' : filters[i]['data'].value});
};
filterstring = Ext.util.JSON.encode(myarray);
bufferedDataStore.proxy.conn.url = url + "?filters=" + filterstring;
return {'filters' : filterstring};
}
});


thx

m

Thanks!

Its good to see that people already thinking of mixing up FilteredGrid and LiveGrid.. I am trying one myself.. I'll post my codes once I get things up and running.

EDIT: Managed to get the LiveGrid working but I think my filters won't work because I set local:true for the filters.
Do I have to set anything within LiveGrid or do I have to set filters to remote? I am leaning on setting the filter to remote
but I have no script in handling filters on the server-side. >.<



var filters = new Ext.ux.grid.GridFilters({
local:true,
buildQuery : function(filters) {
var myarray = [];
for(var i = 0; i < filters.length; i++) {
myarray.push({'field' : filters[i].field, 'type' : filters[i]['data'].type, 'value' : filters[i]['data'].value});
};
filterstring = Ext.util.JSON.encode(myarray);
bufferedDataStore.proxy.conn.url = GET_STUDY_DATASET_URL + "?filters=" + filterstring;
return {'filters' : filterstring};
},
filters:[
/* some filter data here */
]});


I cannot post the filter data(sorry) but its just some Apache Velocity Template code. :s

2le
20 Feb 2008, 12:54 AM
Hi,

I'm using this live grid in a sort of webmail projet. But when i scroll, I have the following error in firebug and the grid doesn't update.

I don't know why, so any idea is welcome.

You could try at www.kiwi-mail.fr login : demo/demo

Thanks in advance

K has no properties
GridView([Object name=type id=0 style=width:30px;text-align:left;, Object name=subject id=1, Object name=contact id=2, 3 more...], [undefined, undefined, undefined, 3 more...], Object autoLoad=true bufferSize=150 reader=Object, 93, 6, false)ext-all.js (line 141)
GridView(93, 93)ext-all.js (line 141)
replaceLiveRows(171, true)BufferedGridView.... (line 1371)
updateLiveRows(171, true, undefined)BufferedGridView.... (line 1222)
adjustVisibleRows()BufferedGridView.... (line 1477)
layout()BufferedGridView.... (line 434)
initComponent()ext-all.js (line 140)
initComponent(1043, 251)ext-all.js (line 62)
onLayout(Object x=0 y=0 width=1043 height=251)ext-all.js (line 70)
onLayout(Object initialConfig=Object layout=Object title=Messages, Object dom=div#ext-gen40.x-panel-body id=ext-gen40)ext-all.js (line 70)
ContainerLayout()ext-all.js (line 65)
onLayout(Object el=Object resizingEl=Object orientation=1, 200)ext-all.js (line 70)
Observable()ext-all.js (line 12)
Observable()ext-all.js (line 12)
SplitBar(Object browserEvent=Event mousemove button=0)ext-all.js (line 63)
apply()ext-base.js (line 9)
DragDrop(Object browserEvent=Event mousemove button=0)ext-all.js (line 31)
apply()ext-base.js (line 9)
DragDrop(Object browserEvent=Event mousemove button=0)ext-all.js (line 31)
EventManager(Object browserEvent=Event mousemove button=0)ext-all.js (line 13)
getViewWidth(mouseup clientX=0, clientY=0)ext-base.js (line 10)
[Break on this error] Ext.grid.GridView=function(A){Ext.apply(this,A);this.addEvents("beforerowremoved...

khatuido
26 Feb 2008, 3:53 AM
Nice code it works fine :) except when we try use it with an editor grid :(.

There is a first problem in the method ensureVisible cos c is not defined so i add this. It's looks works.


ensureVisible : function(row, col, hscroll)
{
[...]

if(hscroll !== false){
/** AJOUT LIVEGRID */
var g = this.grid;
var c = g.getGridEl();
/* FIN AJOUT LIVEGRID **/
[...]

But i still got a problem when i bufferred the grid. It lost the modify and i cannot edit the last row. Someone use the livegrid with an editor grid?

khatuido
26 Feb 2008, 8:06 AM
in fact i got a problem when the scrollbar is down it put my edit row out of my grid and create an error.

False Maria
27 Feb 2008, 11:52 AM
Hi everyone,

This is my first post, so forgive me if I forget to mention something.

I am working on a web app which will be using ExtJS, mostly for the grid functionality. We ran into an issue when dealing with large amounts of data. The grid was taking too long, ever with paging, so we decided to go with the LiveGrid User Extension.

The problem is this, even when I try and replicate the LiveGrid using hard-coded json in data-proxy.php, it won't sort *any* of the data. It shows the "Loading" screen briefly before coming back, unsorted.

Here is the modified PHP from data-proxy.php

<?php


$length = 500;

$feeds = array('response' => array(
'value' => array()
));


for ($i=1;$i<500;$i++) {

$feeds['response']['value']['items'][] = array(
'id' => $i,
'number_field' => rand(900,1000),
'string_field' => rand(900,1000),
'date_field' => rand(900,1000)
);
}

if (!isset($feeds['response']['value']['items'])) {
$feeds['response']['value']['items'] = array();
}

$feeds['response']['value']['total_count'] = $length;
$feeds['response']['value']['version'] = 1;

// +----------------------------------------------------------------------------
// | You need to json_encode the array. If your PHP installation does not support
// | json_encode, go and get the Zend Framework at http://framework.zend.com,
// | which provides userland json encoding/decoding logic.
// +----------------------------------------------------------------------------
if (function_exists('json_encode')) {
$json = json_encode($feeds);
} else {
require_once 'Zend/Json.php';
$json = Zend_Json::encode($feeds);
}

echo $json;
?>

and here is my modified example.html


<!DOCTYPE htmlPUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html>
<head>

<title>ExtJS (V2 RC1) live grid (user extension)</title>

<!-- your usual ext stuff -->
<script type="text/javascript" src="ext-2.0.1/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-2.0.1/ext-all.js"></script>
<link rel="stylesheet" type="text/css" href="ext-2.0.1/resources/css/ext-all.css"/>

<!-- needed files for the ux -->
<script type="text/javascript" src="ext-2.0.1/ux/widgets/grid/BufferedGridView.js"></script>
<script type="text/javascript" src="ext-2.0.1/ux/widgets/grid/BufferedRowSelectionModel.js"></script>
<script type="text/javascript" src="ext-2.0.1/ux/widgets/grid/BufferedStore.js"></script>
<script type="text/javascript" src="ext-2.0.1/ux/widgets/BufferedGridToolbar.js"></script>
<script type="text/javascript" src="ext-2.0.1/ux/data/BufferedJsonReader.js"></script>


</head>
<body>


<h1>Live Grid Example</h1>
<p>This example shows how to create a grid representing a large amount of data without additional
paging buttons.</p>
<p>The grid sits in a Ext.Window to demonstrate the BufferedGridView's resize behavior.</p>
<p></p>
<p>Please report bugs and feature requests to Thorsten Suckow-Homberg &lt;<a href="mailto:ts@siteartwork.de">ts@siteartwork.de</a>&gt;</p>
<p><a href="http://www.siteartwork.de">http://www.siteartwork.de</a></p>
<p>Forum entry: <a href="http://extjs.com/forum/showthread.php?p=84902#post84902">http://extjs.com/forum/showthread.php?p=84902#post84902</a></p>
<p>Blog entry: <a href="http://www.siteartwork.de/2007/11/10/livegrid-component-with-extjs/">http://www.siteartwork.de/2007/11/10/livegrid-component-with-extjs/</a></p>

<p>Project home: <a href="http://www.siteartwork.de/livegrid">http://www.siteartwork.de/livegrid</a></p>
<script type="text/javascript">




Ext.onReady(function(){

// +----------------------------------------------------------------------------
// | How to use your new components...
// +----------------------------------------------------------------------------
/**
* BufferedJsonReader derives from Ext.data.JsonReader and allows to pass
* a version value representing the current state of the underlying data
* repository.
* Version handling on server side is totally up to the user. The version
* property should change whenever a record gets added or deleted on the server
* side, so the store can be notified of changes between the previous and current
* request. If the store notices a version change, it will fire the version change
* event. Speaking of data integrity: If there are any selections pending,
* the user can react to this event and cancel all pending selections.
*/
var bufferedReader = new Ext.ux.data.BufferedJsonReader({
root : 'response.value.items',
versionProperty : 'response.value.version',
totalProperty : 'response.value.total_count',
id : 'id'
}, [ {
name : 'number_field', sortType : 'int'
},{
name : 'string_field', sortType : 'string'
},{
name : 'date_field', sortType : 'int'
}]);

/**
* Set up your store.
* An instance of BufferedJsonReader is needed if you want to listen to
* <tt>versionchange</tt> events.
* Make sure you set the config option bufferSize high enough
* (something between 100 and 300 works good).
*/
var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
sortInfo : {field: 'number_field', direction: 'ASC'},
url : 'data-proxy.php'
});

/**
* Here is where the magic happens: BufferedGridView. The nearLimit
* is a parameter for the predictive fetch algorithm within the view.
* If your bufferSize is small, set this to a value around a third or a quarter
* of the store's bufferSize (e.g. a value of 25 for a bufferSize of 100;
* a value of 100 for a bufferSize of 300).
* The loadMask is optional but should be used to provide some visual feedback
* for the user when the store buffers (the loadMask from the GridPanel
* will only be used for initial loading, sorting and reloading).
*/
var bufferedView = new Ext.ux.grid.BufferedGridView({
nearLimit : 100,
loadMask : {
msg : 'Please wait...'
}});

/**
* You can use an instance of BufferedGridToolbar for keeping track of the
* current scroll position. It also gives you a refresh button and a loading
* image that gets activated when the store buffers.
* ...Yeah, I pretty much stole this one from the PagingToolbar!
*/
var bufferedGridToolbar = new Ext.ux.BufferedGridToolbar({
view : bufferedView,
displayInfo : true
});

/**
* BufferedRowSelectionModel introduces a different selection model and a
* new <tt>selectiondirty</tt> event.
* You can keep selections between <b>all</bb> ranges in the grid; records which
* are currently in the buffer and are selected will be added to the selection
* model as usual. Rows representing records <b>not</b> loaded in the current
* buffer will be marked using a predictive index when selected.
* Selected rows will be successively read into the selection store
* upon scrolling through the view. However, if any records get added or removed,
* and selection ranges are pending, the selectiondirty event will be triggered.
* It is up to the user to either clear the pending selections or continue
* with requesting the pending selection records from the data repository.
* To put the whole matter in a nutshell: Selected rows which represent records
* <b>not</b> in the current data store will be identified by their assumed
* index in the data repository, and <b>not</b> by their id property.
* Events such as <tt>versionchange</tt> or <tt>selectiondirty</tt>
* can help in telling if their positions in the data repository changed.
*/
var bufferedSelectionModel = new Ext.ux.grid.BufferedRowSelectionModel();




// +----------------------------------------------------------------------------
// | ... nothing fancy in here. The usual Ext setup process of the panel
// | and the column model, totally independent of the above configuration
// | options.
// +----------------------------------------------------------------------------
var colModel = new Ext.grid.ColumnModel([
{header: "Number", align : 'left', width: 160, sortable: true, dataIndex: 'number_field'},
{header: "String", align : 'left', width: 160, sortable: true, dataIndex: 'string_field'},
{header: "Date", align : 'right', width: 160, sortable: true, dataIndex: 'date_field'}
]);


var grid = new Ext.grid.GridPanel({
ds : bufferedDataStore,
enableDragDrop : false,
cm : colModel,
sm : bufferedSelectionModel,
loadMask : {
msg : 'Loading...'
},
view : bufferedView,
title : 'Large table',
bbar : bufferedGridToolbar
});

var w = new Ext.Window({
title : 'Ext.ux.grid.BufferedGridView V0.1',
maximizable : true,
resizable : true,
layout : 'fit',
items : [grid],
height : 400,
width : 500
});

w.show();

});


</script>

</body>
</html>

Sultanalifezar
4 Mar 2008, 5:21 PM
The reason is that the grid doesn't sort, it expects you to sort it, it sends the dataindex of the store and a sort direction to your php as parameters

sort=number_field&dir=ASC

So you need to handle it in your php

Hope that helps

Emt
6 Mar 2008, 9:21 PM
Excellent work. Can I use this component for loading data from XML Dom instead of hitting Database every time.

efattal
10 Mar 2008, 2:03 AM
Hi guys,

Did anyone manage to make Livegrid work with Ext 2.0.2?

Thanks for you help.

hallikpapa
14 Mar 2008, 9:13 PM
very nice. I am using the GroupingStore and GroupingView for my grids datastore, and the ux filters plugin, etc, so I can filter, and group columns together. I wonder if there is a way to combine all these together. I am looking at the code now, but wondered if anyone else has tried to accomplish this.

From the looks of it, it seems I can use the filter and livegrid together, but give up the grouping view, but I may be wrong.

ThorstenSuckow
18 Mar 2008, 3:45 AM
I have updated the code so it works with Ext 2.0.2 (haven't tested with 2.0.1, though).

Regards

Thorsten

gtaylor
18 Mar 2008, 4:51 AM
For our education, what did you have to change to get Livegrid to work with 2.02?
Thanks for addressing the issue.

ThorstenSuckow
18 Mar 2008, 5:16 AM
I have changed the getRows-method in BufferedGridView - it checks wether the return parameter of ensureVisible is null (seems like Ext.Element.setXY assumes it is all the time set). There was also a bug in ensureVisible where the row-index to scroll to may have been lees than 0.

mepfuso
18 Mar 2008, 5:36 AM
Servus aus M

efattal
19 Mar 2008, 1:10 AM
Thanks Thorsten.

ThorstenSuckow
19 Mar 2008, 2:55 AM
[QUOTE=mepfuso;139739]Servus aus M

bluefeet
19 Mar 2008, 12:25 PM
What is the chance of this ever being included as part of the ExtJS download? I'd like to use LiveGrid, but I'm concerned that this add-on will loose favor and maintenance will stop at some point (as all small projects eventually do). Anything you can share that would help me feel better about using this tool in the corporate environment that I am in would be greatly appreciated.

Good work, BTW!

ThorstenSuckow
19 Mar 2008, 1:18 PM
Excellent work. Can I use this component for loading data from XML Dom instead of hitting Database every time.

No support for XML data right now. the best way to work with this kind of data is to transform it server side into json encoded data.

ThorstenSuckow
19 Mar 2008, 1:25 PM
In sum,

Live Grid over Live Data (data that might change during use) poses the above challenges. Live Grid over historical data that doesn't change poses none of the above challenges.

If dealing with Live Data, then Live Grid poses difficulties for managing range selections and actions on those selections. ID-based single selections are no problem, of course.

In the case of actionable lists over live data, a paging interface may be preferred, simply to avoid such issues.

Opinions?

Thanks Again,
Joe Hanink

I introduced the versionChange property to deal with this. It is up to the backend to change this property and send it to the client whenever you can tell that data on the server side changed. An event will be fired then and you can react to it right after way: Clearing all pending selections, for example.

andreas.linde
27 Mar 2008, 9:59 AM
Hi,

thanks for the great plugin. Just playing around with it to find out the consequences using it. So I stumpled uppon a problem where using the following code with "enableRowBody" does not have any effect :-/



viewConfig: {
enableRowBody:true,
forceFit:true,
showPreview:true,
getRowClass : function(record, rowIndex, p, store){
if(this.showPreview){
p.body = '<p>'+record.data.excerpt+'</p>';
return 'x-grid3-row-expanded';
}
return 'x-grid3-row-collapsed';
}
},


Any ideas?

ThorstenSuckow
27 Mar 2008, 10:09 AM
Hi,

thanks for the great plugin. Just playing around with it to find out the consequences using it. So I stumpled uppon a problem where using the following code with "enableRowBody" does not have any effect :-/



viewConfig: {
enableRowBody:true,
forceFit:true,
showPreview:true,
getRowClass : function(record, rowIndex, p, store){
if(this.showPreview){
p.body = '<p>'+record.data.excerpt+'</p>';
return 'x-grid3-row-expanded';
}
return 'x-grid3-row-collapsed';
}
},


Any ideas?

The rowHeight is fixed in the gridView to compute buffer ranges, rows to render etc. pp. I have never played with the enableRowBody option so yeah, this might be broken and I'm not sure wether this can be implemented easily. Sorry I have no better news for you atm. ~o)

jbd007
27 Mar 2008, 10:40 AM
Really want to get this working but I keep getting this error in Firebug:

this.addEvents is not a function (on line 113 of BufferedStore.js)

Anyone have any ideas? It doesn't seem to mind the other objects using that method but it doesn't seem to like this JS file?

ThorstenSuckow
27 Mar 2008, 10:45 AM
Really want to get this working but I keep getting this error in Firebug:

this.addEvents is not a function (on line 113 of BufferedStore.js)

Anyone have any ideas? It doesn't seem to mind the other objects using that method but it doesn't seem to like this JS file?


Never run into this error. I guess you don't get this error when looking at http://www.siteartwork.de/livegrid_demo ?

What does your setup look like?

jbd007
27 Mar 2008, 12:23 PM
I had a dumb typo that I just didn't catch for the longest time, so sorry for wasting your time on that last one.

But I'm still noticing some strange behavior now that I have it working: It seems to get stuck in an infinite loop if I scroll too quickly? If I have a list 1000 rows long, set my buffer to 100 and my nearLimit to 25 .... I can 'slowly' scroll down the list and it works. But if I grab the scrollbar and scroll all the way to the bottom, it just keeps flashing 'Please Wait' with the loading symbol in the middle of the grid (and sometimes it flashes to the upper left corner of the grid)? And because I have Firebug I can see that it's just repeatedly hitting the server (and seems to be just calling 'start' as 0?). Am I doing something wrong here?

ThorstenSuckow
27 Mar 2008, 7:49 PM
I had a dumb typo that I just didn't catch for the longest time, so sorry for wasting your time on that last one.

But I'm still noticing some strange behavior now that I have it working: It seems to get stuck in an infinite loop if I scroll too quickly? If I have a list 1000 rows long, set my buffer to 100 and my nearLimit to 25 .... I can 'slowly' scroll down the list and it works. But if I grab the scrollbar and scroll all the way to the bottom, it just keeps flashing 'Please Wait' with the loading symbol in the middle of the grid (and sometimes it flashes to the upper left corner of the grid)? And because I have Firebug I can see that it's just repeatedly hitting the server (and seems to be just calling 'start' as 0?). Am I doing something wrong here?

Not to sure about this. Please provide an example or a link to your setup so I can check it out myself.

gelleneu
1 Apr 2008, 12:29 AM
I have the same problem. Firebug says something like an error with ds.getTotalCount()... Any solution?

jbd007
1 Apr 2008, 11:54 AM
I don't really have an external app that I can make available to you .... let me ask you this since it has always kind of confused me:

Here is my code for the bufferedstore (and reader):
var accountStore = new Ext.ux.grid.BufferedStore({
url:'../json/ips/accountinquiryajaxcontroller.jsp',
sortInfo:{field:'accountNumber', direction:'ASC'},
bufferSize:20,
reader: new Ext.ux.data.BufferedJsonReader({
root:'accounts',
versionProperty:'results',
totalProperty:'results',
id:'invoiceControlId'
}, InvoiceControl),
remoteSort:true
});

If I am not updating the Grid, do I need to specify the 'versionProperty' ? I just set it to be the same as my total count ('results') thinking that should uniquely identify the 'version'. Could use (or incorrect use) of version property be what is maybe causing my 'constant update' problem?

ThorstenSuckow
1 Apr 2008, 4:09 PM
I don't really have an external app that I can make available to you .... let me ask you this since it has always kind of confused me:

Here is my code for the bufferedstore (and reader):
var accountStore = new Ext.ux.grid.BufferedStore({
url:'../json/ips/accountinquiryajaxcontroller.jsp',
sortInfo:{field:'accountNumber', direction:'ASC'},
bufferSize:20,
reader: new Ext.ux.data.BufferedJsonReader({
root:'accounts',
versionProperty:'results',
totalProperty:'results',
id:'invoiceControlId'
}, InvoiceControl),
remoteSort:true
});

If I am not updating the Grid, do I need to specify the 'versionProperty' ? I just set it to be the same as my total count ('results') thinking that should uniquely identify the 'version'. Could use (or incorrect use) of version property be what is maybe causing my 'constant update' problem?


Thx for your post. As I'm not able to test it right away, please do the following: Check the number of visible rows in your grid, i.e. how many rows are displayed? The value 20 for the bufferSize seems to be too low so I suggest to set this value to anything between 100 and 200.

Digital God
1 Apr 2008, 10:25 PM
There is one bug in live grid - it doesn't show the last row in grid
showing "Claim 25980-25996 of 25997"

jbd007
2 Apr 2008, 8:23 AM
Well with a larger dataset it does seem to work now .... I'm not sure why it was failing with the smaller dataset size .....

I had one DB with only 31 entries in the table so I was using (20/5) as my buffer and nearlimit and it didn't like that. But with a DB that had 800 entries, I used (400/100) and that seemed to work.

ThorstenSuckow
2 Apr 2008, 10:08 AM
Well with a larger dataset it does seem to work now .... I'm not sure why it was failing with the smaller dataset size .....

I had one DB with only 31 entries in the table so I was using (20/5) as my buffer and nearlimit and it didn't like that. But with a DB that had 800 entries, I used (400/100) and that seemed to work.

Okay, so the algorithm for computing the fetched rows together with the nearLimit and the bufferSize seems to cause the problems. I'll take care of this.

msynovic
7 Apr 2008, 7:46 AM
First. My compliments on creating a very useful extension. I am just starting to explore ExtJS and started playing with your current version of the LiveGrid solution.

With my POC I found a bug in your BufferedGridView.updateLiveRows method:


Ext.apply(params, this.ds.lastOptions);should be


Ext.apply(params, this.ds.lastOptions.params);I found this because my POC was passing a custom parameter into the load method of the store, but that parameter was not being passed to subsequent data calls by LiveGrid.

Also, I am experiencing a problem it seems with the render algorithm. It is randomly duplicating rows of data. See the attached screen shot, you can see row 26 is duplicated. I've been trying to isolate the cause but have so far been unsuccessful.

I have verified that the problem is not with the return data. Only one object is returned with the details displayed for row 26. My data set contains 166 total rows, with a bufferSize value of 100 and nearLimit value of 25.

What is interesting is that the problem doesn't exist while scrolling through the original data set, but only appears after a fetch for more data is made and I start scrolling up and down. The row that is duplicated changes but I can consistently get a duplicate row to appear. I see the problem in both IE and Firefox.

Has anyone else experienced this behavior?

msynovic
7 Apr 2008, 10:39 AM
Also, I am experiencing a problem it seems with the render algorithm. It is randomly duplicating rows of data. See the attached screen shot, you can see row 26 is duplicated. I've been trying to isolate the cause but have so far been unsuccessful.


Don't waste any cycles on this issue. It was a problem with my POC - the control works beautifully.

jbd007
7 Apr 2008, 3:38 PM
Thanks MindPatterns, glad I could help in the testing ... I can see end-users liking this much more than the 'paging' interface because it makes them 'feel' like they are getting 'everything' back when they query; whereas they complain when I use something like the paging inteface because they feel like we are 'limiting' them. In reality, you limit them too, it's just not as obvious. In our industry, like many others, perception is reality. :)

ohhowihateie
8 Apr 2008, 2:38 PM
This plugin is fantastic, and is a great solution for a number of situations. Is there any way to get grouping to work with this? Has anyone else tried this?

MindPatterns said on 11-23-2007 that he did not think it was possible without major revisions to BufferedGridView. Has anyone tried this?

zergworld
9 Apr 2008, 11:27 PM
The rowHeight is fixed in the gridView to compute buffer ranges, rows to render etc. pp. I have never played with the enableRowBody option so yeah, this might be broken and I'm not sure wether this can be implemented easily. Sorry I have no better news for you atm. ~o)

I was able to make this work by changing the assumption in BufferedGridView.adjustVisibleRows() that initializes the rowheight only once. So, the rowheight is still fixed over all the rows, but this allows it to change based on the rowbody mode in effect and basically allows for expressing data as "inline detail"

changed the beginning portion to

if (this.getRows()[0]) {
this.rowHeight = this.getRows()[0].offsetHeight;
} else {
return;
}

zergworld
9 Apr 2008, 11:38 PM
Okay, so the algorithm for computing the fetched rows together with the nearLimit and the bufferSize seems to cause the problems. I'll take care of this.

I had an N+1 problem when viewing a data set that was 1 larger than the buffer.

i fixed this by modifying BufferedGridView.isInRange() to

{
var lastRowIndex = Math.min(this.ds.totalLength-1, rowIndex + this.visibleRows);
return (rowIndex >= this.bufferRange[0]) &&
(lastRowIndex <= this.bufferRange[1]) &&
(this.bufferRange[1] > (rowIndex + this.visibleRows));
}

luxxxian
10 Apr 2008, 7:05 AM
Firstly I would like to thank Thorsten for taking the time to make such a great plug-in and share it with us :>

I am trying now to prepare a demo where I am replacing an older application which used Rico Live grid with this plug-in.
I need to determine which are the First and Last rows selected with Shift, and the rows selected with Control. I have searched this topic, but unfortunately I didn't find anything helpful, and also debugging with Firebug I wasn't able to determine this.
Any help is very appreciated, as I need to show this demo tomorrow afternoon, and I am running out of time :)

w011117
15 Apr 2008, 4:54 PM
Hello,
My compliments for an absolutely GREAT plugin.
I am having a problem whereby the grid does not fully render in a TabPanel (Not first or active tab) when I have deferredRender set to True. It works perfectly when the deferred render is set to False.
Any suggestions?

Thanks,
Timmer

herve
16 Apr 2008, 12:51 AM
Hello,

First of all, congratulations for this great extension.

I have a couple of problems/comments/questions. All the problems observed with firefox 2 on windows xp (not tried another browser). Note that the files in attachment show how to reproduce the problems. I have implemented a fake proxy to help the debugging and simplify the reporting of problems, but it shows the same behavior with the httpProxy.

1. small bug: when you maximize the window containing the grid, the scrollbar moves to the top, but the first row remains to what it was so you cannot scroll up anymore.

2. I tried to scroll to end by calling ensureVisible. It works but it raises an exception (see attachement to reproduce).

3. when I call reload() function, the scrollbar moves to the top. I don't know if this is a bug or a feature, but it could be annoying for users, especially with large datasets.

4. I would like to get rid of the load mask, which is not useful for an intranet application. I have overriden the showLoadMask method. It almost works except when you call reload. It would be great to have a configurable option to properly disable the loadmask.

Thanks

Yann

bemn
17 Apr 2008, 1:11 AM
Hi,

Thanks for this great tool!

Does anyone have some experience with adding a record to the end of the view. (I want to "tail" some records, and watch them when they are added at the end of the grid).

Thx!

dandvd
17 Apr 2008, 10:23 PM
Great work, Thorsten! Thanks for coding LiveGrid, it rocks!

I tried to make the columns auto-size to the width of the largest cell, like a regular HTML table, using Animal's code (http://extjs.com/forum/showthread.php?p=97676#post97676) with a small modification: instead of iterating through the elements in the store (300 by default), I iterated only through the visible rows (the rest of the rows are not rendered, so getRow(this.view.visibleRows) would return null. Here is the code and please let me know if it can be improved:


var grid = new Ext.grid.GridPanel({
...
autoSizeColumns: function() {
for (var i = 0; i < this.colModel.getColumnCount(); i+=1) {
this.colModel.setColumnWidth(i, this.autoSizeColumn(i));
}
},

autoSizeColumn: function(c) {
var w = this.view.getHeaderCell(c).firstChild.scrollWidth;
var count = this.view.visibleRows;
for (var i = 0; i < count; i+=1) {
w = Math.max(w, this.view.getCell(i, c).firstChild.scrollWidth);
}
return w;
}
}


Two questions:

The grid seems to redraw itself after each column's width is modified. Is there a way to do this redrawing only once, after changing the widths of all columns?
The code must be called from an event triggered after the grid has loaded data. I currently use a button. Where should the call be placed so that it's called as the users scrolls through the grid?

http://automaticallyyours.com/icons/smiley4.gif

Daniel_Brazil_Campinas
18 Apr 2008, 9:20 AM
Guys,

I updated 2 files to keep rows selected after a refresh or reload.
I had to comment some code lines to keep selection.

The first file was : BufferedGridView.js :
On reset method, we removed the line that was clearing the selections.
this.grid.selModel.clearSelections(true);.

The second file was: BufferedRowSelectionModel.js
On onRefresh method looks like that :

onRefresh : function()
{
var ds = this.grid.store, index;
var s = this.getSelections();
//this.clearSelections(true);
for(var i = 0, len = s.length; i < len; i++){
var r = s[i];
if((index = ds.indexOfId(r.id)) != -1){
this.selectRow(index, true);
}
}
}

I have tested, and for our case, it seems to be ok.

If anybody realize a problem in that, could you comment ?

I hope it helps some of you.

Regards.

herve
22 Apr 2008, 12:07 AM
Hi,

Thanks for this great tool!

Does anyone have some experience with adding a record to the end of the view. (I want to "tail" some records, and watch them when they are added at the end of the grid).

Thx!

Hello,

I have attached to this post my example to add records. The intent is to implement something similar to unix 'tail' in a browser.

This example does not require any server (there is a special proxy to keep the data in the browser), but I think it can be changed to use the regular http proxy instead.

Yann

ohhowihateie
22 Apr 2008, 7:59 AM
Has anyone else had the problem of not being able to see/scroll to the records at the bottom of the list? When I reorder the results (remotely via MySQL) I can see the ones that I missed, but then the ones at the other end are missing.



var store = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : reader,
sortInfo:{
field: 'id',
direction: "ASC"
},
proxy: new Ext.data.HttpProxy({ url: 'data.php' })
});

var view = new Ext.ux.grid.BufferedGridView({
nearLimit : 100,
forceFit:true,
emptyText: 'No results found',
loadMask : { msg : 'Please wait...'}
});

var bufferedSelectionModel = new Ext.ux.grid.BufferedRowSelectionModel();

var bufferedGridToolbar = new Ext.ux.BufferedGridToolbar({
view : view,
displayInfo : true
});

var cm = new Ext.grid.ColumnModel([
{id: 'id', header: 'ID', dataIndex: 'id', align: 'left', width: 70},
...
{id: 'updated', header: 'Updated', type: 'date', dataIndex: 'updated', renderer: Ext.util.Format.dateRenderer('m/d/Y')}
]);
cm.defaultSortable='true';

var grid = new Ext.grid.GridPanel({
id:'Grid',
store: store,
enableDragDrop : false,
sm : bufferedSelectionModel,
loadMask : {
msg : 'Loading...'
},
tbar: mainGridTbar,
cm: cm,
view: view,
frame:true,
collapsible:true,
autoHeight: true,
layout:'fit',
bbar: bufferedGridToolbar
});
The data being loaded from JSON is coming in properly. I get the correct number of results and the results come in right, it just seems that I cannot scroll to the bottom if the results go off the page/outside of the window.

sdetweil
23 Apr 2008, 7:31 PM
I have been integrating the Livegrid code into cfext, and have discovered a problem..

after a sort, on a different column, how do you recalc the buffer position and then scroll the right records?

The initial sort column is specified on the store, and is never changed.

so, you scroll down, and are at row 627 of 5000, and decide to sort on a different column.
three things..
1. is the grid after sort showing the same record (top, bottom, or cursor position) that was show before the sort.. (would be nice)..
2. where is that in the buffer.
3. how do you move in the buffer train from there..?

based on my test, the sort column info passed to the URL remains the same (uses the same column).. so this will cause a problem.. for example, if you sort on name you are in trouble..

the sample php code does "SELECT * FROM $table ORDER BY" which is ALL rows.. but for a big database this would be very bad.. (mine is 1.6 million rows, or 100,000, or 50,000 or 200)

so I think the start variable has to change columns and the php code (or whatever) has to deal with starting in the middle of the database, with no inital column sorted, and have to search backwards.

select * from table where $name<=$start_name order by $name $desc limit , $limit
(db2 terms fetch first $limit rows only)

so, I think on a sort column change, you can't let the store do the sort, you have to get the back end to do it. and you have to change the ordering parm in the store so load will work correctly, so I think you have to change the store parms, and then call reset.. you will loose the current position.. but then the buffer will work correctly..

so, in BufferedGridView.updateLiveRows() has to be changed to return the value of the cell at the index for the sorted column
var bufferOffset = this.getPredictedBufferIndex(index, inRange, down);

and the data worker has to use the column name, and this new start value as the control of the data read.

select * from table where $start(>=)$sort order by $start $direction fetch first $limit rows only
(in db2 syntax).
the (>=) has to be dependent on the direction.. if this is descending, then it would be '<='

the start value has to become optional, or if non text (ie 0), then then syntax would be
select * from table fetch first $limit rows only
this takes the first 'limit' rows, unordered.

this causes a problem however if you need to skip over sections of the data. like skip to the end.. hm..

Sam

freddyk
24 Apr 2008, 11:17 PM
Hi!
LiveGrid is very impressive ! Good work !!!

I use Livegrid with an EditorGrid which have a columnModel and "editor: new Ext.form.TextField({}) o NumberField" for each column. LiveGrid works fine !

but I have just a little problem with editorGrid, the 13 first rows can be edit but when I move to the others rows after the 13 first rows, they can not be edit and my listener "validateedit" cause an error in ext_all_debug.js at line 30029
Firebug says me "this.getRow(row) has no properties return this.getRow(row).getElementsByTagName('td')[col];"
It's very stange
What happens ? Why the others can't be edit ? How can I solve this problem please ?

Many thanks!

dshorthouse
25 Apr 2008, 7:24 AM
Great work, Thorsten!

I got filtering to work well and am now trying to implement some additions/deletions/edits either via inline editing or a new window. I have both (sort of) working, but only on the records visible in the initial view. In other words, no amount of scrolling past the initially viewable records permits inline editing or new window because I cannot figure out how to implement the equivalent of bufferedDataStore.getAt(rowIndex). rowIndex is evidently not what I should be using to grab the index/contents of the clicked row. Can anyone advise?

drew
30 Apr 2008, 7:03 PM
Is there a formula for the buffer size and buffer near for live grid?

Basically how can I determine the smallest buffer I can possibly use given x amount of rows on screen.

Has anyone else thought about this...obviously the smaller the buffer the less data you have to pull and the faster you get the data :)

sharpguy
3 May 2008, 7:32 PM
Sounds great, keep it up.

thanks

mattb
7 May 2008, 2:38 PM
Here are some diffs against the current livegrid source that enable combining editor grid functionality. Most of the changes involve overriding the getRow method of the GridView class to handle changing absolute row indexes into relative ones suitable for accessing the data store.

This fixes most of the bugs I've been able to find. There is one rather subtle one where the store and the view can get out of sync when scrolling up after the store loads new data. I suppose when I get more time I'll look into it...

Please don't email me with questions about this stuff - try it for yourself; if you find problems, submit a fix...

Matt

freddyk
8 May 2008, 10:18 AM
Oh very good Mattb, good Work !!!

Since, I found an other solution, I use the Livegrid with a simple Grid panel and when I click on a row + button "Modifier" (tbar button named "change" in English) an other window is open, it contains a form panel wich permits to change the row values and saves the change.

but I will see your solution, I think it will be more simple for the final users and I'll test it.

Many thanks ! ;)

dkuz
9 May 2008, 4:32 AM
Thanks. excelent component.

I think there is small problem w/ parameters passed to proxy. if proxy requeires additional parameters parameters, they are passed differently when scrolling happens.

in BufferGridView.updateLiveRows



var params = {};
Ext.apply(params, this.ds.lastOptions);
params.start = bufferOffset;
params.limit = this.ds.bufferSize;


i think should be replaced w/



var params = {};
Ext.apply(params, this.ds.lastOptions.params);
params.start = bufferOffset;
params.limit = this.ds.bufferSize;


thank you

sinma
13 May 2008, 11:51 PM
Hi,

There is the possibility to grouping columns too?

Thanks.

freddyk
16 May 2008, 2:04 AM
Bonjour,

Je viens d'essayer la solution de Mattb en page 17 pour utiliser un LiveGrid avec un EditorGrid. Avant cette solution, je ne pouvais pas modifier les lignes allant de 14

as
16 May 2008, 5:32 AM
I am using livegrid in a portlet. It works Ok in IE7 and FF2, but in Safari 3 the last row won't be displayed when the scrollbar is activated (i.e. there are more rows than can be rendered in the screen).

The disposition of the livegrid is as follows:

The liveGrid inserted in the tab panel is created as follows:



bufferedReader = new Ext.ux.grid.BufferedJsonReader({
root: "messages",
totalProperty: "total",
id: "id"}, [
{ name: "id" },
{ name: "type" },
{ name: "subject" }
]
);

bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad: false,
bufferSize: 100,
reader: bufferedReader,
url: this.config.url.load,
baseParams: {
param1: paramValue
}
});

bufferedSelectionModel = new Ext.ux.grid.BufferedRowSelectionModel();

bufferedGridColumnModel = new Ext.grid.ColumnModel([
{
id: 'subject',
header: "Subject",
menuDisabled: true,
dataIndex: 'subject'
}]);

bufferedGridPanel = new Ext.grid.GridPanel({
ds: bufferedDataStore,
enableDragDrop: false,
ddGroup: this.folderSettings.ddGroup,
ddText: this.config.label.dndText,
cm: bufferedGridColumnModel,
sm: bufferedSelectionModel,
view: bufferedView,
border: false,
stripeRows: true,
autoExpandColumn : 'subject',
header: true
});


The tab panel inserted in the container is as follows:



tabPanel = new Ext.TabPanel({
items: [bufferedGridPanel],
bodyBorder: false,
border: false,
autoWidth: true,
layoutOnTabChange: true,
deferredRender: false
});


I have a container panel that is the main portlet panel:



container = new Ext.Panel({
renderTo: 'topic.grid',
layout: 'fit',
height: 470,
autoWidth: true,
items: [tabPanel],
border: false,
monitorResize: true
});


Does anyone have any hint on what might be going wrong?

I believe there might be something wrong or misconfigured in my components structure, since the livegrid demo seems to work just fine in safari.

Any help will be tremendous appreciated.

Thanks in advance.

freddyk
17 May 2008, 1:00 AM
Hi !

The bufferSize must be higher than the total count of data to display in the Livegrid.
;)

ThorstenSuckow
17 May 2008, 5:53 AM
I am using livegrid in a portlet. It works Ok in IE7 and FF2, but in Safari 3 the last row won't be displayed when the scrollbar is activated (i.e. there are more rows than can be rendered in the screen).


Confirmed, this seems to be a bug with Safari. I'm taking care of this.

as
20 May 2008, 4:57 AM
Confirmed, this seems to be a bug with Safari. I'm taking care of this.

Hello MindPatterns.

Would you suggest any quick fix we could apply to temporarily solve this?

Thanks.

ThorstenSuckow
20 May 2008, 5:08 AM
Hello MindPatterns.

Would you suggest any quick fix we could apply to temporarily solve this?

Thanks.

Not right now, sorry. I'm currently at the point where I have cleaned up the code, optimized some method calls and adjusted behavior when it comes to adding/removing rows in accordance with the selectionmodel.

RWaters
21 May 2008, 12:58 PM
Hey, I've been helping a client implement this component, definitely nice work.

It seems to make sense to buffer the scroll event listener a tad so that it doesn't fire so much as the user scrolls down the page. A quick tweak to BufferedGridView to make the two 'on' calls add the buffer parameter did the trick nicely.


@@ -355,7 +355,7 @@
// liveScroller and liveScrollerInset
this.liveScroller = new E(cs[0]);
this.liveScrollerInset = this.liveScroller.dom.firstChild;
- this.liveScroller.on('scroll', this.onLiveScroll, this);
+ this.liveScroller.on('scroll', this.onLiveScroll, this, {buffer: 250});

this.mainHd = new E(this.mainWrap.dom.firstChild);
this.innerHd = this.mainHd.dom.firstChild;
@@ -1501,7 +1501,7 @@

if (suspendEvent === true) {
liveScroller.dom.scrollTop = liveScroller.dom.scrollTop;
- liveScroller.on('scroll', this.onLiveScroll, this);
+ liveScroller.on('scroll', this.onLiveScroll, this, {buffer: 250});
}

}

magunes117
22 May 2008, 6:14 AM
Hey, I've been helping a client implement this component, definitely nice work.

It seems to make sense to buffer the scroll event listener a tad so that it doesn't fire so much as the user scrolls down the page. A quick tweak to BufferedGridView to make the two 'on' calls add the buffer parameter did the trick nicely.


@@ -355,7 +355,7 @@
// liveScroller and liveScrollerInset
this.liveScroller = new E(cs[0]);
this.liveScrollerInset = this.liveScroller.dom.firstChild;
- this.liveScroller.on('scroll', this.onLiveScroll, this);
+ this.liveScroller.on('scroll', this.onLiveScroll, this, {buffer: 250});

this.mainHd = new E(this.mainWrap.dom.firstChild);
this.innerHd = this.mainHd.dom.firstChild;
@@ -1501,7 +1501,7 @@

if (suspendEvent === true) {
liveScroller.dom.scrollTop = liveScroller.dom.scrollTop;
- liveScroller.on('scroll', this.onLiveScroll, this);
+ liveScroller.on('scroll', this.onLiveScroll, this, {buffer: 250});
}

}


Hi Rich,

Can you make it a little more clear please? I am using this component in a .NET environment to view about a million records. When I hold the scrollbar and start scrolling it makes the first request and it makes another one when I release the bar. I need to prevent the first request and get the results only for the second one. Is your modification the solution for that?

I know the first request is useful most of the times, but when I try to get the results of a query which returns one million rows of sorted and filtered data, it takes 40 seconds. So two requests doubles this time. I need to omit the first.

Thanks.

RWaters
22 May 2008, 6:26 AM
That is along the lines of what my tweak is for, buffer basically tells it to wait for so many milliseconds before allowing the event to fire, if it gets the same event again within that time period it continues to buffer and only fires that event once. In our cases (which were much smaller than a million records) adding the buffer eliminated the extra first call, though if you are slow about scrolling down you can still get extra calls.

magunes117
22 May 2008, 6:32 AM
Thank you,

I will try and see the results for a million records.

Regards.

magunes117
22 May 2008, 7:03 AM
Hi Rich,

I tried your solution and it worked beautifully for one million records. Thank you very much.

I am having this problem in FF, that when I use horizontal scrollbar to see the right side of grid - when I click o a row it goes to the beginning again. I mean the horizontal scrollbar returns to left-end when I click on a row. May I ask if you or anyone else have the same problem?

Regards.

ThorstenSuckow
22 May 2008, 12:37 PM
Hi Rich,

I tried your solution and it worked beautifully for one million records. Thank you very much.

I am having this problem in FF, that when I use horizontal scrollbar to see the right side of grid - when I click o a row it goes to the beginning again. I mean the horizontal scrollbar returns to left-end when I click on a row. May I ask if you or anyone else have the same problem?

Regards.

Confirmed, will be fixed in the next update.

Snuyt
27 May 2008, 12:57 AM
Hello,

I use firefox 2.0.0.14 (dutch version on windows XP), with the following extensions:

charles autoconfiguration 3.2, dom inspector 1.8.1.14, firebug 1.05, google toolbar 3.0.20070525W, IE tab 1.3.3.20070528, Skype extension 2.2.0.70, Talkback 2.0.0.11, Thumbs 0.6.5, Web Developer 1.1.5, Zend Studio Toolbar 2.0.2

I have a problem with the Vertical scrollbar and the mouse wheel. The mouse wheel does not work and the vertical scrollbar is not visible (see attached image). I get this in the demo livegrid, so no further modifications.

ThorstenSuckow
28 May 2008, 6:38 PM
As I'm close to finish the beta state of my larger application, I am now at the point where I need to polish the livegrid-extension. I moved the source completely over to google-code http://code.google.com/p/ext-ux-livegrid/, so you might want to check out the latest release from the trunk.


Here's the latest changelog - not all of the community additions have made it in there, but I'm looking forward to implement them as quick as possible.

2008-05-28
==========
- fixed: wrong calculation of last displayable row after removing a row caused selection-model
to get out of synch with the store's data

2008-05-17
==========
- enhancement: BufferedStore: removed custom applySort() implementation due to changes in findInsertIndex
- enhancement: BufferedStore: changed findInsertIndex to use parent implementation first, then check
return value and adjust the index if needed
- enhancement: BufferedStore/BufferedGridView: moved bufferRange-member to BufferedStore
- enhancement: BufferedStore: optimized insert() method in BufferedStore
- fixed: when adding a record to the store on the fly, the ensureVisible-method
would not work always corect afterwards
- fixed: when adding records, a previously made selection would block selecting the
newly added record
- enhancement: allowed to add records at position "0" in grid (existing records get shifted down)
- fixed: skipped request for updateLiveRows in Ext.ux.grid.BufferedGridView.adjustVisibleRows
when number of total records in store is less than the number of visible rows
- fixed: request for buffering data in Ext.ux.grid.BufferedGridView.updateLiveRows() did
not apply the property "lastOptions.params" to the params sent with the buffer-request

JEBriggs
29 May 2008, 7:22 AM
Very impressive. I would like to have a live grid that reads from a large store of objects in memory. How easy would it be for me to adapt your code for this requirement?

mlarese
30 May 2008, 7:35 AM
Hi Rich,

I tried your solution and it worked beautifully for one million records. Thank you very much.

I am having this problem in FF, that when I use horizontal scrollbar to see the right side of grid - when I click o a row it goes to the beginning again. I mean the horizontal scrollbar returns to left-end when I click on a row. May I ask if you or anyone else have the same problem?

Regards.

Who is going to read one milion of records?
:))

ThorstenSuckow
30 May 2008, 7:45 AM
Hi Rich,

I tried your solution and it worked beautifully for one million records. Thank you very much.

I am having this problem in FF, that when I use horizontal scrollbar to see the right side of grid - when I click o a row it goes to the beginning again. I mean the horizontal scrollbar returns to left-end when I click on a row. May I ask if you or anyone else have the same problem?

Regards.

Fixed in SVN. See changelog on page 1.

mystix
30 May 2008, 7:53 AM
OT:

Who is going to read one milion of records?
:))
you know what they say:


An apple A record a day...

rtozati
30 May 2008, 10:06 AM
Has anyone noticed that using the live grid demo (http://www.siteartwork.de/livegrid_demo/) if you scroll down some rows (let's say 50 rows) and maximize the window, the live grid scroll bar goes to the top?

This happens in Firefox 2 and Safari 3 (not in IE 7).

I am using the live grid inside a TabPanel, so when I change through tab the live grid always loose the scroll position.

Any solution for this problem?

Thank you.

NoahK17
30 May 2008, 11:37 AM
Also confirmed for FF 3.0 RC1. It scrolls to the top when you maximize, yet keeps the original records on the screen.

el777
30 May 2008, 3:23 PM
Great! I'm really wondered!
I've decided to devote time forlearning this library and your extension.
But only 2 questions: is there any way to make it editable? Howcan we filter rowsin away like filter plugin does?

Cheers

Andrewd2
1 Jun 2008, 3:05 AM
hi
did you think about use BufferedStore in combobox ? is it possible ?

DaveBrewster
2 Jun 2008, 10:27 AM
I'm getting the following 2 request against my rest service when retrieving data:

First request
dirASClimit50sortBranchNamestart30

Second request:
dirASClimit50sortBranchNamestartNaN
Notice the NaN above.

After this the UI goes into a loop continually asking for this record.

The loop continues even if I modify my service to handle this (either to return nothing or return the first N records).

Any thoughts?

Thanks,

Dave

DaveBrewster
2 Jun 2008, 10:58 AM
nearLimit was > bufferSize

Should livegrid throw if it is configured this way?



I'm getting the following 2 request against my rest service when retrieving data:

First request
dirASClimit50sortBranchNamestart30

Second request:
dirASClimit50sortBranchNamestartNaN
Notice the NaN above.

After this the UI goes into a loop continually asking for this record.

The loop continues even if I modify my service to handle this (either to return nothing or return the first N records).

Any thoughts?

Thanks,

Dave

DaveBrewster
2 Jun 2008, 11:23 AM
Nevermind... I hate java script. I had the property nearLimt, not nearLimit

Thanks for playing...

Dave


nearLimit was > bufferSize

Should livegrid throw if it is configured this way?

DaveBrewster
2 Jun 2008, 1:47 PM
I'm seeing the same problem as people were in March. I have a grid that has about 550 records in it. When I scroll fast the view keeps painting (and requesting data) over and over again.

I started debugging it and noticed that the row index it wants to fetch is the first row and the return from getPredictedBufferIndex returns my buffer size (150) - the first row (510), but then it compares the buffer against the last row so it never thinks the data is in range and it keeps requesting the same stuff.

I can create an example if need be. But all I did was take feed viewer and put your component as the grid.

Thanks,

Dave

ThorstenSuckow
2 Jun 2008, 10:23 PM
I can create an example if need be. But all I did was take feed viewer and put your component as the grid.


Hi Dave,

if you are still experiencing this, please submit a bug report under http://code.google.com/p/ext-ux-livegrid

Regards

Thorsten

DaveBrewster
3 Jun 2008, 7:50 AM
I am and I did.

Thanks for such a great widget.



Hi Dave,

if you are still experiencing this, please submit a bug report under http://code.google.com/p/ext-ux-livegrid

Regards

Thorsten

brookd
3 Jun 2008, 8:12 AM
First, thank you for this great extension, its awesome. I am trying to figure out a couple of things:

1. How do I use the versionChange property? Basically, my data set may have records appended to it server side. Lets say I store the totalRecord count on the server and when it changes send the versioChange property. Then, do I need to do anything else client side? How would that work for deleted records?

2. The first row of my grid is always empty - why is this? The data returned does not have a blank row of data. What would cause this?

Thanks for your help!

brookd
3 Jun 2008, 8:54 AM
I finally found grid.selModel.bufferedSelections() to get the array of selected row indexes. Is this the best way to do it?

ftftft
3 Jun 2008, 10:28 AM
I did some code change to make it to support EditorGridPanel. It works. However, I am still reviewing and see if it is good enough.

In the BufferedGridView.js. I added a method.

getCell : function(row, col, adjusted){
if ( !adjusted ) {
row = row-this.rowIndex;
}
return this.getRow(row).getElementsByTagName('td')[col];
}

And replace three occurrences that used getCell() with code like

this.getCell(xxxx, xxx, true);




Great! I'm really wondered!
I've decided to devote time forlearning this library and your extension.
But only 2 questions: is there any way to make it editable? Howcan we filter rowsin away like filter plugin does?

Cheers

DaveBrewster
4 Jun 2008, 2:30 PM
Ok, I figured out the problem.

My content has variable row heights. I'm fine with fixing the row height to the max height (it just has some images in it) but how do I do that? I know how to tell livegrid but how do I tell the backing renderer? Do I need my own?

Thanks,

Dave




I'm seeing the same problem as people were in March. I have a grid that has about 550 records in it. When I scroll fast the view keeps painting (and requesting data) over and over again.

I started debugging it and noticed that the row index it wants to fetch is the first row and the return from getPredictedBufferIndex returns my buffer size (150) - the first row (510), but then it compares the buffer against the last row so it never thinks the data is in range and it keeps requesting the same stuff.

I can create an example if need be. But all I did was take feed viewer and put your component as the grid.

Thanks,

Dave

yhwh
6 Jun 2008, 5:07 PM
Hello,

I use firefox 2.0.0.14 (dutch version on windows XP), with the following extensions:

charles autoconfiguration 3.2, dom inspector 1.8.1.14, firebug 1.05, google toolbar 3.0.20070525W, IE tab 1.3.3.20070528, Skype extension 2.2.0.70, Talkback 2.0.0.11, Thumbs 0.6.5, Web Developer 1.1.5, Zend Studio Toolbar 2.0.2

I have a problem with the Vertical scrollbar and the mouse wheel. The mouse wheel does not work and the vertical scrollbar is not visible (see attached image). I get this in the demo livegrid, so no further modifications.

Well i think i have found the problem :)

In fact i had the same problem on linux with gnome and Glider theme the vertical scrollbar disapear! And i was unable to scroll the grid content:

http://extjs.com/forum/attachment.php?attachmentid=7319&stc=1&d=1212798680

Well now i have tried to change the theme of my gnome window manager with Crux, look the result:

http://extjs.com/forum/attachment.php?attachmentid=7320&stc=1&d=1212798807

With all others standard gnome theme livegrid works (Clearlooks, Glossy, High Contrast, High Contrast Inverse, Low contrast, Mist).


So you may try to change your windows XP theme.

neha.chopra
9 Jun 2008, 8:11 AM
I am a newbie to using Extjs and have used it for a popup window.
and now to fetch the records of that window, i want to use live grid so as to avoid the use of pagination for large amount of data.
In my window, with the data i also have a filter option to filter the data that is fetched upon executing some queries on the server side.

Can live grid work for dynamic data?

zhiliang
10 Jun 2008, 8:29 AM
Hi, I tried your solution, it works well in IE6, but in FF2 there is a bug, if the cell is under horizontal scrollbar, it can not get editable, anyone know how to solve this problem? thx



I did some code change to make it to support EditorGridPanel. It works. However, I am still reviewing and see if it is good enough.

In the BufferedGridView.js. I added a method.

getCell : function(row, col, adjusted){
if ( !adjusted ) {
row = row-this.rowIndex;
}
return this.getRow(row).getElementsByTagName('td')[col];
}

And replace three occurrences that used getCell() with code like

this.getCell(xxxx, xxx, true);

tyr
13 Jun 2008, 7:45 AM
Hi,

today I try to migrate to livegrid. But I does not find a solution to use a RowExpander-Plugin inside a livegrid (attached screenshot). Hints?

Greetings

xenon
16 Jun 2008, 9:53 AM
hi, im new on extjs and nice work mindpatterns, by the way to all, is it possible to set limit on Ext.ux.grid.BufferedStore proxy? My problem is, im loading 15000+ records with 10 columns so it loads about more than 30 seconds, my objective is to load only the desired data to minimize the processing time... below is an example of what i want to do.

First Load:


var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
url : 'email-proxy.php?start=0&limit=100'
});

Scroll Down:


var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
url : 'email-proxy.php?start=100&limit=200'
});

any brilliant ideas? :D

pjordan
16 Jun 2008, 10:22 AM
Thorsten, any idea how difficult this could be adapt to a DataView?

I could really use this, and I would not mind paying for your time. I figure you are most intimate with the inner workings or LiveGrid, so you'd be the best to ask first.

You can PM me if you wish.

Best,

Paul

Bing Qiao
17 Jun 2008, 2:15 AM
Is the source code of data_proxy.php still available? I couldn't find it anywhere.

Thanks!

wm003
17 Jun 2008, 3:50 AM
Is the source code of data_proxy.php still available? I couldn't find it anywhere.

Thanks!

Here's the code from March, don't know if it changed until now...


<?php
/**
* 73 lines of license free PHP basics.
*
*
* @author Thorsten Suckow-Homberg <ts@siteartwork.de>
*/


// +----------------------------------------------------------------------------
// | Connection settings. Adjust the following lines (see "livegrid.sql").
// +----------------------------------------------------------------------------
$host = "localhost";
$user = "root";
$password = "";
$database = "livegrid";
$table = "livegrid";


// +----------------------------------------------------------------------------
// | Query stuff. As long as everything works fine, you can ignore the following
// | lines. Scroll down to the part where the json encoding happens...
// | WARNING: Script does not check for valid POST vars...
// +----------------------------------------------------------------------------
$conn = mysql_connect($host, $user, $password);
mysql_select_db($database, $conn);

$sql2 = "SELECT COUNT(id) AS count_id FROM $table";
$res2 = mysql_query($sql2);

$row2 = mysql_fetch_assoc($res2);

$length = $row2['count_id'];

$feeds = array('response' => array(
'value' => array()
));

$sql = "SELECT * FROM $table ORDER BY ".$_POST['sort']." ".$_POST['dir'].
" LIMIT ".$_POST['start'].",".$_POST['limit'];

$res = mysql_query($sql);

while (($row = mysql_fetch_assoc($res))) {
$feeds['response']['value']['items'][] = array(
'id' => $row['id'],
'number_field' => $row['number_field'],
'string_field' => $row['string_field'],
'date_field' => $row['date_field']
);
}

if (!isset($feeds['response']['value']['items'])) {
$feeds['response']['value']['items'] = array();
}

$feeds['response']['value']['total_count'] = $length;
$feeds['response']['value']['version'] = 1;

// +----------------------------------------------------------------------------
// | You need to json_encode the array. If your PHP installation does not support
// | json_encode, go and get the Zend Framework at http://framework.zend.com,
// | which provides userland json encoding/decoding logic.
// +----------------------------------------------------------------------------
if (function_exists('json_encode')) {
$json = json_encode($feeds);
} else {
require_once 'Zend/Json.php';
$json = Zend_Json::encode($feeds);
}

echo $json;
?>

xenon
17 Jun 2008, 4:17 PM
As i was looking at data_proxy.php source, I notice that the answer to my question is already answered. :D thanks wm003 for posting. and thanks mindpatterns for the great ext.

ub3rn00b
19 Jun 2008, 12:11 AM
hi, im new on extjs and nice work mindpatterns, by the way to all, is it possible to set limit on Ext.ux.grid.BufferedStore proxy? My problem is, im loading 15000+ records with 10 columns so it loads about more than 30 seconds, my objective is to load only the desired data to minimize the processing time... below is an example of what i want to do.

First Load:


var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
url : 'email-proxy.php?start=0&limit=100'
});

Scroll Down:


var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
url : 'email-proxy.php?start=100&limit=200'
});

any brilliant ideas? :D

Am also looking for someway to do something similar, so I can hook up some filtering into the grid

xenon
19 Jun 2008, 12:40 AM
Am also looking for someway to do something similar, so I can hook up some filtering into the grid

great, just keep us posted if you found a way.

ub3rn00b
19 Jun 2008, 12:58 AM
great, just keep us posted if you found a way.

Will do

tmaung
19 Jun 2008, 11:55 AM
hi, im new on extjs and nice work mindpatterns, by the way to all, is it possible to set limit on Ext.ux.grid.BufferedStore proxy? My problem is, im loading 15000+ records with 10 columns so it loads about more than 30 seconds, my objective is to load only the desired data to minimize the processing time... below is an example of what i want to do.

First Load:


var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
url : 'email-proxy.php?start=0&limit=100'
});
Scroll Down:


var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
url : 'email-proxy.php?start=100&limit=200'
});
any brilliant ideas? :D


Here's what gets sent to the server using POST


dir: ASC
asc: col
limit: 300
start: 0
As you scroll down, another POST:


dir: ASC
asc: col
limit: 300
start: 285
So what you could do at the server-side script is to have:


start = $POST['start'];
end = start + $POST['limit'];
You don't even have to include all that GET request in the URL. It always sends the buffer size and also the predicted start index so you just use those request parameters to figure out your start and end. If it is about the time it takes to acquire the data, then set the buffersize smaller and also the nearlimit to a value between 1/2 and 1/3 of the buffersize. Please ignore my syntax above because I haven't worked with PHP in a long time.

My answer is based on what I think you are trying to ask. If you only want certain definite ranges instead of predicted ranges, then the best bet is the paging grid. What would happen if you are viewing records 95-105? Hope it helps.

c.barca
20 Jun 2008, 8:35 AM
Hi all,
I would use the grouping store for group my records.
It's possible use the magical BufferedDataStore togheter GroupingStore?
If yes, how to use ?

Thank you for your precious effort.

All the best

Claudio

RWaters
23 Jun 2008, 7:43 AM
This hasn't been thoroughly tested (That's what the community is for, right? :P), though I figured there may be some interest. I've added some additional keyNav handlers to the bufferedRowSelectionModel to go along with the up and down arrows that it gets from extending the standard RowSelectionModel

An updated version of this is posted below


Index: BufferedRowSelectionModel.js
===================================================================
--- BufferedRowSelectionModel.js (revision 741)
+++ BufferedRowSelectionModel.js (working copy)
@@ -47,6 +47,46 @@

this.grid.store.on('add', this.onAdd, this);
this.grid.store.on('selectionsload', this.onSelectionsLoad, this);
+
+ this.pgRowNav = new Ext.KeyNav(this.grid.getGridEl(), {
+ "pageUp" : function(e) {
+ var vw = this.grid.getView();
+ if (this.lastActive !== false) {
+ if (e.shiftKey && this.last !== false) {
+ var last = this.last;
+ this.selectRange(this.last, this.lastActive
+ - vw.visibleRows);
+ if (last !== false) {
+ this.last = last;
+ }
+ } else {
+ this.selectRow(this.lastActive - vw.visibleRows);
+ }
+ vw.focusRow(this.lastActive);
+ } else {
+ this.selectFirstRow();
+ }
+ },
+ "pageDown" : function(e) {
+ var vw = this.grid.getView();
+ if (this.lastActive !== false) {
+ if (e.shiftKey && this.last !== false) {
+ var last = this.last;
+ this.selectRange(this.last, this.lastActive
+ + vw.visibleRows);
+ if (last !== false) {
+ this.last = last;
+ }
+ } else {
+ this.selectRow(this.lastActive + vw.visibleRows);
+ }
+ vw.focusRow(this.lastActive);
+ } else {
+ this.selectFirstRow();
+ }
+ },
+ scope : this
+ });
},

srikanthnukala
24 Jun 2008, 7:57 AM
Hello,

i have filters and when i click on a button, the live grid should reload everything with these filters.




this.bufferedDataStore.on('beforeload',this.beforeLoad,this);
this.on('filterApplied',this.applyFilters,this);


beforeLoad: function(st,t,p,k){
console.log('called before load');
st.custParams = {
entity: 'srikanth'
};
debugger;

},
applyFilters: function(){
console.log('apply filters');
this.entityId = 'asdfasdf';
this.bufferedDataStore.reload();
},



How do i manipulate the params being sent for reload request to add filters?

srikanthnukala
24 Jun 2008, 8:44 AM
params and filters in live grid.

I am able to apply the parameters :


onBeforeLoad : function(store, options)
{

if (!options.params) {
options.params = {start : 0, limit : this.ds.bufferSize};
} else {
options.params.start = 0;
options.params.limit = this.ds.bufferSize;
}


if(this.filters){
console.dir(this.filters);
Ext.apply(options.params, this.filters);
}

options.scope = this;
options.callback = function(){this.reset(false);};

return true;
},

inside the grid component beforeLoad of buffered store, set this.bufferedView.filters = { //params/filters u want to send}

RWaters
24 Jun 2008, 9:42 AM
Spent a bit more time on the keyboard navigation addtion and have an update to my above code:


this.pgRowNav = new Ext.KeyNav(this.grid.getGridEl(), {
"pageUp" : function(e) {
var vw = this.grid.getView();
if (this.lastActive !== false) {
var r = Math.max(0,(this.lastActive - vw.visibleRows));
if (e.shiftKey && this.last !== false) {
this.selectRange(this.last, r);
} else {
this.selectRow(r);
}
vw.focusRow(r);
} else {
this.selectRow(0);
vw.focusRow(0);
}
vw.focusEl.focus();
},
"pageDown" : function(e) {
var vw = this.grid.getView();

if (this.lastActive !== false) {
var r = Math.min((this.lastActive + vw.visibleRows), this.grid.store.getTotalCount()-1);
if (e.shiftKey && this.last !== false) {
this.selectRange(this.last, r);
} else {
this.selectRow(r);
}
vw.focusRow(r);
} else {
var loc = this.grid.store.getTotalCount()-1;
this.selectRow(loc);
vw.focusRow(loc)
}
vw.focusEl.focus();
},
"home" : function(e) {
this.selectFirstRow();
this.grid.getView().focusRow(0);
},
"end" : function(e) {
var loc = this.grid.store.getTotalCount()-1;
this.selectRow(loc);
this.grid.getView().focusRow(loc);
},
scope : this
});

Still goes into the same place in BufferedRowSelectionModel

mprice
25 Jun 2008, 2:44 PM
I saw a few requests for the LiveGrid to support reading from a local data store. I too have this need, primarly to avoid a steady stream of SQL calls as users scroll. I figured out how to "fool" LiveGrid into getting all of the data upfront. The grid rendering seems to still be very fast. I am curious what others and the LiveGrid creator think of this approach? Any problems I might be causing?

What I did was simply set the bufferSize property in the BufferedStore to the total number of records in the dataset. This caused the entire dataset to be loaded into the store, and then when the grid is scrolled it never goes back to the server. The nearLimit property of the BufferedGridView seems to have no impact on things if I do this.

I tested this for 10000 records and the grid loaded in about 3.5 seconds (mostly to download all that data).

Bing Qiao
26 Jun 2008, 4:43 AM
LiveGrid is really awesome. The one issue I have is using it with grids that have a large number of columns. For example, one of my grids has 40 columns, all of which are important. This makes vertical scrolling really slow and cluncky. Is it possible to remove columns from the view that are out of scroll range but still display the horizontal scroll bar as if all the columns were there? Then, when the user scrolls horizontally, dynamically add/remove the columns to the view. This would make LiveGrid perform well even with a large number of columns.

Our app has exactly the same issue. We need to load more than 100 columns but then the vertical scrolling is a bit too slow.

Would there be any consideration of this feature like the virtual rendering in ActiveWidgets?

Many thanks!

xenon
26 Jun 2008, 6:18 PM
Hello again, I have a livegrid inside Ext.BoxComponent and collapsible == true. The scenario is when i scroll the livegrid halfway and turn the BoxComponent collapsed then expand it again, the scroll move's back to top..

Any suggestions to make the scroll bar back into place? Thanks in advance.

Scorpie
26 Jun 2008, 10:27 PM
Nice work, its a very nice extension!

Bing Qiao
1 Jul 2008, 11:47 PM
With standard Ext paging GridPanel, you can load two hundred columns with a page size of 50 and scroll quite smoothly both vertically and horizontally on the same page. It takes about 15 seconds in total to load and render that amount of data but once it's done, scrolling seems not being affected severely by having more columns.

This is not the case for livegrid. With dozens of columns you would have felt scrolling becomes much less smoothly.

I guess this might be caused by BufferedGridView only rendering visible rows even though there is more data in the buffer. However it looks like rendering the data takes much longer than loading it from the server with large number of columns. So I was wondering if rendering a number of nonvisible rows (a novisiblerenderedrows confg property?) above and below the visible ones in advance would improve the scrolling performance (within the novisiblerenderedrows) of livegrid with a large number of columns?

I haven't succeeded in making changes to BufferedGridView, but would like to hear from others if this idea will work or not.

Many thanks!

ThorstenSuckow
2 Jul 2008, 1:11 AM
With standard Ext paging GridPanel, you can load two hundred columns with a page size of 50 and scroll quite smoothly both vertically and horizontally on the same page.

Hi, the use cases I had in mind when developing the Livegrid did quite differ from those scenarios when a grid would have more than 20-or-so columns. The reason why a grid with paging is much faster in scrolling is because the whole grid is rendered as once during initialization, then never touched again (except for adding/removing/editing rows), whereas the Livegrid removes and prepends/appends rows during scrolling.

Bing Qiao
2 Jul 2008, 2:15 AM
Hi, the use cases I had in mind when developing the Livegrid did quite differ from those scenarios when a grid would have more than 20-or-so columns. The reason why a grid with paging is much faster in scrolling is because the whole grid is rendered as once during initialization, then never touched again (except for adding/removing/editing rows), whereas the Livegrid removes and prepends/appends rows during scrolling.

Thanks very much for the explanation!

I'd really like to have livegrid to replace our existing data-grid (which is not as feature-rich and sleek-looking but works great with a large number of columns via prepending/appending rows during scrolling and rendering invisible rows in advance).

By rendering extra invisible rows, it will take longer to render everytime it does (but will this anyway make no big difference for 20- columns grid, but help improve user experience for grid with larger number of columns?), but within the limit of all rendered rows, it will allow for no-delay scroll for very large number of columns until it spills beyond all rendered rows. So basically "smaller delay for every scroll" vs "no delay for a number of scrolls then a bigger one (or maybe without the bigger delay at all if you don't jump page but scroll continuously)", in the case of large number of columns.

I understand that this scenario doesn't fit your use case, but just wonder if a new config property like that would help livegrid to scale better with more columns?

And I guess this too may help with performance if rendering takes longer than usual because of some custom complex rendering even with a limited number of columns?

Many thanks

eliasp
14 Jul 2008, 6:46 AM
Hi,

I'm using the LiveGrid together with GridFilter. It seems, LiveGrid causes some trouble regarding the update of the datastore, as hendricd supposed in the GridFilter thread (http://extjs.com/forum/showthread.php?p=192855#post192855):


GridFilters uses the EventManager to trap beforeload so that the filters can be added to the request params (along with all other beforeload consumers).

Could it be that LiveGrid does not raise (fireEvent) beforeload, thus GridFilters never gets the chance to update the params?


So I took a look at the LiveGrid sources, where I found this in src/BufferedGridView.js:



302 /**
303 * The extended implementation attaches an listener to the beforeload
304 * event of the store of the grid. It is guaranteed that the listener will
305 * only be executed upon reloading of the store, sorting and initial loading
306 * of data. When the store does "buffer", all events are suspended and the
307 * beforeload event will not be triggered.
308 *
309 * @param {Ext.grid.GridPanel} grid The grid panel this view is attached to
310 */
311 init: function(grid)
312 {
313 Ext.ux.grid.BufferedGridView.superclass.init.call(this, grid);
314
315 this.ds.on('beforeload', this.onBeforeLoad, this);
316 },
317


I couldn't find a way to work around this and to me it seems, like it is the reason for my troubles. Is this easily fixable for one of you pros? Maybe by setting a property to disable this behaviour?

Best regards,
Elias P.

nctag
21 Jul 2008, 10:45 PM
First of all thank you for that really nice extension. I want to test it to decide wheter to use it in my project or not. But I cannot find the proxy-data.php on your hompepage. I'm not very expirienced with JSON, so I cannot write it by my self at the moment. I hope someone can helps me and tell me where I can find this file. Thank you.

wm003
22 Jul 2008, 12:00 AM
First of all thank you for that really nice extension. I want to test it to decide wheter to use it in my project or not. But I cannot find the proxy-data.php on your hompepage. I'm not very expirienced with JSON, so I cannot write it by my self at the moment. I hope someone can helps me and tell me where I can find this file. Thank you.
look some posts above (http://extjs.com/forum/showthread.php?p=182844#post182844). Is that what you are looking for?

nctag
22 Jul 2008, 3:23 AM
Thank you very much.

I tried out this extension. I really like how it is developed and how it works. Great work. But If I resize the window there is no reaction from the livegrid. The scrollbar doesn't adjust to the new situation (the new dimensions). Is it possible that I have to write my own onResize event? I thought it should be done by the livegrid because its really nearly perfect.

Thank you for inputs.

ThorstenSuckow
22 Jul 2008, 3:49 AM
Thank you very much.

I tried out this extension. I really like how it is developed and how it works. Great work. But If I resize the window there is no reaction from the livegrid. The scrollbar doesn't adjust to the new situation (the new dimensions). Is it possible that I have to write my own onResize event? I thought it should be done by the livegrid because its really nearly perfect.

Thank you for inputs.

If you do not experience any resizing problems using http://www.siteartwork.de/livegrid_demo/ , please post some code examples.

nctag
22 Jul 2008, 4:02 AM
I'm surprised. In the example it works fine. But in my own script it doesn't cause any resizing. So the scrollbar doen't change and the data doesn't adjust to the new dimensions.

Some help?
[CODE] //bufferedReader
var bufferedReader = new Ext.ux.data.BufferedJsonReader({
root : 'response.value.items',
versionProperty : 'response.value.version',
totalProperty : 'response.value.total_count',
id : 'id'
}, rArr );

//url
var url = 'data-proxy.php?table='+this.table+'&cols=';
for( var i=0; i < fArr.length; i++ )
{
url += fArr[i];
if( i+1 < fArr.length )
{
url += ',';
}
}

//store
var bufferedDataStore = new Ext.ux.grid.BufferedStore({
autoLoad : true,
bufferSize : 300,
reader : bufferedReader,
sortInfo : {field: fArr[0], direction: 'ASC'},
url : url
});

//view
var bufferedView = new Ext.ux.grid.BufferedGridView({
nearLimit : 100,
loadMask : {
msg : 'Please wait...'
}});

//toolbar
var bufferedGridToolbar = new Ext.ux.BufferedGridToolbar({
view : bufferedView,
displayInfo : true
});

//selectionModel
var bufferedSelectionModel = new Ext.ux.grid.BufferedRowSelectionModel();

//colModel
var colModel = new Ext.grid.ColumnModel( cArr );

//grid
this.grid = new Ext.grid.GridPanel({
ds : bufferedDataStore,
enableDragDrop : false,
cm : colModel,
sm : bufferedSelectionModel,
loadMask : { msg : 'Loading...' },
view : bufferedView,
border : false,
id : this.id+'grid',
bbar : bufferedGridToolbar
});

//tbar
var tbar = [];
if( tbarxml.getAttribute( "add" ) != 'false' )
tbar.push({ id: 'add', icon: 'images/add.gif', cls:"x-btn-text-icon", text:'Hinzuf

nctag
22 Jul 2008, 4:33 AM
If i have only 4 records and the window could display 10 then the scrollbar is disabled.
But if I resize the window to 3 records only. Then the scrollbar doesn't enable and the data doesn't load new.

khatuido
22 Jul 2008, 7:20 AM
Is there a way to scroll up the scrollbar after insert a row on the rowIndex = 0?

mystix
22 Jul 2008, 7:53 AM
Is there a way to scroll up the scrollbar after insert a row on the rowIndex = 0?
http://extjs.com/docs/?class=Ext.grid.GridView&member=focusCell

nctag
22 Jul 2008, 12:33 PM
I did not get any inputs to my reported issue. Perhaps I was not able to correctly explain the issue. I try it another time. Situation is the following: I have a livegrid that has a height about 400px so that there could be many rows. But in my MySQL table there are only a few records. So the livegrid has less than 1 page data. The scrollbar is not used and correctly disabled. I resize the window so that it is smaller and displays only 2 records and there would be the consequence that live grid should enable the scrollbar and hide the record overflow. I hope someony can understand my problem and help me in any way or tell me that this is a bug?

Thank you very much.

nctag
23 Jul 2008, 6:23 AM
I do really need some support. Home somebody can tell me wheter it is bug and will be fixxed or I have to do it by my own. Thank you for your support / input.

Kango_V
24 Jul 2008, 3:39 AM
Is it easy to do this same thing with ExtGWT?

We've written the same behaviour in Java/SWT and C++/MFC before, but are just starting to learn GWT.

Any help would be appreciated.

nctag
26 Jul 2008, 2:32 PM
I do another try to request help for my detected behavour. Please give me some input wheter this is a bug or what to do with this situation. I described the details above, but here is a small summary below.

If there are less records then whether they could be displayed in the livegrid, then there is no event that will be called if I perform a resize or other events.

It is really important for me and I have to solve that problem. I'll try by my self, but every input from your side would be very helpful.

have a nice day.

loverofdream
28 Jul 2008, 3:16 AM
It can't work well when I use row number such as



var colModel = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
{header: "Number", align : 'left', width: 160, sortable: true, dataIndex: 'number_field'},
{header: "String", align : 'left', width: 160, sortable: true, dataIndex: 'string_field'},
{header: "Date", align : 'right', width: 160, sortable: true, dataIndex: 'date_field'}
]);

rusty124
28 Jul 2008, 10:11 AM
I have seen several posts relating to combining liveGrid and gridFilters. The issue is that the filters do not get passed when the buffer is updated. Has anyone been able to get this to work?

imnphd
31 Jul 2008, 4:57 AM
Do you plan to extend the code to maintain the selection state after you sort/filter the livegrid? I believe it would be relatively easy to implement it with a CheckboxSelectionModel but instead of checking the 'bufferedSelections' and 'pendingSelections' arrays in the class you would get it from the store by passing a checked = true/false.

Isaac

mepfuso
11 Aug 2008, 8:15 AM
The LiveGrid doesn't work properly with Ext 2.2 anymore. At least with me. When scrolling up and down in large grids, the focus jumps around between the first row and the visible area crazily.

This is most probably due to the changes made on the Ext.grid.GridView, as published in the release notes:



* Fixes to sync the invisible focus element on row add/remove actions


Thus, to remove that feature again without going back to Ext 2.1, I had to include the following override to the Ext.grid.GridView:



Ext.override(Ext.grid.GridView, {

removeRow : function(row){
Ext.removeNode(this.getRow(row));
//this.focusRow(row);
},

removeRows : function(firstRow, lastRow){
var bd = this.mainBody.dom;
for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
Ext.removeNode(bd.childNodes[firstRow]);
}
//this.focusRow(firstRow);
},

insertRows : function(dm, firstRow, lastRow, isUpdate){
if(!isUpdate && firstRow === 0 && lastRow >= dm.getCount()-1){
this.refresh();
}else{
if(!isUpdate){
this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
}
var html = this.renderRows(firstRow, lastRow);
var before = this.getRow(firstRow);
if(before){
Ext.DomHelper.insertHtml('beforeBegin', before, html);
}else{
Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
}
if(!isUpdate){
this.fireEvent("rowsinserted", this, firstRow, lastRow);
this.processRows(firstRow);
}
}
//this.focusRow(firstRow);
}
});


As you see, i copied the methods from the Ext source and just out-commented the calls to this.focusRow(...).

Seems to work for me so far.

suzan
12 Aug 2008, 7:24 AM
hi,
i am trying to get this component but i am getting this message.
This Domain is currently inaccessible!
kind regards.

zhiliang
12 Aug 2008, 9:47 AM
Hello everyone, first thanks for this great plugin

now i implement livegrid with editorgrid, RowExpander and filterplugin, every thing work well at the beginning, but there are servel bugs when the data is out of buffersize, the cell can not be edited and the rowexpander doesn't work either, when i use 'cellIndex' to add listener for the grid, the listener can not work when the store load new data, anyone have the same problem? thx




I did some code change to make it to support EditorGridPanel. It works. However, I am still reviewing and see if it is good enough.

In the BufferedGridView.js. I added a method.

getCell : function(row, col, adjusted){
if ( !adjusted ) {
row = row-this.rowIndex;
}
return this.getRow(row).getElementsByTagName('td')[col];
}

And replace three occurrences that used getCell() with code like

this.getCell(xxxx, xxx, true);

zhiliang
13 Aug 2008, 7:27 AM
Hello, i solve my problem, it is because the store can not get the data record

so i override getAt in BufferedStore.js

getAt : function(index){

var startindex = this.bufferRange[0];
if(startindex==0){
var newindex = index;
}else{
var newindex = index-startindex;
}

return this.data.itemAt(newindex);
},

bjcullinan
13 Aug 2008, 11:27 AM
I too had the same problem as mepfuso. I recommend just modifying the BufferedGridView and adding the 2 functions:

removeRow : function(row){
Ext.removeNode(this.getRow(row));
//this.focusRow(row);
},

removeRows : function(firstRow, lastRow){
var bd = this.mainBody.dom;
for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
Ext.removeNode(bd.childNodes[firstRow]);
}
//this.focusRow(firstRow);
},
Since insertRows is already overridden you don't need to add that also. By overriding the GridView you risk loosing functionality that may come in handy somewhere else.
In my case I was able to just add the extra code to a class that extended BufferedGridView.

Nic
18 Aug 2008, 4:56 AM
Thanks bjcullinan, that did it for me, too. I just applied an override to Ext.ux.grid.BufferedGridView:



// Fix for LiveGrid scrolling in Ext2.2
Ext.override(Ext.ux.grid.BufferedGridView, {
removeRow: function(row){
Ext.removeNode(this.getRow(row));
},
removeRows: function(firstRow, lastRow){
var bd = this.mainBody.dom;
for (var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
Ext.removeNode(bd.childNodes[firstRow]);
}
}
});