I am using R's bsplus package to build a carousel of images. I want to move the chevrons next to the bullets.
I am aware of this SO sol'n regarding how to reposition the prev/next chevrons.
I can get close (see the 'right' chevron) but when I position it where I want it (see the 'left' chevron) it's no longer clickable.
Why is this?
How can I position the chevrons next to the bullets and maintain their functionality?
R Script
library("shiny")
library("bsplus")
ui <- fluidPage(
includeCSS("/home/law/whatbank_home/tests/bullet.css"),
# Application title
titlePanel("Carousel Demo"),
uiOutput("carousel")
)
server <- shinyServer(function(input, output) {
output$carousel <- renderUI({
bs_carousel(id = "images", use_indicators = TRUE) %>%
bs_append(
content = bs_carousel_image(src = "https://placehold.it/900x500/3c8dbc/ffffff&text=Merry")
) %>%
bs_append(
content = bs_carousel_image(src = "https://placehold.it/900x500/3c8dbc/ffffff&text=Christmas")
) %>%
bs_append(
content = bs_carousel_image(src = "https://placehold.it/900x500/3c8dbc/ffffff&text=To")
) %>%
bs_append(
content = bs_carousel_image(src = "https://placehold.it/900x500/3c8dbc/ffffff&text=All")
)
})
})
# Run the application
shinyApp(ui = ui, server = server)
css
.carousel-control.left,
.carousel-control.right {
background: transparent;
}
.carousel-indicators .active {
background-color: #FCB700;
margin-bottom: 70px;
}
.carousel-indicators li {
background-color: #D8D8D8;
border: 1px solid #000;
margin-bottom: 70px;
}
.carousel-control.left .glyphicon {
left: 180px;
margin-left: 180px;
top: 183px;
margin-top: 183px;
}
.carousel-control.right .glyphicon {
right: 180px;
margin-right: 180px;
top: 160px;
margin-top: 160px;
}
You should try
.carousel-control {
width: 2%
}
In the example below, I use 2%.
library(shiny)
library(shinydashboardPlus) ### carousel() is from this package
library(DT)
jscode <-"
$(document).ready(function(){
$('#mycarousel').carousel( { interval: false } );
});"
shinyApp(
ui = dashboardPage(
header = dashboardHeader(),
sidebar = dashboardSidebar(),
body = dashboardBody(
tags$head(
tags$style(HTML("
#mycarousel {
width:900px;
height:600px;
}
.carousel-control{
color:#FF0000;
width: 2%;
}
"))
),
tags$head(tags$script(HTML(jscode))),
carousel(
id = "mycarousel",
carouselItem(
DTOutput("show_iris_dt")
),
carouselItem(
caption = "An image file",
tags$img(src = "YBS.png")
),
carouselItem(
caption = "Item 3",
tags$img(src = "http://placehold.it/900x500/39CCCC/ffffff&text=Happy+New+Year")
)
)
),
title = "Carousel Demo"
),
server = function(input, output) {
output$show_iris_dt <- renderDT({
datatable(iris)
})
}
)
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)
Hi I have a problem with a download button in my Shiny APP. I have created the button dynamically when the corresponding DF has been created. Now I have the problem that the download doesn't work. If I created the button directly the download works.
I did the same with a reset function and everything works here.
Can someone tell me what I am doing wrong?
This is the Button Code in the UI:
column(3, offset = 0, uiOutput("download.action", style = "text-align: center;"))
and my Server code looks like this:
output$download.action <- renderUI({
div(style = "display:inline-block;width:0%;", actionButton("downloadData", "Download", icon = icon("download"),
style = "
flex-grow: 1;
display: inline-block;
background-color:#999;
text-decoration: none;
font-weight: 300;
border: 1px dash transparent;
letter-spacing: 0.98pt;
border-color:#00245d;"))
})
output$downloadData <- downloadHandler(
filename = function() {
paste("test.xlsx")
},
content = function(file) {
write.xlsx(test3, file, row.names = FALSE)
}
)
})
When I create the Button directly everything works fine.
Shiny gives no Error Messages. Only the Button didn't work.
You should replace actionButton with downloadButton.
output$download.action <- renderUI({
div(style = "display:inline-block;width:0%;", downloadButton("downloadData", "Download", icon = icon("download"),
style = "
flex-grow: 1;
display: inline-block;
background-color:#999;
text-decoration: none;
font-weight: 300;
border: 1px dash transparent;
letter-spacing: 0.98pt;
border-color:#00245d;"))
})
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 a problem with my shinyapp. I want to upload data for my calculations. When I do so the app automatically runs through the whole script the moment the upload is complete, so I implemented an action button. When I start the app and upload the data I have to click on the action button, the program executes and everything works fine. But when I start the app and click on the action Button first and then upload data, the program executes without having to click on the run button again. I made an example here. Because my actual app is ways bigger I need this feature that the programs is not executing automatically after uploading new data once the action button was clicked for the data I uploaded in the first place. I know that there is isolate() and I tried to implement it in every position possible but without any result. Can somebody help me out here?
Here the code. with example data.
Mydata<-data.frame(A=1:1100,B=rnorm(1100, 50, 5))
write.csv(Mydata, file = "MyData.csv")
and the app:
ui <- fluidPage(
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('files1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv'), multiple = TRUE),
tags$hr(),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
','),
actionButton("go","run",class = "btn-primary"),br()
),
mainPanel(tags$head(tags$style(type="text/css", "
#loadmessage {
position: fixed;
top: 95%;
left: 0px;
width: 100%;
padding: 5px 0px 5px 0px;
text-align: center;
font-weight: bold;
font-size: 100%;
color: #000000;
background-color: #CCFF66;
z-index: 105;
}
")),
conditionalPanel(condition="$('html').hasClass('shiny-busy')",
tags$div("Loading...",id="loadmessage")),
verbatimTextOutput('text1')
)
)
)
server <- function(input, output) {
observeEvent(input$go,{
mapz <- reactive({
inFiles <- input$files1
if (is.null(inFiles))
return(NULL)
Q <- read.csv(input$files1[[1, 'datapath']],sep=input$sep,dec="." )
names(Q)<-c("A","B")
Q<-Q[Q$A<1000,]
nom<-seq(round(min(Q$A)),floor(max(Q$A)),by=1)
counts<-matrix(NA,nrow=length(nom),ncol=length(input$files1[,1]))
return(list(as.matrix(nom),counts))
})
output$text1 <-renderPrint(if(is.null(input$files1)==FALSE) as.data.frame(mapz()[[1]]))
})}
shinyApp(ui, server)
Many thanks!
One very quick and effective way you can do this is to make that part of the UI unavailable until the file or files are uploaded. Basically make a uiOutput() call in place of the actionButton() call and move the actionButton() into a renderUI() function in server that has a conditional looking for a not NULL return for mapz(). The button isnt available to be pressed unless there is a non NULL return for mapz(). You should also move the reactive that creates mapz() outside of the observeEvent() so that it becomes usable to the app regardless of whether the button is pressed or not. Now as a caveat this never resets the button so as long as there is a file uploaded the button is pressable. It is functionally the same so the ! operator works like the ==FALSE conditional. Heres the code with the suggested changes :
ui <- fluidPage(
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('files1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv'), multiple = TRUE),
tags$hr(),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
','),
uiOutput("runbutton"),br()
),
mainPanel(tags$head(tags$style(type="text/css", "
#loadmessage {
position: fixed;
top: 95%;
left: 0px;
width: 100%;
padding: 5px 0px 5px 0px;
text-align: center;
font-weight: bold;
font-size: 100%;
color: #000000;
background-color: #CCFF66;
z-index: 105;
}
")),
conditionalPanel(condition="$('html').hasClass('shiny-busy')",
tags$div("Loading...",id="loadmessage")),
verbatimTextOutput('text1')
)
)
)
server <- function(input, output) {
output$runbutton <- renderUI({
if(!is.null(mapz()){
actionButton("go","run",class = "btn-primary")
}
})
mapz <- reactive({
inFiles <- input$files1
if (is.null(inFiles))
return(NULL)
Q <- read.csv(input$files1[[1, 'datapath']],sep=input$sep,dec="." )
names(Q)<-c("A","B")
Q<-Q[Q$A<1000,]
nom<-seq(round(min(Q$A)),floor(max(Q$A)),by=1)
counts<-matrix(NA,nrow=length(nom),ncol=length(input$files1[,1]))
return(list(as.matrix(nom),counts))
})
observeEvent(input$go,{
output$text1 <-renderPrint(if(is.null(mapz())==FALSE) as.data.frame(mapz()[[1]]))
})}
shinyApp(ui, server)
dont know why exactly, but this seems to work:
ui <- fluidPage(
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('files1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv'), multiple = TRUE),
tags$hr(),
radioButtons('sep', 'Separator',
c(Comma=',',
Semicolon=';',
Tab='\t'),
','),
actionButton("go","run",class = "btn-primary"),br()
),
mainPanel(tags$head(tags$style(type="text/css", "
#loadmessage {
position: fixed;
top: 95%;
left: 0px;
width: 100%;
padding: 5px 0px 5px 0px;
text-align: center;
font-weight: bold;
font-size: 100%;
color: #000000;
background-color: #CCFF66;
z-index: 105;
}
")),
conditionalPanel(condition="$('html').hasClass('shiny-busy')",
tags$div("Loading...",id="loadmessage")),
verbatimTextOutput('text1')
)
)
)
server <- function(input, output) {
observeEvent(input$go,{
mapz1 <- reactive({
inFiles <- input$files1
if (is.null(inFiles))
return(NULL)
Q <- read.csv(input$files1[[1, 'datapath']],sep=input$sep,dec="." )
names(Q)<-c("A","B")
Q<-Q[Q$A<1000,]
nom<-seq(round(min(Q$A)),floor(max(Q$A)),by=1)
counts<-matrix(NA,nrow=length(nom),ncol=length(input$files1[,1]))
return(list(as.matrix(nom),counts))
})
mapz<-reactive({isolate(mapz1())})
output$text1 <-renderPrint(as.data.frame(mapz()[[1]]))
})}
shinyApp(ui, server)