jeffreydwalter / ColReorderWithResize

Column reordering and resizing plug-in for DataTables
http://www.datatables.net/
MIT License
42 stars 51 forks source link

Fix for wrong columns being selected during state save/restore, inaccurate resizing with scrollY & how to state save widths #24

Closed sophanox closed 5 years ago

sophanox commented 5 years ago

Hey there,

I just wanted to share a quick fix I've put in which has made this plugin work much better for me.

Firstly, I was having issues with column indexes changing when this plugin is combined with a state save. This meant that some columns would have incorrect widths applied to them when restored. To remediate this I check for the title attribute to ensure it matches (instead of trusting the index).

Secondly I found that using the jquery .width() sometimes reported back the wrong width. I'm not sure why this happens, perhaps some quirk of jquery. In any case, using the width attribute from the inline style gave me much better results.

To apply these fixes, on line 1263, comment out:

this.s.dt.aoColumns[colResized].sWidth = $(this.s.mouse.resizeElem).width() + "px";

and replace with:

                var thisColTitle = this.s.mouse.resizeElem[0].textContent;
                for (var i = 0; i < this.s.dt.aoColumns.length; i++) {
                    if (this.s.dt.aoColumns[i].sTitle === thisColTitle) {
                        this.s.dt.aoColumns[i].sWidth = this.s.mouse.resizeElem[0].style.width;
                    }
                }

Lastly, whilst I'm here, I figured I may as well share my state saving code as it's alluded to elsewhere but never described. I save the widths as percentages but then restore into px, so that they should be preserved across all screen sizes.

In the datatables options add:

        stateSave: true,
        stateLoadParams: function(settings, data) {
          if (data.columnWidths) {
            data.columnWidths.forEach((item) => {
              const thisColIdx = settings.aoColumns.findIndex(x => x.sTitle === item.key);
              const newWidth = (parseInt(item.value) / 100) * tableWidth; 
              settings.aoColumns[thisColIdx].sWidthOrig = `${newWidth}px`
            });
          }
        },
        stateSaveParams: function(settings, data) {
          // save column widths
          data.columnWidths = [];
          settings.aoColumns.forEach((item) => {
            if (item.sWidth != null) {
              const newWidth = (parseInt(item.sWidth) / tableWidth) * 100; 
              data.columnWidths.push({key: item.sTitle, value: `${newWidth}%`});
            }
          });
        },

Note that this uses ES6 so will need transpiled/polyfilled or modified manually for ES5. The tableWidth is the width of your table. Hope this helps someone - and thanks a lot Jeffrey for the great plugin!

sophanox commented 5 years ago

Closed as this is a solution that I hope helps others and not a bug per se :)