4 Replies Latest reply on Mar 25, 2009 12:34 PM by nbelaevski

    scrollable tables

    kragoth

      In my project I need a scrollable table.

      Richfaces provides two(well, now 3) types of tables.

      the rich:dataTable which provides a excelent table with auto sizing columns. But, I cannot keep my headers at the top/floating.

      the rich:scrollableDataTable provides the scrolling capabilities but outputs a bogus column that no production system wants to have.

      Why can't we have something like this:
      http://www.cubido.at/Portals/7/docs/Blog/Karin/HTML%20and%20Javascript/ResizeColumns/Table.htm

      Is this even possible with the current richfaces library?

      If so, how can I achieve this?

      If not.... does anyone have a solution that they have used?

        • 1. Re: scrollable tables
          nbelaevski

          Hello,

          the rich:scrollableDataTable provides the scrolling capabilities but outputs a bogus column that no production system wants to have.

          What bogus column are you referring to?

          Why can't we have something like this:
          http://www.cubido.at/Portals/7/docs/Blog/Karin/HTML%20and%20Javascript/ResizeColumns/Table.htm
          Why not? I think you'll able to build the proposed solution using several rich:dataTable components and a set of Facelets templates.

          • 2. Re: scrollable tables
            nbelaevski
            • 3. Re: scrollable tables
              kragoth

              The bogus column in the rich:scrollableDataTable is at the right side of the table. If you resize the last column and make it smaller, then another empty column fills up the space beside it. There's already a lot of posts about this.

              Anyway, for those people that want to achieve what I asked for, I have found a solution. I did a bit of searching and discovered that with a little bit of css you can get the desired functionality.

              Note: My solution has only been tested in IE6 and FF 3. I'm sure if you wanted more browser compatability it would be just a matter of adding/changing the necessary styles.

              So my solution is based on this example:
              http://www.stansight.com/sort/LockTableHeadSort.html
              This table had all the functionality that I was looking for and so I made a component that is a direct subclass of the rich:dataTable but, turns it into a scrolling table with fixed headers.

              Here is the code

              package gekko.web.jsf.components;
              
              import java.io.IOException;
              
              import javax.faces.context.FacesContext;
              import javax.faces.context.ResponseWriter;
              
              import org.richfaces.component.html.HtmlDataTable;
              
              import gekko.util.StringUtils;
              
              import static gekko.web.utils.HtmlConstants.CLASS_ATTR;
              
              public class UIShortList extends HtmlDataTable {
              
               @Override
               public void encodeBegin(FacesContext context) throws IOException {
               ResponseWriter writer = context.getResponseWriter();
               writeStyle(context);
               writer.startElement("div", null);
               writer.writeAttribute(CLASS_ATTR, "shortList", null);
               String styleString = "height:" + getHeightValue();
               styleString = styleString + "overflow:auto;border: 1px solid #C1DAD7;";
               writer.writeAttribute("style", styleString, "style");
              
              
              
               if (null == this.getAttributes().get("rowClasses")) {
               this.getAttributes().put(
               "rowClasses", "rich-table-row1,rich-table-row2");
               }
              
               super.encodeBegin(context);
               }
              
               private String getHeightValue() {
               String height = (String) getAttributes().get("height");
               String numericChars = "";
               String suffix = "";
               for (int i = 0; i < height.length(); i++) {
               char c = height.charAt(i);
               if (Character.isDigit(c)) {
               numericChars = numericChars + c;
               } else {
               suffix = height.substring(i);
               break;
               }
               }
               if (StringUtils.isBlank(numericChars)) {
               throw new IllegalStateException(
               this.getClass().getSimpleName() +
               " Component with id: " + getId() +
               " had an invalid height");
               }
              
               int actualHeight = Integer.parseInt(numericChars) + 30;
              
               return String.valueOf(actualHeight) + suffix + ";";
              
               }
              
               @Override
               public void encodeEnd(FacesContext context) throws IOException {
               super.encodeEnd(context);
               ResponseWriter writer = context.getResponseWriter();
               writer.endElement("div");
               }
              
               private void writeStyle(FacesContext context) throws IOException {
               ResponseWriter writer = context.getResponseWriter();
              
               String clientId = this.getClientId(context);
               String styleClass = clientId.replace(":", "");
              
               String styleTemplate =
               " ." + styleClass + " {\n" +
               " border: none;\n" +
               " }" +
               "\n" +
               " ." + styleClass + " tbody {\n" +
               " height:150px;\n" +
               " overflow-x:hidden;\n" +
               " overflow-y:auto;\n" +
               " }" +
               "\n" +
               " ." + styleClass + " tr {\n" +
               " height: auto;\n" +
               " white-space: nowrap;\n" +
               " }\n" +
               "\n" +
               " /* Prevent Mozilla scrollbar from hiding right-most cell content */\n" +
               " ." + styleClass + " tr td:last-child {\n" +
               " padding-right: 20px;\n" +
               " }\n" +
               "\n" +
               " /* Fixed Header Height */\n" +
               " ." + styleClass + " thead tr {\n" +
               " position: relative;\n" +
               " height: auto;\n" +
               " /* this fixes IE header jumping bug when mousing over rows in the tbody */\n" +
               " top: expression( this.parentNode.parentNode.parentNode.scrollTop + 'px' );\n" +
               " }\n";
               writer.startElement("style", null);
               writer.writeAttribute("type", "text/css", null);
               writer.writeText(styleTemplate, null);
               writer.endElement("style");
              
               this.setStyleClass(styleClass);
               }
              
              }
              


              There is a little bit of custom styling due to my project and the name of the component is a little miss leading (but due to an already established name in my project).

              I'm going to assume you know how to add a new component to your library so I'm not going to show faces-config.xml etc. If you need this information let me know and I'll post it.

              If the richfaces team can see the value in adding this sort of functionality as standard in the richfaces library I think that would be a great addition to the library.

              Nbelaevski,

              I appreciate your attempt to help me in this matter, but neither of the solutions provided are really production solutions. One of them even states:

              The solution is not clever: it clones current header and place on top of the table, synchronize width and scroll.

              This doesn't sound like a good idea. On a large table this would be slow and buggy.

              And I'm too far into the project to introduce another technology - jquery.

              With regards to using facelet templates and multiple dataTables.... I considered the multiple table solution but, This seems like a lot of work for what ultimately is a pretty common requirement. how many people want tables where the header dissapears?

              Anyway, I'm happy with the solution I have now. No javascript (well, a small expression in the css), no jquery, and all done via CSS. So this is lightweight and scales well to large tables.

              • 4. Re: scrollable tables
                nbelaevski

                 

                "Kragoth" wrote:
                The bogus column in the rich:scrollableDataTable is at the right side of the table. If you resize the last column and make it smaller, then another empty column fills up the space beside it. There's already a lot of posts about this.

                I see... Thank you for explaining!

                "Kragoth" wrote:
                If the richfaces team can see the value in adding this sort of functionality as standard in the richfaces library I think that would be a great addition to the library.


                "Kragoth" wrote:
                Nbelaevski,

                I appreciate your attempt to help me in this matter, but neither of the solutions provided are really production solutions. One of them even states:

                The solution is not clever: it clones current header and place on top of the table, synchronize width and scroll.

                This doesn't sound like a good idea. On a large table this would be slow and buggy.

                And I'm too far into the project to introduce another technology - jquery.
                Yes, looks like my attempt was not very useful. But as you can see both scrollable and extended data table use widths synchronization and looks like that is the only truly cross-browser solution (we need to support this feature for Safari and Opera). jQuery plugins mentioned is not the only possible way to solve the problem; maybe there are some more mature ones. Frankly speaking, I haven't tested thoroughly, just looked at demo.

                "Kragoth" wrote:
                With regards to using facelet templates and multiple dataTables.... I considered the multiple table solution but, This seems like a lot of work for what ultimately is a pretty common requirement. how many people want tables where the header dissapears?
                Lot of people don't want scrolls at all.

                "Kragoth" wrote:
                Anyway, I'm happy with the solution I have now. No javascript (well, a small expression in the css), no jquery, and all done via CSS. So this is lightweight and scales well to large tables.
                Great! I've asked Ilya to add your solution to Wiki Cookbook so that it won't get lost.