/* -------------------------------------------------------------

Table Row Rendering

-------------------------------------------------------------
337601
public final void openHeaderRow(TrTag.State state, AbstractRenderAppender appender) {
        if(state == null)
            state = TR_STATE;

        appender.append(LINE_BREAK);
        _trRenderer.doStartTag(appender, state);
    }
947511
private function displayEnterAnotherRow()
    {
        $columns = $this->parent->getVisibleColumns();

        $this->createEmbeddedWidgets();

        /*
         * Get column position of enter-a-new-row text. The text is displayed
         * underneath the first input cell that is not blank. If all cells are
         * blank, text is displayed underneath the first cell.
         */
        $position = 0;
        $colspan = 0;
        foreach ($columns as $column) {
            if (
                array_key_exists($column->id, $this->input_cells) &&
                !(
                    $this->input_cells[$column->id] instanceof
                    SwatRemoveInputCell
                )
            ) {
                $position = $colspan;
                break;
            }
            $colspan += $column->getXhtmlColspan();
        }

        $close_length = $this->parent->getXhtmlColspan() - $position - 1;

        $tr_tag = new SwatHtmlTag('tr');
        $tr_tag->id = $this->getId() . '_enter_row';
        $tr_tag->class = 'swat-table-view-input-row-add-row';
        $tr_tag->open();

        if ($position > 0) {
            $td = new SwatHtmlTag('td');
            $td->colspan = $position;
            $td->open();
            echo '&nbsp;';
            $td->close();
        }

        // use the same style as table-view column
        $td = new SwatHtmlTag('td', $column->getTdAttributes());
        $td->open();
        $this->enter_another_link->display();
        $td->close();

        if ($close_length > 0) {
            $td = new SwatHtmlTag('td');
            $td->colspan = $close_length;
            $td->open();
            echo '&nbsp;';
            $td->close();
        }

        $tr_tag->close();
    }
967514
function(item, tableRow) {
			mExplorer.SelectionRenderer.prototype.renderRow.call(this, item, tableRow);
			if (item.type !== "file") { //$NON-NLS-0$
				tableRow.classList.add("searchDetailRow"); //$NON-NLS-0$
			}
		}
608364
public function render()
    {
        if (empty($this->_rows) || empty($this->_columns)) {
            return;
        }

        $stream = $this->getRtf()->getWriter();
        $stream->write('\pard');

        foreach ($this->_rows as $row) {
            $this->renderRowDefinition($row);
            $stream->write("\r\n");
            $this->renderRowCells($row);
            $stream->write("\r\n" . '\row' . "\r\n");
        }

        $stream->write('\pard\itap0' . "\r\n");
    }
485014
public function render()
	{
		/**
		 * Check whether datagrid has set some columns, initiated data source, etc
		 */
		if (!($this->dataModel instanceof DataModel)) {
			throw new DataGridException('You have to set a data source first.');
		}

		if (empty($this->columns)) {
			throw new DataGridException('You have to add at least one column.');
		}

		$template = $this->getTemplate();
		$template->setTranslator($this->getTranslator());

		/**
		 * Invoke possible events
		 */
		$this->onRender($this);

		/**
		 * Prepare data for rendering (datagrid may render just one item)
		 */
		$rows = [];

		if (!empty($this->redraw_item)) {
			$items = $this->dataModel->filterRow($this->redraw_item);
		} else {
			$items = Nette\Utils\Callback::invokeArgs(
				[$this->dataModel, 'filterData'],
				[
					$this->getPaginator(),
					$this->createSorting($this->sort, $this->sort_callback),
					$this->assembleFilters(),
				]
			);
		}

		$callback = $this->rowCallback ?: null;
		$hasGroupActionOnRows = false;

		foreach ($items as $item) {
			$rows[] = $row = new Row($this, $item, $this->getPrimaryKey());

			if (!$hasGroupActionOnRows && $row->hasGroupAction()) {
				$hasGroupActionOnRows = true;
			}

			if ($callback) {
				$callback($item, $row->getControl());
			}

			/**
			 * Walkaround for item snippet - snippet is the <tr> element and its class has to be also updated
			 */
			if (!empty($this->redraw_item)) {
				$this->getPresenter()->payload->_datagrid_redraw_item_class = $row->getControlClass();
				$this->getPresenter()->payload->_datagrid_redraw_item_id = $row->getId();
			}
		}

		if ($hasGroupActionOnRows) {
			$hasGroupActionOnRows = $this->hasGroupActions();
		}

		if ($this->isTreeView()) {
			$template->add('tree_view_has_children_column', $this->tree_view_has_children_column);
		}

		$template->rows = $rows;

		$template->columns = $this->getColumns();
		$template->actions = $this->actions;
		$template->exports = $this->exports;
		$template->filters = $this->filters;
		$template->toolbar_buttons = $this->toolbar_buttons;
		$template->aggregation_functions = $this->getAggregationFunctions();
		$template->multiple_aggregation_function = $this->getMultipleAggregationFunction();

		$template->filter_active = $this->isFilterActive();
		$template->original_template = $this->getOriginalTemplateFile();
		$template->icon_prefix = static::$icon_prefix;
		$template->icon_prefix = static::$icon_prefix;
		$template->items_detail = $this->items_detail;
		$template->columns_visibility = $this->getColumnsVisibility();
		$template->columnsSummary = $this->columnsSummary;

		$template->inlineEdit = $this->inlineEdit;
		$template->inlineAdd = $this->inlineAdd;

		$template->hasGroupActions = $this->hasGroupActions();
		$template->hasGroupActionOnRows = $hasGroupActionOnRows;

		/**
		 * Walkaround for Latte (does not know $form in snippet in {form} etc)
		 */
		$template->filter = $this['filter'];

		/**
		 * Set template file and render it
		 */
		$template->setFile($this->getTemplateFile());
		$template->render();
	}
