Exposing a more surgical method of updating column/cell widths

1,017 views
Skip to first unread message

Eric Miller

unread,
Dec 30, 2013, 7:16:27 PM12/30/13
to slic...@googlegroups.com
Hi Michael!

I'd like help create a more surgical way of updating the widths of column headers and cells.
Right now the only way I've seen to do it is to change the data on the cols object and call .setColumns.

I think there's a good use case for a more specific method, and I think there's a chance it's a small and precise change.

I am hoping to get your thoughts, see how you'd like it implemented, then write it and do a pull request.

My understanding of the wiki made me think this is the right place to put this type of discussion.


My use case is sizing the columns to fit displayed content onViewportChanged. Because I'd like to to happen quickly and beautifully as one scrolls, performance is important. I have debounced the event but would like a little more responsiveness.

The sizing involves two steps:
  1. Measure all the visible content
  2. Apply calculated sizes
I have step 1 pretty fast now (0.5-2ms).
Step 2 is slow (~150ms) using the provided API (setColumns). I think this is just because that method kicks of a long chain of events including re-rendering the grid.

I investigated and it looks like there are 3 internal methods that handle width sizing:

`applyColumnHeaderWidths`
Resizes the column header cells individually
  They fill the parent container as inline block elements
`updateCanvasWidth`
Resizes the parent container (size is based on summing the column widths)
Calls `applyColumnWidths` if the size is different, or always if passed `true`

`applyColumnWidths`
Writes the css rules for left and right offsets

If I exposed a method on the grid instance that was intended to update widths (given that the width data in the column object has already been set), it could look like this:

updateWidths = function() {
  applyColumnHeaderWidths();
  updateCanvasWidth(); // will call applyColumnWidths if there's been a change
  return this;
}
$.extend(this, {
  // ...
  'updateWidths': updateWidths
  // ...
});

Michael, do you like this? Think it is a good idea in general? How about the approach?

Eric Miller

unread,
Dec 30, 2013, 7:24:44 PM12/30/13
to slic...@googlegroups.com
Oh, I forgot to include maybe the most compelling data point.

When I use the .setColumns() method to update width, I get performance between 110 and 140ms for the update. If I use the applyColumnHeaderWidths() + updateCanvasWidth() method, performance is in the 5-10ms range.

The gain is awesome and the results are the same for my use case as far as I can tell.

Eric Miller

unread,
Jan 7, 2014, 2:06:56 PM1/7/14
to slic...@googlegroups.com
Any interest in a pull request for this? The performance gain is so big I think we're looking at maintaining our own fork otherwise :(

Hopefully I'm not missing something, but `applyColumnHeaderWidths()` and `updateCanvasWidth()` seem to do all the width management needed.

Coyote FourTilSeven

unread,
Nov 20, 2014, 10:42:02 PM11/20/14
to slic...@googlegroups.com
Eric, I needed a way to toggle columns. Hacked per your code and things worked on the first try. Here's your code with a usage example, etc., and inline howto instructions. Crude but a half toss from a diff.

Cheers.


[EXISTING CODE ca line 1392]
    // a debug helper to be able to access private members
    this.eval = function (expr) {
      return eval(expr);
    };

[Add the Eric Miller Mod]
    // Modification to add direct control of column widths
    // 10 based on https://groups.google.com/forum/#!topic/slickgrid/BBB-Qhg7TvU
    // 20 posted there, too
    // 30 GOTO 10

    updateWidths = function() {
        applyColumnHeaderWidths();
        updateCanvasWidth(); // will call applyColumnWidths if there's been a change
        return this;
    }
   

    /*    This is a simple usage example that will :
          makes the column's width toggle when the header is clicked
          probably should inline-block display for the span
          drop this code into your page after your create (instantiate) your grid

        var columnToggle = function( _index, _grid ) {
            var index = _index;
            var grid = _grid;
            var toggler = function( eventObjIThink ) {
                alert('foo' + index);
                var cols = grid.getColumns();
                var newWidth = cols[index].width == 10 ? 100 : 10;
                cols[index].width = newWidth;
                grid.updateWidths();
            }
            return toggler;
        }
        // sledgehammer. it will hammer _every_ active slickgrid on the page
        $('div.slick-header div.slick-header-columns div.slick-header-column span.slick-column-name')
            .each(function( index ) {
                var toggler = _toggler;
                $(this).css( 'width', '80%' )
                .css( 'background-color', '#EEF' )
                .css( 'border', '1px solid #DDE' )
                .on( 'click', toggler );
        });
    */
 [END]
  
    //////////////////////////////////////////////////////////////////////////////////////////////
    // Public API

    $.extend(this, {
      "slickGridVersion": "2.1",
 [SNIP]

[ADD THIS]     
       // supporting width mod (see above)
       'updateWidths': updateWidths

Coyote FourTilSeven

unread,
Nov 20, 2014, 10:45:26 PM11/20/14
to slic...@googlegroups.com
I should add, for anyone doing this manually, the file to modify is SlickGrid/slick.grid.js

Who knows... someone more knowledgable than I could start a google code project with a single diff file ;-)

Kathryn Simmons

unread,
Jan 14, 2015, 12:15:30 PM1/14/15
to slic...@googlegroups.com
Have you tried posting this as an issue on github?  There is a definite need!
Reply all
Reply to author
Forward
0 new messages