<?xml version="1.0" encoding="UTF-8"?>
<!-- XSLDataGrid.xsl -->
<!-- Author: Lindsey Simon <lsimon@commoner.com> -->
<!-- @copyright 2006 -->
<xsl:stylesheet 
   version="1.0" 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   >
   <xsl:output
      method="xml"
      version='1.0'
      omit-xml-declaration="yes"
      indent="no" />
      
   <xsl:variable name="container_id" select="/div/@id" />
   <xsl:variable name="colspan" select="count(/div/table/thead/tr/th) + 1" />
   
   
   <!-- outer containers -->
   <xsl:template match="/div/table[@class='XSLTable']">
      
      <!-- the width of each column + 1 for bordering -->
      <xsl:variable name="table_width">
         <xsl:choose>
            <xsl:when test="number(thead/tr/th/@width) = number(thead/tr/th/@width)">
               <xsl:value-of select="sum(thead/tr/th/@width) + count(thead/tr/th)" /><xsl:text>px</xsl:text>
            </xsl:when>
            <xsl:otherwise>
               <xsl:text>100%</xsl:text>
            </xsl:otherwise>
         </xsl:choose>            
      </xsl:variable>
      
      <div
         class="xdgFrame"
         id="xdgFrame_{$container_id}"
         >
         <div
            class="xdgSuperContainer"
            >
            <div
               id="xdgContainer_{$container_id}"
               class="xdgContainer"
               containerwidth="{$table_width}"
               >
               <xsl:apply-templates select="thead">
                  <xsl:with-param name="table_width" select="$table_width" />
               </xsl:apply-templates>
               
               <xsl:for-each select="tbody">
                  <xsl:call-template name="xdgDataContainer">
                     <xsl:with-param name="table_width" select="$table_width" />
                  </xsl:call-template>
               </xsl:for-each>
            <!-- End xdgContainer -->
            </div>
         <!-- End xdgSuperContainer -->   
         </div>
         <!-- Get the rest of the needed goods from the footer -->
         <xsl:call-template name="gridFooter" />
      <!-- End xdgSuperduperContainer -->   
      </div>
   </xsl:template>
   
   
   
   <!-- header table -->
   <xsl:template match="thead">
      <xsl:param name="container_id" select="$container_id" /> 
      <xsl:param name="table_width" /> 
      <table
         id="xdgHeaderTable_{$container_id}"
         class="xdgHeaderTable"
         style="width: {$table_width};"
         border="0"
         cellpadding="0" 
         cellspacing="0"
         >
         <tbody>
            <xsl:for-each select="tr">
            <tr
               id="xdgHeaderRow_{$container_id}"
               class="xdgHeaderRow"
               >
               <xsl:for-each select="th">
                  <xsl:variable name="col_id" select="@id" />	
                  <xsl:variable name="col_width">
                     <xsl:choose>
                        <xsl:when test="@width[number(.) = number(.)]">
                           <xsl:value-of select="@width" /><xsl:text>px</xsl:text>
                        </xsl:when>
                        <xsl:otherwise>
                           <xsl:value-of select="@width" />
                        </xsl:otherwise>
                     </xsl:choose>
                  </xsl:variable>
                  
                  <xsl:variable name="col_label" select="." />
                  <!-- table header -->
                  <th
                     id="xdgHeaderCell_{$container_id}_{$col_id}"
                     style="width: {$col_width};"
                     col_id="{$col_id}"
                     col_label="{$col_label}"
                     >
                     <!-- no formatting here to avoid linebreaks -->
                     <xsl:attribute name="data-type"><xsl:choose><xsl:when test="@data-type"><xsl:value-of select="@data-type" /></xsl:when><xsl:otherwise>text</xsl:otherwise></xsl:choose></xsl:attribute> 
                     <xsl:attribute name="class"><![CDATA[xdgHeaderCell ]]><xsl:for-each select="@class"><xsl:value-of select="." /></xsl:for-each></xsl:attribute>
                    
                     <!-- header float container -->
                     <div
                        id="xdgHeaderLabel_{$container_id}_{$col_id}"
                        class="xdgHeaderLabel"
                        >
                        
                        <!-- label text -->
                        <div
                           id="xdgHeaderLabelText_{$container_id}_{$col_id}"
                           >
                           <!-- sort by col in title -->
                           <xsl:if test="contains(@class, 'sortable')">
                              <xsl:attribute name="title"><![CDATA[Sort by ]]><xsl:value-of select="$col_label" /></xsl:attribute>
                           </xsl:if>
                           <!-- sortable in class -->
                           <xsl:attribute name="class"><![CDATA[xdgHeaderLabelText]]><xsl:if test="contains(@class, 'sortable')"><xsl:text> </xsl:text>sortable</xsl:if></xsl:attribute>
                           
                           <xsl:value-of select="$col_label" />
                        </div>
                        
                        
                        <!-- sort icon (the text space is necessary) -->
                        <div
                           id="xdgHeaderSortIcon_{$container_id}_{$col_id}"
                           >
                           <xsl:attribute name="class">
                              <xsl:choose>
                                 <xsl:when test="contains(@class, 'ascending')"><![CDATA[xdgHeaderSortIcon_ascending]]></xsl:when>
                                 <xsl:when test="contains(@class, 'descending')"><![CDATA[xdgHeaderSortIcon_descending]]></xsl:when>
                                 <xsl:otherwise><![CDATA[xdgHeaderSortIcon]]></xsl:otherwise>
                              </xsl:choose>
                           </xsl:attribute>
                           <xsl:text> </xsl:text>
                        </div>
                        
                        <!-- resizer -->
                        <xsl:if test="contains(@class, 'resizable')">
                           <div 
                              id="xdgColResizer_{$container_id}_{$col_id}"
                              class="xdgColResizer"
                           ></div>
                        </xsl:if>
                        
                     </div>
                  </th>
               </xsl:for-each>
               <th
                  id="xdgHeaderCell_{$container_id}_LAST"
                  class="xdgHeaderCell LAST"
                  style="border-right: 0px;">
                  <xsl:text> </xsl:text>
               </th>
            </tr>
         </xsl:for-each>
         </tbody>
      </table>
   </xsl:template>
   
   <!-- xdgDataContainer  -->
   <xsl:template name="xdgDataContainer">
      <xsl:param name="container_id" select="$container_id" /> 
      <xsl:param name="colspan" select="$colspan" />
      <xsl:param name="table_width" />
      
      <xsl:param name="sort_position">
         <xsl:for-each select="/div/table/thead/tr/th">
            <xsl:if test="@sort='ascending' or @sort='descending'"><xsl:value-of select="position()" /></xsl:if>
         </xsl:for-each>
      </xsl:param>
      
      <xsl:param name="sort_order_explicit" select="/div/table/thead/tr/th[position()=$sort_position]/@sort" />
      <xsl:param name="sort_order">
         <xsl:choose>
            <xsl:when test="$sort_order_explicit">
               <xsl:value-of select="$sort_order_explicit" />
            </xsl:when>
            <xsl:otherwise>ascending</xsl:otherwise>
         </xsl:choose>
      </xsl:param>
      
      <xsl:param name="sort_data_type_explicit" select="/div/table/thead/tr/th[position()=$sort_position]/@data_type" />
      <xsl:param name="sort_data_type">
         <xsl:choose>
            <xsl:when test="$sort_data_type_explicit">
               <xsl:value-of select="$sort_data_type_explicit" />
            </xsl:when>
            <xsl:otherwise>text</xsl:otherwise>
         </xsl:choose>
      </xsl:param>
      
      <xsl:param name="group_position">
         <xsl:for-each select="/div/table/thead/tr/th">
            <xsl:if test="contains(@class, 'grouped')">
               <xsl:value-of select="position()" />
            </xsl:if>
         </xsl:for-each>
      </xsl:param>
      
      <xsl:param name="group_label" select="/div/table/thead/tr/th[$group_position]" />
      
      <div 
         class="xdgDataContainer" 
         id="xdgDataContainer_{$container_id}"
         style="width: {$table_width};"
         >
         <table
            id="xdgDataTable_{$container_id}" 
            style="width: {$table_width};"
            cellspacing="0"
            cellpadding="0"
            border="0"
            >
            
            <!-- call colgroup -->
            <xsl:call-template name="colgroup" />
            
            <xsl:choose>
               <!-- call tbody grouped -->
               <xsl:when test="number($group_position) = number($group_position)">
                  <xsl:call-template name="tbody_grouped">
                     <xsl:with-param name="sort_position" select="$sort_position" />
                     <xsl:with-param name="sort_order" select="$sort_order" />
                     <xsl:with-param name="sort_data_type" select="$sort_data_type" />
                     <xsl:with-param name="group_position" select="$group_position" />
                     <xsl:with-param name="group_label" select="$group_label" />
                  </xsl:call-template>
               </xsl:when>
               <xsl:otherwise>
                  <!-- call tbody -->
                  <xsl:call-template name="tbody">
                     <xsl:with-param name="sort_position" select="$sort_position" />
                     <xsl:with-param name="sort_order" select="$sort_order" />
                     <xsl:with-param name="sort_data_type" select="$sort_data_type" />
                  </xsl:call-template>
               </xsl:otherwise>
            </xsl:choose>
         </table>
      </div>
   </xsl:template>


   
   <!-- colgroup -->
   <xsl:template name="colgroup">
      <xsl:param name="container_id" select="$container_id" />
      <colgroup 
         id="xdgDataColgroup_{$container_id}">
         <xsl:for-each select="../thead/tr/th">
            <xsl:variable name="col_id" select="@id" />
            <xsl:variable name="col_width">
               <xsl:choose>
                  <xsl:when test="number(@width) = number(@width)">
                     <xsl:value-of select="@width" /><xsl:text>px</xsl:text>
                  </xsl:when>
                  <xsl:otherwise>
                     <xsl:value-of select="@width" />
                  </xsl:otherwise>
               </xsl:choose>
            </xsl:variable>
            <col
               id="xdgDataCol_{$container_id}_{$col_id}"
               style="width: {$col_width};" />
         </xsl:for-each>
         <col id="xdgDataCol_{$container_id}_LAST" style="width: 0px;" />
      </colgroup>
   </xsl:template>
   
   <!-- tbody -->
   <xsl:template name="tbody">
      <xsl:param name="container_id" select="$container_id" />
      <xsl:param name="colspan" select="$colspan" />
      <xsl:param name="sort_position" />
      <xsl:param name="sort_order" />
      <xsl:param name="sort_data_type" />
      <tbody
         id="xdgRowSet_{$container_id}"
         class="xdgRowSet"
         >
         <xsl:choose>
            <!-- do sorting of rows via xsl -->
            <xsl:when test="number($sort_position) = number($sort_position)">
               <xsl:for-each select="tr">
                  <xsl:sort select="td[position()=$sort_position]" order="{$sort_order}" data-type="{$sort_data_type}" />
                  <xsl:call-template name="tr" />
               </xsl:for-each>
            </xsl:when>
            <!-- leave sorted as is -->
            <xsl:otherwise>
               <xsl:for-each select="tr">
                  <xsl:call-template name="tr" />
               </xsl:for-each>
            </xsl:otherwise>
         </xsl:choose>
      </tbody>
   </xsl:template>
   
   
   <!-- tbody grouped -->
   <xsl:template name="tbody_grouped">
      <xsl:param name="container_id" select="$container_id" />
      <xsl:param name="colspan" select="$colspan" />
      <xsl:param name="group_position" />
      <xsl:param name="group_label" />
      <xsl:param name="sort_position" />
      <xsl:param name="sort_order" />
      <xsl:param name="sort_data_type" />
      
      <!-- loop through a node-set of unique values, sorted -->
      <!-- #TODO apply Muenchian-style key to speed this up -->
      <xsl:for-each select="tr[./td[position()=$group_position and not(.=preceding::tr/td)]]">
         <xsl:sort select="td[position()=$sort_position]" order="{$sort_order}" data-type="{$sort_data_type}" />
         <xsl:variable name="groupedNodeSet" select="//tr[./td[position()=$group_position and .=current()/td]]" />
         <tbody
            class="xdgGroupedColBody"
            >
            <tr
               class="xdgGroupedSetTop"
               >
               <td 
                  colspan="{$colspan}"
                  class="xdgGroupedCellTop"
                  >
                  <div class="xdgGroupedColTop">
                     <div class="xdgGroupedColTopLeft"><xsl:text> </xsl:text></div>
                     <div class="xdgGroupedColTopMiddle">
                        <xsl:value-of select="$group_label" /><xsl:text> '</xsl:text><xsl:value-of select="current()/td[$group_position]" /><xsl:text>' (</xsl:text><xsl:value-of select="count($groupedNodeSet)" /><xsl:text> total)</xsl:text>
                     </div>
                  </div>
               </td>
            </tr>
         </tbody>
         
         <tbody
            id="xdgRowSet_{$container_id}_{generate-id()}"
            class="xdgRowSet"
            >
            <!-- go back to the data and pluck out all the rows in this group -->
            <xsl:for-each select="$groupedNodeSet">
               <xsl:call-template name="tr">
                  <!-- we want to send the overall position -->
                  <xsl:with-param name="row_id"	select="generate-id()" />
               </xsl:call-template>
            </xsl:for-each>
         </tbody>
         
         <tbody class="xdgGroupedColBody">
            <tr class="xdgGroupedSetBottom">
               <td
                  colspan="{$colspan}"
                  class="xdgGroupedCellBottom"
                  >
                  <div class="xdgGroupedColBottom">
                     <div class="xdgGroupedColBottomLeft"></div>
                  </div>
               </td>
            </tr>
         </tbody>
       </xsl:for-each>
   </xsl:template>
   
   
   <!-- tr table rows -->
   <xsl:template name="tr">
      <xsl:param name="row_id" select="position()" />
      <xsl:param name="container_id" select="$container_id" />
      <xsl:param name="colspan" select="$colspan" />
      <xsl:param name="stripe">
         <xsl:choose>
            <xsl:when test="position() mod 2 = 1">odd</xsl:when>
            <xsl:otherwise>even</xsl:otherwise>
         </xsl:choose>
      </xsl:param>
      
      <tr>
         <!-- tack on any extra attributes found in the original tr tag -->
         <!-- but always overwrite id and class -->
         <xsl:for-each select="@*">
            <xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>
         </xsl:for-each>
         <xsl:attribute name="id">xdgDataRow_<xsl:value-of select="$container_id" />_<xsl:value-of select="$row_id" /></xsl:attribute>
         <xsl:attribute name="class"><xsl:value-of select="$stripe" /></xsl:attribute>
         
         <!-- so that subsequent calls from the client lop off the extra cell -->
         <xsl:for-each select="td[position()&lt;$colspan]">
             <xsl:copy-of select="." />
         </xsl:for-each>
         <td></td>
      </tr>
   </xsl:template>
   
   
  
   
   <!-- gridFooter -->
   <xsl:template name="gridFooter">
      <div
         id="xdgScrollContainer_{$container_id}"
         class="xdgScrollContainer"
         >
         <div
            id="xdgScroller_{$container_id}"
            class="xdgScroller"
            >
            <div id="xdgScrollHeight_{$container_id}" class="xdgScrollHeight"></div>
         </div>
      </div>
      
      <!-- resize column guide -->
      <div
         id="xdgResizeGuide_{$container_id}"
         class="xdgResizeGuide"
         style="display: none;"
         >
         <xsl:text> </xsl:text>
      </div>
      
      <!-- Right-click menu options for columns -->
      <div
         id="xdgPopupDiv"
         style="display: none;"
         >
         <xsl:text> </xsl:text>
      </div>
      
      <!-- overlay to disable grid on server callbacks -->
      <div 
         id="xdgOverlay_{$container_id}"
         class="xdgOverlay"
         style="display: none;"
         >
         <xsl:text> </xsl:text>
      </div>
      <!-- loading graphic -->
      <div 
         id="xdgLoading_{$container_id}"
         class="xdgLoading"
         style="display: none;"
         >
         <xsl:text> </xsl:text>
      </div>
      
      <!-- contextMenuItem templates 
      
        onmouseover="this.className='xdgColContextMenuListItemHover';"
         onmouseout="this.className='xdgColContextMenuListItem';"
      -->
      <div
         id="xdgColContextMenuItemTemplate"
         class="xdgColContextMenuListItem"
         style="display: none;"
         >
         <div 
            class="menuItemIcon"
            >
            <xsl:text> </xsl:text>
         </div>
         <div 
            class="menuItemText"
            >
            <xsl:text> </xsl:text>
         </div>
      </div>
      <div
         id="xdgColContextMenuItemFilterTemplate"
         class="xdgColContextMenuListItem"
         style="display: none;"
         >
         <div 
            class="menuItemIcon filterByColumnIcon"
            >
            <xsl:text> </xsl:text>
         </div>
         <input
            type="text"
            class="filterByColumnInput"
            />
      </div>
      
   </xsl:template>
   
</xsl:stylesheet>