921788
@Override
	public void doRender(final WComponent component, final WebXmlRenderContext renderContext) {
		WDataTableRowRenderer renderer = (WDataTableRowRenderer) component;
		XmlStringBuilder xml = renderContext.getWriter();
		WDataTable table = renderer.getTable();
		TableDataModel dataModel = table.getDataModel();
		UIContext uic = UIContextHolder.getCurrent();

		final int numCols = table.getColumnCount();
		int[] columnOrder = table.getColumnOrder();
		int rowIndex = getRowIndex(table, (SubUIContext) uic);
		boolean unselectable = table.getSelectMode() != SelectMode.NONE
				&& !dataModel.isSelectable(rowIndex);

		xml.appendTagOpen("ui:tr");
		xml.appendAttribute("rowIndex", rowIndex);
		xml.appendOptionalAttribute("unselectable", unselectable, "true");
		xml.appendOptionalAttribute("selected", table.getSelectedRows().contains(rowIndex), "true");
		xml.appendOptionalAttribute("filterValues", getFilterValues(dataModel, rowIndex));

		if (table.getExpandMode() != WDataTable.ExpandMode.NONE && dataModel instanceof TreeTableDataModel) {
			TableTreeNode node = ((TreeTableDataModel) dataModel).getNodeAtLine(rowIndex);
			boolean expandable = !node.isLeaf() && !node.isExpanded();
			xml.appendOptionalAttribute("expandable", expandable, "true");
		}

		xml.appendClose();

		if (table.isShowRowHeaders()) {
			xml.appendTag("ui:th");
			renderer.getRowHeader().paint(renderContext);
			xml.appendEndTag("ui:th");
		}

		for (int i = 0; i < numCols; i++) {
			int colIndex = columnOrder == null ? i : columnOrder[i];
			WTableColumn col = table.getColumn(colIndex);

			if (col.isVisible()) {
				xml.appendTag("ui:td");
				renderer.getRenderer(colIndex).paint(renderContext);
				xml.appendEndTag("ui:td");
			}
		}

		if (table.getExpandMode() != WDataTable.ExpandMode.NONE && dataModel instanceof TreeTableDataModel) {
			TreeTableDataModel treeModel = (TreeTableDataModel) dataModel;
			TableTreeNode node = treeModel.getNodeAtLine(rowIndex);

			if (!node.isLeaf()) {
				xml.appendTagOpen("ui:subtr");
				xml.appendOptionalAttribute("open", node.isExpanded(), "true");
				xml.appendClose();

				if (node.isExpanded() || table.getExpandMode() == ExpandMode.CLIENT) {
					WRepeater repeater = table.getRepeater();

					// If there a renderer specified by any child, we only paint content that has a specified renderer
					boolean rendererPresent = false;

					for (Iterator<TreeNode> i = node.children(); !rendererPresent && i.hasNext();) {
						TableTreeNode child = (TableTreeNode) i.next();

						if (child.getRendererClass() != null) {
							rendererPresent = true;
						}
					}

					// Paint immediate children only.
					if (rendererPresent) {
						xml.appendTagOpen("ui:content");
						xml.appendOptionalAttribute("spanAllCols", node.isRendererSpansAllCols(),
								"true");
						xml.appendClose();

						for (Iterator<TreeNode> i = node.children(); i.hasNext();) {
							TableTreeNode child = (TableTreeNode) i.next();
							Integer rowId = child.getRowIndex() - 1;
							UIContext nodeContext = repeater.getRowContext(rowId);

							WComponent expandedRenderer = renderer.getExpandedTreeNodeRenderer(
									child.getRendererClass());

							if (expandedRenderer != null) {
								UIContextHolder.pushContext(nodeContext);

								try {
									expandedRenderer.paint(renderContext);
								} finally {
									UIContextHolder.popContext();
								}
							}
						}

						xml.appendEndTag("ui:content");
					} else {
						for (Iterator<TreeNode> i = node.children(); i.hasNext();) {
							TableTreeNode child = (TableTreeNode) i.next();
							Integer rowId = child.getRowIndex() - 1;
							UIContext nodeContext = repeater.getRowContext(rowId);

							UIContextHolder.pushContext(nodeContext);

							try {
								render(component, renderContext);
							} finally {
								UIContextHolder.popContext();
							}
						}
					}
				}

				xml.appendEndTag("ui:subtr");
			}
		}

		xml.appendEndTag("ui:tr");
	}
