2017-02-24 42 views
2

在R中构建Shiny应用程序时遇到此问题。在应用程序中,使用操作按钮触发隐藏的下载按钮。这将允许我观察操作按钮事件,对该事件作出反应,然后触发下载过程。设置显示属性为none删除href目标

但是,当我设置的下载按钮的隐藏按钮,它一般针对类似"session/1c47..ef8/download/download_show?w="的href目标的显示属性,失踪了。

下面是一个较小的Shiny应用程序,它再现了这个问题。

shinyApp(
    ui = fluidPage(
    tags$head(
     tags$style(HTML(".hide { display: none; }")), 
     tags$script(HTML(' 
     Shiny.addCustomMessageHandler("trigger-button", function(message) { 
      document.getElementById(message.button_id).click(); 
     }); 
     ')) 
    ), 
    div(
     class = "disable", 
     downloadButton("download_shown", "Shown"), 
     div(
     class = "hide", 
     downloadButton("download_hidden", "Hidden") 
    ) 
    ), 
    br(), 
    actionButton("trigger_shown", "I can trigger the visible button!"), 
    actionButton("trigger_hidden", "I can trigger the hidden button!") 
), 
    server = function(input, output, session) { 
    output$download_shown <- downloadHandler(
     filename = "sample.txt", 
     content = function(file) { 
     cat("I'm visible!\n", file = file) 
     } 
    ) 

    output$download_hidden <- downloadHandler(
     filename = "sample2.txt", 
     content = function(file) { 
     cat("I'm hidden!\n", file = file) 
     } 
    ) 

    observeEvent(input$trigger_shown, { 
     session$sendCustomMessage(
     "trigger-button", 
     list(button_id = "download_shown") 
    ) 
    }) 

    observeEvent(input$trigger_hidden, { 
     session$sendCustomMessage(
     "trigger-button", 
     list(button_id = "download_hidden") 
    ) 
    }) 
    } 
) 

在应用中,两个操作按钮触发其相应的下载按钮。触发可见的下载按钮会导致文件sample.txt的正确下载。触发隐藏的下载按钮会导致下载HTML文件(网页),而不是文件sample2.txt。此外,如果您检查生成的HTML,则可以看到download_hidden下载按钮具有不带目标的href属性。

  • HTML规范中是否有任何规定隐藏元素的东西 不能有href目标?这似乎不太可能,我的搜索没有任何一个或任何事情证实了这一点。
  • 内部确实闪亮忽略隐藏的元素?
  • 与此同时,没有人有没有使用hiddendisplay: none;隐藏按钮 的建议吗?

在此先感谢您。

回答

1

我发现这个解决方案归功于GitHub上的这个issue

闪亮,默认情况下挂起隐藏的对象。因此,通过隐藏downloadButton,相应的downloadHandler被暂停。我仍然不确定Shiny如何使用downloadHandler来注册一个下载,但是然而这个过程是有效的,如果正如我所说的那样,如果隐藏了相应的downloadButton,它就不会被触发。

解决方法是使用Shiny提供的outputOptions函数。从帮助页面outputOptions

suspendWhenHidden,当TRUE(默认),输出对象将暂停(不执行),当它被隐藏在网页上。当FALSE,时隐时现的输出对象不会暂停,如果它已经隐藏和暂停,然后它会立即恢复。

通过定义downloadHandler我们可以防止在原来的问题描述中的href问题后指定suspendWhenHidden = FALSE

下面是包含在原来的问题,小闪亮应用程序的修订,工作版本。

shinyApp(
    ui = fluidPage(
    tags$head(
     tags$style(HTML(".hide { display: none; }")), 
     tags$script(HTML(' 
     Shiny.addCustomMessageHandler("trigger-button", function(message) { 
      document.getElementById(message.button_id).click(); 
     }); 
     ')) 
    ), 
    div(
     class = "disable", 
     downloadButton("download_shown", "Shown"), 
     div(
     class = "hide", 
     downloadButton("download_hidden", "Hidden") 
    ) 
    ), 
    br(), 
    actionButton("trigger_shown", "I can trigger the visible button!"), 
    actionButton("trigger_hidden", "I can trigger the hidden button!") 
), 
    server = function(input, output, session) { 
    output$download_shown <- downloadHandler(
     filename = "sample.txt", 
     content = function(file) { 
     cat("I'm visible!\n", file = file) 
     } 
    ) 
    outputOptions(output, "download_shown", suspendWhenHidden = FALSE) 

    output$download_hidden <- downloadHandler(
     filename = "sample2.txt", 
     content = function(file) { 
     cat("I'm hidden!\n", file = file) 
     } 
    ) 
    outputOptions(output, "download_hidden", suspendWhenHidden = FALSE) 

    observeEvent(input$trigger_shown, { 
     session$sendCustomMessage(
     "trigger-button", 
     list(button_id = "download_shown") 
    ) 
    }) 

    observeEvent(input$trigger_hidden, { 
     session$sendCustomMessage(
     "trigger-button", 
     list(button_id = "download_hidden") 
    ) 
    }) 
    } 
) 

记住相应的反应性则表达式来output分配后发出呼叫到outputOptions,否则outputOptions会引发错误。

2

display:none;导致任何元素为未呈现。因此,它不会在文档中占用任何空间。因此,它不会收到任何(真实的)pointer-events

我甚至不会在其接收能力编程触发计数指针事件,我预计至少有几个主要的浏览器干扰,在一般浏览安全原则名称。

如果你希望你的元素是用户交互(真实或程序)一个有效的目标,我建议使用...

opacity: .01; 

...就可以了。这样它会被渲染。如果您不希望它占用内容流中的任何空间,请考虑将它应用于position:absolute