Forum

November 2nd, 2014
A A A
Avatar

Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

The forums are currently locked and only available for read only access
sp_Feed Topic RSS sp_TopicIcon
Virtual scroll with dynamic row height
17/09/2011
17:44
Avatar
ericisko
Member
Members
Forum Posts: 5
Member Since:
17/09/2011
sp_UserOfflineSmall Offline

Hi,

I am working on virtual scrolling with dynamic (changing) row height. I think I have it mostly working. This is how it works:

- calculate average row height from the currently displayed data: divide data table height with number of rows in the table

- use this row height in updatepager() to calculate total div height as well as 'top' div height

- use the same row height for calculating next page to load in pageVisible()

- every time new/updated data is loaded, average row height along with total height and 'top' div height is recalculated. This new row height is used for paging in pageVisible()

- scrollTop is adjusted in updatepager() to account for average row height change as data currently loaded/displayed is changed so the current row appears at the same location as before (this is not working 100% yet)

I tested it with local data only (loadonce is true).

Any comments on this approach? Where can I submit the code?

Thanks,

Erik

22/09/2011
16:57
Avatar
ericisko
Member
Members
Forum Posts: 5
Member Since:
17/09/2011
sp_UserOfflineSmall Offline

Hi,

I resolved the issue with scrollTop and it seems to be working correctly. Bellow is the diff against jqGrid 4.1.2:

--- jquery.jqGrid.src.js.orig    2011-07-20 11:00:22.000000000 -0400
+++ jquery.jqGrid.src.js    2011-09-22 09:47:03.965509200 -0400
@@ -782,26 +782,39 @@
                 if (!dh) { return; }
                 var table = $("table:first", grid.bDiv);
                 var rows, rh;