749818
public function renderRow()
    {
        $this->t_row->trySet($this->current_row);

        $this->t_row->trySet('_title', $this->model->getTitle());
        $this->t_row->trySet('_href', $this->url(['id'=>$this->current_id]));
        $this->t_row->trySet('_id', $this->current_id);

        $html = $this->t_row->render();
        if ($this->template->hasTag('rows')) {
            $this->template->appendHTML('rows', $html);
        } else {
            $this->template->appendHTML('_top', $html);
        }
    }
521631
function(table,index,rowObj,createFlag,displayFlag){
			var row = table.insertRow(index + 1);
			row.setAttribute("role","row");
			if(!this.options.autoExpand && row.level > 0 && displayFlag != 'block'){
				row.style.display = 'none';
			}
			this.createContentOneRowTdForIE(row,rowObj,createFlag);
		}
1078443
public static function render() {
        self::newRow();
        ob_start();
        ?>

        <table <?php echo (!empty(self::$table_attributes)) ? self::parseAttributes(self::$table_attributes) : ""; ?>>
            <?php
            if (!empty(self::$headers)) {
                ?>

                <thead>
                    <tr>
                        <?php
                        foreach (self::$headers as $header) {
                            ?>

                            <th <?php echo self::parseAttributes($header[1]); ?>><?php echo $header[0] ?></th>
                            <?php
                        }
                        ?>

                    </tr>
                </thead>
                <?php
            }
            if (!empty(self::$rows)) {
                ?>

                <tbody>
                    <?php
                    foreach (self::$rows as $rowData) {
                        if (count($rowData) > 1) {
                            ?>

                            <tr <?php echo self::parseAttributes($rowData[0]); ?>>
                                <?php
                                foreach ($rowData[1] as $row) {
                                    ?>
                                    <td <?php echo self::parseAttributes($row[1]); ?>><?php echo $row[0] ?></td>
                                    <?php
                                }
                                ?>

                            </tr>
                            <?php
                        }
                    }
                    ?>

                </tbody>
                <?php
            }
            if (!empty(self::$footers)) {
                ?>

                <tfoot>
                    <tr>
                        <?php
                        foreach (self::$footers as $footer) {
                            ?>

                            <th <?php echo self::parseAttributes($footer[1]); ?>><?php echo $footer[0] ?></th>
                            <?php
                        }
                        ?>

                    </tr>
                </tfoot>
            <?php }
            ?>
        </table>
        <?php
        return ob_get_clean();
    }
907610
protected function displayRenderers($row)
    {
        $offset = $this->offset;

        if ($this->title != '') {
            if ($offset === 0) {
                $offset = 1;
            }

            $th_tag = new SwatHtmlTag('th', $this->getThAttributes());
            $th_tag->colspan = $offset;
            $th_tag->setContent(
                sprintf(Swat::_('%s:'), $this->title),
                $this->title_content_type
            );
            $th_tag->display();
        } elseif ($offset > 0) {
            $td_tag = new SwatHtmlTag('td');
            $td_tag->colspan = $offset;
            $td_tag->setContent('&nbsp;', 'text/xml');
            $td_tag->display();
        }

        $td_tag = new SwatHtmlTag('td', $this->getTdAttributes());
        $td_tag->colspan = $this->view->getXhtmlColspan() - $offset;

        $td_tag->open();
        $this->displayRenderersInternal($row);
        $td_tag->close();
    }
