在闪亮的 R 中自动调整 textAreaInput 的大小

Posted

技术标签:

【中文标题】在闪亮的 R 中自动调整 textAreaInput 的大小【英文标题】:auto-resize textAreaInput in shiny R 【发布时间】:2021-05-31 01:15:22 【问题描述】:

我正在尝试调整 this SO answer 关于如何通过 javascript 为闪亮 R 自动调整 textarea 输入的大小。理想情况下,我想避免使用 ShinyJS 等帮助程序包。

首先我尝试了一个纯 javascript 实现,在该实现中我将 javascript 按原样加载到应用程序中(方法 1)。然后我尝试从闪亮的observeEvent触发javascript函数(方法2)。

这两种方法都不起作用。 好像我错过了什么。

方法一:

library(shiny)

jsCode1 <- "
            var observe;
            if (window.attachEvent) 
            observe = function (element, event, handler) 
            element.attachEvent('on'+event, handler);
            ;
            
            else 
            observe = function (element, event, handler) 
            element.addEventListener(event, handler, false);
            ;
            
            function init () 
            var text = document.getElementById('text');
            function resize () 
            text.style.height = 'auto';
            text.style.height = text.scrollHeight+'px';
            
            /* 0-timeout to get the already changed text */
            function delayedResize () 
            window.setTimeout(resize, 0);
            
            observe(text, 'change',  resize);
            observe(text, 'cut',     delayedResize);
            observe(text, 'paste',   delayedResize);
            observe(text, 'drop',    delayedResize);
            observe(text, 'keydown', delayedResize);

            text.focus();
            text.select();
            resize();
            

            init();
            "

shinyApp(ui = 

           fluidPage(

                        tags$script(jsCode1),

                        tags$head(

                          tags$style("
                                     textarea 
                                     border: 0 none white;
                                     overflow: hidden;
                                     padding: 0;
                                     outline: none;
                                     background-color: #D0D0D0;
                                     
                                     "
                          )

                          ),

                               shiny::tagAppendAttributes(
                                 textAreaInput(inputId = "text",
                                               label = "Enter text here",
                                               placeholder = "insert your text here",
                                               width = "100%"),
                                 style = "width: 100%;")

                        ),

         server = function(input, output, session) 

         
                      )

方法2:

library(shiny)

jsCode2 <- "

            Shiny.addCustomMessageHandler('handler1', init);

            function init (el) 
            var text = document.getElementById(el);
            function resize () 
            text.style.height = 'auto';
            text.style.height = text.scrollHeight+'px';
            
            /* 0-timeout to get the already changed text */
            function delayedResize () 
            window.setTimeout(resize, 0);
            
            observe(text, 'change',  resize);
            observe(text, 'cut',     delayedResize);
            observe(text, 'paste',   delayedResize);
            observe(text, 'drop',    delayedResize);
            observe(text, 'keydown', delayedResize);

            text.focus();
            text.select();
            resize();
            "

shinyApp(ui = 

           fluidPage(

                        tags$script(jsCode2),

                        tags$head(

                          tags$style("
                                     textarea 
                                     border: 0 none white;
                                     overflow: hidden;
                                     padding: 0;
                                     outline: none;
                                     background-color: #D0D0D0;
                                     
                                     "
                          )

                          ),

                               shiny::tagAppendAttributes(
                                 textAreaInput(inputId = "text",
                                               label = "Enter text here",
                                               placeholder = "insert your text here",
                                               width = "100%"),
                                 style = "width: 100%;")

                        ),

         server = function(input, output, session) 

           observeEvent(input$text,

             session$sendCustomMessage("handler1", message = "text")

           )

         
                      )

【问题讨论】:

【参考方案1】:

可能是您尝试在 textinput() 添加到 DOM 之前将调整大小事件附加到后者。

我添加了一个事件侦听器,该侦听器在附加调整大小事件之前等待 DOM 加载完毕。

document.addEventListener('DOMContentLoaded', function(event) ...)

shinyjs 会自动为您执行此操作。添加上面的事件监听器,你可以不使用shinyjs 让它工作。

Javascript 代码:

jsCode <- "document.addEventListener('DOMContentLoaded', function(event) 
    var observe;
    if (window.attachEvent) 
      observe = function (element, event, handler) 
        element.attachEvent('on'+event, handler);
      ;
    
    else 
      observe = function (element, event, handler) 
        element.addEventListener(event, handler, false);
      ;
    
    function init () 
      var text = document.getElementById('text');
      function resize () 
        text.style.height = 'auto';
        text.style.height = text.scrollHeight+'px';
      
      /* 0-timeout to get the already changed text */
        function delayedResize () 
          window.setTimeout(resize, 0);
        
      observe(text, 'change',  resize);
      observe(text, 'cut',     delayedResize);
      observe(text, 'paste',   delayedResize);
      observe(text, 'drop',    delayedResize);
      observe(text, 'keydown', delayedResize);

      text.focus();
      text.select();
      resize();
    ;init()
  )
"

应用程序:

library(shiny)

ui <- fluidPage(
  shiny::tags$script(jsCode),
  textAreaInput(inputId = "text", label = "a", value = "b")
)

server <- function(input, output, session) 


shinyApp(ui, server)

【讨论】:

像魅力一样工作!

以上是关于在闪亮的 R 中自动调整 textAreaInput 的大小的主要内容,如果未能解决你的问题,请参考以下文章

调整操作按钮的大小会导致闪亮仪表板中的标题错位

R闪亮:填写提示用户并支持自动填充功能的表单时不需要的反应

调整/更新过滤器选择以适应闪亮的 DT 数据表中已应用的过滤器

在Rmarkdown文档中调整嵌入式Shiny App的大小

如何让 Leaflet for R 使用 100% 的闪亮仪表板高度

在闪亮的应用程序中调整嵌入图像的大小