使用jQuery在RShiny中按行添加自定义类。

huangapple go评论127阅读模式
英文:

adding custom class by row in RShiny using jQuery

问题

此问题只是此问题的延伸。

以下代码由两个sortable R包的容器或divs或bucket_lists组成,每个bucket_list都包含两个add_rank_list函数。

第一个容器的元素完全不可移动,每个add_rank_list中的disabled参数都设置为TRUE,而第二个容器允许用户拖放项目,除了第一个项目,因为第一个add_rank_list函数中的disabled参数设置为TRUE,但在第二个函数中设置为FALSE

如果第二个容器中的元素值为"Camp",我想将其背景颜色设置为红色。此外,如果第一个容器中与"Camp"元素同一行的元素也设置为相同的背景颜色。

简而言之,我并没有问题将类添加到第二个容器中的"Camp"元素,因为我的代码可以做到。然而,我的主要问题是将类添加到第一个容器中与第二个容器中的"Camp"元素在同一行的元素上,并考虑到用户可以在第二个容器中拖放"Camp"元素

尽管尝试了不同的方法,我仍然无法实现这个结果。任何帮助将不胜感激。

library(shiny)
library(sortable)

ui <- fluidPage(
  actionButton(inputId = "id1", "run"),
  uiOutput("id2")
)

server <- function(input, output, session) {
  observeEvent(input$id1, {
    output$id2 <- renderUI({
      
      tagList(
        tags$style(
          HTML(paste0(
            ".custom-sortable .rank-list-item-Camp {
              background-color: red 
            }"
          ))
        ),
        tags$script(
          HTML("
            $(document).ready(function() {
              $('.custom-sortable .rank-list-item').each(function(index) {
                if ($(this).text() === 'Camp') {
                  targetIndex = index;
                }
              });
              $('.custom-sortable .rank-list-item').eq(targetIndex).addClass('rank-list-item-Camp');
            });
          ")
        ),
        div(
          style = "width: 15%; float: left; overflow: hidden;",
          bucket_list(
            header = NULL,
            class = c("default-sortable","custom-sortable" ),
            orientation = c("vertical"),
            add_rank_list(
              text = NULL,
              labels = 100,
              options = sortable_options(disabled = T)
            ),
            add_rank_list(
              text = NULL,
              labels = c(50,40,30,15),
              options = sortable_options(disabled = T)
            )
          )
        ),
  
        div(
          style = "width: 15%; float: left; overflow: hidden;",
          bucket_list(
            header = NULL,
            class = c("default-sortable", "custom-sortable"),
            orientation = c("vertical"),
            add_rank_list(
              text = NULL,
              labels = c("Fixed"),
              options = sortable_options(disabled = T)
            ),
            add_rank_list(
              text = NULL,
              labels = c("Camp", rep("No Info",3)),
              options = sortable_options(disabled = F)
            )
          )
        )
        
      )
    })
  })
}
shinyApp(ui, server)
英文:

This question is just an extention of this question

The following code consists of two containers or divs or bucket_lists from the sortable R package and each bucket_list consists of two add_rank_list functions.

The first container elements are completly unmovable where the disabled arguments in each add_rank_list are set to TRUE, while the second container allows the user to drag and drop the items except the first item, since the disabled argument in the first add_rank_list function is set to TRUE but in the second function is set to FALSE.

I would like to apply a red background color to the element in the second container if its value is "Camp". Additionally, I would like to apply the same background color to the element in the first container that shares the same row with the "Camp" element.

So briefly I do not have a problem with adding the class to the "Camp" element in the second container since my code can do this. However, my main point is to add the class to the element in the first container which has the same row as the "Camp" element in the second container and take into consideration that the user can drag and drop "Camp" element in the second container.

Despite attempting different methods, I have been unable to achieve this outcome. Any assistance would be greatly appreciated.

