Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two column layout with high level header #117

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: gtExtras
Title: Extending 'gt' for Beautiful HTML Tables
Version: 0.5.0.9004
Version: 0.5.0.9005
Authors@R: c(
person("Thomas", "Mock", , "j.thomasmock@gmail.com", role = c("aut", "cre", "cph")),
person("Daniel D.", "Sjoberg", , "danield.sjoberg@gmail.com", role = "ctb",
Expand Down Expand Up @@ -48,6 +48,6 @@ Suggests:
xml2 (>= 1.3.3)
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
RoxygenNote: 7.3.1
Config/testthat/edition: 3
Config/testthat/parallel: true
77 changes: 71 additions & 6 deletions R/two-column-layouts.R
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ gt_double_table <- function(data, gt_fn, nrows = NULL, noisy = TRUE) {
#' @param ... Additional arguments passed to `webshot2::webshot()`, only to be used if `output = "save"`, saving the two-column layout tables to disk as a `.png`.
#' @param zoom Argument to `webshot2::webshot()`. A number specifying the zoom factor. A zoom factor of 2 will result in twice as many pixels vertically and horizontally. Note that using 2 is not exactly the same as taking a screenshot on a HiDPI (Retina) device: it is like increasing the zoom to 200 doubling the height and width of the browser window. This differs from using a HiDPI device because some web pages load different, higher-resolution images when they know they will be displayed on a HiDPI device (but using zoom will not report that there is a HiDPI device).
#' @param expand Argument to `webshot2::webshot()`. A numeric vector specifying how many pixels to expand the clipping rectangle by. If one number, the rectangle will be expanded by that many pixels on all sides. If four numbers, they specify the top, right, bottom, and left, in that order. When taking screenshots of multiple URLs, this parameter can also be a list with same length as url with each element of the list containing a single number or four numbers to use for the corresponding URL.
#' @param tab_header_from If `NULL` (the default) renders tab headers of each table individually. If one of "table1" or "table2", the function extracts tab header information (including styling) from table 1 or table 2 respectively and renders it as high level header for the combined view (individual headers will be removed).
#' @return Saves a `.png` to disk if `output = "save"`, returns HTML to the viewer via `htmltools::browsable()` when `output = "viewer"`, or returns raw HTML if `output = "html"`.
#' @export
#' @family Utilities
Expand Down Expand Up @@ -157,7 +158,8 @@ gt_double_table <- function(data, gt_fn, nrows = NULL, noisy = TRUE) {
gt_two_column_layout <- function(tables = NULL, output = "viewer",
filename = NULL, path = NULL,
vwidth = 992, vheight = 600, ...,
zoom = 2, expand = 5) {
zoom = 2, expand = 5,
tab_header_from = NULL) {
if (length(tables) != 2) {
stop("Two 'gt' tables must be provided like `list(table1, table2)` and be of length == 2", call. = FALSE)
}
Expand All @@ -171,11 +173,36 @@ gt_two_column_layout <- function(tables = NULL, output = "viewer",
stopifnot("Two 'gt' tables must be provided like `list(table1, table2)`" = !is.null(tables))
stopifnot("Two 'gt' tables must be provided like `list(table1, table2)`" = is.list(tables))
stopifnot("Both tables in the list must be a 'gt_tbl' object" = all(c(class(tables[[1]])[1], class(tables[[2]])[1]) == "gt_tbl"))

double_tables <- htmltools::div(
htmltools::div(tables[1], style = "display: inline-block;float:left;"),
htmltools::div(tables[2], style = "display: inline-block;float:right;")
)

if (!is.null(tab_header_from)){
stopifnot("The `tab_header_from` argument must be one of 'table1', or 'table2'" = tab_header_from %in% c("table1", "table2"))
extract_from <- switch (tab_header_from,
"table1" = tables[[1]],
"table2" = tables[[2]]
)
header_data <- extract_tab_header_and_style(extract_from)
double_tables <- htmltools::div(
id = "mycombinedtable",
htmltools::tag("style", header_data[["style"]]),
htmltools::div(
header_data[["title"]],
class = header_data[["title_class"]],
style = header_data[["title_style"]]
),
htmltools::div(
header_data[["subtitle"]],
class = header_data[["subtitle_class"]],
style = header_data[["subtitle_style"]]
),
htmltools::div(tables[[1]] %>% gt::tab_header(NULL, NULL), style = "display: inline-block;float:left;"),
htmltools::div(tables[[2]] %>% gt::tab_header(NULL, NULL), style = "display: inline-block;float:right;")
)
} else {
double_tables <- htmltools::div(
htmltools::div(tables[1], style = "display: inline-block;float:left;"),
htmltools::div(tables[2], style = "display: inline-block;float:right;")
)
}

if (output == "viewer") {
htmltools::browsable(double_tables)
Expand Down Expand Up @@ -214,3 +241,41 @@ gt_two_column_layout <- function(tables = NULL, output = "viewer",
double_tables
}
}

extract_tab_header_and_style <- function(table) {
raw_html <- gt::as_raw_html(table, inline_css = FALSE) %>%
xml2::read_html()

gt_title <- raw_html %>%
xml2::xml_find_first("//*[contains(concat(' ',normalize-space(@class),' '),' gt_title ')]")

gt_subtitle <- raw_html %>%
xml2::xml_find_first("//*[contains(concat(' ',normalize-space(@class),' '),' gt_subtitle ')]")

gt_table_id <- raw_html %>%
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gt writes the table id into the selectors of the stylesheet. We extract that id here to replace it with our own id in the next step.

xml2::xml_find_all("//body/div") %>%
xml2::xml_attr("id")

s <- raw_html %>%
xml2::xml_find_first("//style") %>%
xml2::xml_contents() %>%
xml2::xml_text() %>%
gsub(gt_table_id, "mycombinedtable", x = .) %>%
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is necessary to apply the style to our top level heading

gsub("mycombinedtable table", "mycombinedtable div", x = .)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table selector sets font. Since we put the header in div tags we replace table with div in the style sheet.


list(
title = xml_missing(gt_title),
title_class = paste("gt_table", xml2::xml_attr(gt_title, "class")),
title_style = xml2::xml_attr(gt_title, "style"),
subtitle = xml_missing(gt_subtitle),
subtitle_class = paste("gt_table", xml2::xml_attr(gt_subtitle, "class")),
subtitle_style = xml2::xml_attr(gt_subtitle, "style"),
style = s
)
}

xml_missing <- function(xml){
xml_txt <- xml2::xml_text(xml)
if (is.na(xml_txt)) return(NULL)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xml2 returns NA if the text is missing. We return NULL to drop it entirely from the html.

xml_txt
}
7 changes: 5 additions & 2 deletions man/gt_two_column_layout.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading