org.magicwerk.brownies.html.content.HtmlTableFormatter Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2012 by Thomas Mauch
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Id$
*/
package org.magicwerk.brownies.html.content;
import org.jdom2.Element;
import org.magicwerk.brownies.core.CheckTools;
import org.magicwerk.brownies.core.ObjectTools;
import org.magicwerk.brownies.core.collections.GridSelection;
import org.magicwerk.brownies.core.collections.IGrid;
import org.magicwerk.brownies.core.collections.SpanCell;
import org.magicwerk.brownies.core.collections.SpanGrid;
import org.magicwerk.brownies.core.print.PrintTools;
import org.magicwerk.brownies.core.strings.StringFormatter;
import org.magicwerk.brownies.core.types.Type;
import org.magicwerk.brownies.core.values.ITableModel;
import org.magicwerk.brownies.html.HtmlConst;
import org.magicwerk.brownies.html.HtmlElement;
import org.magicwerk.brownies.html.HtmlFlow;
import org.magicwerk.brownies.html.HtmlResource;
import org.magicwerk.brownies.html.HtmlResources;
import org.magicwerk.brownies.html.HtmlTable;
import org.magicwerk.brownies.html.HtmlTbody;
import org.magicwerk.brownies.html.HtmlThead;
import org.magicwerk.brownies.html.HtmlTools;
import org.magicwerk.brownies.html.HtmlTr;
import org.magicwerk.brownies.html.content.HtmlFormatters.Context;
import org.magicwerk.brownies.html.content.HtmlFormatters.HtmlFormatter;
/**
* Class {@link HtmlTableFormatter} formats a {@link IGrid} into a HTML table.
*/
public class HtmlTableFormatter {
static class HtmlRegionFormatter {
GridSelection region;
HtmlFormatter formatter;
HtmlRegionFormatter(GridSelection region, HtmlFormatter formatter) {
this.region = region;
this.formatter = formatter;
}
GridSelection getRegion() {
return region;
}
HtmlFormatter getFormatter() {
return formatter;
}
}
/** CSS class which marks a table as begin active supporting sorting and filtering */
public static final String CLASS_ACTIVE_TABLE = "activeTable";
/** CSS class which marks a table as having a fixed, i.e. always visible header if it is scrolled */
public static final String CLASS_FIXED_HEADER = "fixedHeader";
// See https://adrianroselli.com/2020/01/fixed-table-headers.html
// @formatter:off
static final String CSS_FIXED_HEADER =
"table.fixedHeader th {\r\n"
+ " position: -webkit-sticky;\r\n"
+ " position: sticky;\r\n"
+ " top: 0;\r\n"
+ " z-index: 2;\r\n"
+ "}\r\n"
+ "\r\n"
+ "table.fixedHeader th[scope=row] {\r\n"
+ " position: -webkit-sticky;\r\n"
+ " position: sticky;\r\n"
+ " left: 0;\r\n"
+ " z-index: 1;\r\n"
+ "}\r\n"
+ "";
// @formatter:on
// Members
/** True to make this an active table supporting sorting and filtering */
boolean active;
/** True to fix the table header if the table is scrolled (only used if a table is rendered) */
boolean fixedHeader;
/** Controls whether the header row is shown if a table is rendered (ignored if a grid is rendered) */
boolean showHeader = true;
/** Controls the number of header rows if a grid rendered (ignored if a table is rendered) */
int headerRows;
/** Controls the number of header cols if a grid rendered (ignored if a table is rendered) */
int headerCols;
/** True to use colspan/rowspan for display. Only used if the input grid is of type SpanGrid. */
boolean useSpans = true;
/** Formatter */
HtmlFormatters formatters = new HtmlFormatters();
/**
* Returns static HTML resources needed for formatting tables.
*/
public static HtmlResources getHtmlResources() {
HtmlResource res = new HtmlResource("HtmlTableFormatter");
res.getHead().addStyleCss("table.activeTable th { cursor: pointer; }");
res.getHead().addStyleCss("table.activeTable th .filter { background-color: #ffffcc; font-weight: normal; }");
res.getHead().addStyleCss(CSS_FIXED_HEADER);
res.getHead().addScriptJs(HtmlTools.normalizeJs(HtmlJs.getHtmlTableFormatterJs()));
res.getHead().addScriptJs(HtmlTools.normalizeJs(HtmlJs.getDialogJs()));
HtmlResources rs = new HtmlResources();
rs.add(HtmlJs.getJqueryResource());
rs.add(HtmlJs.getJqueryUiResource());
rs.add(res);
return rs;
}
/**
* Returns JS code to enable dynamic display options for the specified table (sorting, filtering).
*/
public static String getJsToActivateTable(HtmlTable tab) {
String id = HtmlTools.getOrSetId(tab);
String js = StringFormatter.format("activateTable($('#{}'));", id);
return js;
}
// Methods
/** Setter for {@link #formatters} */
public HtmlTableFormatter setFormatters(HtmlFormatters formatters) {
this.formatters = formatters;
return this;
}
/** Setter for {@link #active} */
public HtmlTableFormatter setActive(boolean active) {
this.active = active;
return this;
}
/** Setter for {@link #fixedHeader} */
public HtmlTableFormatter setFixedHeader(boolean fixedHeader) {
this.fixedHeader = fixedHeader;
return this;
}
/** Setter for {@link #showHeader} */
public HtmlTableFormatter setShowHeader(boolean showHeader) {
this.showHeader = showHeader;
return this;
}
/** Setter for {@link #headerRows} */
public HtmlTableFormatter setHeaderRows(int headerRows) {
this.headerRows = headerRows;
return this;
}
/** Setter for {@link #headerCols} */
public HtmlTableFormatter setHeaderCols(int headerCols) {
this.headerCols = headerCols;
return this;
}
/** Setter for {@link #useSpans} */
public HtmlTableFormatter setUseSpans(boolean useSpans) {
this.useSpans = useSpans;
return this;
}
HtmlTable createTable() {
HtmlTable t = new HtmlTable();
if (active) {
t.addClass(CLASS_ACTIVE_TABLE);
}
if (fixedHeader) {
t.addClass(CLASS_FIXED_HEADER);
}
return t;
}
public HtmlTable format(IGrid> grid) {
if (grid instanceof ITableModel) {
return formatTable((ITableModel) grid);
} else {
return formatGrid(grid);
}
}
/**
* Convert content stored in a table into a HTML table.
* If showHeader is set, a header row is inserted before the values.
*
* @param table table to convert
* @return HTML table with content of table
*/
HtmlTable formatTable(ITableModel table) {
CheckTools.checkNonNull(table, "table");
formatters.checkFormatters(table.getNumRows(), table.getNumCols());
Context ctx = new Context();
ctx.source = table;
HtmlTable t = createTable();
// Header
if (showHeader) {
HtmlThead th = t.newThead();
ctx.row = -1;
HtmlTr tr = th.newTr();
for (int c = 0; c < table.getNumCols(); c++) {
ctx.col = c;
ctx.val = table.getColName(c);
ctx.str = (String) ctx.val;
HtmlFlow cell = tr.newTh();
formatters.formatElem(cell, ctx);
}
}
// Body
HtmlTbody tb = t.newTbody();
for (int r = 0; r < table.getNumRows(); r++) {
HtmlTr tr = tb.newTr();
ctx.row = r;
for (int c = 0; c < table.getNumCols(); c++) {
ctx.col = c;
ctx.val = table.getElem(r, c);
@SuppressWarnings("unchecked")
Type