library(shiny)
library(sortable)
ui &lt;- fluidPage(
actionButton(inputId = &quot;id1&quot;, &quot;run&quot;),
uiOutput(&quot;id2&quot;)
)
server &lt;- function(input, output, session) {
observeEvent(input$id1, {
output$id2 &lt;- renderUI({
tagList(
tags$style(
HTML(paste0(&quot;
.custom-sortable .rank-list-item-Camp {
background-color: red 
}
&quot;))
),
tags$script(
HTML(&quot;
$(document).ready(function() {
$(&#39;.custom-sortable .rank-list-item&#39;).each(function(index) {
if ($(this).text() === &#39;Camp&#39;) {
targetIndex = index;
}
});
$(&#39;.custom-sortable .rank-list-item&#39;).eq(targetIndex).addClass(&#39;rank-list-item-Camp&#39;);
});
&quot;)
),
div(
style = &quot;width: 15%; float: left; overflow: hidden;&quot;,
bucket_list(
header = NULL,
class = c(&quot;default-sortable&quot;,&quot;custom-sortable&quot; ),
orientation = c(&quot;vertical&quot;),
add_rank_list(
text = NULL,
labels = 100,
options = sortable_options(disabled = T)
),
add_rank_list(
text = NULL,
labels = c(50,40,30,15),
options = sortable_options(disabled = T)
)
)
),
div(
style = &quot;width: 15%; float: left; overflow: hidden;&quot;,
bucket_list(
header = NULL,
class = c(&quot;default-sortable&quot;, &quot;custom-sortable&quot;),
orientation = c(&quot;vertical&quot;),
add_rank_list(
text = NULL,
labels = c(&quot;Fixed&quot;),
options = sortable_options(disabled = T)
),
add_rank_list(
text = NULL,
labels = c(&quot;Camp&quot;, rep(&quot;No Info&quot;,3)),
options = sortable_options(disabled = F)
)
)
)
)
})
}
)
}
shinyApp(ui, server)

答案1

得分: 1

您可以指定自定义处理程序执行魔术:

```r
css <- HTML("
.bucket-list-container .default-sortable .rank-list .highlight-marker {
   background-color: red;
}

.bucket-list-container .default-sortable .rank-list .highlight-marker:hover:not(.disabled)  {
   background-color: red;
}

.sortable-container {
   width: 15%; 
   float: left; 
   overflow: hidden;   
}")
   
js <- HTML("
   function init() {
      const pos = $('#camp_container .rank-list-container:nth(1) .rank-list-item span').index('#camp');
      $('#camp').parent().addClass('highlight-marker');
      $('#clone_container .rank-list-container:nth(1) .rank-list-item').eq(pos).addClass('highlight-marker');
   }
   
   function move_handler(evt) {
      const $elem = $(evt.item);
      if ($elem.has('#camp').length) {
         const $old = $('#clone_container .rank-list-container:nth(1) .rank-list-item').eq(evt.oldIndex);
         const $new = $('#clone_container .rank-list-container:nth(1) .rank-list-item').eq(evt.newIndex);
         $old.removeClass('highlight-marker');
         $new.addClass('highlight-marker');
      }
   }")

ui <- fluidPage(
   singleton(tags$head(tags$style(css))),
   singleton(tags$head(tags$script(js, type = "text/javascript"))),
   actionButton("run", "Run!"),
   uiOutput("container")
)

server <- function(input, output, session) {
   output$container <- renderUI({
      req(input$run)
      bucket_1 <- bucket_list(
         header = NULL,
         add_rank_list(
            text = NULL,
            labels = 100,
            options = sortable_options(disabled = TRUE)
         ),
         add_rank_list(
            text = NULL,
            labels = c(50, 40, 30, 15),
            options = sortable_options(disabled = TRUE)
         ),
         class = c("default-sortable","custom-sortable"),
         orientation = "vertical"
      )
      
      bucket_2 <- bucket_list(
         header = NULL,
         add_rank_list(
            text = NULL,
            labels = "Fixed",
            options = sortable_options(disabled = TRUE)
         ),
         add_rank_list(
            text = NULL,
            labels = c(list(span("Camp", id = "camp")), 
                       rep(list(span("No Info")), 3L)),
            options = sortable_options(disabled = FALSE, 
                                       onSort = "move_handler",
                                       onLoad = "init"
            )
         ),
         class = c("default-sortable","custom-sortable" ),
         orientation = "vertical")
      
      container_1 <- div(
         class = "sortable-container",
         id = "clone_container",
         bucket_1
      )
      container_2 <- div(
         class = "sortable-container",
         id = "camp_container",
         bucket_2
      )
      tagList(container_1,
              container_2)
   })
}

shinyApp(ui, server)
英文:

You can specify custom handlers which do the magic:

css &lt;- HTML(&quot;
.bucket-list-container .default-sortable .rank-list .highlight-marker {
   background-color: red;
}

.bucket-list-container .default-sortable .rank-list .highlight-marker:hover:not(.disabled)  {
   background-color: red;
}

.sortable-container {
   width: 15%; 
   float: left; 
   overflow: hidden;   
}&quot;)

js &lt;- HTML(&quot;
   function init() {
      const pos = $(&#39;#camp_container .rank-list-container:nth(1) .rank-list-item span&#39;).index(&#39;#camp&#39;);
      $(&#39;#camp&#39;).parent().addClass(&#39;highlight-marker&#39;);
      $(&#39;#clone_container .rank-list-container:nth(1) .rank-list-item&#39;).eq(pos).addClass(&#39;highlight-marker&#39;);
   }
   
   function move_handler(evt) {
      const $elem = $(evt.item);
      if ($elem.has(&#39;#camp&#39;).length) {
         const $old = $(&#39;#clone_container .rank-list-container:nth(1) .rank-list-item&#39;).eq(evt.oldIndex);
         const $new = $(&#39;#clone_container .rank-list-container:nth(1) .rank-list-item&#39;).eq(evt.newIndex);
         $old.removeClass(&#39;highlight-marker&#39;);
         $new.addClass(&#39;highlight-marker&#39;);
      }
   }
&quot;)

ui &lt;- fluidPage(
   singleton(tags$head(tags$style(css))),
   singleton(tags$head(tags$script(js, type = &quot;text/javascript&quot;))),
   actionButton(&quot;run&quot;, &quot;Run!&quot;),
   uiOutput(&quot;container&quot;)
)

server &lt;- function(input, output, session) {
   output$container &lt;- renderUI({
      req(input$run)
      bucket_1 &lt;- bucket_list(
         header = NULL,
         add_rank_list(
            text = NULL,
            labels = 100,
            options = sortable_options(disabled = TRUE)
         ),
         add_rank_list(
            text = NULL,
            labels = c(50, 40, 30, 15),
            options = sortable_options(disabled = TRUE)
         ),
         class = c(&quot;default-sortable&quot;,&quot;custom-sortable&quot;),
         orientation = &quot;vertical&quot;
      )
      
      bucket_2 &lt;- bucket_list(
         header = NULL,
         add_rank_list(
            text = NULL,
            labels = &quot;Fixed&quot;,
            options = sortable_options(disabled = TRUE)
         ),
         add_rank_list(
            text = NULL,
            labels = c(list(span(&quot;Camp&quot;, id = &quot;camp&quot;)), 
                       rep(list(span(&quot;No Info&quot;)), 3L)),
            options = sortable_options(disabled = FALSE, 
                                       onSort = &quot;move_handler&quot;,
                                       onLoad = &quot;init&quot;
            )
         ),
         class = c(&quot;default-sortable&quot;,&quot;custom-sortable&quot; ),
         orientation = &quot;vertical&quot;)
      
      container_1 &lt;- div(
         class = &quot;sortable-container&quot;,
         id = &quot;clone_container&quot;,
         bucket_1
      )
      container_2 &lt;- div(
         class = &quot;sortable-container&quot;,
         id = &quot;camp_container&quot;,
         bucket_2
      )
      tagList(container_1,
              container_2)
   })
}

shinyApp(ui, server)

The CSS selectors and the marker class are quick and dirty and you can improve them, but you get the gist.


Update

  • Fixed the CSS such that we do not need !important
  • Added an if clause in the JS to make sure it fires only for the element containing #camp.
  • Removed the hard coded position in the init function such that the code will also work, if Camp is not in the first position.

huangapple
  • 本文由 发表于 2023年3月15日 18:54:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75743732.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定