819077
public function renderTableFooter()
    {
        $cells = [];
        foreach ($this->columns as $column) {
            /* @var $column TreeColumn */
            $cells[] = $column->renderFooterCell();
        }
        $content = Html::tag('tr', implode('', $cells), $this->footerRowOptions);
        return "<tfoot>\n" . $content . "\n</tfoot>";
    }
1210245
public function renderTableAsHtml()
    {
        $render = '';
        $tableConfig = $this->getTable()->getOptions();

        if ($tableConfig->getShowColumnFilters()) {
            $render .= $this->renderFilters();
        }

        $render .= $this->renderHead();
        $render = sprintf('<thead>%s</thead>', $render);
        $render .= $this->getTable()->getRow()->renderRows();
        $table = sprintf('<table %s>%s</table>', $this->getTable()->getAttributes(), $render);

        $view = new \Zend\View\Model\ViewModel();
        $view->setTemplate('container');

        $view->setVariable('table', $table);

        $view->setVariable('paginator', $this->renderPaginator());
        $view->setVariable('paramsWrap', $this->renderParamsWrap());
        $view->setVariable('itemCountPerPage', $this->getTable()->getParamAdapter()->getItemCountPerPage());
        $view->setVariable('quickSearch', $this->getTable()->getParamAdapter()->getQuickSearch());
        $view->setVariable('name', $tableConfig->getName());
        $view->setVariable('itemCountPerPageValues', $tableConfig->getValuesOfItemPerPage());
        $view->setVariable('showQuickSearch', $tableConfig->getShowQuickSearch());
        $view->setVariable('showPagination', $tableConfig->getShowPagination());
        $view->setVariable('showItemPerPage', $tableConfig->getShowItemPerPage());
        $view->setVariable('showExportToCSV', $tableConfig->getShowExportToCSV());

        return $this->getRenderer()->render($view);
    }
630059
def _handle_table_row(self):
        """"""
        self._head += 2
        if not self._can_recurse():
            self._emit_text("|-")
            self._head -= 1
            return

        self._push(contexts.TABLE_OPEN | contexts.TABLE_ROW_OPEN)
        padding = self._handle_table_style("\n")
        style = self._pop()

        # Don't parse the style separator:
        self._head += 1
        row = self._parse(contexts.TABLE_OPEN | contexts.TABLE_ROW_OPEN)

        self._emit_table_tag("|-", "tr", style, padding, None, row, "")
        # Offset displacement done by parse():
        self._head -= 1
