Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R Shiny – Make wellPanel pop-up follow as you scroll with CSS

PROBLEM: R Shiny – Make wellPanel pop-up follow as you scroll with CSS

Hi Stack Users,

I've created a Shiny application that has a data table wherein when a user clicks on a row, a hidden wellPanel will pop-up beside it to show more details related to that row.

The length of the pop-up wellPanel is long but the length of the table is longer (row count non-negotiable). I would like to make the wellPanel follow as I scroll UNTIL the top part of the wellPanel reaches the top visible part of the page. At that point, the wellPanel sticks until the bottom of the page is reached (see images of preferred state below).

Using CSS position: fixed didn’t do the trick because above the table and the panel, there are instructions for the intended users. As a result, using position: fixed just permanently sticks the wellPanel to one-part of the webpage and some information gets cut out (see sample app below).

Now, I’m not a web developer/designer by background so my knowledge of CSS is very very minimal, but I had hoped that the CSS solution in this previous post (How do you make a div follow as you scroll? / specifically: https://www.w3schools.com/css/css_positioning.asp) using position: sticky would work but it still didn't do it.

Hoping to hear from the experts in the community. Thanks!

Miklos

Simplified sample of my app along with images showing preferred state below:

setup.R

#### LOAD PACKAGES ######################
require(shiny)
require(shinyjs)
require(data.table)
require(dplyr)
require(DT)

#### PREPARE DATA ######################
id <- c('10001','10002','10003','10004','10005',
        '10006','10007','10008','10009','10010',
        '10011','10012','10013','10014','10015',
        '10016','10017','10018','10019','10020',
        '10021','10022','10023','10024','10025',
        '10026','10027','10028','10029','10030',
        '10031','10032','10033','10034','10035',
        '10036','10037','10038','10039','10040'
        )

info <- c('Info','Info','Info','Info','Info',
          'Info','Info','Info','Info','Info',
          'Info','Info','Info','Info','Info',
          'Info','Info','Info','Info','Info',
          'Info','Info','Info','Info','Info',
          'Info','Info','Info','Info','Info',
          'Info','Info','Info','Info','Info',
          'Info','Info','Info','Info','Info'
          )

info2 <- sample(1:100,40,replace=T)
info3 <- sample(1:100,40,replace=T)
info4 <- sample(1:100,40,replace=T)
info5 <- sample(1:100,40,replace=T)
info6 <- sample(1:100,40,replace=T)
info7 <- sample(1:100,40,replace=T)
info8 <- sample(1:100,40,replace=T)
info9 <- sample(1:100,40,replace=T)
info10 <- sample(1:100,40,replace=T)
info11 <- sample(1:100,40,replace=T)
info12 <- sample(1:100,40,replace=T)
info13 <- sample(1:100,40,replace=T)
info14 <- sample(1:100,40,replace=T)
info15 <- sample(1:100,40,replace=T)
info16 <- sample(1:100,40,replace=T)

dt <- data.table(id=id,info=info,info2=info2,
                 info3=info3,info4=info4,info5=info5,
                 info6=info6,info7=info7,info8=info8,
                 info9=info9,info10=info10,info11=info11,
                 info12=info12,info13=info13,info14=info14,
                 info15=info15,info16=info16
                 )

#### INSTANTIATE FUNCTIONS ######################
get_instructions <- function() {
  "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 
  "
}

render_my_table <- function(dt, sel) {
  if(missing(sel)) {
    sel = list(mode='single')
  }  else {
    sel = list(mode='single', selected = sel)
  }
  return (DT::datatable(dt[, list("ID" = id, "Info"=info)], 
                        selection = sel, filter="top", 
                        options = list(sDom  = '<"top">lrt<"bottom">ip', 
                                       lengthChange = FALSE, 
                                       pageLength = 40)))
}

generate_popup_details <- function(user) {
  c(
    paste("Info 2: ", user$info2),
    paste("Info 3: ", user$info3),
    paste("Info 4: ", user$info4),
    paste("Info 5: ", user$info5),
    paste("Info 6: ", user$info6),
    paste("Info 7: ", user$info7),
    paste("Info 8: ", user$info8),
    paste("Info 9: ", user$info9),
    paste("Info 10: ", user$info10),
    paste("Info 11: ", user$info11),
    paste("Info 12: ", user$info12),
    paste("Info 13: ", user$info13),
    paste("Info 14: ", user$info14),
    paste("Info 15: ", user$info15),
    paste("Info 16: ", user$info16)
    )
}

ui.R

source("setup.R")

shinyUI(fluidPage(
  useShinyjs(),
  titlePanel("My Shiny Application"),
  hr(),
  h3("Some Instructions to Users:"),
  h5(get_instructions()),
  hr(),
  mainPanel("",         
            fluidRow(
              splitLayout(div(DT::dataTableOutput('my_table')), 
                          div(
                            shinyjs::hidden(
                              wellPanel(id="my_panel", style = "position:fixed;",
                                        h3("More Information",align="center"),
                                        htmlOutput("my_popup")
                              )
                            )
                          )
              )
            )
  ) 
))

server.R

source("setup.R")

function(input, output, session) {

  output$my_table = DT::renderDataTable({
    render_my_table(dt)
  }, server=TRUE)

  observeEvent(input$my_table_cell_clicked, {
    row = as.numeric(input$my_table_rows_selected)
    user = dt[row]
    if(nrow(user) == 0) {
      return ()
    }
    output$my_popup <- renderUI({ 
      HTML(paste(generate_popup_details(user) ,collapse="<br/>"))
    })

    shinyjs::showElement(id= "my_panel")
  })

}

PREFERRED STATE:

App upon load App upon load

User reaches bottom of the page and wellPanel stays at the top part of the visible page User reaches bottom of the page and wellPanel stays at the top part of the visible page

like image 871
Miklos Morada Avatar asked Feb 07 '20 12:02

Miklos Morada


People also ask

How to give your shiny app a special look with CSS?

You can give your Shiny app a special look with cascading style sheets (CSS). CSS is a style language which gives HTML documents a sophisticated look. Since the Shiny app user-interface (UI) is an HTML document, you can use CSS to control how you want your Shiny app to look.

How do I add CSS to an element in shiny?

To add CSS to an individual element, pass it to the style argument of the Shiny function that you use to create that element. In the script below, I set the style of the title of the Shiny app with the style argument of h1 in headerPanel. The style relies on a font that I import with tags$style in tags$head.

How do I create a row within a shiny bootstrap application?

The create this row within a Shiny application you’d use the following code: Note that the total size of the nested columns is 9, the same as their parent column. The Bootstrap grid system supports responsive CSS, which enables your application to automatically adapt its layout for viewing on different sized devices.

What is the best way to use HTML dependencies in shiny?

Inline CSS p (style = "color:red;", "Red text"). However, if you correctly followed the previous part about HTML dependencies, the best way in Shiny is to create a dependency, and attach it to a tag: Following this method, you make the file accessible on the server, thereby easing the debugging process. When should we apply the above method?


1 Answers

Use this JavaScript code:

js <- "
$(document).ready(function(){
  var tbl = document.getElementById('my_table');
  $('#my_panel').css('top', tbl.getBoundingClientRect().top);
  $(window).scroll(function() { 
    var tbltop = tbl.getBoundingClientRect().top;
    var x = tbltop < 0 ? 0 : tbltop;
    $('#my_panel').css('top', x);
  });
});"

To include in the app like this:

ui <- fluidPage(
  tags$head(tags$script(HTML(js))),
  useShinyjs(),
  ......

(Do not change anything else).

enter image description here

like image 141
Stéphane Laurent Avatar answered Oct 15 '22 02:10

Stéphane Laurent