How to keep background elements available when a popup window is open

Viewed 426

I am using a popup window in R Shiny with the following code:

library(shiny)
library(shinyjqui)

ui = basicPage(
  actionButton("show", "Show modal dialog"),

  textAreaInput(
    inputId = 'textEditor', 
    label   = NULL, 
    value   = "R is a free software environment for statistical computing and graphics.",
    height  = "300",
    resize  = "none"
  )
)

server = function(input, output) 
{
  observeEvent(input$show, 
  {
    showModal(draggableModalDialog(
      title = "Add the following text in the box at the left:",
      "The R language is widely used among statisticians and data miners.",
  
      footer = tagList(
        actionButton("ok", "OK")
      )
    ))
  })

  observeEvent(input$ok, 
  {
    removeModal()
    print("OK") 
  })
}

shinyApp(ui = ui, server = server)

It strikes me that when the popup window is open, you can not use the elements on the background. The whole background is greyed-out.

In most cases this may be the right behaviour, but in my case I would like to be able to edit the text in the left window while the popup window is open.

Is it possible to make this possible? If so, how?

2 Answers

You are trying to use a modal dialog in a way it is not intended to be used, so you need to make some manual changes in its behaviour. There are three problems you need to solve to fully remove the gray background and allow interactions with everything in the background:

  1. You have to hide the backdrop (the gray background) itself.
  2. The movable modal has a parent overlay that covers the full screen in order to allow free movement. This overlay captures all pointer events and makes everything below it unclickable.
  3. The draggableModalDialog element has attribute tabindex="-1", which is a HTML trick that prevents interactions with input fields outside of the modal. See the source on Github.

Problems #1 and #2 are solvable with a little CSS:

ui = basicPage(
  tags$head(tags$style(HTML("
    .modal-backdrop {  # hide backdrop
      display: none;
    }
    .modal {  # pass through clicks etc. on the overlay
      pointer-events: none;
    }
    .modal-dialog {  # do capture mouse events on the modal itself
      pointer-events: all;
    }"
  ))),

  [...]
)

For problem #3 you actually need to modify the draggableModalDialog function. You can copy-paste the original definition and remove the tabindex definition:

customDraggableModalDialog <- function(..., title = NULL,
                                 footer = shiny::modalButton("Dismiss"),
                                 size = c("m", "s", "l"),
                                 easyClose = FALSE, fade = TRUE) {
  size <- match.arg(size)
  cls <- if (fade) { "modal fade" } else { "modal" }
  shiny::div(
    id = "shiny-modal",
    class = cls,
    # tabindex = "-1", This line should be commented out or removed
    `data-backdrop` = if (!easyClose) { "static" } ,
    `data-keyboard` = if (!easyClose) { "false" } ,
    shiny::div(
      class = "modal-dialog",
      class = switch(size, s = "modal-sm", m = NULL, l = "modal-lg"),
      jqui_draggable(shiny::div(
        class = "modal-content",
        if (!is.null(title)) {
          shiny::div(
            class = "modal-header",
            shiny::tags$h4(class = "modal-title",  title)
          )
        },
        shiny::div(class = "modal-body", ...),
        if (!is.null(footer)) {
          shiny::div(class = "modal-footer", footer)
        }
      ))
    ),
    shiny::tags$script("$('#shiny-modal').modal().focus();")
  )
}

Then you can replace uses of draggableModalDialog with customDraggableModalDialog.

Resolution:

We had been struggling with modals opening in background since 6 months and the following settings has resolved it for all our clients:

Change the cache behavior in IE from “automatic” to “Every time the page changes” and you will never face this quirky issue :)

Related