412197
function () {
      var r, c, rlen, clen, emptyRows = 0, emptyCols = 0, recreateRows = false, recreateCols = false, val;

      var $tbody = $(priv.tableBody);

      //fix changes that may have come from loadData
      var dlen = priv.settings.data.length;
      while (self.rowCount < dlen) {
        self.view.createRow();
        recreateRows = true;
      }
      while (self.rowCount > dlen) {
        self.view.removeRow();
        recreateRows = true;
      }
      while (self.colCount < self.countCols()) {
        self.view.createCol();
        self.view.renderCol(self.colCount - 1);
        recreateRows = true;
      }
      while (self.colCount > self.countCols()) {
        self.view.removeCol();
        recreateRows = true;
      }

      //count currently empty rows
      rows : for (r = self.countRows() - 1; r >= 0; r--) {
        for (c = 0, clen = self.colCount; c < clen; c++) {
          val = datamap.get(r, datamap.colToProp(c));
          if (val !== '' && val !== null && typeof val !== 'undefined') {
            break rows;
          }
        }
        emptyRows++;
      }

      //should I add empty rows to data source to meet startRows?
      rlen = self.countRows();
      if (rlen < priv.settings.minRows) {
        for (r = 0; r < priv.settings.minRows - rlen; r++) {
          datamap.createRow();
        }
      }

      //should I add empty rows to table view to meet startRows?
      if (self.countRows() < priv.settings.minRows) {
        for (; self.countRows() < priv.settings.minRows; emptyRows++) {
          self.view.createRow();
          self.view.renderRow(self.countRows() - 1);
          recreateRows = true;
        }
      }

      //should I add empty rows to meet minSpareRows?
      if (emptyRows < priv.settings.minSpareRows) {
        for (; emptyRows < priv.settings.minSpareRows && self.countRows() < priv.settings.maxRows; emptyRows++) {
          datamap.createRow();
          self.view.createRow();
          self.view.renderRow(self.countRows() - 1);
          recreateRows = true;
        }
      }

      //should I add empty rows to meet minHeight
      //WARNING! jQuery returns 0 as height() for container which is not :visible. this will lead to a infinite loop
      if (priv.settings.minHeight) {
        if ($tbody.height() > 0 && $tbody.height() <= priv.settings.minHeight) {
          while ($tbody.height() <= priv.settings.minHeight && self.countRows() < priv.settings.maxRows) {
            datamap.createRow();
            self.view.createRow();
            self.view.renderRow(self.countRows() - 1);
            recreateRows = true;
          }
        }
      }

      //count currently empty cols
      if (self.countRows() - 1 > 0) {
        cols : for (c = self.countCols() - 1; c >= 0; c--) {
          for (r = 0; r < self.countRows(); r++) {
            val = datamap.get(r, datamap.colToProp(c));
            if (val !== '' && val !== null && typeof val !== 'undefined') {
              break cols;
            }
          }
          emptyCols++;
        }
      }

      //should I add empty cols to meet minCols?
      if (self.countCols() < priv.settings.minCols) {
        for (; self.countCols() < priv.settings.minCols; emptyCols++) {
          if (!priv.settings.columns) {
            datamap.createCol();
          }
          self.view.createCol();
          self.view.renderCol(self.countCols() - 1);
          recreateCols = true;
        }
      }

      //should I add empty cols to meet minSpareCols?
      if (priv.dataType === 'array' && emptyCols < priv.settings.minSpareCols) {
        for (; emptyCols < priv.settings.minSpareCols && self.countCols() < priv.settings.maxCols; emptyCols++) {
          if (!priv.settings.columns) {
            datamap.createCol();
          }
          self.view.createCol();
          self.view.renderCol(self.colCount - 1);
          recreateCols = true;
        }
      }

      //should I add empty rows to meet minWidth
      //WARNING! jQuery returns 0 as width() for container which is not :visible. this will lead to a infinite loop
      if (priv.settings.minWidth) {
        if ($tbody.width() > 0 && $tbody.width() <= priv.settings.minWidth) {
          while ($tbody.width() <= priv.settings.minWidth && self.countCols() < priv.settings.maxCols) {
            if (!priv.settings.columns) {
              datamap.createCol();
            }
            self.view.createCol();
            self.view.renderCol(self.colCount - 1);
            recreateCols = true;
          }
        }
      }

      if (!recreateRows && priv.settings.enterBeginsEditing) {
        for (; ((priv.settings.minRows && self.countRows() > priv.settings.minRows) && (priv.settings.minSpareRows && emptyRows > priv.settings.minSpareRows) && (!priv.settings.minHeight || $tbody.height() - $tbody.find('tr:last').height() - 4 > priv.settings.minHeight)); emptyRows--) {
          self.view.removeRow();
          datamap.removeRow();
          recreateRows = true;
        }
      }

      if (!recreateCols && priv.settings.enterBeginsEditing) {
        for (; ((priv.settings.startCols && self.countCols() > priv.settings.startCols) && (priv.settings.minSpareCols && emptyCols > priv.settings.minSpareCols) && (!priv.settings.minWidth || $tbody.width() - $tbody.find('tr:last').find('td:last').width() - 4 > priv.settings.minWidth)); emptyCols--) {
          if (!priv.settings.columns) {
            datamap.removeCol();
          }
          self.view.removeCol();
          recreateCols = true;
        }
      }

      var rowCount = self.countRows();
      var colCount = self.countCols();

      if (rowCount === 0 || colCount === 0) {
        selection.deselect();
      }

      if (recreateRows && priv.selStart) {
        //if selection is outside, move selection to last row
        if (priv.selStart.row > rowCount - 1) {
          priv.selStart.row = rowCount - 1;
          if (priv.selEnd.row > priv.selStart.row) {
            priv.selEnd.row = priv.selStart.row;
          }
        } else if (priv.selEnd.row > rowCount - 1) {
          priv.selEnd.row = rowCount - 1;
          if (priv.selStart.row > priv.selEnd.row) {
            priv.selStart.row = priv.selEnd.row;
          }
        }
      }

      if (recreateCols && priv.selStart) {
        //if selection is outside, move selection to last row
        if (priv.selStart.col > colCount - 1) {
          priv.selStart.col = colCount - 1;
          if (priv.selEnd.col > priv.selStart.col) {
            priv.selEnd.col = priv.selStart.col;
          }
        } else if (priv.selEnd.col > colCount - 1) {
          priv.selEnd.col = colCount - 1;
          if (priv.selStart.col > priv.selEnd.col) {
            priv.selStart.col = priv.selEnd.col;
          }
        }
      }

      if (recreateRows || recreateCols) {
        selection.refreshBorders();
        self.blockedCols.update();
        self.blockedRows.update();
      }

      return (recreateRows || recreateCols);
    }
