Package org.olat.core.gui.components.table

Source Code of org.olat.core.gui.components.table.TableRenderer

/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) 1999-2006 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/

package org.olat.core.gui.components.table;

import java.util.BitSet;
import java.util.List;

import org.apache.commons.lang.StringEscapeUtils;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.ComponentRenderer;
import org.olat.core.gui.control.winmgr.AJAXFlags;
import org.olat.core.gui.render.RenderResult;
import org.olat.core.gui.render.Renderer;
import org.olat.core.gui.render.RenderingState;
import org.olat.core.gui.render.StringOutput;
import org.olat.core.gui.render.URLBuilder;
import org.olat.core.gui.translator.Translator;
import org.olat.core.logging.OLATRuntimeException;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;

/**
* enclosing_type Description: <br>
*
* @author Felix Jost
*/
public class TableRenderer implements ComponentRenderer {
  private OLog log = Tracing.createLoggerFor(this.getClass());
 
  protected static final String TABLE_MULTISELECT_GROUP = "tb_ms";

  /**
   * Constructor for TableRenderer. There must be an empty contructor for the
   * Class.forName() call
   */
  public TableRenderer() {
    super();
  }

  /**
   * @see org.olat.core.gui.render.ui.ComponentRenderer#render(org.olat.core.gui.render.Renderer,
   *      org.olat.core.gui.render.StringOutput, org.olat.core.gui.components.Component,
   *      org.olat.core.gui.render.URLBuilder, org.olat.core.gui.translator.Translator,
   *      org.olat.core.gui.render.RenderResult, java.lang.String[])
   */
  public void render(Renderer renderer, StringOutput target, Component source, URLBuilder ubu, Translator translator,
      RenderResult renderResult, String[] args) {
    Table table = (Table) source;
   
    // render form for multiselect
    String formName = "tb_ms_" + source.hashCode();
    target.append("<form method=\"post\" name=\"");
    target.append(formName);
    target.append("\" action=\"");
    boolean iframePostEnabled = renderer.getGlobalSettings().getAjaxFlags().isIframePostEnabled();
    ubu.buildURI(target, null, null, iframePostEnabled ? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL);
    target.append("\" id=\"");
    target.append(formName);
    target.append("\"");
    if (iframePostEnabled) {
      ubu.appendTarget(target);
    }
    target.append(" onsubmit=\"o_beforeserver();\">");
    // starting real table table
    target.append("<div class=\"b_overflowscrollbox\" id=\"b_overflowscrollbox_").append(table.hashCode()).append("\"><table id=\"b_table").append(table.hashCode()).append("\">");

    int rows = table.getRowCount();
    int cols = table.getColumnCount();

    boolean asc = table.isSortAscending();
    boolean selRowUnSelectable = table.isSelectedRowUnselectable();

    // build header links
    if (table.isDisplayTableHeader()) {
      target.append("<thead><tr>");

      ColumnDescriptor sortedCD = table.getCurrentlySortedColumnDescriptor();
      for (int i = 0; i < cols; i++) {
        ColumnDescriptor cd = table.getColumnDescriptor(i);
        String header;
        if(cd.translateHeaderKey())
          header = translator.translate(cd.getHeaderKey());
        else
          header = cd.getHeaderKey();

        target.append("<th class=\"");
        // add css class for first and last column to support older browsers
        if (i == 0) target.append(" b_first_child");
        if (i == cols-1) target.append(" b_last_child");
        target.append("\">");

        // add 'move column left' link (if we are not at the leftmost position)
        if (i != 0 && table.isColumnMovingOffered()) {
          if(table.markMoveL && table.markedColumn == i){
            target.append("<span style=\"border:2px solid red;\">");
          }
         
          target.append("<a href=\"JavaScript:tableFormInjectCommandAndSubmit('");
          target.append(formName).append("', '" + Table.COMMAND_MOVECOLUMN_LEFT + "', '").append(i).append("');\" class=\"b_table_move_left\" title=\"");
          target.append(StringEscapeUtils.escapeHtml(translator.translate("row.move.left"))).append("\">&laquo;</a> ");
         
          if(table.markMoveL && table.markedColumn == i){
            target.append("</span>");
          }
        }
        // header either a link or not
        if (table.isSortingEnabled() && cd.isSortingAllowed()) {
          if(table.markSort && table.markedColumn == i){
            target.append("<span style=\"border:2px solid red;\">");
          }
         
          target.append("<a href=\"JavaScript:tableFormInjectCommandAndSubmit('");
          target.append(formName).append("', '" + Table.COMMAND_SORTBYCOLUMN + "', '").append(i).append("');\" title=\"");
          target.append(StringEscapeUtils.escapeHtml(translator.translate("row.sort"))).append("\">");
          target.append(header);
          target.append("</a>");
         
          if(table.markSort && table.markedColumn == i){
            target.append("</span>");
          }
        } else {
          target.append(header);
        }
        // mark currently sorted row special
        if (table.isSortingEnabled() && cd == sortedCD) {
          //REVIEW:fj:pb I think this should look the same as the above link?
          if(table.markSort && table.markedColumn == i){
            target.append("<span style=\"border:2px solid red;\">");
          }
         
          target.append("<a href=\"JavaScript:tableFormInjectCommandAndSubmit('");
          target.append(formName).append("', '" + Table.COMMAND_SORTBYCOLUMN + "', '").append(i).append("');\" title=\"");
          target.append(StringEscapeUtils.escapeHtml(translator.translate("row.sort.invert"))).append("\">&nbsp;");
          target.append((asc ? "&darr;"  : "&uarr;"));
          target.append("</a>");
         
          if(table.markSort && table.markedColumn == i){
            target.append("</span>");
          }
        }

        // add 'move column right' link (if we are not at the rightmost
        // position)
        if (i != cols - 1 && table.isColumnMovingOffered()) {
          if(table.markMoveR && table.markedColumn == i){
            target.append("<span style=\"border:2px solid red;\">");
          }
         
          target.append("<a href=\"JavaScript:tableFormInjectCommandAndSubmit('");
          target.append(formName).append("', '" + Table.COMMAND_MOVECOLUMN_RIGHT + "', '").append(i).append("');\" class=\"b_table_move_right\" title=\"");
          target.append(StringEscapeUtils.escapeHtml(translator.translate("row.move.right"))).append("\">&raquo;</a>");
         
          if(table.markMoveR && table.markedColumn == i){
            target.append("</span>");
          }
        }
        target.append("</th>");
      }
      target.append("</tr></thead>");
    }

    // build rows
    target.append("<tbody>");
    // the really selected rowid (from the tabledatamodel)
    int selRowId = table.getSelectedRowId();
    String cssClass;

    int resultsPerPage = table.getResultsPerPage();
    Integer currentPageId = table.getCurrentPageId();
    boolean usePageing;
    int startRowId = 0;
    int endRowId = rows;
    // initalize pageing
    if (table.isPageingEnabled() && currentPageId != null && !table.isShowAllSelected()) {
      startRowId = ((currentPageId.intValue() - 1) * resultsPerPage);
      endRowId = startRowId + resultsPerPage;
      if (endRowId > rows) endRowId = rows;
      usePageing = true;
    } else {
      startRowId = 0;
      endRowId = rows;
      usePageing = false;
    }
       
    BitSet multiSelectSelectedRows = table.getMultiSelectSelectedRows();
    int lastVisibleRowId = endRowId-1;
    for (int i = startRowId; i < endRowId; i++) {
      // the position of the selected row in the tabledatamodel
      int currentPosInModel = table.getSortedRow(i);
      boolean isMark = selRowUnSelectable && (selRowId == currentPosInModel);

      // use alternating css class
      if (i % 2 == 0) cssClass = "";
      else cssClass = "b_table_odd";
      // add css class for first and last column to support older browsers
      if (i == startRowId) cssClass += " b_first_child";
      if (i == lastVisibleRowId) cssClass += " b_last_child";

      target.append("<tr class=\"").append(cssClass).append("\">");
      for (int j = 0; j < cols; j++) {
        ColumnDescriptor cd = table.getColumnDescriptor(j);
        int alignment = cd.getAlignment();
        cssClass = (alignment == ColumnDescriptor.ALIGNMENT_LEFT ? "b_align_normal" : (alignment == ColumnDescriptor.ALIGNMENT_RIGHT ? "b_align_inverse" : "b_align_center"));
        // add css class for first and last column to support older browsers
        if (j == 0) cssClass += " b_first_child";
        if (j == cols-1) cssClass += " b_last_child";       
        target.append("<td class=\"").append(cssClass);
        if (isMark) {
          target.append(" b_table_marked");
        }
        target.append("\">");
        if (j == 0) target.append("<a name=\"b_table\"></a>"); //add once for accessabillitykey
        String action = cd.getAction(i);
        StringOutput so = new StringOutput();
        cd.renderValue(so, i, renderer);
        String renderval = so.toString();
        log.debug("render: i=" + i + " renderval=" + renderval );

        if (action != null) {
          // If we have actions on the table rows, we just submit traditional style (not via form.submit())
          // Note that changes in the state of multiselects will not be reflected in the model.
          HrefGenerator hrefG = cd.getHrefGenerator();

          if (hrefG != null) {
            if(table.markSelectedRowId == currentPosInModel && action.equals(table.markActionId)){
              target.append("<span style=\"border:2px solid red;\">");
            }
           
            target.append("<a href=\"");
            StringOutput link = new StringOutput();
            ubu.buildURI(link, new String[] { Table.COMMANDLINK_ROWACTION_CLICKED, Table.COMMANDLINK_ROWACTION_ID }, new String[] {
                String.valueOf(currentPosInModel), action }); // url
            target.append(hrefG.generate(currentPosInModel, link.toString()));
            target.append("\">");
           
          } else if (cd.isPopUpWindowAction()) {
            if(table.markSelectedRowId == currentPosInModel && action.equals(table.markActionId)){
              target.append("<span style=\"border:2px solid red;\">");
            }
           
            // render as popup window
            target.append("<a href=\"");
            target.append("javascript:{var win=window.open('");
            ubu.buildURI(target, new String[] { Table.COMMANDLINK_ROWACTION_CLICKED, Table.COMMANDLINK_ROWACTION_ID }, new String[] {
                String.valueOf(currentPosInModel), action }); // url
            target.append("','tw_").append(i + "_" + j); // javascript window
                                                          // name
            target.append("','");
            String popUpAttributes = cd.getPopUpWindowAttributes();
            if (popUpAttributes != null) target.append(popUpAttributes);
            target.append("');win.focus();}\">");
          } else {
            if(table.markSelectedRowId == currentPosInModel && action.equals(table.markActionId)){
              target.append("<span style=\"border:2px solid red;\">");
            }
           
            // render in same window
            target.append("<a href=\"");
            ubu.buildURI(target, new String[] { Table.COMMANDLINK_ROWACTION_CLICKED, Table.COMMANDLINK_ROWACTION_ID }, new String[] {
                String.valueOf(currentPosInModel), action }, iframePostEnabled? AJAXFlags.MODE_TOBGIFRAME : AJAXFlags.MODE_NORMAL);
            target.append("\"  onclick=\"return o2cl()\"");
            if (iframePostEnabled) {
              ubu.appendTarget(target);
            }
            target.append(">");
           
          }
          target.append(renderval);
          target.append("</a>");
         
          if(table.markSelectedRowId == currentPosInModel && action.equals(table.markActionId)){
            target.append("</span>");
          }
        } else {
          target.append(renderval);
        }
        target.append("</td>");
      }
      target.append("</tr>");
    }       
    // end of table table
    target.append("</tbody></table></div>");
   
    // if multiselect, add "select all" / "deselect all" buttons
    if (table.isMultiSelect()) {
      target.append("<div class=\"b_togglecheck\">");
      target.append("<a href=\"#\" onclick=\"javascript:b_table_toggleCheck('" + formName + "', true)\">");
      target.append("<input type=\"checkbox\" checked=\"checked\" disabled=\"disabled\" />");
      target.append(translator.translate("checkall"));
      target.append("</a> <a href=\"#\" onclick=\"javascript:b_table_toggleCheck('" + formName + "', false)\">");
      target.append("<input type=\"checkbox\" disabled=\"disabled\" />");
      target.append(translator.translate("uncheckall"));
      target.append("</a></div>");
    }
   
    if(table.isShowAllSelected() && (rows > resultsPerPage) ) {
      target.append("<div class=\"b_table_page\">");
      target.append("<a href=\"JavaScript:tableFormInjectCommandAndSubmit('");
      target.append(formName).append("', '" + Table.COMMAND_PAGEACTION).append("', '" + Table.COMMAND_SHOW_PAGES + "');\" onclick=\"return o2cl();\">");
      target.append("[").append(translator.translate("table.showpages")).append("]</a>");
      target.append("</div>");
    }

    // add table paging
    if (usePageing && (rows > resultsPerPage)) {
      int pageid = currentPageId.intValue();
      //paging bug OLAT-935 part missing second page, or missing last page due rounding issues.
      int maxpageid = (int)Math.ceil(((double)rows / (double)resultsPerPage));
      target.append("<div class=\"b_table_page\">");
      // back link if not on first page
      if (pageid > 1) {
        if(table.markPageBackward){
          target.append("<span style=\"border:2px solid red;\">");
        }
       
        target.append("<a class=\"b_table_backward\" href=\"JavaScript:tableFormInjectCommandAndSubmit('");
        target.append(formName).append("', '" + Table.COMMAND_PAGEACTION + "', '").append(Table.COMMAND_PAGEACTION_BACKWARD).append("');\" onclick=\"return o2cl();\">");
        target.append(translator.translate("table.backward")).append("</a>");

        if(table.markPageBackward){
          target.append("</span>");
        }
      }
      // page number links

      if(table.markActivatePageX == pageid){
        target.append("<span style=\"border:2px solid red;\">");
      }
     
      addPageNumberLinks(target, formName, pageid, maxpageid);

      if(table.markActivatePageX == pageid){
        target.append("</span>");
      }
      // next link
      if ((pageid * resultsPerPage) < rows) {
        if(table.markPageForward){
          target.append("<span style=\"border:2px solid red;\">");
        }
       
        target.append("<a class=\"b_table_forward\" href=\"JavaScript:tableFormInjectCommandAndSubmit('");
        target.append(formName).append("', '" + Table.COMMAND_PAGEACTION + "', '").append(Table.COMMAND_PAGEACTION_FORWARD).append("');\" onclick=\"return o2cl();\">");
        target.append(translator.translate("table.forward")).append("</a>");
       
        if(table.markPageForward){
          target.append("</span>");
        }
      }
      // show all results link
      if (table.isShowAllLinkEnabled()) {
        target.append("</div><div class=\"b_table_page_all\">");
 
        if(table.markPageShowAll){
          target.append("<span style=\"border:2px solid red;\">");
        }
        target.append("<a href=\"JavaScript:tableFormInjectCommandAndSubmit('");
        target.append(formName).append("', '" + Table.COMMAND_PAGEACTION + "', '").append(Table.COMMAND_PAGEACTION_SHOWALL).append("');\" onclick=\"return o2cl();\">");
        target.append("[").append(translator.translate("table.showall")).append("]</a>");
 
        if(table.markPageShowAll){
          target.append("</span>");
        }
      }
      target.append("</div>");
     
    }
   
    // add multiselect form actions
    List multiSelectActionsi18nKeys = table.getMultiSelectActionsI18nKeys();
    List multiSelectActionsIdentifiers = table.getMultiSelectActionsIdentifiers();
    if (table.isMultiSelect() && multiSelectActionsi18nKeys.size() == 0) throw new OLATRuntimeException(null,
        "Action key in multiselect table is undefined. Use addMultiSelectI18nAction(\"i18nkey\", \"action\"); to set an action for this multiselect table.", null);
    target.append("<div class=\"b_table_buttons\">");
    for (int i = 0; i < multiSelectActionsi18nKeys.size(); i++) {
      String multiSelectActionsi18nKey = (String)multiSelectActionsi18nKeys.get(i);
      String multiSelectActionIdentifer = (String)multiSelectActionsIdentifiers.get(i);
      if (table.markActionId != null && table.markActionId.equals(multiSelectActionIdentifer))
        target.append("<span style=\"border:2px solid red;\">");
      target.append("<input type=\"submit\" name=\"" + multiSelectActionIdentifer + "\" value=\""
          + StringEscapeUtils.escapeHtml(translator.translate(multiSelectActionsi18nKey)) + "\" class=\"b_button\" />");
      if (table.markActionId != null && table.equals(multiSelectActionIdentifer))
        target.append("</span>");
    }
    target.append("</div>");
    // add hidden action command placeholders to the form. these will be manipulated when
    // the user clicks on a regular link within the table to e.g. re-sort the columns.
    target.append("<input type=\"hidden\" name=\"cmd\" value=\"\" />");
    target.append("<input type=\"hidden\" name=\"param\" value=\"\" />");
    // close multiselect form
    target.append("</form>");
   
    // JS code to resize table to browser view port and display scrollbars in the table
    // when not in pageing mode and more than 1000 results are shown.
    // This prevents a very strange overflow problem in FF that makes all
    // entries after the 1023 entry or even the entire table unreadable.
    // Comment CDATA section to make it work with prototype's stripScripts method !
    if (!usePageing && rows > 1000) {
      target.append("<script type=\"text/javascript\">/* <![CDATA[ */\n ");
      target.append("Ext.onReady(function() { $('b_overflowscrollbox_").append(source.hashCode()).append("').setStyle({'height': b_viewportHeight()/3*2 + 'px'});});");
      target.append("/* ]]> */\n</script>");
    }
  }

