javascriptjqueryrshinyjsshinyjqui

How to make an orderInput item resizeable with jqui_resizable


Update: Here is graphical explanation from what I want: There are to features: 1. resizing with the mouse and 2. rotating the text.

enter image description here This is a follow-up question to this Drag and drop with shinyjqui to a grid-table.

First answer: I am trying to make the item or button with the label A resizeable like explained here https://yang-tang.github.io/shinyjqui/: 'Resizable: Change the size of an element using the mouse.'

Is this possible? I have tried the generic function of the package jqui_sortable and also a custom JS code like in the example below:

library(shiny)
library(shinyjqui)

connections <- paste0("droppable_cell_", 1) # id of the grid cells

ui <- fluidPage(
  tags$head(
    tags$script(
      JS(
        "
$(document).on('shiny:connected', function() {
$('#letters').resizable({
alsoResize: '.shinyjqui-sortable-item',
minHeight: 20,
minWidth: 20
});
});


$(function() {
$('[id^=droppable_cell]').sortable({
connectWith: '#letters',
drop: function(event, ui) {
$(this).append(ui.draggable);
}
})
});
"
      )
    ),
# some styling
tags$style(
  HTML(
    "
.grid-table {
width: 150px;
border-collapse: collapse;
}
.grid-cell {
width: 100%;
height: 200px;
border: 1px solid black;
background-color: white;
text-align: center;
margin: 0;
padding: 5px;
}
.grid-cell-text {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
background-color: steelblue;
color: white;
font-size: 18px;
}
.droppable-cell {
background-color: lightgray;
}
.table-container {
display: flex;
position: absolute;
left: 10px;
top: 10px;
margin-top: 0px;
overflow: hidden;
}
"
  )
)
  ),

div(
  class = "table-container",
  div(
    class = "grid-table",
    id = "my_grid",
    div(
      class = "grid-row",
      div(class = "grid-cell grid-cell-text", "my_grid"),
      div(id = "droppable_cell_1", class = "grid-cell droppable-cell", ""),
    )
  ),
  
  orderInput('letters', 'Letters', items = LETTERS[1],
             connect = connections) # defined above
)
)

server <- function(input, output, session) {
  
}

shinyApp(ui, server)

Solution

  • Here is one approach for implementing the two features.

    For the resizeable buttons, your JS is already good, but you should rather apply it to .btn, not to #letters.

    The rotated buttons could be obtained by

    $('.btn').on('resize', function() {
        $(this).css({'transform': 'rotate(270deg)',
                     'line-height': $(this).height().toString() + 'px'});
    })
    

    This will have the following effects:

    1. If a button is resized (you can of course delete or alter this trigger), then the button gets rotated by 270 degrees. Notice that what is more desirable is to only rotate the text of the button, not the button itself, but I think one has to manipulate the HTML more in-depth for obtaining this. Also notice that writing-mode: sideways-rl is suitable for this, but unfortunately this is currently not supported by all browsers.

    2. Since the buttons have text-align: center and vertical-align: middle by default, the line-height: $(this).height().toString() + 'px' is sufficient for setting that the text of the button (here: "A") always will be displayed in the center of the button after resizing.

    This is how it could look like after resizing:

    enter image description here

    library(shiny)
    library(shinyjqui)
    
    connections <- paste0("droppable_cell_", 1) # id of the grid cells
    
    ui <- fluidPage(
        tags$head(
            tags$script(
                JS(
                    "
    $(document).on('shiny:connected', function() {
        $('.btn').resizable({
            alsoResize: '.shinyjqui-sortable-item',
            minHeight: 20,
            minWidth: 20
    });
    
    $('.btn').on('resize', function() {
        $(this).css({'transform': 'rotate(270deg)',
                     'line-height': $(this).height().toString() + 'px'});
    })
    });
    
    
    $(function() {
    $('[id^=droppable_cell]').sortable({
    connectWith: '#letters',
    drop: function(event, ui) {
    $(this).append(ui.draggable);
    }
    })
    });
    "
                )
            ),
            # some styling
            tags$style(
                HTML(
                    "
    .grid-table {
    width: 150px;
    border-collapse: collapse;
    }
    .grid-cell {
    width: 100%;
    height: 200px;
    border: 1px solid black;
    background-color: white;
    text-align: center;
    margin: 0;
    padding: 5px;
    }
    .grid-cell-text {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    background-color: steelblue;
    color: white;
    font-size: 18px;
    }
    .droppable-cell {
    background-color: lightgray;
    }
    .table-container {
    display: flex;
    position: absolute;
    left: 10px;
    top: 10px;
    margin-top: 0px;
    overflow: hidden;
    }
    "
                )
            )
        ),
        
        div(
            class = "table-container",
            div(
                class = "grid-table",
                id = "my_grid",
                div(
                    class = "grid-row",
                    div(class = "grid-cell grid-cell-text", "my_grid"),
                    div(id = "droppable_cell_1", class = "grid-cell droppable-cell", ""),
                )
            ),
            
            orderInput('letters', 'Letters', items = LETTERS[1],
                       connect = connections) # defined above
        )
    )
    
    server <- function(input, output, session) {
        
    }
    
    shinyApp(ui, server)