796279
function render(data) {
                if (!this._rendered) {
                    if (this.template) {
                        if (data) {
                            this.data = data;
                        }
                        var options = this._options,
                            parentChildren = this._parentChildren,
                            decoder = new Decoder(this.template),
                            template = decoder.render(this.data);
                        if (this.el) {
                            var parent = this.el.parentNode;
                            if (parent) {
                                parent.replaceChild(template.fragment, this.el);
                            }
                            if (this.elGroup && this.elGroup.get(this.el)) {
                                this.elGroup.delete(this.el);
                                this.el = template.fragment;
                                this.elGroup.set(template.fragment, this);
                            }
                        } else {
                            this.el = template.fragment;
                        }

                        this.root = new dom.Element(template.fragment, {
                            name: 'root',
                            data: {}
                        });

                        this.children = applyElement(template.children, options);
                        applyParent(this, parentChildren, this.data);
                        this.bindings = setBinders(this.children, true);

                        if (this.data) {
                            this.applyBinders(this.data, this);
                        }

                        setRoutes(this.children, this.context);
                        addChildren(this, this.root);
                        this.rendered.apply(this, _toConsumableArray(this._arguments));
                        this._rendered = true;
                    } else {
                        var HTMLelement = document.createElement('div');
                        this.root = new dom.Element(HTMLelement, {
                            name: 'root',
                            data: {}
                        });
                        if (this.el) {
                            var _parent = this.el.parentNode;
                            if (_parent) {
                                _parent.replaceChild(HTMLelement, this.el);
                            }
                        }
                        this.el = HTMLelement;
                        this.children = {};
                        addChildren(this, this.root);

                        this.rendered.apply(this, _toConsumableArray(this._arguments));
                        this._rendered = true;
                    }
                }
            }
643443
public function renderTable() : string
    {
        if ($this->table->isEmpty()) throw new BuilderException('Cannot render empty table');

        $visibleColumns = $this->table->getVisibleColumns();

        // border for header and footer
        $borderParts = array_map(function ($columnName) {
            $width = $this->table->getColumnWidth($columnName);
            return str_repeat(self::CHAR_LINE_SEPARATOR, ($width + 2));
        }, $visibleColumns->toArray());

        $border = self::CHAR_CORNER_SEPARATOR
                . join(self::CHAR_CORNER_SEPARATOR, $borderParts)
                . self::CHAR_CORNER_SEPARATOR;

        $headerCells = array_map(function ($columnName) {
            return new Cell($columnName, $columnName);
        }, $visibleColumns->toArray());

        $headerRow = new Row();
        $headerRow->addCells(...$headerCells);
        $header = $this->renderRow($headerRow, $visibleColumns);

        $body = '';
        $rows = $this->table->getRows();
        $visibleColumns = $this->table->getVisibleColumns();
        foreach ($rows as $row) {
            $currentLine = $this->renderRow($row, $visibleColumns);
            $body .= $currentLine . PHP_EOL;
        }

        $tableAsString = $border . PHP_EOL . $header . PHP_EOL . $border . PHP_EOL . $body . $border;
        return $tableAsString;
    }
682458
public function renderAsTable() {
    $html = '';
    foreach ($this->cells as $iRow => $rowCells) {
      $rowHtml = '';
      foreach ($rowCells as $iCol => $cell) {
        $rowHtml .= $cell->render();
      }
      $html .= '    <tr>' . $rowHtml . '</tr>' . "\n";
    }
    return "<table>\n  <tbody>\n" . $html . "  </tbody>\n</table>\n";
  }