javascriptrshiny

Adding a tag for scrolling and continuously scrolling to the bottom?


Following this I have implemented a container for continuously capturing R console output including scrolling capabilities.

Prompted by a comment below, I have generated a minimal example which looks like this (console output here is simulated by adding lorem ipsum text):

library(magrittr)
pkgs <- c(
  "lorem",
  "shiny",
  "shinyjs",
  "stringi"
)
for (pkg in pkgs) requireNamespace(pkg)

ui <- shiny::fluidPage(
  shinyjs::useShinyjs(),
  shiny::sidebarPanel(
    shiny::actionButton(
      inputId = "loreming",
      label   = "Add more"
    )
  ),
  shiny::mainPanel(
    shiny::verbatimTextOutput("muchlorem", placeholder = TRUE),
    shiny::tags$head(
      shiny::tags$style(
        "#muchlorem{overflow-y: scroll; max-height: 200px;}"
      )
    )
  )
)

server <- function(input, output, session)
{
  shiny::observeEvent(input$loreming, {
    shinyjs::html(
      id = "muchlorem",
      html = lorem::ipsum(5) %>%
        stringi::stri_wrap(prefix = "\n") %>%
        paste(collapse = ""),
      add = TRUE)
  })
}

shiny::shinyApp(ui, server)

I am aiming at a scroll state that automatically scrolls to the end of the muchlorem whenever something is added. How would that be achievable?


Solution

  • In your example you have an observeEvent on input$loreming in which the shinyjs::html() is added. After this is appended, you can execute the JS

    var objDiv = document.getElementById("muchlorem");
    objDiv.scrollTop = objDiv.scrollHeight;
    

    which scrolls the container with id = "muchlorem" to the bottom. I implemented this below using shinyjs::runjs().

    enter image description here

    library(magrittr)
    pkgs <- c(
      "lorem",
      "shiny",
      "shinyjs",
      "stringi"
    )
    for (pkg in pkgs) requireNamespace(pkg)
    
    ui <- shiny::fluidPage(
      shinyjs::useShinyjs(),
      shiny::sidebarPanel(
        shiny::actionButton(
          inputId = "loreming",
          label   = "Add more"
        )
      ),
      shiny::mainPanel(
        shiny::verbatimTextOutput("muchlorem", placeholder = TRUE),
        shiny::tags$head(
          shiny::tags$style(
            "#muchlorem{overflow-y: scroll; max-height: 200px;}"
          )
        )
      )
    )
    
    server <- function(input, output, session)
    {
      shiny::observeEvent(input$loreming, {
        shinyjs::html(
          id = "muchlorem",
          html = lorem::ipsum(5) %>%
            stringi::stri_wrap(prefix = "\n") %>%
            paste(collapse = ""),
          add = TRUE)
        shinyjs::runjs('
                       var objDiv = document.getElementById("muchlorem");
                       objDiv.scrollTop = objDiv.scrollHeight;
                       ')
      })
    }
    
    shiny::shinyApp(ui, server)