In my shiny app, I have a box with a dropdown menu in the top left corner. However, some of the elements in my box are being cut off by the dropwdown menu (for example, in the pic below the table in my box is being covered by the menu). Is there a way to have the menu to always stay above other elements in my box?
This is my code. I noticed this issue only occurs if I use rhandsontable to render my tables. Unfortunately, I do need to use rhandsontable.
library(shiny)
library(shinyWidgets)
library(shinydashboard)
library(rhandsontable)
factorUI <- function(id) {
ns <- NS(id)
box(
width=6,
title = "Charts",
closable = TRUE,
status = "danger",
solidHeader = TRUE,
collapsible = TRUE,
dropdown(
style = "material-circle",
selectInput(ns("options"),"Select an option:",
choices = list("All" = "all", "Option1" = "option1","Option2" = "option2"),selected = "all"),
conditionalPanel("input.options == 'option1'",ns=ns, sliderInput(ns("shr.month"),"No of months:",min=0,max=1,value=c(0,1),step = 1)),
conditionalPanel("input.options == 'option2'",ns=ns, sliderInput(ns("fh.month"),"No of months:",min=0,max=1,value=c(0,1),step = 1)),
conditionalPanel("input.manual == 'Y'",fileInput(ns("upload"),"Upload new pattern",accept = ".csv")),
materialSwitch(inputId = ns("factorind"),label = "Apply factor",status = "primary",right = TRUE),
conditionalPanel("input.factorind == true",ns=ns,
numericInput(ns("start"),"Apply from:",value = NULL,min=0,step=1),
numericInput(ns("factor"),"Factor:",value=NULL,min=0)),
id = ns("sidebar"),
status = "danger",
size = "sm",
icon = shiny::icon("sliders")),
rHandsontableOutput(ns("table")),
)
}
factor <- function(id) {(
moduleServer(
id,
function(input,output,session) {
output$table <- renderRHandsontable({
rhandsontable(iris)
})
}
)
)}
ui <- fluidPage(
titlePanel("Example"),
sidebarLayout(
sidebarPanel(),
mainPanel(factorUI("test"))
)
)
server <- function(input, output) {
factor("test")
}
shinyApp(ui = ui, server = server)
Increase the z-index of dropdown, you can add the style before the end of box like this:
box(
...,
tags$style('.sw-dropdown-content {z-index: 105;}')
)
The CSS z-index decides the layer order of elements, which one is on top which is below. The table has index of 102, so if you make a number larger than that one for your dropdown (shinyWidgets dropdown default is 5), your drop down will be on top.
Related
I'm trying to embed a real-time bslib theme into my shiny app. It was working previously, and when I try it on a new plain shiny app it works, but for some reasons, I keep receiving the same error when I run my shiny app:
Error : bslib::bs_themer() requires shiny::bootstrapLib() to be present in the app's UI. Consider providing bslib::bs_theme() to the theme argument of the relevant page layout function (or, more generally, adding bootstrapLib(bs_theme()) to the UI.
I appreciate your support. Here is my code:
ui <- navbarPage(theme = bs_theme(), h4(""),
tabPanel(
title = h6(""),
dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu()),
dashboardBody(
fluidRow(
box(plotlyOutput(outputId = "plotly_1"), height = 300),
box(plotlyOutput(outputId = "plotly"), height = 300 )),
fluidRow(column(12),
box(DTOutput(outputId = "dt_output"), height = 300),
)))),
tabPanel(title = h6(""),
dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu()),
dashboardBody(
fluidRow(
box(plotlyOutput(outputId = "plotly_2"), height = 300),
box(plotlyOutput(outputId = "plotly_3"), height = 300 )),
))))
server <- function(input, output, session) {
bs_themer()
output$plotly_1 <- renderPlotly ({})
output$plotly <- renderPlotly ({})
output$dt_output <- DT:: renderDataTable ()
}
shinyApp(ui = ui, server = server)'
I have a dashboard with several (planned - only two shown here) tabs. After the app has been started, the user should see only the first tab "settings" to load data. After the data have been loaded the other tabs should appear.
I managed to hide the tab "Plot" with hidden() but I have problems to have it appear properly:
whereas the selectInput item appears correctly on the sidebar, the Plot "menuItem" is not shown. I would like to see the Tab "Plot" below settings, so that the user can switch between tabs as soon as the dataset has been chosen. In principle it should look like without the hidden function. I'd be grateful for any help on this.
Here is a reproducible example:
library(shiny)
library(shinydashboard)
library(shinyjs)
ui <- dashboardPage(
dashboardHeader(title = "plot datasets"),
dashboardSidebar(
useShinyjs(),
sidebarMenu(id = "menu", style = "position: Scroll; overflow: visible",
menuItem("Setttings ", tabName = "settings",icon = icon("wrench")),
hidden(
menuItem("Plot",tabName = "Plot",icon = icon("envira"))),
conditionalPanel(condition = "input.menu == 'Plot'",
tags$hr(),
selectInput(inputId = "Variables", label = "Variables", choices = NULL)
)
)
),
dashboardBody(
tabItems(
tabItem(tabName = "settings",
fluidRow(style = "background-color:#D3D3D3;",
column(12,h2("Test mtcars"),h3("Please adjust some settings:")),
),
fluidRow(
column(6,
tags$br(),
selectInput(inputId = "set", label = "Which dataset do you want to plot?",
choices = c("","mtcars","iris"), selected = "")
),
)
),
tabItem(tabName = "Plot",
plotOutput("plot1")
)
)
)
)
server <- function(input, output, session){
data <- reactive({
if(input$set == ""){
NULL
}else{
name <- as.character(input$set)
get(name)
}
})
observe({
choice <- colnames(data())
updateSelectInput(session, "Variables", "Variables", choices = sort(choice))
})
observeEvent(nrow(data())>1,{
req(input$set)
show(selector = '[data-value="Plot"]')
})
output$plot1<- renderPlot({
p <- plot(data()[,2:3])
p
})
}
shinyApp(ui, server)
Button(
onClick = {
raceOn = !raceOn
if (raceOn) {
text.value = "Stop!"
color.value = Color.Red
} else {
text.value = "Go!"
color.value = Color.Green
}
},
modifier = Modifier.background(color = color.value),
content = {
Text(
text = "${text.value}",
)
}
)
Using the code above, I got the attached image. What I want is the inside of the button to be green and not the background behind it. I couldn't the right property to modify.
Has anyone here tried to modify the Button background? Or perhaps suggest another solution. I tried the OutlinedButton and wasn't successful.
Thanks!
Use the MaterialTheme ButtonColors.
val colors: ButtonColors = ButtonDefaults.primaryButtonColors(backgroundColor = Color.Red)
Button(onClick = { /*TODO*/ }, colors = ButtonDefaults.primaryButtonColors()) {
// TODO
}
You can also update via setting the MaterialTheme defaults.
val wearColorPalette: Colors = Colors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200,
secondaryVariant = Teal200,
error = Red400,
onPrimary = Color.Black,
onSecondary = Color.Black,
onError = Color.Black
)
...
MaterialTheme(
colors = wearColorPalette,
typography = Typography,
// For shapes, we generally recommend using the default Material Wear shapes which are
// optimized for round and non-round devices.
content = content
)
This question is more conceptual than explicit to a particular piece of code so I guess there's no toy-code this time.
I have a rather large shiny app that uses some d3.js scripts. The D3 objects access a few global variables when their update functions are called. I'd like to control these variables from the Shiny server - is this possible?
This app assumes the global variable was assigned to the window. Then it uses a custom message handler to create the original variable (#1) and another to manipulate the value of that variable (#2).
Edited to have message sent back to R with the state of the global variable.
R Code:
library(shiny)
ui <- fluidPage(
# Application title
titlePanel("Global Variable Manipulation"),
mainPanel(
sliderInput("data", "Element", min = 0, max = 100, value = 0),
actionButton("go", "GO"),
textOutput("var"),
singleton(
tags$head(tags$script(src = "message-handler.js"))
),
singleton(
tags$head(tags$script(src = "message-handler2.js"))
),
singleton(
tags$head(tags$script(src = "back-to-shiny.js"))
)
)
)
server <- function(input, output, session) {
observe({
session$sendCustomMessage(type = 'testmessage',
message = list(a = 1, b = 'text',
controller = input$data))
})
observeEvent(input$go,{
session$sendCustomMessage(type = 'changeMessage',
message = list(2))
})
output$var <- renderPrint({
input$jsvalue
})
}
# Run the application
shinyApp(ui = ui, server = server)
message-handler.js code:
Shiny.addCustomMessageHandler("testmessage",
function(message) {
window.globalVar = message.controller
alert(JSON.stringify(window.globalVar));
}
);
message-handler2.js code:
Shiny.addCustomMessageHandler("changeMessage",
function(message) {
window.globalVar = window.globalVar-message;
alert(JSON.stringify(window.globalVar));
}
);
back-to-shiny.js code:
setInterval(function(){
var message = window.globalVar;
Shiny.onInputChange("jsvalue", message);
},0);
While it looks like you can change the order of a tab within a window by updating the tab .index property, it doesn't look like the tabs api directly supports the move of a tab to another window.
Am I missing something? Is there a viable workaround?
It is possible through the low level module window/utils. The example below duplicates the active tab across every open window
const { getMostRecentBrowserWindow, windows: getWindows } = require("sdk/window/utils");
const { ActionButton } = require("sdk/ui/button/action");
var button = ActionButton({
id: "duplicatetab-button",
label: "Duplicate tab",
icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACUElEQVQ4jaWTTWtTURCGjzc33CCpbVKN4kexC9EUY1Hov+iqPyDrbgtuCrViKUERqsWVguBGQaW4UiKiaEVxoShFGgnuBMUqNW3zce49Z+ZxUWtwoRR8YXbzPswM7xj+JgVEiXGsYVknxgII4Ltt5p8AB8RArOAUVQfqQJNtAFA8QgvF6i9PR1Dt0KbVBTjncM4hIni/OZv3HsRB+wvefiP2LcQnJIkQe49FEJFNQLPZZHh4mEwmQyqVoqenh3K5TGvlK1dOlageH+HG4DFar1/S0A6Lr99xdN8QxWKRXC6HGR0dJZvNMjk5Sb1ep1gskk6nuTo/D+/ec7dvkBdhP9cKeX7UXxEZQ2/YRxRFLC8vY+bm5qhUKnjvsdYyPj5OFEWcnTnHujiS5TfcPDbAw50h9w7u5f7UadLZFLVaDRHBiGzuY61lbGyMXC5HoVBgrbGGWAW/TvvxHR7s7udFKs/1oyfZ+PSRTqeDqm7eoFqtEoYhmUyG2dlZVJU4iREfI/WP3Nt9iMUdu7jdf5Anly5i0oaVlRWazSZmYWGBIAiIoohyucz09DQTExPMnJli9dlT5vcM8Kh3gFsHDuNqb9mb7yXMRBhjWFpawpRKJVKpFMYYgiAgDEOCIOD81BkunBjh8pEhKqUhGkvP6bQ/U//wgUP5/YRhSDabxbTbbVQV5xyq2q0kgR8NdOM7JKuo/Y5qggqIdPvMlnkrQCKCquJFsOrxeHAJxA48eFU6Xv4EqOpv41YqnQirqliv4MEmQtN7RBSs7wL+/gvb038DfgJnyUabbHzUbQAAAABJRU5ErkJggg==",
onClick: function() {
var xulwindows = getWindows("navigator:browser");
var xulactivewindow = getMostRecentBrowserWindow();
var xulactivetab = xulactivewindow.gBrowser.selectedTab;
xulwindows.forEach(function(win){
if(win === xulactivewindow)
return;
var duplicatedtab = win.gBrowser.duplicateTab(xulactivetab);
win.gBrowser.moveTabTo(duplicatedtab, 0); // the second argument is the index
});
}
});
#paa's solution is nice but it doesn't move a tab. His is duplicating the tab. So flash movies will not retain their position etc. And its not a move its a duplicatio, like he explained.
I did a lot of research was real fun. The way they move tabs in Firefox is via docShell swapping. This will accomplish what you want. It's written for bootstrap though so needs touch up for addon sdk.
Pass second argument as string of tabbed or non-tabbed if you want to move it to a new window. Else pass second argument an existing window and it will be moved there. can copy paste and run this code from sratchpad.
this uses the gBrowser.swapBrowsersAndCloseOther function
function moveTabToWin(aTab, tDOMWin) {
//tDOMWin means target DOMWindow means the window you want the tab in
//if tDOMWin == 'tabbed' or == 'non-tabbed' it opens in a new window
//if aTopContWin is the last in its window, then its window is closed
if (tDOMWin == 'tabbed' || tDOMWin == 'non-tabbed') {
var sa = Cc["#mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
var wuri = Cc["#mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
wuri.data = 'about:blank';
sa.AppendElement(wuri);
let features = "chrome,dialog=no";
if (tDOMWin == 'tabbed') {
features += ',all';
}
var sDOMWin = aTab.ownerGlobal; //source DOMWindow
if (PrivateBrowsingUtils.permanentPrivateBrowsing || PrivateBrowsingUtils.isWindowPrivate(sDOMWin)) {
features += ",private";
} else {
features += ",non-private";
}
var XULWindow = Services.ww.openWindow(null, 'chrome://browser/content/browser.xul', null, features, sa);
XULWindow.addEventListener('load', function() {
var DOMWindow = XULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
DOMWindow.gBrowser.selectedTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
DOMWindow.gBrowser.swapBrowsersAndCloseOther(DOMWindow.gBrowser.selectedTab, aTab);
//DOMWindow.gBrowser.selectedTab = newTab;
}, false);
} else if (tDOMWin) {
//existing dom window
var newTab = tDOMWin.gBrowser.addTab('about:blank');
newTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
tDOMWin.gBrowser.swapBrowsersAndCloseOther(newTab, aTab);
tDOMWin.gBrowser.selectedTab = newTab;
}
}
moveTabToWin(gBrowser.selectedTab, 'tabbed');
I'v got inspired by #Noitidart's answer and came up with my solution.
I'm adding setWindow(window, index) method to Tab's prototype, so that any SDK tab can be moved to another window from anywhere in the addon with a simple call like this:
browserWindows[0].activeTab.setWindow(browserWindows.activeWindow, 0);
This will move active tab of window 0 to the beginning of active window.
And here is the method:
Update:
I've put together a module to do exactly this: jetpack-tab-setwindow
Old solution (breaks in FF43)
var Tab = require("sdk/tabs/tab").Tab;
Tab.prototype.setWindow = function (window, index) {
var tab = this;
var oldWindow = tab.window;
if ( oldWindow !== window ) {
// We have to use lower-level API here
var Ci = require('chrome').Ci;
var viewFor = require("sdk/view/core").viewFor;
var aTab = viewFor(tab);
var aWin = viewFor(window);
var gBrowser = aWin.gBrowser;
// Get tab properties
var isSelected = oldWindow.activeTab == tab;
var isPinned = aTab.pinned;
// Log for debugging:
var tabId = tab.id;
console.log('setWindow', {index, isSelected, isPinned, tab, tabId});
// Create a placeholder-tab on destination windows
var newTab = gBrowser.addTab('about:newtab');
newTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL); // we don't need this tab anyways
// If index specified, move placeholder-tab to desired index
if ( index != undefined ) {
var length = gBrowser.tabContainer.childElementCount;
if ( index < 0 ) index = length - index;
if( 0 <= index && index < length ) {
gBrowser.moveTabTo(newTab, index);
}
}
// Copy tab properties to placeholder-tab
if ( isPinned ) {
gBrowser.pinTab(newTab);
}
// For some reason this doesn't seem to work :-(
if ( isSelected ) {
gBrowser.selectedTab = newTab;
}
// Swap tabs and remove placeholder-tab
gBrowser.swapBrowsersAndCloseOther(newTab, aTab);
}
};