Search code examples
javascriptrshinyflexdashboard

Flexdashboard sidebar pickerInput overflow hijacking scrollbar


I previously used the response in this question Flexdashboard sidebar pickerInput overflow with scrollbar to modify pickerInputs with wide values so that all value names in the filter would be visible using JS. I have recently come across an issue with this where if the sidebar is long enough to have a scrollbar and you scroll on the sidebar at all and then click a pickerInput that uses the JS the entire sidebar moves to the default position. The issue with this is if you have a lot of filters and are on a smaller screen, when you click on a filter to open it, it moves to a position that you cannot view. I have included a reprex where the third filter causes this behavior. Looking to resolve the sidebar scroll hijacking that occurs while clicking on the JS wide filters.

---
title: "TEST"
runtime: shiny
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
    
---


```{r setup, include=FALSE}
library(dplyr)
library(shiny)
library(DT)
library(shinyWidgets)


Name <- c("LONNGGGGGGGGGGGGGGG TEXXTTTTTTTTTTTTTTTTTT", "Bill", "Maria", "Ben", "Tina")
Age <- c(23, 41, 32, 58, 26)

df <- data.frame(Name, Age)

```

```{js}
$(document).ready(function(){  
    $('#name1').on('show.bs.select', function() {
    $(".sidebar").css("overflow", "visible");    
        $(".sidebar").css("z-index", "10000");
  }).on('hide.bs.select', function() {
    $(".sidebar").css("overflow-y", "auto");
  });
});
```

Sidebar {.sidebar}
=======================================================================

### Filters

```{r}

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name,
  multiple = TRUE)


pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name1",
  label = "Third Filter",
  choices = df$Name,
  selected = df$Name,
  multiple = TRUE,
   options = list(`actions-box` = TRUE,
                 `selected-text-format` = paste0("count > ", length(unique(df$Name, split=";")) -1),`count-selected-text` = "All"))

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)

pickerInput(
  inputId = "name",
  label = "test",
  choices = df$Name,
  selected = df$Name)
```

TEST
=======================================================================

Row 
-------------------------------------

```{r}
filtered_data <-
    reactive ({
      req(input$name)

      df %>%
        filter(Name %in% input$name) 

    })

renderDataTable(filtered_data(), class = 'cell-border stripe',
              extensions = 'Buttons',
              rownames = FALSE,
              options = list(
                columnDefs = list(list(className = 'dt-center',width = '100px', targets = "_all"))),fillContainer=TRUE)
```

Solution

  • Indeed, when setting overflow to visible, the sidebar jumps to its initial position, and it is no longer scrollable so there's no JavaScript way to scroll it.

    That said, setting a negative top margin seems to give a nice result:

    ```{css}
    .section.sidebar {
      overflow-y: auto;
      z-index: 0;
    }
    ```    
    
    ```{js}
    $(document).ready(function(){  
        $('#name1').on('show.bs.select', function() {
          var $sidebar = $(".sidebar");
          var x = - $sidebar.scrollTop();
          $sidebar.css("margin-top", x + "px");
          $sidebar.css("overflow", "visible");
      }).on('hide.bs.select', function() {
          var $sidebar = $(".sidebar");
          $sidebar.css("margin-top", "0px");
          $sidebar.css("overflow-y", "auto");
      });
    });
    ```
    

    Note: you have some duplicated ids in your code ("name"), and this is bad.