'R Shiny shinyjs window.scrollTo scroll distance limited to active tab

I have a shiny app with a sidebar menue and several different tabs. Within each tab, there is a lot of content that is supposed to be seen together, so the tabs are quite lengthy and navigating can be a pain because a lot of scrolling is needed. However, spliting the content into sub-tabs is not an option.

I have thus tried to implement "location markers" as fake sub-tabs to navigate through.

This works fine, except when you are on another tab and you want to switch directly to the bottom of another tab, i.e. from subtab_1_1 directly to subtab_2_2. In that case, the tab switches over correctly to subtab_2_1 but the scrollposition() afterwards does not actually scroll the full 50000 pixels, but to the maximum distance of the active tab (i.e. the bottom of Tab 1).

As @YBS pointed out, one solution would be to add lines to each Tab so that they all share the same length. However, that would make using the scroll bar to scroll manualy very unintuitive, as some tabs would go on for much longer as the content of the tab.

Is there any way to circumvent this limitation of window.scrollTo()?

Here is a minimal working example:

library(shiny)
library(shinydashboard)
library(shinyjs)

ui <- dashboardPage(
    title = "Title",
    dashboardHeader(title = "Header", titleWidth = 350),
    skin = "blue",
    dashboardSidebar(
        width = 350,
        disable = FALSE,
        sidebarMenu(
            id = "tabs",
            menuItem(
                text = "Tab 1",
                tabName = "Tab_1",
                icon = icon("database"),
                hidden(menuSubItem(
                    text = "Subtab 1.1",
                    tabName = "Subtab_1_1",
                    icon = icon("angle-right")
                )),
                menuSubItem(
                    text = "Proxy Subtab 1.1",
                    tabName = "Proxy_Subtab_1_1",
                    icon = icon("angle-right")
                ),
                menuSubItem(
                    text = "Subtab 1.2",
                    tabName = "Subtab_1_2",
                    icon = icon("angle-right")
                )
            ),
            menuItem(
                text = "Tab 2",
                tabName = "Tab_2",
                icon = icon("database"),
                hidden(menuSubItem(
                    text = "Subtab 2.1",
                    tabName = "Subtab_2_1",
                    icon = icon("angle-right")
                )),
                menuSubItem(
                    text = "Proxy Subtab 2.1",
                    tabName = "Proxy_Subtab_2_1",
                    icon = icon("angle-right")
                ),
                menuSubItem(
                    text = "Subtab 2.2",
                    tabName = "Subtab_2_2",
                    icon = icon("angle-right")
                )
            )
        )
    ),
    dashboardBody(
        useShinyjs(),
        extendShinyjs(
            text = "shinyjs.scrollposition = function(y) {window.scrollTo(0, y)};",
            functions = c("scrollposition")
        ),
        tags$script(HTML("$('body').addClass('fixed');")),
        tabItems(
            tabItem(
                tabName = "Subtab_1_1",
                fluidPage(
                    h1("This is Subtab 1_1"),
                    HTML(rep("<br/><br/><br/>&darr;<br/>", 10)),
                    h1("This is supposed to be Subtab 1_2")
                )
            ),
            tabItem(
                tabName = "Subtab_2_1",
                fluidPage(
                    h1("This is Subtab 2_1"),
                    plotOutput("Plot_1"),
                    plotOutput("Plot_2"),
                    plotOutput("Plot_3"),
                    plotOutput("Plot_4"),
                    plotOutput("Plot_5"),
                    plotOutput("Plot_6"),
                    h1("This is supposed to be Subtab 2_2")
                )
            )
        )
    )
)
        
        
server <- function(input, output, session) {
    
    observeEvent(input$tabs, {
        
        if(sum(c("Proxy_Subtab_1_1", "Proxy_Subtab_2_1","Subtab_1_2", "Subtab_2_2") %in% input$tabs) > 0) {
            updateTabsetPanel(session, "tabs", switch(input$tabs,
                                                      "Proxy_Subtab_1_1" = "Subtab_1_1",
                                                      "Proxy_Subtab_2_1" = "Subtab_2_1",
                                                      "Subtab_1_2" = "Subtab_1_1",
                                                      "Subtab_2_2" = "Subtab_2_1")
                              )
            js$scrollposition(case_when(input$tabs == "Proxy_Subtab_1_1" ~ 0,
                                        input$tabs == "Proxy_Subtab_2_1" ~ 0,
                                        input$tabs == "Subtab_1_2" ~ 50000,
                                        input$tabs == "Subtab_2_2" ~ 50000)
                              )
        }
        
    })
    
    output$Plot_1 <- output$Plot_2 <- output$Plot3 <- 
        output$Plot_4 <- output$Plot_5 <- output$Plot6 <- renderPlot(
            ggplot(data.frame(
                    x = c(1, 2, 3),
                    y = c(1, 2, 3),
                    labels = c(
                        "",
                        "Some plots",
                        ""
                        )
                    )
            ) + 
            geom_text(aes(x = x, y = y, label = labels), size = 6)
        )
}

shinyApp(ui = ui, server = server)


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source