I use the insertUI() function to create new dragUI() dynamically. Unfortunatly, the newly created dragUI does not behave as expected. I can’t drag them as dragUI that were created from the ui initial function.
library(shiny)
library(shinyDND)
ui <- fluidPage(
actionButton('insertBtn', 'Insert'),
dropUI("Box", row_n = 3, col_n = 3, style = "height: 200px; width: 700px"),
dragUI("Drag0",style = "display: inline-block; height: 100px; width: 100px",tags$a("Initial"))
)
shinyApp(ui, server = function(input, output) {
observeEvent(input$insertBtn, {
insertUI(
selector = '#Box',
where = c("afterEnd"),
ui = (dragUI(id="newDragUI",style = "display: inline-block; height: 100px; width: 100px",tags$a("new")))
)
})
})
Related
I have this example app:
library(shiny)
ui <- fluidPage(
textInput("a", "A", width = 20),
textInput("b", "B", width = 20),
tags$img(
src = "https://posit.co/wp-content/uploads/2022/10/09_HOMEPAGE.svg",
style = 'position: absolute'
)
)
server <- function(input, output, session) {
}
shinyApp(ui, server)
Which creates this:
How can I position the textInput widgets like this way:
You can change the order to have the image first with static sizing then embed the input in a div with absolute position:
ui <- fluidPage(
tags$img(
src = "https://posit.co/wp-content/uploads/2022/10/09_HOMEPAGE.svg",
style = 'position: absolute; width: 1024px; height: 768px;'
),
tags$div(
textInput("a", "A", width = 20),
style = 'position: absolute;left: 420px; top: 100px;'),
)
Here is a link to a two slide slickR carousel that works well on a desktop but when viewed on an iphone, the image is cut off. ie it is not responsive.
How do I use slickR's carousel with images and have it work on both desktop and mobile without images being cutoff?
Do I need to add the responsive behaviour manually? The original JS page talks about it, but I'm not sure how to translate that to R.
R Script
library(shiny)
library(slickR)
# Test #########################################################################
gic_changed_filenames <- c( "/home/law/whatbank_website/static/fb/img/gic1-5_yield_curve_d9bf51fdc3ec3cec.png",
"/home/law/whatbank_website/static/fb/img/gic1-5_yield_curve_fb2482d0f9923086.png")
################################################################################
num_slides <- length(gic_changed_filenames)
# Capture everything after img/ and add to link
chart_names <- paste0("http://whatbank.ca/fb/img/", sub(".*img/", "", gic_changed_filenames))
ui <- fluidPage(
tags$head(
tags$style(HTML("
.arrows {
height: 20px;
}
.slick-prev {
left: 230px; # moves right
}
.slick-next {
left: 250px; # moves right
}
"))
),
fluidRow(
column(6,),
column(2,
tags$div(class="arrows"
)),
column(4)),
slickROutput("slick_output")
)
server <- function(input, output, session) {
output$slick_output <- renderSlickR({
slickR(obj = chart_names, height = 300, width = "100%") +
settings(dots = TRUE, appendArrows = '.arrows')
})
}
shinyApp(ui, server)
By default "auto" is set for .slick-slide img's width property. You can overwrite this setting using relative css units (% / vw / vh) to rescale the image:
Edit: removed the column chaos and calculated relative positions for the arrows.
library(shiny)
library(slickR)
# Test #########################################################################
gic_changed_filenames <- c( "/home/law/whatbank_website/static/fb/img/gic1-5_yield_curve_d9bf51fdc3ec3cec.png",
"/home/law/whatbank_website/static/fb/img/gic1-5_yield_curve_fb2482d0f9923086.png")
################################################################################
num_slides <- length(gic_changed_filenames)
# Capture everything after img/ and add to link
chart_names <- paste0("http://whatbank.ca/fb/img/", sub(".*img/", "", gic_changed_filenames))
ui <- fluidPage(
tags$head(
tags$style(HTML("
.arrows {
height: 20px;
}
.slick-prev {
left: calc(50% - 30px);
}
.slick-next {
right: calc(50% - 30px);
}
.slick-slide img {
width: 100% !important;
}
"))
),
fluidRow(
column(12, tags$div(class="arrows"))
),
slickROutput("slick_output")
)
server <- function(input, output, session) {
output$slick_output <- renderSlickR({
slickR(obj = chart_names, height = "50%") +
settings(dots = TRUE, appendArrows = '.arrows')
})
}
shinyApp(ui, server)
I'm wondering whether these is any option to include math mode in tooltip title using bsTooltip() from shinyBS package.
Small example:
rm(list = ls())
library(shiny)
library(shinyBS)
ui <- basicPage(
headerPanel("Tooltip test"),
bsTooltip(id = "Equation", title = "\\(\\bar{X} = \\frac{1}{n}\\sum_{p = 1}^{n}X_p\\)", placement = "bottom", trigger = "hover", options = NULL),
mainPanel(
p("some text", htmlOutput("Equation", inline = TRUE))
)
)
server <- shinyServer(function(input, output,session) {
output$Equation <- renderUI({HTML("<font color='blue'><u>something which needs equation</u></font>")})
})
shinyApp(ui = ui, server = server)
The result (math mode) is not satisfactory:
No way with 'shinyBS'.
Here is a way using the qTip2 JavaScript library.
In order to use it, you have to download the files jquery.qtip.min.css and jquery.qtip.min.js, and put these two files in the www subfolder of the Shiny app.
library(shiny)
js <- "
$(document).ready(function() {
$('#Equation').qtip({
overwrite: true,
content: {
text: $('#tooltip')
},
position: {
my: 'top left',
at: 'bottom right'
},
show: {
ready: false
},
hide: {
event: 'unfocus'
},
style: {
classes: 'qtip-youtube qtip-rounded'
},
events: {
blur: function(event, api) {
api.elements.tooltip.hide();
}
}
});
});
"
library(shiny)
ui <- basicPage(
tags$head(
tags$link(rel = "stylesheet", href = "jquery.qtip.min.css"),
tags$script(src = "jquery.qtip.min.js"),
tags$script(HTML(js)),
),
withMathJax(),
headerPanel("Tooltip test"),
mainPanel(
p("some text", htmlOutput("Equation", inline = TRUE)),
div(
id = "tooltip", style = "display: none;",
HTML("$$\\int_0^1 f(x) dx = \\pi$$")
)
)
)
server <- shinyServer(function(input, output,session) {
output$Equation <-
renderUI({HTML("<font color='blue'><u>something which needs equation</u></font>")})
})
shinyApp(ui = ui, server = server)
Just to add another option, we could create our own tooltip class following the example from W3 here. Then we can use {shiny}'s withMathJax() function to render the tooltip as formula.
I usually use custom tooltips in cases where I only have a few tooltips that I want to customize. It has the advantage that it comes with no additional dependencies. The major drawbacks of this custom tooltip are that (1) it is displayed as child element and not in a separate container on the top layer like tooltips generated with javascript and that (2) you have to create css classes for each arrow direction. So if you have many tooltips pointing in different directions an additional javascript library like qTip2 should be definitely worth the dependency.
library(shiny)
ui <- fluidPage(
tags$head(
tags$style(HTML(
# tooltip implementation from:
# https://www.w3schools.com/css/tryit.asp?filename=trycss_tooltip_arrow_top
# just added a `t` to make classes unique
".ttooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
}
.ttooltip .ttooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
top: 150%;
left: 50%;
margin-left: -60px;
}
.ttooltip .ttooltiptext::after {
content: '';
position: absolute;
bottom: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent black transparent;
}
.ttooltip:hover .ttooltiptext {
visibility: visible;
}")
)
),
headerPanel("Tooltip test"),
mainPanel(
p("some text", htmlOutput("Equation", inline = TRUE)),
))
server <- shinyServer(function(input, output,session) {
output$Equation <- renderUI({
span(class = "ttooltip",
style = "color: blue",
"something which needs equation",
span(class = "ttooltiptext",
withMathJax("$$\\bar{X} = \\frac{1}{n}\\sum_{p = 1}$$"))
)
})
})
shinyApp(ui = ui, server = server)
I'm struggling to find out how to target 1 of the two dropdowns specifically with css styling code.
I can style the dropdowns in general, but not individually
I have tried to target it in the following ways, but none work.
#MyDropDown1 .sw-show.sw-dropdown-content {
#sw-content-MyDropDown1 .sw-show.sw-dropdown-content {
.dropdown-content-MyDropDown1 {
#dropdown-content-MyDropDown1 {
#dropdown-menu-MyDropDown1 {
How to find the right syntax to target the 1st dropdown?
here is the app:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
tags$head(tags$style(HTML('
.sw-show.sw-dropdown-content {
display: block;
left: 200px;
top: 100px;
height: 300px;
width:
} '))),
dropdown(inputId = "MyDropDown1",
tags$h3("List of Input")),
dropdown(inputId = "MyDropDown2",
tags$h3("List of Input"))
)
server <- function(input, output, session){
}
shinyApp(ui = ui, server = server)
Maybe this is a way to go. But unfortunately because of the margin I end up with 2 boxes...
But at least the css style apply only on the first dropdown
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
tags$head(tags$style(HTML('
.test {
display: block;
background-color:red;
left: 200px;
top: 100px;
height: 300px;
width:
} '))),
dropdown(inputId = "MyDropDown1",
tags$h3("List of Input"), class = "test"),
dropdown(inputId = "MyDropDown2",
tags$h3("List of Input"))
)
server <- function(input, output, session){
}
shinyApp(ui = ui, server = server)
I have an app which generates a csv file to download. The process takes some time, and I'm trying to display a downloading..... message in the meanwhile. Based on some other answers on SO, I have figured out how to display that message when I'm trying to render a plot/table, but in this case I'm just trying to download a file. Currently, this is what I have-
library(shiny)
library(dplyr)
library(shinyjs)
jsResetCode <- "shinyjs.reset = function() {history.go(0)}" # Define the js method that resets the page
shinyApp(
ui = fluidPage(
useShinyjs(),
extendShinyjs(text = jsResetCode),
tags$head(tags$style(type="text/css", "
#loadmessage {
position: fixed;
bottom: 0px;
right: 0px;
width: 20%;
padding: 10px 0px 10px 0px;
text-align: center;
font-weight: bold;
font-size: 150%;
color: white;
background-color: #034f84;
z-index: 10;}")),
conditionalPanel(condition="$('html').hasClass('shiny-busy')",
tags$div("Loading...",id="loadmessage")),
downloadButton('dwd', "Download!"),
textOutput("text"),
actionButton("calc", 'Calculate'),
actionButton("reset", "Reset"),
dataTableOutput("tbl")
),
server = function(input, output) {
observeEvent(input$reset, {js$reset()}) # Reset the app
output$text <- renderText({
if(input$rnd > 0)
paste("loading....")
})
output$dwd <- downloadHandler(
filename = function(){
paste0("Iris.csv")
},
content = function(file){
Sys.sleep(3)
write.csv(iris, file)
}
)
observeEvent(input$calc, {
Sys.sleep(3)
output$tbl <- DT::renderDataTable(
DT::datatable(iris)
)
})
observe({
if(is.null(input$rnd)){
runjs("
var click = 0;
Shiny.onInputChange('rnd', click)
var dwnldBtn = document.getElementById('dwd')
dwnldBtn.onclick = function() {click += 1; Shiny.onInputChange('rnd', click)}
click = 0;
")
}
})
}
)
This displays the loading... message when I first download the file, but then the message persists. Is there any way that the Loading... message which is displayed during rendering the table can be displayed when trying to download the file too?
Thanks!