【问题标题】:setting display attribute to none removes href target将 display 属性设置为 none 会删除 href 目标
【发布时间】:2017-02-24 22:43:36
【问题描述】:

我在 R 中构建 Shiny 应用程序时遇到了这个问题。在应用程序中,操作按钮用于触发隐藏的下载按钮。这将允许我观察操作按钮事件,对该事件做出反应,然后触发下载过程。

但是,当我将下载按钮的显示属性设置为隐藏按钮的 href 目标时,它通常以 "session/1c47..ef8/download/download_show?w=" 之类的目标为目标。

下面是一个较小的 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 目标?这似乎不太可能,我的 搜索出现了任何证实这一点的 -one 或 -thing。
  • Shiny 在内部会忽略隐藏的元素吗?
  • 同时,有没有人建议隐藏按钮 不使用hiddendisplay: none;

提前谢谢你。

【问题讨论】:

    标签: html css r shiny


    【解决方案1】:

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

    我什至不会指望它能够接收以编程方式触发的指针事件,因为我预计至少有几个主要浏览器会以一般浏览安全原则的名义进行干预。

    如果您希望您的元素成为用户交互(真实或程序化)的有效目标,我建议使用...

    opacity: .01;
    

    ...在上面。这样它就会被渲染。如果您不希望它占用内容流中的任何空间,请考虑对其应用position:absolute

    【讨论】:

      【解决方案2】:

      感谢 GitHub 上的 issue,我找到了解决方案。

      默认情况下,Shiny 会挂起隐藏的对象。因此,通过隐藏downloadButton,相应的downloadHandler 将被挂起。我仍然不确定 Shiny 是如何使用 downloadHandler 注册下载的,但是但是该过程有效,如果正如我所说,相应的 downloadButton 被隐藏,则不会触发它。

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

      suspendWhenHidden,当为TRUE(默认)时,输出对象在网页上隐藏时会被挂起(不执行)。 FALSE时,输出对象隐藏时不会挂起,如果已经隐藏并挂起,则立即恢复。

      通过在定义downloadHandler后指定suspendWhenHidden = FALSE,我们可以防止原问题中描述的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)
            }
          )
          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会报错。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-04
        • 2013-06-27
        • 2014-06-20
        • 2021-11-22
        • 2019-02-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多