ChevCast
ChevCast

Reputation: 59213

How do you duplicate "freeze pane" functionality on an HTML table?

I have a widget in an ASP.NET project that I'm developing for my job. It has to be 300 pixels wide and cannot be any wider. Unfortunately what they want has proven to be fairly complicated for such a small widget. Here is what I have right now:

http://www.codetunnel.com/content/images/widget/currentWidget.jpg

As you can see, this is a jQuery UI accordion control. As each accordion pane expands an ajax call is made to load its contents asynchronously. Right now it spits out an HTML table containing the desired data. The table is within a DIV with style overflow: auto; so that we get scroll bars on the bottom and the right.

My problem is that I want some pretty custom functionality (like the freeze pane ability in excel). When scrolling left and right I want all rows, including header, to scroll left and right except for the far left column, "product name". Like this:

http://www.codetunnel.com/content/images/widget/scrollRight.jpg

When scrolling up and down I want all columns, including the left column, to scroll up and down except for the header row. Like this:

http://www.codetunnel.com/content/images/widget/scrollDown.jpg

What is the best way to achieve this functionality? Or is there a way?

Upvotes: 10

Views: 2093

Answers (2)

Bryan B
Bryan B

Reputation: 4535

Is this something that tbody can solve inside of a fixed-size table? It seems that you could put overflow:auto on the tbody.

Upvotes: 0

mikemanne
mikemanne

Reputation: 3575

I built something somewhat similar, but much less complex: I wanted the first row of the table (the headers) to be frozen while the data rows scrolled vertically. I implemented it as 2 different tables, each with fixed-width cells, each in their own DIV. The "header" div simply sat static, and the "body" div used overflow:auto to scroll.

Your problem is more complex, because you want to "freeze panes" on both axes, and support scrolling on both axes (I had a lot more real estate to work with, and didn't have to account for horizontal scrolling at all). Nevertheless, I wonder if you could start from that position and work from there...

Define 4 divs:

  • NW: this one doesn't scroll at all, ever. It's the "product name" cell in your example
  • NE: this one scrolls horizontally only. It's the top/header row in your example
  • SW: this one scrolls vertically only. It's the left-side column in your example
  • SE: this one scrolls both directions. It's the primary data grid in your example

With 4 DIVs, you'd be dealing with 4 distinct tables, so we'll need to keep their cell widths and cell heights in sync. Ideally we could do this at render-time, if we can make them fixed values. Otherwise, we might be able to write some client-side jquery/JS to iterate the cells in the SE table when the page first loads (or is resized), and force the size of the other tables to match them.

With 4 DIVs, we also need to synchronize scrolling: when SE scrolls horizonally, NE must scroll to the same position. When SE scrolls vertically, SW must scroll to the same position. I suspect there must be some client-side scrolling events we can hook, to detect when SE is scrolled. Within those events, we should be able to force NE and/or SW to be scrolled the same way.

Sorry this is such a vague/abstract response. The nitty-gritty of implementing something like this will take more time than I could comfortably steal away from my main work. But this is something that's been rattling around in my brain, so figured I share it with you. I hope it gets you at least a little closer to a solution. Cheers!

Upvotes: 4

Related Questions