#' @title Progress Bars
#'
#' @description Create a progress bar to provide feedback on calculation.
#'
#' @param id An id used to update the progress bar.
#' If in a Shiny module, it use same logic than inputs : use namespace in UI, not in server.
#' @param value Value of the progress bar between 0 and 100, if >100 you must provide total.
#' @param total Used to calculate percentage if value > 100, force an indicator to appear on top right of the progress bar.
#' @param display_pct logical, display percentage on the progress bar.
#' @param size Size, `NULL` by default or a value in 'xxs', 'xs', 'sm', only work with package `shinydashboard`.
#' @param status Color, must be a valid Bootstrap status : primary, info, success, warning, danger.
#' @param striped logical, add a striped effect.
#' @param title character, optional title.
#' @param range_value Default is to display percentage (`[0, 100]`), but you can specify a custom range, e.g. `[-50, 50]`.
#' @param commas Deprecated, use `format_display`.
#' @param format_display Function to format the value displayed.
#' @param unit_mark Unit for value displayed on the progress bar, default to `%`.
#'
#' @return A progress bar that can be added to a UI definition.
#'
#' @name progress-bar
#'
#' @seealso [progressSweetAlert] for progress bar in a sweet alert
#'
#' @importFrom htmltools tags tagList singleton HTML
#' @export
#'
#' @examples
#' if (interactive()) {
#'
#' library("shiny")
#' library("shinyWidgets")
#'
#' ui <- fluidPage(
#' column(
#' width = 7,
#' tags$b("Default"), br(),
#' progressBar(id = "pb1", value = 50),
#' sliderInput(
#' inputId = "up1",
#' label = "Update",
#' min = 0,
#' max = 100,
#' value = 50
#' ),
#' br(),
#' tags$b("Other options"), br(),
#' progressBar(
#' id = "pb2",
#' value = 0,
#' total = 100,
#' title = "",
#' display_pct = TRUE
#' ),
#' actionButton(
#' inputId = "go",
#' label = "Launch calculation"
#' )
#' )
#' )
#'
#' server <- function(input, output, session) {
#' observeEvent(input$up1, {
#' updateProgressBar(
#' session = session,
#' id = "pb1",
#' value = input$up1
#' )
#' })
#' observeEvent(input$go, {
#' for (i in 1:100) {
#' updateProgressBar(
#' session = session,
#' id = "pb2",
#' value = i, total = 100,
#' title = paste("Process", trunc(i/10))
#' )
#' Sys.sleep(0.1)
#' }
#' })
#' }
#'
#' shinyApp(ui = ui, server = server)
#'
#' }
progressBar <- function(id,
value,
total = NULL,
display_pct = FALSE,
size = NULL,
status = NULL,
striped = FALSE,
title = NULL,
range_value = NULL,
commas = TRUE,
format_display = function(value) {
prettyNum(value, big.mark = ",", scientific = FALSE)
},
unit_mark = "%") {
if (!is.null(total)) {
percent <- round(value / total * 100)
} else {
value <- round(value)
if (!is.null(range_value)) {
percent <- rescale(x = value, from = range_value, to = c(0, 100))
} else {
percent <- value
}
}
title <- tags$span(
class = "progress-text",
id = paste0(id, "-title"),
title, HTML(" ")
)
value_for_display <- format_display(value)
total_for_display <- format_display(total)
if (!is.null(total)) {
}
total <- tagList(
tags$span(
class = "progress-number pull-right float-end",
style = css(display = if (is.null(total)) "none"),
tags$b(value_for_display, id = paste0(id, "-value")),
"/",
tags$span(id = paste0(id, "-total"), total_for_display)
),
tags$div(class = "clearfix")
)
tagPB <- tags$div(
class = "progress-group",
title, total,
tags$div(
class = "progress",
class = if (!is.null(size)) paste0("progress-", size),
tags$div(
id = id,
style = if (percent > 0) paste0("width:", percent, "%;"),
style = if (display_pct) "min-width: 2em;",
class = "progress-bar",
class = if (!is.null(status)) paste0("progress-bar-", status),
class = if (!is.null(status)) paste0("bg-", status),
class = if (striped) "progress-bar-striped",
role = "progressbar",
if (display_pct) paste0(percent, unit_mark)
)
)
)
attachShinyWidgetsDep(tagPB)
}
#' @param session The 'session' object passed to function given to shinyServer.
#'
#' @export
#'
#' @rdname progress-bar
updateProgressBar <- function(session = getDefaultReactiveDomain(),
id,
value,
total = NULL,
title = NULL,
status = NULL,
range_value = NULL,
commas = TRUE,
format_display = function(value) {
prettyNum(value, big.mark = ",", scientific = FALSE)
},
unit_mark = "%") {
if (!is.null(range_value)) {
percent <- rescale(x = value, from = range_value, to = c(0, 100))
} else {
percent <- -1
}
# If we are inside a module, turn the (relative) id (e.g. 'input') into an absolute id (e.g. 'module-input')
if (inherits(session, "session_proxy")) {
# Keep old code working which externally uses session$ns() to create an absolute id.
if (!starts_with(id, session$ns("")))
id <- session$ns(id)
}
session$sendCustomMessage(
type = "update-progressBar-shinyWidgets",
message = list(
id = id,
value = value,
percent = percent,
total = if (is.null(total)) -1 else total,
value_display = format_display(value),
total_display = format_display(total),
title = as.character(title),
status = status,
commas = commas,
unit_mark = unit_mark
)
)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.