Using jQuery to apply custom classes on a row in RShiny is a great way to

Building upon this initial inquiry, the following code showcases two separate containers, each containing a series of elements provided by the `sortable` R package. Within each container are specific functions called `add_rank_list`, serving different purposes.

The first container consists of elements that are fixed and cannot be moved due to the set `disabled` argument being assigned as `TRUE` for each `add_rank_list`. However, in the second container, elements can be dragged and dropped, except for the first item, where the `disabled` argument is set to `FALSE` instead.

My goal is to highlight any element within the second container labeled as "Camp" with a red background color. Additionally, I aim to apply the same style to the corresponding element in the first container if it shares the same row as the "Camp" element in the second container.

Although successfully adding the desired class to the "Camp" element within the second container, my challenge lies in extending this functionality to the appropriate element in the first container, ensuring synchronization between both despite potential user interactions.

Despite numerous attempts using various techniques, achieving this has proven elusive. Any guidance or support on this matter would be immensely appreciated.

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)

Answer №1

If you want to add custom handlers to perform certain actions, here is how you can do it:

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 initialize() {
      const position = $('#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(position).addClass('highlight-marker');
   }
   
   function move_handler(event) {
      const $element = $(event.item);
      if ($element.has('#camp').length) {
         const $oldItem = $('#clone_container .rank-list-container:nth(1) .rank-list-item').eq(event.oldIndex);
         const $newItem = $('#clone_container .rank-list-container:nth(1) .rank-list-item').eq(event.newIndex);
         $oldItem.removeClass('highlight-marker');
         $newItem.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 = "initialize"
            )
         ),
         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)

The CSS selectors and the marker class can be refined for better performance, but this example gives you a starting point.


Update

  • Optimized the CSS so that we avoid using !important
  • Included an if statement in the JS to ensure it applies only to the element containing #camp.
  • Eliminated hardcoded positioning in the initialize function to make the code adaptable even if Camp is not in the first position.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide to updating textarea background color depending on a specific selection

Looking for some assistance with a form I'm working on. It includes fields for Name, Surname, a dropdown menu for selecting different colors, and a message box (textarea). I would like to dynamically change the background color of the textarea based o ...

The Ajax request is functioning perfectly, but only on the index page

Utilizing a mobile app template within the Framework7 framework for Cordova app development requires making ajax requests on each page to fetch data from a PHP web service. While an ajax request in index.html functions properly, replicating the same reques ...

Issue with Bootstrap form control-file class in a form

The standard form I am using with bootstrap 4.0 is working well, but the input button is not applying Bootstrap's CSS. <div class="form-group"> <input type="file" class="form-control-file" id="exampleFormCont ...

Combining Java with Ajax and JSON for effective file separation using paths

I am encountering an issue with a servlet that generates a JSON string containing file paths. The generated string looks like this: {"files": "li_digitalized#C:\Users\FABIO~1.HAE\AppData\Local\Temp\fusion_capture\fscan18 ...

Is it possible to convert an object and/or a nested array with objects into a JSON string without relying on JSON.stringify?

Struggling to generate a correct JSON string from an object without relying on JSON.stringify(). Presenting my current implementation below - var my_json_encode = function(input) { if(typeof(input) === "string"){ return '"'+input+&apo ...

Implementing dropdown filtering for nested ng-repeats in Angular application

I currently have the following data structure set up: vm.years = [{ year: number, proevents: [{year: number, division: string, level: string, place: string, names: string}], nonproevents: [{year: number, division: string, level: string, place: st ...

Enter the spotlight with all the information you need about AngularJS

Can someone please help me figure out how to display the post->id with a fade in effect? I've tried searching for a solution but haven't had any luck. Your assistance would be greatly appreciated!!! *I apologize in advance if my language is n ...

I am currently in the process of transitioning a Gatsby project from CSS to SCSS, and running into obstacles with the

Currently, I am in the process of converting a Gatsby starter project that utilizes Lost grid from CSS to SCSS for better organization and efficiency. The original starter project can be found here: https://github.com/wpioneer/gatsby-starter-lumen The ma ...

When mousing over a subitem of the Image menu, ensure that the Image menu

Is there a way to prevent the image menu from reverting back to its original image when hovering over its subitems? I have 5 navigation menu items, but only one has a dropdown. Whenever I hover on the subitems of About Us, the image for About Us changes ba ...

AngularJS ng-submit can be configured to trigger two separate actions

I am currently diving into AngularJS and working on a simple project to create an expense tracker as a beginner task. However, I have encountered some issues with my code. While I have successfully implemented most functions, I am struggling with the upda ...

Transmit data in the form of a buffer

const response = await client.render(data); const Writable = require('stream').Writable; var buffer = []; const myWritableStream = new Writable({ write(chunk, encoding, callback) { ...

Update the content of the widget

Currently, I am utilizing the following script to display NBA standings: <script type="text/javascript" src="https://widgets.sports-reference.com/wg.fcgi?script=bbr_standings&amp;params=bbr_standings_conf:E,bbr_standings_css:1&amp"></sc ...

What is causing the peculiar appearance of the shadows on these items in Three.js?

Currently, I am delving into the realm of three.js. To enhance my understanding, I decided to practice with an example. However, the shadow effects on the objects seem off or rather unusual. https://i.sstatic.net/pfg6E.jpg The expected outcome should re ...

Adjust the width of the TinyMCE Editor to automatically resize based on the content being

Is it possible for TinyMCE to adjust the content within an absolutely positioned container and update the width while editing? <div class="container"> <textarea>This is my very long text that should not break. This is my very long text tha ...

Tips for creating line breaks using flex-shrink in CSS?

Currently, I am in the process of creating a chat-like system and have been using this sample as a reference: One adjustment I made was replacing <input type="text"> with <textarea> since messages often consist of multiple lines. Ho ...

Obtaining Spanish characters using JQuery and JSON

I have implemented the following code to retrieve data from the database when a user selects an option: <script type="text/javascript" > function setStore(value) { $.get("getStoreMetaInfo.php", {store_id: value, meta_type : 3},functi ...

Can dark mode be activated and maintained across multiple pages using just one JavaScript file?

I'm facing an issue with maintaining a dark mode across multiple web pages. I tried adding a JavaScript script to all my HTML files, but it didn't work as expected. Then, I experimented by adding the script to just one HTML file, and while it suc ...

Is there a substitute for using CSS divs with display:table?

<div id="wr"> <div id="con"> <div id="unknownWidth">some box with unknown width</div> </div> <div id="knownWidth"></div> </div> #wr { width:300px; height:100px; border:1px sol ...

Scheduled tasks arranged by the user

My goal is to empower my users to schedule specific actions at their preferred times. With a node server hosted on Azure, I am exploring the potential of using node-schedule for this functionality. One idea I'm considering is running a master schedule ...

Vue - Syntax error: Unexpected token, expecting "}."

I recently started working with Vue and have encountered a simple component issue. Sometimes, when I run npm run serve or save a file that is already being served, I receive the following error message: E:\Development\website\app>npm run ...