-                if(table[0].rows.length) {
-                    try {
-                        rows = table[0].rows[1];
-                        rh = rows ? $(rows).outerHeight() || grid.prevRowHeight : grid.prevRowHeight;
-                    } catch (pv) {
+                if (table[0].rows.length) {
+                    if (table[0].rows.length > 1) {
+                        try {
+                            rh = table.height() / (table[0].rows.length - 1);
+                        } catch (pv) {
+                            rh = grid.prevRowHeight;
+                        }
+                    }
+                    else {
                         rh = grid.prevRowHeight;
                     }
                 }
                 if (!rh) { return; }
-                grid.prevRowHeight = rh;
+                grid.prevRowHeight = grid.currRowHeight;
+                grid.prevTableHeight = table.height();
                 var rn = p.rowNum;
                 var scrollTop = grid.scrollTop = grid.bDiv.scrollTop;
                 var ttop = Math.round(table.position().top) - scrollTop;
                 var tbot = ttop + table.height();
                 var div = rh * rn;
                 var page, npage, empty;
-                if ( tbot < dh && ttop <= 0 &&
-                    (p.lastpage===undefined||parseInt((tbot + scrollTop + div - 1) / div,10) <= p.lastpage))
-                {
-                    npage = parseInt((dh - tbot + div - 1) / div,10);
+                if (grid.scrollDiff < 0 && ttop > 0 && ttop < dh) {
+                    grid.scrollDiff = ttop;
+                }
+                else {
+                    if (grid.scrollDiff > 0 && tbot > 0 && tbot < dh)
+                        grid.scrollDiff = tbot;
+                    else
+                        grid.scrollDiff = 0;
+                }
+                if (tbot < dh && ttop <= 0 &&
+                    (p.lastpage === undefined || parseInt((tbot + scrollTop + div - 1) / div, 10) <= p.lastpage) ) {
+                    npage = parseInt((dh - tbot + div - 1) / div, 10);
                     if (tbot >= 0 || npage < 2 || p.scroll === true) {
                         page = Math.round((tbot + scrollTop) / div) + 1;
                         ttop = -1;
@@ -823,18 +836,21 @@
                     } else {
                         p.page = page;
                         if (empty) {
+                            grid.prevTableHeight = 0;
                             grid.selectionPreserver(table[0]);
                             grid.emptyRows(grid.bDiv,false, false);
                         }
                         grid.populate(npage);
                     }
                 }
+                grid.scrollDiff = 0;
             },
             scrollGrid: function( e ) {
                 if(p.scroll) {
                     var scrollTop = grid.bDiv.scrollTop;
                     if(grid.scrollTop === undefined) { grid.scrollTop = 0; }
                     if (scrollTop != grid.scrollTop) {
+                        grid.scrollDiff = scrollTop - grid.scrollTop;
                         grid.scrollTop = scrollTop;
                         if (grid.timer) { clearTimeout(grid.timer); }
                         grid.timer = setTimeout(grid.populateVisible, p.scrollTimeout);
@@ -1537,19 +1553,45 @@
             var cp, last, base, from,to,tot,fmt, pgboxes = "", sppg,
             tspg = ts.p.pager ? "_"+$.jgrid.jqID(ts.p.pager.substr(1)) : "",
             tspg_t = ts.p.toppager ? "_"+ts.p.toppager.substr(1) : "";
+            if (ts.p.page == 0) { ts.p.page = 1; }
             base = parseInt(ts.p.page,10)-1;
             if(base < 0) { base = 0; }
             base = base*parseInt(ts.p.rowNum,10);
             to = base + ts.p.reccount;
             if (ts.p.scroll) {
+                if (!grid.scrollDiff) { grid.scrollDiff = 0; }
                 var rows = $("tbody:first > tr:gt(0)", ts.grid.bDiv);
                 base = to - rows.length;
                 ts.p.reccount = rows.length;
-                var rh = rows.outerHeight() || ts.grid.prevRowHeight;
+                var th = $("table:first", ts.grid.bDiv).height();
+                var rh = th / rows.length;
+                grid.currRowHeight = rh;
                 if (rh) {
                     var top = base * rh;
-                    var height = parseInt(ts.p.records,10) * rh;
-                    $(">div:first",ts.grid.bDiv).css({height : height}).children("div:first").css({height:top,display:top?"":"none"});
+                    var lpCnt = ts.p.records % ts.p.rowNum;
+                    var pgCnt = ts.p.lastpage - ts.p.page - 1;
+                    if (pgCnt < 0) { pgCnt = lpCnt = 0; }
+                    var height = top + th + (pgCnt * ts.p.rowNum + lpCnt) * rh;
+                    if ((top != 0 || (grid.scrollDiff != 0 && ts.p.page == 2)) && grid.prevRowHeight && grid.currRowHeight != grid.prevRowHeight) {
+                        if (grid.prevTableHeight) {
+                            grid.scrollTop = top + grid.prevTableHeight - grid.scrollDiff;
+                        }
+                        else {
+                            if (grid.scrollDiff) {
+                                grid.scrollTop = top - grid.scrollDiff;
+                                var cnt = (Math.floor(rows.length / ts.p.rowNum) - 1) * ts.p.rowNum;
+                                if (rows.length % ts.p.rowNum != 0) { cnt += ts.p.rowNum; }
+                                for (var i = 0; i < cnt; i++) {
+                                    grid.scrollTop += $(rows[i]).outerHeight();
+                                }
+                            }
+                            else {
+                                grid.scrollTop = ts.grid.bDiv.scrollTop * grid.currRowHeight / grid.prevRowHeight;
+                            }
+                        }
+                    }
+                    $(">div:first", ts.grid.bDiv).css({ height: height }).children("div:first").css({ height: top, display: top ? "" : "none" });
+                    ts.grid.bDiv.scrollTop = grid.scrollTop;
                 }
                 ts.grid.bDiv.scrollLeft = ts.grid.hDiv.scrollLeft;
             }

Erik

22/09/2011
18:27
Avatar
ericisko
Member
Members
Forum Posts: 5
Member Since:
17/09/2011
sp_UserOfflineSmall Offline

Hi,

there was an issue when the record count was exact multiply of rowNum. The fixed code below:

--- jquery.jqGrid.src.js.orig    2011-07-20 11:00:22.000000000 -0400
+++ jquery.jqGrid.src.js    2011-09-22 11:22:47.684100300 -0400
@@ -782,26 +782,39 @@
                 if (!dh) { return; }
                 var table = $("table:first", grid.bDiv);
                 var rows, rh;
-                if(table[0].rows.length) {
-                    try {
-                        rows = table[0].rows[1];
-                        rh = rows ? $(rows).outerHeight() || grid.prevRowHeight : grid.prevRowHeight;
-                    } catch (pv) {
+                if (table[0].rows.length) {
+                    if (table[0].rows.length > 1) {
+                        try {
+                            rh = table.height() / (table[0].rows.length - 1);
+                        } catch (pv) {
+                            rh = grid.prevRowHeight;
+                        }
+                    }
+                    else {
                         rh = grid.prevRowHeight;
                     }
                 }
                 if (!rh) { return; }
-                grid.prevRowHeight = rh;
+                grid.prevRowHeight = grid.currRowHeight;
+                grid.prevTableHeight = table.height();
                 var rn = p.rowNum;
                 var scrollTop = grid.scrollTop = grid.bDiv.scrollTop;
                 var ttop = Math.round(table.position().top) - scrollTop;
                 var tbot = ttop + table.height();
                 var div = rh * rn;
                 var page, npage, empty;
-                if ( tbot < dh && ttop <= 0 &&
-                    (p.lastpage===undefined||parseInt((tbot + scrollTop + div - 1) / div,10) <= p.lastpage))
-                {
-                    npage = parseInt((dh - tbot + div - 1) / div,10);
+                if (grid.scrollDiff < 0 && ttop > 0 && ttop < dh) {
+                    grid.scrollDiff = ttop;
+                }
+                else {
+                    if (grid.scrollDiff > 0 && tbot > 0 && tbot < dh)
+                        grid.scrollDiff = tbot;
+                    else
+                        grid.scrollDiff = 0;
+                }
+                if (tbot < dh && ttop <= 0 &&
+                    (p.lastpage === undefined || parseInt((tbot + scrollTop + div - 1) / div, 10) <= p.lastpage) ) {
+                    npage = parseInt((dh - tbot + div - 1) / div, 10);
                     if (tbot >= 0 || npage < 2 || p.scroll === true) {
                         page = Math.round((tbot + scrollTop) / div) + 1;
                         ttop = -1;
@@ -823,18 +836,21 @@
                     } else {
                         p.page = page;
                         if (empty) {
+                            grid.prevTableHeight = 0;
                             grid.selectionPreserver(table[0]);
                             grid.emptyRows(grid.bDiv,false, false);
                         }
                         grid.populate(npage);
                     }
                 }
+                grid.scrollDiff = 0;
             },
             scrollGrid: function( e ) {
                 if(p.scroll) {
                     var scrollTop = grid.bDiv.scrollTop;
                     if(grid.scrollTop === undefined) { grid.scrollTop = 0; }
                     if (scrollTop != grid.scrollTop) {
+                        grid.scrollDiff = scrollTop - grid.scrollTop;
                         grid.scrollTop = scrollTop;
                         if (grid.timer) { clearTimeout(grid.timer); }
                         grid.timer = setTimeout(grid.populateVisible, p.scrollTimeout);
@@ -1537,19 +1553,46 @@
             var cp, last, base, from,to,tot,fmt, pgboxes = "", sppg,
             tspg = ts.p.pager ? "_"+$.jgrid.jqID(ts.p.pager.substr(1)) : "",
             tspg_t = ts.p.toppager ? "_"+ts.p.toppager.substr(1) : "";
+            if (ts.p.page == 0) { ts.p.page = 1; }
             base = parseInt(ts.p.page,10)-1;
             if(base < 0) { base = 0; }
             base = base*parseInt(ts.p.rowNum,10);
             to = base + ts.p.reccount;
             if (ts.p.scroll) {
+                if (!grid.scrollDiff) { grid.scrollDiff = 0; }
                 var rows = $("tbody:first > tr:gt(0)", ts.grid.bDiv);
                 base = to - rows.length;
                 ts.p.reccount = rows.length;
-                var rh = rows.outerHeight() || ts.grid.prevRowHeight;
+                var th = $("table:first", ts.grid.bDiv).height();
+                var rh = th / rows.length;
+                grid.currRowHeight = rh;
                 if (rh) {
                     var top = base * rh;
-                    var height = parseInt(ts.p.records,10) * rh;
-                    $(">div:first",ts.grid.bDiv).css({height : height}).children("div:first").css({height:top,display:top?"":"none"});
+                    var lpCnt = ts.p.records % ts.p.rowNum;
+                    var pgCnt = ts.p.lastpage - ts.p.page - 1;
+                    if (lpCnt == 0) { pgCnt++; }
+                    if (pgCnt < 0) { pgCnt = lpCnt = 0; }
+                    var height = top + th + (pgCnt * ts.p.rowNum + lpCnt) * rh;
+                    if ((top != 0 || (grid.scrollDiff != 0 && ts.p.page == 2)) && grid.prevRowHeight && grid.currRowHeight != grid.prevRowHeight) {
+                        if (grid.prevTableHeight) {
+                            grid.scrollTop = top + grid.prevTableHeight - grid.scrollDiff;
+                        }
+                        else {
+                            if (grid.scrollDiff) {
+                                grid.scrollTop = top - grid.scrollDiff;
+                                var cnt = (Math.floor(rows.length / ts.p.rowNum) - 1) * ts.p.rowNum;
+                                if (rows.length % ts.p.rowNum != 0) { cnt += ts.p.rowNum; }
+                                for (var i = 0; i < cnt; i++) {
+                                    grid.scrollTop += $(rows[i]).outerHeight();
+                                }
+                            }
+                            else {
+                                grid.scrollTop = grid.scrollTop * grid.currRowHeight / grid.prevRowHeight;
+                            }
+                        }
+                    }
+                    $(">div:first", ts.grid.bDiv).css({ height: height }).children("div:first").css({ height: top, display: top ? "" : "none" });
+                    ts.grid.bDiv.scrollTop = grid.scrollTop;
                 }
                 ts.grid.bDiv.scrollLeft = ts.grid.hDiv.scrollLeft;
             }

Erik

17/01/2012
20:24
Avatar
Frank
Germany
New Member
Members
Forum Posts: 2
Member Since:
20/12/2010
sp_UserOfflineSmall Offline

Thank you for your patch.

I applied it against jqGrid 4.3.1, and it seems to work well (tested with a remote data source).

Forum Timezone: Europe/Sofia

Most Users Ever Online: 715

Currently Online:
61 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

OlegK: 1255

markw65: 179

kobruleht: 144

phicarre: 132

YamilBracho: 124

Renso: 118

Member Stats:

Guest Posters: 447

Members: 11373

Moderators: 2

Admins: 1

Forum Stats:

Groups: 1

Forums: 8

Topics: 10592

Posts: 31289

Newest Members:

, razia, Prankie, psky, praveen neelam, greg.valainis@pa-tech.com

Moderators: tony: 7721, Rumen[Trirand]: 81

Administrators: admin: 66

Comments are closed.
Privacy Policy   Terms and Conditions   Contact Information