tabalinas / jsgrid

Lightweight Grid jQuery Plugin
http://js-grid.com
MIT License
1.53k stars 351 forks source link

Freeze Columns #105

Open junelmujar opened 9 years ago

junelmujar commented 9 years ago

Hi! Thank you for this wonderful plugin.

Any plans to support freezing of column(s)/row(s) like Excel?

Thanks!

/Junel

tabalinas commented 9 years ago

Hi! Thank you for the feedback and valuable request! It's definitely the good point.

stephenlawuk commented 8 years ago

I would also love to see this feature, I tried doing it myself but didn't get far. I tried using the onRefreshed callback and css. The following freezes the first column but only works on data that doesn't have a scrollbar as the frozen column doesn't scroll with the right hand side data.

onRefreshed: function (args) {
$('.jsgrid-header-row th:first-child, .jsgrid-filter-row td:first-child, .jsgrid-insert-row td:first-child, .jsgrid-grid-body tr td:first-child')
.css({
position: "absolute",
left: "1px"
});
$('.jsgrid-grid-header, .jsgrid-grid-body').css('margin-left', '100px');
}
jonkrusell commented 8 years ago

I also think frozen columns would be a very valuable feature. I tried something similar to stephenlawuk and ended up with the same result.

stephenlawuk commented 8 years ago

I managed to get a bit further going in a different direction instead of onrefresh I tackled it from a scroll function on the main grid body.

The below freezes the first 2 columns (determined by the nth-child(-n+2)). You can get to any number of frozen columns by changing the 2. The box shadow is a bit of a hack as the borders seem to vanish when you scroll with the frozen columns.

The only issue is that Edit mode is messed up until you scroll. Needs some more code probably in the onItemEditing event to refresh the floating columns position.

$('.jsgrid-grid-body').scroll((function () {
            var left = $('.jsgrid-grid-body').scrollLeft() < $('.jsgrid-grid-body .jsgrid-table').width() - $('.jsgrid-grid-body').width() + 16
                ? $('.jsgrid-grid-body').scrollLeft() : $('.jsgrid-grid-body .jsgrid-table').width() - $('.jsgrid-grid-body').width() + 16;
            $('.jsgrid-header-row th:nth-child(-n+2), .jsgrid-filter-row td:nth-child(-n+2), .jsgrid-insert-row td:nth-child(-n+5), .jsgrid-grid-body tr td:nth-child(-n+2)')
                .css({
                    "position": "relative",
                    "left": left,
                    "box-shadow": "-1px -1px 0px 0px #e9e9e9 inset"
                });
        }));
jonkrusell commented 8 years ago

@stephenlawuk You are a wizard. This worked great!

ghost commented 8 years ago

Hi, tabalinas, thank for this great plugin. With code explain upper I have a problem with scroll in ie11: header remain fixed while content table dont scroll correctly. Maybe is nth:child selector or other?

jonnyglass commented 8 years ago

The issue with the borders is related to border-collapse. When collapsed, the borders "follow" the table and not the scrolled cells. I was able to fix by setting border-collapse to "separate" on the tables and then setting the top and left borders to 0 for all the TH's and TD's. Added these rules to fix it.

.jsgrid-table { border-collapse: separate; }

.jsgrid-grid-body td, .jsgrid-grid-header td, .jsgrid-grid-header th { border-left: 0; border-top: 0; }

Agreed that is a really important feature and would suggest adding it.

stephenlawuk commented 8 years ago

@jonnyglass Thanks for that I agree that is a much cleaner solution compared to my hack which has some weird graphical anomalies.

I also fixed my editing/updating issue but forgot to update here. Anyway for anyone looking this is now my updated solution which addresses the editing/updating issue I previously had as well as including jonnyglass border fix. Here it is, obviously you need to include your own data loading.

<script type="text/javascript">
$("#divGrid").jsGrid({
    width: "100%",
    height: "80%",

    autoload: true,
    heading: true,
    filtering: true,
    inserting: false,
    editing: true,
    selecting: true,
    sorting: true,
    paging: false,
    pageLoading: false,
    onItemUpdated: function (args) {
        UpdateColPos(2);
    },
    onItemEditing: function (args) {
        setTimeout(function () { UpdateColPos(2); }, 1);
    },
    onRefreshed: function (args) {
        UpdateColPos(2);
    }
});

$('.jsgrid-grid-body').scroll(function () {
    UpdateColPos(2);
});

function UpdateColPos(cols) {
    var left = $('.jsgrid-grid-body').scrollLeft() < $('.jsgrid-grid-body .jsgrid-table').width() - $('.jsgrid-grid-body').width() + 16
        ? $('.jsgrid-grid-body').scrollLeft() : $('.jsgrid-grid-body .jsgrid-table').width() - $('.jsgrid-grid-body').width() + 16;
    $('.jsgrid-header-row th:nth-child(-n+' + cols + '), .jsgrid-filter-row td:nth-child(-n+' + cols + '), .jsgrid-insert-row td:nth-child(-n+' + cols + '), .jsgrid-grid-body tr td:nth-child(-n+' + cols + ')')
        .css({
            "position": "relative",
            "left": left
        });
}
</script>
<style>
    .jsgrid-table {
        border-collapse: separate;
    }

    .jsgrid-grid-body td, .jsgrid-grid-header td, .jsgrid-grid-header th {
        border-left: 0;
        border-top: 0;
    }
</style>
jreast commented 7 years ago

Thanks @stephenlawuk you just saved me a lot of hassle. This worked first time.

CameronOC commented 7 years ago

I want to say my thanks to @stephenlawuk this worked wonderfully

jjxtra commented 6 years ago

Is freezing the top header row built in?

tabalinas commented 6 years ago

Here we have the fix to have multiple grids on a page: https://github.com/tabalinas/jsgrid/issues/888

MaheshBalla461 commented 6 years ago

Hi @stephenlawuk . You made my day. Kudos to you.

fsanna commented 2 years ago

Full CSS solution for sticky first column:

td.gridjs-td:first-child{
  color: #517A8F;
  font-size: 14px;
  font-weight: bold;
  position: sticky;
  left: 0;
  z-index: 2;
  box-shadow: -1px 0px #e5e7eb inset;
}

th.gridjs-th:first-child{
  position: sticky;
  left: 0;
  z-index: 2;
  box-shadow: -1px 0px #e5e7eb inset;
}