blob: a1d1835814271b9d91bf958a3adc00914dea2837 [file] [log] [blame]
Hao Zhu501fb452017-07-05 14:37:13 -04001#' Put a HTML table into a scrollable box
2#'
3#' @description This function will put a HTML kable object in a fixed-height,
4#' fixed-width or both box and make it scrollable.
5#'
6#' @param kable_input A HTML kable object
7#' @param height A character string indicating the height of the box, e.g. "50px"
8#' @param width A character string indicating the width of the box, e.g. "100px"
Hao Zhu4b0c51e2017-08-01 15:21:07 -04009#' @param box_css CSS text for the box
10#' @param extra_css Extra CSS styles
Hao Zhu72917f92019-03-15 18:41:42 -040011#' @param fixed_thead HTML table option so table header row is fixed at top.
12#' Values can be either T/F or `list(enabled = T/F, background = "anycolor")`.
Hao Zhu501fb452017-07-05 14:37:13 -040013#'
14#' @export
Irene319a5462018-04-17 15:37:39 -070015#'
16#' @examples
17#' \dontrun{
18#' # Specify table size by pixels
19#' kable(cbind(mtcars, mtcars), "html") %>%
20#' kable_styling() %>%
21#' scroll_box(width = "500px", height = "200px")
22#'
23#' # Specify by percent
24#' kable(cbind(mtcars, mtcars), "html") %>%
25#' kable_styling() %>%
26#' scroll_box(width = "100%", height = "200px")
27#' }
Hao Zhu4b0c51e2017-08-01 15:21:07 -040028scroll_box <- function(kable_input, height = NULL, width = NULL,
29 box_css = "border: 1px solid #ddd; padding: 5px; ",
Hao Zhu72917f92019-03-15 18:41:42 -040030 extra_css = NULL,
31 fixed_thead = TRUE
32 ) {
Hao Zhubf982252020-08-11 01:08:37 -040033 kable_format <- attr(kable_input, "format")
34 if (kable_format != "html") {
35 return(kable_input)
36 }
Hao Zhu501fb452017-07-05 14:37:13 -040037 kable_attrs <- attributes(kable_input)
Hao Zhu72917f92019-03-15 18:41:42 -040038 fixed_thead <- get_fixed_thead(fixed_thead)
39 if (is.null(height)) fixed_thead$enabled <- FALSE
Jrmieaa304982018-12-08 00:14:16 +010040
41 if (fixed_thead$enabled) {
42 box_css = "border: 1px solid #ddd; padding: 0px; "
43 kable_xml <- read_kable_as_xml(kable_input)
Hao Zhu72917f92019-03-15 18:41:42 -040044 all_header_cells <- xml2::xml_find_all(kable_xml, "//thead//th")
45 if (is.null(fixed_thead$background)) fixed_thead$background <- "#FFFFFF"
46 for (i in seq(length(all_header_cells))) {
47 xml_attr(all_header_cells[i], "style") <- paste0(
48 xml_attr(all_header_cells[i], "style"),
49 "position: sticky; top:0; background-color: ",
50 fixed_thead$background, ";"
51 )
Jrmieaa304982018-12-08 00:14:16 +010052 }
53 out <- as.character(as_kable_xml(kable_xml))
54 } else {
55 out <- as.character(kable_input)
56 }
57
Hao Zhu4b0c51e2017-08-01 15:21:07 -040058 box_styles <- c(box_css, extra_css)
Jrmieaa304982018-12-08 00:14:16 +010059
Hao Zhu501fb452017-07-05 14:37:13 -040060 if (!is.null(height)) {
61 box_styles <- c(box_styles,
62 paste0("overflow-y: scroll; height:", height, "; "))
63 }
Jrmieaa304982018-12-08 00:14:16 +010064
Hao Zhu501fb452017-07-05 14:37:13 -040065 if (!is.null(width)) {
66 box_styles <- c(box_styles,
67 paste0("overflow-x: scroll; width:", width, "; "))
68 }
Jrmieaa304982018-12-08 00:14:16 +010069
Hao Zhu501fb452017-07-05 14:37:13 -040070 out <- paste0('<div style="', paste(box_styles, collapse = ""), '">',
71 out, '</div>')
72 out <- structure(out, format = "html",
73 class = "knitr_kable")
74 attributes(out) <- kable_attrs
Jrmieaa304982018-12-08 00:14:16 +010075
Hao Zhuf2100832018-01-11 16:20:29 -050076 if (!"kableExtra" %in% class(out)) class(out) <- c("kableExtra", class(out))
Jrmieaa304982018-12-08 00:14:16 +010077
Hao Zhu501fb452017-07-05 14:37:13 -040078 return(out)
79}
Hao Zhu72917f92019-03-15 18:41:42 -040080
81get_fixed_thead <- function(x) {
82 if (is.logical(x)) {
83 if (x) return(list(enabled = TRUE, background = "#FFFFFF"))
84 return(list(enabled = FALSE))
85 }
86 return(x)
87}