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)
})
}
)
Related
I have a ColourPicker that I use to determine the background color of an action button. What I would like to do is click on the action button and have the hex code that was clicked from the ColourPicker be copied to my clipboard. The goal is to then paste that value to be the background color in a cell of a data table. Right now, I am mostly worried about the copying part.
I have a button that I can copy-button so I can copy a text value, which is easy enough, but this is not what I am trying to do.
What I would like to do is copy the hex code from the small button that is generated in my code, which can change color based on the color selected by the ColourPicker, and access just the hex code value of that button.
Do I need to reference the ID of the ColourPicker in order to access the hex code? Or could I just copy that hex code straight from the button? I haven't been able to find any packages that work with getting hex codes from objects.
For reference, this is basically what I have (much thanks again to #lz100)
library(shiny)
library(shinythemes)
library(sortable)
library(colourpicker)
library(glue)
library(png)
library(dplyr)
library(DT)
library(rclipboard)
# funcs
plate96 <- function(id) {
div(
style = "position: relative; height: 500px",
tags$style(HTML(
'
.wells {
height: 490px;
width: 750px;
overflow: hidden;
min-height: 20px;
padding: 19px;
margin-bottom: 20px;
border: 1px solid #e3e3e3;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgb(0 0 0 / 5%);
box-shadow: inset 0 1px 1px rgb(0 0 0 / 5%);
position: relative;
transform: translateX(50%);
}
.wells:after {
content: "";
height: 450px;
width: 690px;
border: 1px solid;
position: absolute;
transform: translate(15px, -100%);
z-index: -1;
}
.wells .corner-top {
position: absolute;
margin: -20px;
width: 43px;
height: 34px;
transform: rotate(45deg);
background-color: white;
z-index: 1;
left: 30px;
border-right: 1px solid;
}
.wells .corner-bot {
position: absolute;
margin: -20px;
width: 40px;
height: 40px;
transform: rotate(45deg);
background-color: white;
z-index: 1;
left: 35px;
bottom: 20px;
border-top: 1px solid;
}
.wells .html-widget {
transform: translateX(20px);
}
.wells thead tr th {
font-weight: 100;
}
.wells table:after {
content: "";
border: 1px solid #ccc;
position: absolute;
height: 410px;
width: 635px;
z-index: -1;
transform: translate(33px, -99%);
}
.wells table.dataTable.no-footer {
border-spacing: 3px;
border-bottom: unset;
}
.wells table.dataTable thead th {
border-bottom: unset;
}
.wells tbody tr td:not(:first-of-type) {
border-radius: 50%;
border: 1px solid black;
height: 15px;
width: 15px;
padding: 15px;
font-size: 0;
}
.wells table.dataTable.cell-border tbody tr td:first-of-type {
border: unset;
border-right: 1px solid #ccc;
font-weight: 900;
}
'
)),
div(
style = "position: absolute; left: 50%; transform: translateX(-100%);",
div(
class = "wells",
div(class = "corner-top"),
div(class = "corner-bot"),
DT::dataTableOutput(id, width = "90%", height= "100%")
)
)
)
}
renderPlate96 <- function(id, colors = rep("white", 96), byrow = TRUE) {
stopifnot(is.character(colors) && length(colors) == 96)
plate <- matrix(1:96, nrow = 8, ncol = 12, byrow = byrow, dimnames = list(LETTERS[1:8], 1:12))
colnames(plate) <- stringr::str_pad(colnames(plate), 2, "left", "0")
renderDataTable({
datatable(
plate,
options = list(dom = 't', ordering = F),
selection = list(target = 'cell'),
class = 'cell-border compact'
) %>%
formatStyle(
1:12,
cursor = 'pointer',
backgroundColor = styleEqual(1:96, colors, default = NULL)
)
})
}
# app code
ui <- fluidPage(
plate96("plate"),
tags$b("Wells Selected:"),
verbatimTextOutput("well_selected"),
rclipboardSetup(),
numericInput("num_conds",
label = h3("Enter the number of treatments/ conditions"),
min = 1,
max = 20,
value = 1),
uiOutput("cond_colors"),
htmlOutput("cond_buttons", align = 'center'),
# Add a text input
textInput("copytext", "Copy this:", "Test 1"),
# UI ouputs for the copy-to-clipboard buttons
uiOutput("clip"),
# A text input for testing the clipboard content.
textInput("paste", "Paste here:")
)
server <- function(input, output, session){
#####Number output for number of conditions#####
output$value = renderPrint({ input$num_conds })
#### Color selection for UI input####
output$cond_colors <- renderUI({
num_conds <- as.integer(input$num_conds)
lapply(1:num_conds, function(i) {
colourInput(paste0("colors", i),
label = (paste0("Select a color for condition ", i)),
show = c("both"),
value = "black",
palette = c("limited"),
)
})
})
#### Create action buttons for conditions to be selected####
output$cond_buttons <- renderUI({
num_conds = as.integer(input$num_conds)
lapply(1:num_conds, function(i) {
bg = input[[paste0("colors", i)]]
style = paste0(
collapse = " ",
glue("background-color:{bg};
color:#ffffff;
border-color:#000000")
)
label = input[[paste0("condID", i)]]
cond_buttons = actionButton(paste0("cond_buttons", i),
label = label,
style = style
)
})
})
# Add clipboard buttons
output$clip <- renderUI({
output$clip <- renderUI({
rclipButton(
inputId = "clipbtn",
label = "Test copy button",
clipText = input$copytext,
icon = icon("clipboard")
)
})
})
# Workaround for execution within RStudio version < 1.2
if (interactive()){
observeEvent(input$clipbtn, clipr::write_clip(input$copytext))
}
output$plate <- renderPlate96(
"plate",
colors = c(
rep("#eeeeee", 12),
rep("#27408b", 12),
rep("#0f8b44", 12),
rep("#9400d3", 12),
rep("#0701ff", 12),
rep("white", 36)
)
)
output$well_selected <- renderPrint({
input$plate_cells_selected
})
}
shinyApp(ui = ui, server = server)
And here is a picture to kind of explain what I am thinking. Before:
After:
You could set an input value via client-side Javascript, using Shiny.setInputValue and process this value like those provided by UI input elements.
Simple example:
library(shiny)
ui <- shiny::fluidPage(
actionButton('colored_button', 'a green button',
style = 'background-color:#00ff00'
),
actionButton('button_get_color', 'get color'),
textOutput('color_message'),
## inject client-side javascript:
tags$script('
// bind JS code to the getter button:
document.getElementById("button_get_color")
.onclick = function(){
// set input value via JS:
Shiny.setInputValue("color",
// select colored button and get its background color:
document.getElementById("colored_button")
.style.backgroundColor)
}'
)
)
server <- function(input, output) {
observeEvent(input$button_get_color,{
## do stuff, e. g.
output$color_message <- renderPrint(input$color)
})
}
shinyApp(ui, server)
Edit:
You can also use the colored button (or any page element) to set the input value: get the element by ID and have it trigger Shiny.setInputValue on click (or other mouse event)
more information on communicating via JS here
some suggestions on converting RGB to Hex
I create a shiny dashboard in which I have set titleWidth and sidebar width = 0 in order to have them hidden. Then I want to add an image in the left corner of the header section which will completely fit to the header section and then the title in the same row but in the right corner. As you can see now the header section became bigger and also the title seems to be a row lower than the image. Here is my code:
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyjs)
dbHeader <- dashboardHeaderPlus(
titleWidth = "0px",
tags$li(a(href = 'http://https://www.uow.edu.au/',
img(src = 'download.png',
height = "55px",width="232px"),
style = "padding-top:0px; padding-bottom:0px; padding-right:1690px;padding-left:90px;"),
class = "dropdown")
)
shinyApp(
ui = dashboardPagePlus(
header = dbHeader,
sidebar = dashboardSidebar(width = "0px"),
body = dashboardBody(
useShinyjs(),
tags$head(tags$style(".skin-blue .main-header .logo { padding: 0px;}")),
tags$head(tags$style(HTML(
'.myClass {
font-size: 25px;
line-height: 50px;
text-align: left;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
padding: 1500px;
padding-bottom: 0 0px;
padding-top: 0 0px;
overflow: hidden;
color: black;
}
'))),
tags$script(HTML('
$(document).ready(function() {
$("header").find("nav").append(\'<span class="myClass"> Life,Death & Statins </span>\');
})
'))
)
),
server<-shinyServer(function(input, output,session) {
hide(selector = "body > div > header > nav > a")
}
)
)
Perhaps your are looking for this. You can play with padding and margins to get appropriate spacing.
mytitle <- paste0("Life, Death and Statins")
dbHeader <- dashboardHeaderPlus(
titleWidth = "0px",
tags$li(a(href = "https://www.mit.edu/", # 'http://https://www.uow.edu.au/',
div(style = "margin-left:-15px;margin-bottom:-44px;margin-top:-15px;padding: 0px 1190px 0px 0px ; width: 290px;",
img(src = 'YBS.png', height = "55px",width="232px")),
div(style="display: inline; padding: 0px 90px 0px 750px ; font-size: 40px ; width: 300px;",HTML(mytitle, "<br>"))
),
class = "dropdown")
)
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 2 textInput and 2 selectInput functions. One on the dark background on my sidebar and the other on the white (inside the bsModal). My question is: is there a way to style them in different ways? Ideally, I would like to keep the ones on the sidebar the way I styled, and for the ones inside bsModal at least change font color and a border color.
Code:
## Shiny
library(shiny)
library(shinydashboard)
library(shinyBS)
ui <- dashboardPage(
## Header ----
dashboardHeader(
disable = TRUE
),
## Sidebar ----
dashboardSidebar(
sidebarMenu(
div(style = "border-left-color: #1e282c; padding: 10px",
menuItem(text = div(HTML("<left>Search</left>")),
tabName = "search",
icon = icon("search", "fa-2x"))
)
)
),
## Body ----
dashboardBody(
## when header is disabled need to compensate for the missing 50px
## to avoid empty space on the bottom
tags$script('window.onload = function() {
function fixBodyHeight() {
var el = $(document.getElementsByClassName("content-wrapper")[0]);
var h = el.height();
el.css("min-height", h + 50 + "px");
};
window.addEventListener("resize", fixBodyHeight);
fixBodyHeight();
};'),
tags$style(HTML(
"
.well{
background-color: #222C3C;
color: #FFFFFF;
}
.form-control {
background-color: transparent;
border: 0px;
border-bottom: 1px solid #ffffff;
color: #ffffff;
}
.selectize-input{
background: transparent;
}
.selectize-input.items.not-full.has-options {
border: 0px;
border-bottom: 1px solid #ffffff;
border-radius: 0;
}
.selectize-dropdown, .selectize-input, .selectize-input input{
color: #FFFFFF;
}
.selectize-control.multi .selectize-input > div{
background: rgb(9, 231, 178, 0.3);
color: #ffffff;
}
.selectize-dropdown-content {
background: #1B2431;
color: #ffffff;
border-radius: 4px;
}
.selectize-input.full{
background-color: transparent;
color: #FFFFFF;
border: 0px;
border-bottom: 1px solid #ffffff;
border-radius: 0;
}
.selectize-input, .selectize-control.single, .selectize-input.input-active{
background: transparent !important;
}
"
)),
# includeCSS("www/style.css"),
tabItems(
tabItem(
tabName = "search",
sidebarLayout(
sidebarPanel(
tabsetPanel(
tabPanel(div("Search task"),
textInput("searchTextIn", HTML("<i class='fa fa-search'></i> KEYWORDS"), value = ""),
selectizeInput("productFilter", HTML("<i class='fa fa-share-alt gly-rotate-135'></i> PRODUCT OR COMPONENT"),
choices = c("A", "AAA", "B", "BBBBBB", "C", "CCCCCC"),
multiple = TRUE,
selected = c("A", "AAA")),
actionLink("saveToGroup", HTML("<u> Save to group </u>"), style = "color: #d3d3d3cf"),
width = 3)
)),
mainPanel(
bsModal("saveToGroupPopup", "Save to group", "saveToGroup",
div(selectizeInput("saveToGroupSelection",
"Add this search to a search group:",
choices = c("Category A", "Category B", "Category C",
"Batman"),
selected = NULL,
multiple = TRUE,
options = list(maxItems = 1))),
textInput("saveToGroupNew", label = NULL, value = "",
placeholder = "Create new…")
)
)
)
)
)
)
)
server <- function(input, output) {}
shinyApp(ui = ui, server = server)
you can use glamor to style your inputs differently. Basically glamor allows you to write css using javascript like conditions. just pass a boolean variable along with the class and on the basis of that variable choose the style of text field for example
const descDiv = **isDark** => css({
color: isDark ? color.white : colors.gray,
marginBottom: isDark? '0rem' :'1rem',
letterSpacing:isDark ? '0px' :'-0.6px', //if isDark true 0px else -0.6px
width:isDark? '10rem' :'13.5rem'
});
One solution that worked for me is for the textInput is actually quite easy, all I needed to do is in my css:
textInput(id, "")
tags$style(HTML("
#id.form-control{color:gray;}
"))
For the selectize input is a bit more confusing:
selectizeInput(id, ....)
tags$style(HTML("
#id + div>.selectize-input.items.not-full.has-options{border-bottom: 1px solid #F2F2F2;}
#id + div>.selectize-dropdown, #id+ div>.selectize-input, #id+ div>.selectize-input input{ color: gray;}
#id + div> div> .item {color: gray;}
"))