wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

Taming the categorized views - reloaded


My previous solution was designed for categorised views that don't use column totals. The difference between a view control with and without column totals is subtle but important. Without totals a category row is rendered with a colspan attribute that allows the categories to freely flow over the whole width of the table. Are column totals present no colspan is used and the column for the category must be wide enough to accommodate the full content. With a little JavaScript that can be fixed. The server side JS now looks like this:
  1. function getClientJSforTableLayout (tableID ) {
  2.     /**
  3.       * This code has as result JavaScript source code that is send down to the client]
  4.     */
  5.     var curTable = getComponent (tableID ) ;
  6.     var curID = getClientId (tableID ) ;
  7.     var tablewidth = extractWidthFromStyle (curTable. viewStyle ) ;
  8.     var result = "fixCatTableSpan(\"" +curID ;
  9.     result += "\");\n" ;
  10.     result += "fixCatTableWidth(\"" ; // This holds the JavaScript we return to the browser
  11.     result += curID + "\",[\"" ;
  12.     // Here we compute the sizeString
  13.  
  14.     var kids = curTable. getChildren ( ) ;
  15.     var defaultPercent = Math. floor ( 100 /kids. size ( ) ) + "% " ; // You have to love flexi data types
  16.     var perCentArray = [ ] ;
  17.     for ( var x in kids ) {
  18.         var styleCandidate = x. style ;
  19.         if (styleCandidate == null ) {
  20.             perCentArray [perCentArray. length ] = defaultPercent ;
  21.         } else {
  22.             var candidate2 = extractWidthFromStyle (styleCandidate ) ;
  23.             if (candidate2 == "" ) {
  24.                 perCentArray [perCentArray. length ] = defaultPercent ;
  25.             } else {
  26.                 perCentArray [perCentArray. length ] = candidate2 ;
  27.             }
  28.         }  
  29.        
  30.     }
  31.     result += perCentArray. join ( "\", \"" ) ;
  32.     result += "\"],\"" +tablewidth + "\");" ;
  33.     return result ;
  34. }
  35.  
  36. function extractWidthFromStyle (styleCandidate ) {
  37.     var result = "" ;
  38.     var whereisWidth = styleCandidate. indexOf ( "width:" ) ;
  39.     if (whereisWidth < 0 ) {
  40.         result = "" ;
  41.     } else {
  42.         var workString = styleCandidate. substr (whereisWidth + 6 ) ;
  43.         var hasSemiColon = workString. indexOf ( ";" ) ;
  44.             if (hasSemiColon < 0 ) {
  45.                 result = workString ;
  46.             } else {
  47.                 result = workString. substr ( 0 ,hasSemiColon ) ;
  48.             }
  49.     }
  50.     return result ;         
  51. }
while the client side JS now is this:
  1.  
  2. function fixCatTableWidth (tableID , sizeArray , tableSize ) {         
  3.     // Reset the outer table width
  4.     var outer = dojo. byId (tableID + "_OUTER_TABLE" ) ;
  5.     if (tableSize == null || tableSize == "" ) {
  6.         outer. style. width = "100%" ;
  7.     } else {
  8.         outer. style. width = tableSize ;
  9.     }  
  10.  
  11.     var max = sizeArray. length ;
  12.     // Get the table and all header elements
  13.     var table = dojo. byId (tableID ) ;
  14.     var allHeaders = table. getElementsByTagName ( "th" ) ;
  15.     var maxHeaders = allHeaders. length ;
  16.     for (i = 0 ;i <maxHeaders ;i ++ ) {
  17.         var curWidth = (i > max ) ? sizeArray [max ] : sizeArray [i ] ;
  18.         allHeaders [i ]. style. width = curWidth ;
  19.     }
  20. }
  21.  
  22. /**
  23.  * Finds for a given element inside a table hierarchy the table data
  24.  * element it is contained in
  25.  **/  
  26. function getEnclosingTdTag (startElement ) {
  27.     var parent = startElement. parentNode ;
  28.     while (parent != null ) {
  29.         if (parent. tagName == "td" || parent. tagName == "TD" ) {
  30.             break ;
  31.         }      
  32.         parent = parent. parentNode ;
  33.     }
  34.     return parent ;
  35. }
  36.  
  37. /**
  38.  * Gets all categorized rows and replaces empty td with colspan
  39. **/
  40. function fixCatTableSpan (tableID ) {
  41.     var tbl = dojo. byId (tableID ) ;
  42.     var allButtons = tbl. getElementsByTagName ( "button" ) ;
  43.     var max = allButtons. length ;
  44.     for (i = 0 ; i <max ;i ++ ) {
  45.         var curButton = allButtons [i ] ;
  46.         if (curButton. title == "collapsed" || curButton. title == "expanded" ) {
  47.             //We need to process it
  48.             var curTD = getEnclosingTdTag (curButton ) ;
  49.             if (curTD != null ) {
  50.                 replaceEmptyTdWithColSpan (curTD ) ;
  51.             }  
  52.         }
  53.     }
  54. }
  55.  
  56. /**
  57.  * Finds all empty td tags after a given start tag and removes them
  58.  * also inserts the colspan attribute into the start tag
  59. **/
  60. function replaceEmptyTdWithColSpan (startElement ) {
  61.     // No action needed if colspan is aleady > 1
  62.     if (startElement. colSpan > 1 ) {
  63.         return ;
  64.     }  
  65.     var colSpan = 1 ;
  66.    
  67.     var nextSibling = startElement. nextSibling ;
  68.    
  69.     while (nextSibling != null ) {
  70.         var following = nextSibling. nextSibling ;
  71.        
  72.         if (nextSibling. nodeName == "TD" ) {
  73.             // We stop at the first non empty node
  74.             if (nextSibling. firstChild == null ) {
  75.                 nextSibling. parentNode. removeChild (nextSibling ) ;
  76.                 colSpan += 1 ;
  77.             } else {
  78.                 break ;
  79.             }
  80.         }
  81.         nextSibling = following ;
  82.     }
  83.    
  84.     if (colSpan > 1 ) {
  85.         startElement. colSpan = colSpan ;
  86.     }
  87. }
  88.  
  89.  
As usual YMMV.

Posted by on 09 July 2010 | Comments (3) | categories: XPages

Comments

  1. posted by Patrick Kwinten on Friday 16 July 2010 AD:
    what is the value of codelines in the code examples? it makes copy and paste a pain in the ass.

    or is that the though behind it? Emoticon cry.gif
  2. posted by Stephan H. Wissel on Friday 16 July 2010 AD:
    Ah.. got me there. The idea is to allow line specific questions like: In line xx why do you do that. Need to rethink that approach.
  3. posted by Stephan H. Wissel on Friday 16 March 2012 AD:
    Patrick: did you copy & paste? The code lines don't get copied!