  /**
   * @param target
   * @param ubu
   * @param pageid
   * @param maxpageid
   */
  private void addPageNumberLinks(StringOutput target, String formName, int pageid, int maxpageid) {
    /*
     * simple case where only 1 to pageId numbers have to be generated
     */
    if (maxpageid < 12) {
      for (int i = 1; i <= maxpageid; i++) {
        target.append("<a ");
        if (pageid == i) {
          target.append(" class=\"b_table_page_active\"");
        }
        target.append(" href=\"JavaScript:tableFormInjectCommandAndSubmit('");
        target.append(formName).append("', '" + Table.COMMAND_PAGEACTION + "', '").append(i).append("');\">");
        target.append(i).append("</a>");
      }
      return;
    }

    int powerOf10 = String.valueOf(maxpageid).length() - 1;
    int maxStepSize = (int) Math.pow(10, powerOf10);
    int stepSize = (int) Math.pow(10, String.valueOf(pageid).length() - 1);
    boolean isStep = false;
    int useEveryStep = 3;
    int stepCnt = 0;
    boolean isNear = false;
    int nearleft = 5;
    int nearright = 5;
    if (pageid < nearleft) {
      nearleft = pageid;
      nearright += (nearright - nearleft);
    } else if (pageid > (maxpageid - nearright)) {
      nearright = maxpageid - pageid;
      nearleft += (nearleft - nearright);
    }
    for (int i = 1; i <= maxpageid; i++) {
      // adapt stepsize if needed
      if (i < pageid && stepSize > 1 && ((pageid - i) / stepSize == 0)) {
        stepSize = stepSize / 10;
      } else if (i > pageid && stepSize < maxStepSize && ((i - pageid) / stepSize == 9)) {
        stepSize = stepSize * 10;
      }

      isStep = ((i % stepSize) == 0);
      if (isStep) {
        stepCnt++;
        isStep = isStep && (stepCnt % useEveryStep == 0);
      }
      isNear = (i > (pageid - nearleft) && i < (pageid + nearright));
      if (i == 1 || i == maxpageid || isStep || isNear) {
        target.append("<a ");
        if (pageid == i) {
          target.append(" class=\"b_table_page_active\"");
        }
        target.append(" href=\"JavaScript:tableFormInjectCommandAndSubmit('");
        target.append(formName).append("', '" + Table.COMMAND_PAGEACTION + "', '").append(i).append("');\">");
        target.append(i).append("</a>");
      }
    }
  }

  /**
   * @see org.olat.core.gui.render.ui.ComponentRenderer#renderHeaderIncludes(org.olat.core.gui.render.Renderer,
   *      org.olat.core.gui.render.StringOutput, org.olat.core.gui.components.Component,
   *      org.olat.core.gui.render.URLBuilder, org.olat.core.gui.translator.Translator)
   */
  public void renderHeaderIncludes(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, RenderingState rstate) {
  //
  }

  /**
   * @see org.olat.core.gui.render.ui.ComponentRenderer#renderBodyOnLoadJSFunctionCall(org.olat.core.gui.render.Renderer,
   *      org.olat.core.gui.render.StringOutput, org.olat.core.gui.components.Component)
   */
  public void renderBodyOnLoadJSFunctionCall(Renderer renderer, StringOutput sb, Component source, RenderingState rstate) {
    //
  }

}
TOP

Related Classes of org.olat.core.gui.components.table.TableRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.